2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
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.
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.
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.
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
43 * Provides CAM functionality.
48 #include "ocs_device.h"
50 /* Default IO timeout value for initiators is 30 seconds */
51 #define OCS_CAM_IO_TIMEOUT 30
58 } ocs_dmamap_load_arg_t;
60 static void ocs_action(struct cam_sim *, union ccb *);
61 static void ocs_poll(struct cam_sim *);
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 *);
75 ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role);
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);
83 int32_t ocs_tgt_find(ocs_fcport *fcp, ocs_node_t *node);
85 static inline ocs_io_t *ocs_scsi_find_io(struct ocs_softc *ocs, uint32_t tag)
88 return ocs_io_get_instance(ocs, tag);
91 static inline void ocs_target_io_free(ocs_io_t *io)
93 io->tgt_io.state = OCS_CAM_IO_FREE;
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);
102 ocs_attach_port(ocs_t *ocs, int chan)
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);
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");
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);
125 mtx_unlock(&ocs->sim_lock);
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);
140 callout_init_mtx(&fcp->ldt, &ocs->sim_lock, 0);
141 TASK_INIT(&fcp->ltask, 1, ocs_ldt_task, fcp);
147 ocs_detach_port(ocs_t *ocs, int32_t chan)
149 ocs_fcport *fcp = NULL;
150 struct cam_sim *sim = NULL;
151 struct cam_path *path = NULL;
152 fcp = FCPORT(ocs, chan);
157 callout_drain(&fcp->ldt);
158 ocs_ldt_task(fcp, 0);
161 mtx_lock(&ocs->sim_lock);
162 ocs_tgt_resource_abort(ocs, &fcp->targ_rsrc_wildcard);
164 xpt_async(AC_LOST_DEVICE, path, NULL);
168 xpt_bus_deregister(cam_sim_path(sim));
170 cam_sim_free(sim, FALSE);
172 mtx_unlock(&ocs->sim_lock);
179 ocs_cam_attach(ocs_t *ocs)
181 struct cam_devq *devq = NULL;
183 uint32_t max_io = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_IOS);
185 if (NULL == (devq = cam_simq_alloc(max_io))) {
186 device_printf(ocs->dev, "Can't allocate SIMQ\n");
192 if (mtx_initialized(&ocs->sim_lock) == 0) {
193 mtx_init(&ocs->sim_lock, "ocs_sim_lock", NULL, MTX_DEF);
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);
203 ocs->io_high_watermark = max_io;
209 ocs_detach_port(ocs, i);
212 cam_simq_free(ocs->devq);
214 if (mtx_initialized(&ocs->sim_lock))
215 mtx_destroy(&ocs->sim_lock);
221 ocs_cam_detach(ocs_t *ocs)
225 for (i = (ocs->num_vports); i >= 0; i--) {
226 ocs_detach_port(ocs, i);
229 cam_simq_free(ocs->devq);
231 if (mtx_initialized(&ocs->sim_lock))
232 mtx_destroy(&ocs->sim_lock);
237 /***************************************************************************
238 * Functions required by SCSI base driver API
242 * @ingroup scsi_api_target
243 * @brief Attach driver to the BSD SCSI layer (a.k.a CAM)
245 * Allocates + initializes CAM related resources and attaches to the CAM
247 * @param ocs the driver instance's software context
249 * @return 0 on success, non-zero otherwise
252 ocs_scsi_tgt_new_device(ocs_t *ocs)
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");
263 * @ingroup scsi_api_target
264 * @brief Tears down target members of ocs structure.
266 * Called by OS code when device is removed.
268 * @param ocs pointer to ocs
270 * @return returns 0 for success, a negative error code value for failure.
273 ocs_scsi_tgt_del_device(ocs_t *ocs)
280 * @ingroup scsi_api_target
281 * @brief accept new domain notification
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().
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
291 * This function will only be called if the base-driver has been enabled for
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.
297 * @param domain pointer to domain
299 * @return returns 0 for success, a negative error code value for failure.
302 ocs_scsi_tgt_new_domain(ocs_domain_t *domain)
308 * @ingroup scsi_api_target
309 * @brief accept domain lost notification
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.
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.
317 * @param domain pointer to domain
319 * @return returns 0 for success, a negative error code value for failure.
322 ocs_scsi_tgt_del_domain(ocs_domain_t *domain)
328 * @ingroup scsi_api_target
329 * @brief accept new sli port (sport) notification
331 * Called by base drive when new sport is discovered. A target-server
332 * will use this call to prepare for new remote node notifications
333 * arising from ocs_scsi_new_initiator().
335 * The domain context has an element <b>ocs_scsi_tgt_sport_t tgt_sport</b>
336 * which is declared by the target-server code and is used for
337 * target-server private data.
339 * This function will only be called if the base-driver has been enabled for
342 * Note that this call is made to target-server backends,
343 * the ocs_scsi_tgt_new_domain() is called to initiator-client backends.
345 * @param sport pointer to SLI port
347 * @return returns 0 for success, a negative error code value for failure.
350 ocs_scsi_tgt_new_sport(ocs_sport_t *sport)
352 ocs_t *ocs = sport->ocs;
354 if(!sport->is_vport) {
355 sport->tgt_data = FCPORT(ocs, 0);
362 * @ingroup scsi_api_target
363 * @brief accept SLI port gone notification
365 * Called by base-driver when a sport goes away. A target-server will
366 * use this call to clean up all sport scoped resources.
368 * Note that this call is made to target-server backends,
369 * the ocs_scsi_ini_del_sport() is called to initiator-client backends.
371 * @param sport pointer to SLI port
373 * @return returns 0 for success, a negative error code value for failure.
376 ocs_scsi_tgt_del_sport(ocs_sport_t *sport)
382 * @ingroup scsi_api_target
383 * @brief receive notification of a new SCSI initiator node
385 * Sent by base driver to notify a target-server of the presense of a new
386 * remote initiator. The target-server may use this call to prepare for
387 * inbound IO from this node.
389 * The ocs_node_t structure has and elment of type ocs_scsi_tgt_node_t named
390 * tgt_node that is declared and used by a target-server for private
393 * This function is only called if the target capability is enabled in driver.
395 * @param node pointer to new remote initiator node
397 * @return returns 0 for success, a negative error code value for failure.
402 ocs_scsi_new_initiator(ocs_node_t *node)
404 ocs_t *ocs = node->ocs;
405 struct ac_contract ac;
406 struct ac_device_changed *adc;
408 ocs_fcport *fcp = NULL;
410 fcp = node->sport->tgt_data;
412 ocs_log_err(ocs, "FCP is NULL \n");
417 * Update the IO watermark by decrementing it by the
418 * number of IOs reserved for each initiator.
420 atomic_subtract_acq_32(&ocs->io_high_watermark, OCS_RSVD_INI_IO);
422 ac.contract_number = AC_CONTRACT_DEV_CHG;
423 adc = (struct ac_device_changed *) ac.contract_data;
424 adc->wwpn = ocs_node_get_wwpn(node);
425 adc->port = node->rnode.fc_id;
426 adc->target = node->instance_index;
428 xpt_async(AC_CONTRACT, fcp->path, &ac);
434 * @ingroup scsi_api_target
435 * @brief validate new initiator
437 * Sent by base driver to validate a remote initiatiator. The target-server
438 * returns TRUE if this initiator should be accepted.
440 * This function is only called if the target capability is enabled in driver.
442 * @param node pointer to remote initiator node to validate
444 * @return TRUE if initiator should be accepted, FALSE if it should be rejected
450 ocs_scsi_validate_initiator(ocs_node_t *node)
456 * @ingroup scsi_api_target
457 * @brief Delete a SCSI initiator node
459 * Sent by base driver to notify a target-server that a remote initiator
460 * is now gone. The base driver will have terminated all outstanding IOs
461 * and the target-server will receive appropriate completions.
463 * This function is only called if the base driver is enabled for
466 * @param node pointer node being deleted
467 * @param reason Reason why initiator is gone.
469 * @return OCS_SCSI_CALL_COMPLETE to indicate that all work was completed
474 ocs_scsi_del_initiator(ocs_node_t *node, ocs_scsi_del_initiator_reason_e reason)
476 ocs_t *ocs = node->ocs;
478 struct ac_contract ac;
479 struct ac_device_changed *adc;
480 ocs_fcport *fcp = NULL;
482 fcp = node->sport->tgt_data;
484 ocs_log_err(ocs, "FCP is NULL \n");
488 ac.contract_number = AC_CONTRACT_DEV_CHG;
489 adc = (struct ac_device_changed *) ac.contract_data;
490 adc->wwpn = ocs_node_get_wwpn(node);
491 adc->port = node->rnode.fc_id;
492 adc->target = node->instance_index;
494 xpt_async(AC_CONTRACT, fcp->path, &ac);
497 if (reason == OCS_SCSI_INITIATOR_MISSING) {
498 return OCS_SCSI_CALL_COMPLETE;
502 * Update the IO watermark by incrementing it by the
503 * number of IOs reserved for each initiator.
505 atomic_add_acq_32(&ocs->io_high_watermark, OCS_RSVD_INI_IO);
507 return OCS_SCSI_CALL_COMPLETE;
511 * @ingroup scsi_api_target
512 * @brief receive FCP SCSI Command
514 * Called by the base driver when a new SCSI command has been received. The
515 * target-server will process the command, and issue data and/or response phase
516 * requests to the base driver.
518 * The IO context (ocs_io_t) structure has and element of type
519 * ocs_scsi_tgt_io_t named tgt_io that is declared and used by
520 * a target-server for private information.
522 * @param io pointer to IO context
523 * @param lun LUN for this IO
524 * @param cdb pointer to SCSI CDB
525 * @param cdb_len length of CDB in bytes
526 * @param flags command flags
528 * @return returns 0 for success, a negative error code value for failure.
530 int32_t ocs_scsi_recv_cmd(ocs_io_t *io, uint64_t lun, uint8_t *cdb,
531 uint32_t cdb_len, uint32_t flags)
533 ocs_t *ocs = io->ocs;
534 struct ccb_accept_tio *atio = NULL;
535 ocs_node_t *node = io->node;
536 ocs_tgt_resource_t *trsrc = NULL;
538 ocs_fcport *fcp = NULL;
540 fcp = node->sport->tgt_data;
542 ocs_log_err(ocs, "FCP is NULL \n");
546 atomic_add_acq_32(&ocs->io_in_use, 1);
548 /* set target io timeout */
549 io->timeout = ocs->target_io_timer_sec;
551 if (ocs->enable_task_set_full &&
552 (ocs->io_in_use >= ocs->io_high_watermark)) {
553 return ocs_task_set_full_or_busy(io);
555 atomic_store_rel_32(&io->node->tgt_node.busy_sent, FALSE);
558 if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) {
559 trsrc = &fcp->targ_rsrc[lun];
560 } else if (fcp->targ_rsrc_wildcard.enabled) {
561 trsrc = &fcp->targ_rsrc_wildcard;
565 atio = (struct ccb_accept_tio *)STAILQ_FIRST(&trsrc->atio);
570 STAILQ_REMOVE_HEAD(&trsrc->atio, sim_links.stqe);
572 atio->ccb_h.status = CAM_CDB_RECVD;
573 atio->ccb_h.target_lun = lun;
576 atio->init_id = node->instance_index;
577 atio->tag_id = io->tag;
578 atio->ccb_h.ccb_io_ptr = io;
580 if (flags & OCS_SCSI_CMD_SIMPLE)
581 atio->tag_action = MSG_SIMPLE_Q_TAG;
582 else if (flags & FCP_TASK_ATTR_HEAD_OF_QUEUE)
583 atio->tag_action = MSG_HEAD_OF_Q_TAG;
584 else if (flags & FCP_TASK_ATTR_ORDERED)
585 atio->tag_action = MSG_ORDERED_Q_TAG;
587 atio->tag_action = 0;
589 atio->cdb_len = cdb_len;
590 ocs_memcpy(atio->cdb_io.cdb_bytes, cdb, cdb_len);
592 io->tgt_io.flags = 0;
593 io->tgt_io.state = OCS_CAM_IO_COMMAND;
594 io->tgt_io.lun = lun;
596 xpt_done((union ccb *)atio);
601 ocs->dev, "%s: no ATIO for LUN %lx (en=%s) OX_ID %#x\n",
602 __func__, (unsigned long)lun,
603 trsrc ? (trsrc->enabled ? "T" : "F") : "X",
604 be16toh(io->init_task_tag));
606 io->tgt_io.state = OCS_CAM_IO_MAX;
607 ocs_target_io_free(io);
614 * @ingroup scsi_api_target
615 * @brief receive FCP SCSI Command with first burst data.
617 * Receive a new FCP SCSI command from the base driver with first burst data.
619 * @param io pointer to IO context
620 * @param lun LUN for this IO
621 * @param cdb pointer to SCSI CDB
622 * @param cdb_len length of CDB in bytes
623 * @param flags command flags
624 * @param first_burst_buffers first burst buffers
625 * @param first_burst_buffer_count The number of bytes received in the first burst
627 * @return returns 0 for success, a negative error code value for failure.
629 int32_t ocs_scsi_recv_cmd_first_burst(ocs_io_t *io, uint64_t lun, uint8_t *cdb,
630 uint32_t cdb_len, uint32_t flags,
631 ocs_dma_t first_burst_buffers[],
632 uint32_t first_burst_buffer_count)
638 * @ingroup scsi_api_target
639 * @brief receive a TMF command IO
641 * Called by the base driver when a SCSI TMF command has been received. The
642 * target-server will process the command, aborting commands as needed, and post
643 * a response using ocs_scsi_send_resp()
645 * The IO context (ocs_io_t) structure has and element of type ocs_scsi_tgt_io_t named
646 * tgt_io that is declared and used by a target-server for private information.
648 * If the target-server walks the nodes active_ios linked list, and starts IO
649 * abort processing, the code <b>must</b> be sure not to abort the IO passed into the
650 * ocs_scsi_recv_tmf() command.
652 * @param tmfio pointer to IO context
653 * @param lun logical unit value
654 * @param cmd command request
655 * @param abortio pointer to IO object to abort for TASK_ABORT (NULL for all other TMF)
658 * @return returns 0 for success, a negative error code value for failure.
660 int32_t ocs_scsi_recv_tmf(ocs_io_t *tmfio, uint64_t lun, ocs_scsi_tmf_cmd_e cmd,
661 ocs_io_t *abortio, uint32_t flags)
663 ocs_t *ocs = tmfio->ocs;
664 ocs_node_t *node = tmfio->node;
665 ocs_tgt_resource_t *trsrc = NULL;
666 struct ccb_immediate_notify *inot = NULL;
668 ocs_fcport *fcp = NULL;
670 fcp = node->sport->tgt_data;
672 ocs_log_err(ocs, "FCP is NULL \n");
676 if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) {
677 trsrc = &fcp->targ_rsrc[lun];
678 } else if (fcp->targ_rsrc_wildcard.enabled) {
679 trsrc = &fcp->targ_rsrc_wildcard;
682 device_printf(tmfio->ocs->dev, "%s: io=%p cmd=%#x LU=%lx en=%s\n",
683 __func__, tmfio, cmd, (unsigned long)lun,
684 trsrc ? (trsrc->enabled ? "T" : "F") : "X");
686 inot = (struct ccb_immediate_notify *)STAILQ_FIRST(&trsrc->inot);
691 ocs->dev, "%s: no INOT for LUN %llx (en=%s) OX_ID %#x\n",
692 __func__, (unsigned long long)lun, trsrc ? (trsrc->enabled ? "T" : "F") : "X",
693 be16toh(tmfio->init_task_tag));
696 ocs_scsi_io_complete(abortio);
698 ocs_scsi_io_complete(tmfio);
699 goto ocs_scsi_recv_tmf_out;
703 tmfio->tgt_io.app = abortio;
705 STAILQ_REMOVE_HEAD(&trsrc->inot, sim_links.stqe);
707 inot->tag_id = tmfio->tag;
708 inot->seq_id = tmfio->tag;
710 if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) {
711 inot->initiator_id = node->instance_index;
713 inot->initiator_id = CAM_TARGET_WILDCARD;
716 inot->ccb_h.status = CAM_MESSAGE_RECV;
717 inot->ccb_h.target_lun = lun;
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;
728 case OCS_SCSI_TMF_QUERY_TASK_SET:
729 device_printf(ocs->dev,
730 "%s: OCS_SCSI_TMF_QUERY_TASK_SET not supported\n",
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;
736 case OCS_SCSI_TMF_ABORT_TASK_SET:
737 inot->arg = MSG_ABORT_TASK_SET;
739 case OCS_SCSI_TMF_CLEAR_TASK_SET:
740 inot->arg = MSG_CLEAR_TASK_SET;
742 case OCS_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT:
743 inot->arg = MSG_QUERY_ASYNC_EVENT;
745 case OCS_SCSI_TMF_LOGICAL_UNIT_RESET:
746 inot->arg = MSG_LOGICAL_UNIT_RESET;
748 case OCS_SCSI_TMF_CLEAR_ACA:
749 inot->arg = MSG_CLEAR_ACA;
751 case OCS_SCSI_TMF_TARGET_RESET:
752 inot->arg = MSG_TARGET_RESET;
755 device_printf(ocs->dev, "%s: unsupported TMF %#x\n",
757 STAILQ_INSERT_TAIL(&trsrc->inot, &inot->ccb_h, sim_links.stqe);
758 goto ocs_scsi_recv_tmf_out;
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,
770 xpt_done((union ccb *)inot);
773 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_DEV;
774 rc = ocs_scsi_tgt_abort_io(abortio, ocs_io_abort_cb, tmfio);
777 ocs_scsi_recv_tmf_out:
782 * @ingroup scsi_api_initiator
783 * @brief Initializes any initiator fields on the ocs structure.
785 * Called by OS initialization code when a new device is discovered.
787 * @param ocs pointer to ocs
789 * @return returns 0 for success, a negative error code value for failure.
792 ocs_scsi_ini_new_device(ocs_t *ocs)
799 * @ingroup scsi_api_initiator
800 * @brief Tears down initiator members of ocs structure.
802 * Called by OS code when device is removed.
804 * @param ocs pointer to ocs
806 * @return returns 0 for success, a negative error code value for failure.
810 ocs_scsi_ini_del_device(ocs_t *ocs)
818 * @ingroup scsi_api_initiator
819 * @brief accept new domain notification
821 * Called by base drive when new domain is discovered. An initiator-client
822 * will accept this call to prepare for new remote node notifications
823 * arising from ocs_scsi_new_target().
825 * The domain context has the element <b>ocs_scsi_ini_domain_t ini_domain</b>
826 * which is declared by the initiator-client code and is used for
827 * initiator-client private data.
829 * This function will only be called if the base-driver has been enabled for
830 * initiator capability.
832 * Note that this call is made to initiator-client backends,
833 * the ocs_scsi_tgt_new_domain() function is called to target-server backends.
835 * @param domain pointer to domain
837 * @return returns 0 for success, a negative error code value for failure.
840 ocs_scsi_ini_new_domain(ocs_domain_t *domain)
846 * @ingroup scsi_api_initiator
847 * @brief accept domain lost notification
849 * Called by base-driver when a domain goes away. An initiator-client will
850 * use this call to clean up all domain scoped resources.
852 * This function will only be called if the base-driver has been enabled for
853 * initiator capability.
855 * Note that this call is made to initiator-client backends,
856 * the ocs_scsi_tgt_del_domain() function is called to target-server backends.
858 * @param domain pointer to domain
860 * @return returns 0 for success, a negative error code value for failure.
863 ocs_scsi_ini_del_domain(ocs_domain_t *domain)
868 * @ingroup scsi_api_initiator
869 * @brief accept new sli port notification
871 * Called by base drive when new sli port (sport) is discovered.
872 * A target-server will use this call to prepare for new remote node
873 * notifications arising from ocs_scsi_new_initiator().
875 * This function will only be called if the base-driver has been enabled for
878 * Note that this call is made to target-server backends,
879 * the ocs_scsi_ini_new_sport() function is called to initiator-client backends.
881 * @param sport pointer to sport
883 * @return returns 0 for success, a negative error code value for failure.
886 ocs_scsi_ini_new_sport(ocs_sport_t *sport)
888 ocs_t *ocs = sport->ocs;
889 ocs_fcport *fcp = FCPORT(ocs, 0);
891 if (!sport->is_vport) {
892 sport->tgt_data = fcp;
893 fcp->fc_id = sport->fc_id;
900 * @ingroup scsi_api_initiator
901 * @brief accept sli port gone notification
903 * Called by base-driver when a sport goes away. A target-server will
904 * use this call to clean up all sport scoped resources.
906 * Note that this call is made to target-server backends,
907 * the ocs_scsi_ini_del_sport() function is called to initiator-client backends.
909 * @param sport pointer to SLI port
911 * @return returns 0 for success, a negative error code value for failure.
914 ocs_scsi_ini_del_sport(ocs_sport_t *sport)
916 ocs_t *ocs = sport->ocs;
917 ocs_fcport *fcp = FCPORT(ocs, 0);
919 if (!sport->is_vport) {
925 ocs_scsi_sport_deleted(ocs_sport_t *sport)
927 ocs_t *ocs = sport->ocs;
928 ocs_fcport *fcp = NULL;
930 ocs_xport_stats_t value;
932 if (!sport->is_vport) {
936 fcp = sport->tgt_data;
938 ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &value);
940 if (value.value == 0) {
941 ocs_log_debug(ocs, "PORT offline,.. skipping\n");
945 if ((fcp->role != KNOB_ROLE_NONE)) {
946 if(fcp->vport->sport != NULL) {
947 ocs_log_debug(ocs,"sport is not NULL, skipping\n");
951 ocs_sport_vport_alloc(ocs->domain, fcp->vport);
958 ocs_tgt_find(ocs_fcport *fcp, ocs_node_t *node)
960 ocs_fc_target_t *tgt = NULL;
963 for (i = 0; i < OCS_MAX_TARGETS; i++) {
966 if (tgt->state == OCS_TGT_STATE_NONE)
969 if (ocs_node_get_wwpn(node) == tgt->wwpn) {
978 * @ingroup scsi_api_initiator
979 * @brief receive notification of a new SCSI target node
981 * Sent by base driver to notify an initiator-client of the presense of a new
982 * remote target. The initiator-server may use this call to prepare for
983 * inbound IO from this node.
985 * This function is only called if the base driver is enabled for
986 * initiator capability.
988 * @param node pointer to new remote initiator node
996 ocs_update_tgt(ocs_node_t *node, ocs_fcport *fcp, uint32_t tgt_id)
998 ocs_fc_target_t *tgt = NULL;
1000 tgt = &fcp->tgt[tgt_id];
1002 tgt->node_id = node->instance_index;
1003 tgt->state = OCS_TGT_STATE_VALID;
1005 tgt->port_id = node->rnode.fc_id;
1006 tgt->wwpn = ocs_node_get_wwpn(node);
1007 tgt->wwnn = ocs_node_get_wwnn(node);
1012 ocs_add_new_tgt(ocs_node_t *node, ocs_fcport *fcp)
1016 struct ocs_softc *ocs = node->ocs;
1017 union ccb *ccb = NULL;
1018 for (i = 0; i < OCS_MAX_TARGETS; i++) {
1019 if (fcp->tgt[i].state == OCS_TGT_STATE_NONE)
1023 if (NULL == (ccb = xpt_alloc_ccb_nowait())) {
1024 device_printf(ocs->dev, "%s: ccb allocation failed\n", __func__);
1028 if (CAM_REQ_CMP != xpt_create_path(&ccb->ccb_h.path, xpt_periph,
1029 cam_sim_path(fcp->sim),
1030 i, CAM_LUN_WILDCARD)) {
1032 ocs->dev, "%s: target path creation failed\n", __func__);
1037 ocs_update_tgt(node, fcp, i);
1043 ocs_scsi_new_target(ocs_node_t *node)
1045 ocs_fcport *fcp = NULL;
1048 fcp = node->sport->tgt_data;
1050 printf("%s:FCP is NULL \n", __func__);
1054 i = ocs_tgt_find(fcp, node);
1057 ocs_add_new_tgt(node, fcp);
1061 ocs_update_tgt(node, fcp, i);
1066 ocs_delete_target(ocs_t *ocs, ocs_fcport *fcp, int tgt)
1068 struct cam_path *cpath = NULL;
1071 device_printf(ocs->dev, "%s: calling with NULL sim\n", __func__);
1075 if (CAM_REQ_CMP == xpt_create_path(&cpath, NULL, cam_sim_path(fcp->sim),
1076 tgt, CAM_LUN_WILDCARD)) {
1077 xpt_async(AC_LOST_DEVICE, cpath, NULL);
1079 xpt_free_path(cpath);
1084 * Device Lost Timer Function- when we have decided that a device was lost,
1085 * we wait a specific period of time prior to telling the OS about lost device.
1087 * This timer function gets activated when the device was lost.
1088 * This function fires once a second and then scans the port database
1089 * for devices that are marked dead but still have a virtual target assigned.
1090 * We decrement a counter for that port database entry, and when it hits zero,
1091 * we tell the OS the device was lost. Timer will be stopped when the device
1092 * comes back active or removed from the OS.
1097 ocs_fcport *fcp = arg;
1098 taskqueue_enqueue(taskqueue_thread, &fcp->ltask);
1102 ocs_ldt_task(void *arg, int pending)
1104 ocs_fcport *fcp = arg;
1105 ocs_t *ocs = fcp->ocs;
1106 int i, more_to_do = 0;
1107 ocs_fc_target_t *tgt = NULL;
1109 for (i = 0; i < OCS_MAX_TARGETS; i++) {
1112 if (tgt->state != OCS_TGT_STATE_LOST) {
1116 if ((tgt->gone_timer != 0) && (ocs->attached)){
1117 tgt->gone_timer -= 1;
1122 if (tgt->is_target) {
1124 ocs_delete_target(ocs, fcp, i);
1127 tgt->state = OCS_TGT_STATE_NONE;
1131 callout_reset(&fcp->ldt, hz, ocs_ldt, fcp);
1133 callout_deactivate(&fcp->ldt);
1139 * @ingroup scsi_api_initiator
1140 * @brief Delete a SCSI target node
1142 * Sent by base driver to notify a initiator-client that a remote target
1143 * is now gone. The base driver will have terminated all outstanding IOs
1144 * and the initiator-client will receive appropriate completions.
1146 * The ocs_node_t structure has and elment of type ocs_scsi_ini_node_t named
1147 * ini_node that is declared and used by a target-server for private
1150 * This function is only called if the base driver is enabled for
1151 * initiator capability.
1153 * @param node pointer node being deleted
1154 * @param reason reason for deleting the target
1156 * @return Returns OCS_SCSI_CALL_ASYNC if target delete is queued for async
1157 * completion and OCS_SCSI_CALL_COMPLETE if call completed or error.
1162 ocs_scsi_del_target(ocs_node_t *node, ocs_scsi_del_target_reason_e reason)
1164 struct ocs_softc *ocs = node->ocs;
1165 ocs_fcport *fcp = NULL;
1166 ocs_fc_target_t *tgt = NULL;
1170 ocs_log_err(ocs,"OCS is NULL \n");
1174 fcp = node->sport->tgt_data;
1176 ocs_log_err(ocs,"FCP is NULL \n");
1180 tgt_id = ocs_tgt_find(fcp, node);
1182 ocs_log_err(ocs,"target is invalid\n");
1186 tgt = &fcp->tgt[tgt_id];
1188 // IF in shutdown delete target.
1189 if(!ocs->attached) {
1190 ocs_delete_target(ocs, fcp, tgt_id);
1193 tgt->state = OCS_TGT_STATE_LOST;
1194 tgt->gone_timer = 30;
1195 if (!callout_active(&fcp->ldt)) {
1196 callout_reset(&fcp->ldt, hz, ocs_ldt, fcp);
1204 * @brief Initialize SCSI IO
1206 * Initialize SCSI IO, this function is called once per IO during IO pool
1207 * allocation so that the target server may initialize any of its own private
1210 * @param io pointer to SCSI IO object
1212 * @return returns 0 for success, a negative error code value for failure.
1215 ocs_scsi_tgt_io_init(ocs_io_t *io)
1221 * @brief Uninitialize SCSI IO
1223 * Uninitialize target server private data in a SCSI io object
1225 * @param io pointer to SCSI IO object
1227 * @return returns 0 for success, a negative error code value for failure.
1230 ocs_scsi_tgt_io_exit(ocs_io_t *io)
1236 * @brief Initialize SCSI IO
1238 * Initialize SCSI IO, this function is called once per IO during IO pool
1239 * allocation so that the initiator client may initialize any of its own private
1242 * @param io pointer to SCSI IO object
1244 * @return returns 0 for success, a negative error code value for failure.
1247 ocs_scsi_ini_io_init(ocs_io_t *io)
1253 * @brief Uninitialize SCSI IO
1255 * Uninitialize initiator client private data in a SCSI io object
1257 * @param io pointer to SCSI IO object
1259 * @return returns 0 for success, a negative error code value for failure.
1262 ocs_scsi_ini_io_exit(ocs_io_t *io)
1267 * End of functions required by SCSI base driver API
1268 ***************************************************************************/
1270 static __inline void
1271 ocs_set_ccb_status(union ccb *ccb, cam_status status)
1273 ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1274 ccb->ccb_h.status |= status;
1278 ocs_task_set_full_or_busy_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status,
1279 uint32_t flags, void *arg)
1282 ocs_target_io_free(io);
1288 * @brief send SCSI task set full or busy status
1290 * A SCSI task set full or busy response is sent depending on whether
1291 * another IO is already active on the LUN.
1293 * @param io pointer to IO context
1295 * @return returns 0 for success, a negative error code value for failure.
1299 ocs_task_set_full_or_busy(ocs_io_t *io)
1301 ocs_scsi_cmd_resp_t rsp = { 0 };
1302 ocs_t *ocs = io->ocs;
1305 * If there is another command for the LUN, then send task set full,
1306 * if this is the first one, then send the busy status.
1308 * if 'busy sent' is FALSE, set it to TRUE and send BUSY
1309 * otherwise send FULL
1311 if (atomic_cmpset_acq_32(&io->node->tgt_node.busy_sent, FALSE, TRUE)) {
1312 rsp.scsi_status = SCSI_STATUS_BUSY; /* Busy */
1313 printf("%s: busy [%s] tag=%x iiu=%d ihw=%d\n", __func__,
1314 io->node->display_name, io->tag,
1315 io->ocs->io_in_use, io->ocs->io_high_watermark);
1317 rsp.scsi_status = SCSI_STATUS_TASK_SET_FULL; /* Task set full */
1318 printf("%s: full tag=%x iiu=%d\n", __func__, io->tag,
1319 io->ocs->io_in_use);
1322 /* Log a message here indicating a busy or task set full state */
1323 if (OCS_LOG_ENABLE_Q_FULL_BUSY_MSG(ocs)) {
1324 /* Log Task Set Full */
1325 if (rsp.scsi_status == SCSI_STATUS_TASK_SET_FULL) {
1326 /* Task Set Full Message */
1327 ocs_log_info(ocs, "OCS CAM TASK SET FULL. Tasks >= %d\n",
1328 ocs->io_high_watermark);
1330 else if (rsp.scsi_status == SCSI_STATUS_BUSY) {
1331 /* Log Busy Message */
1332 ocs_log_info(ocs, "OCS CAM SCSI BUSY\n");
1336 /* Send the response */
1338 ocs_scsi_send_resp(io, 0, &rsp, ocs_task_set_full_or_busy_cb, NULL);
1343 * @brief Process target IO completions
1346 * @param scsi_status did the IO complete successfully
1348 * @param arg application specific pointer provided in the call to ocs_target_io()
1352 static int32_t ocs_scsi_target_io_cb(ocs_io_t *io,
1353 ocs_scsi_io_status_e scsi_status,
1354 uint32_t flags, void *arg)
1356 union ccb *ccb = arg;
1357 struct ccb_scsiio *csio = &ccb->csio;
1358 struct ocs_softc *ocs = csio->ccb_h.ccb_ocs_ptr;
1359 uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
1360 uint32_t io_is_done =
1361 (ccb->ccb_h.flags & CAM_SEND_STATUS) == CAM_SEND_STATUS;
1363 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1365 if (CAM_DIR_NONE != cam_dir) {
1366 bus_dmasync_op_t op;
1368 if (CAM_DIR_IN == cam_dir) {
1369 op = BUS_DMASYNC_POSTREAD;
1371 op = BUS_DMASYNC_POSTWRITE;
1373 /* Synchronize the DMA memory with the CPU and free the mapping */
1374 bus_dmamap_sync(ocs->buf_dmat, io->tgt_io.dmap, op);
1375 if (io->tgt_io.flags & OCS_CAM_IO_F_DMAPPED) {
1376 bus_dmamap_unload(ocs->buf_dmat, io->tgt_io.dmap);
1380 if (io->tgt_io.sendresp) {
1381 io->tgt_io.sendresp = 0;
1382 ocs_scsi_cmd_resp_t resp = { 0 };
1383 io->tgt_io.state = OCS_CAM_IO_RESP;
1384 resp.scsi_status = scsi_status;
1385 if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
1386 resp.sense_data = (uint8_t *)&csio->sense_data;
1387 resp.sense_data_length = csio->sense_len;
1389 resp.residual = io->exp_xfer_len - io->transferred;
1391 return ocs_scsi_send_resp(io, 0, &resp, ocs_scsi_target_io_cb, ccb);
1394 switch (scsi_status) {
1395 case OCS_SCSI_STATUS_GOOD:
1396 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
1398 case OCS_SCSI_STATUS_ABORTED:
1399 ocs_set_ccb_status(ccb, CAM_REQ_ABORTED);
1402 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
1406 if ((io->tgt_io.flags & OCS_CAM_IO_F_ABORT_NOTIFY) == 0) {
1407 ocs_target_io_free(io);
1410 io->tgt_io.state = OCS_CAM_IO_DATA_DONE;
1411 /*device_printf(ocs->dev, "%s: CTIO state=%d tag=%#x\n",
1412 __func__, io->tgt_io.state, io->tag);*/
1421 * @note 1. Since the CCB is assigned to the ocs_io_t on an XPT_CONT_TARGET_IO
1422 * action, if an initiator aborts a command prior to the SIM receiving
1423 * a CTIO, the IO's CCB will be NULL.
1426 ocs_io_abort_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg)
1428 struct ocs_softc *ocs = NULL;
1429 ocs_io_t *tmfio = arg;
1430 ocs_scsi_tmf_resp_e tmf_resp = OCS_SCSI_TMF_FUNCTION_COMPLETE;
1435 io->tgt_io.flags &= ~OCS_CAM_IO_F_ABORT_DEV;
1437 /* A good status indicates the IO was aborted and will be completed in
1438 * the IO's completion handler. Handle the other cases here. */
1439 switch (scsi_status) {
1440 case OCS_SCSI_STATUS_GOOD:
1442 case OCS_SCSI_STATUS_NO_IO:
1445 device_printf(ocs->dev, "%s: unhandled status %d\n",
1446 __func__, scsi_status);
1447 tmf_resp = OCS_SCSI_TMF_FUNCTION_REJECTED;
1451 ocs_scsi_send_tmf_resp(tmfio, tmf_resp, NULL, ocs_target_tmf_cb, NULL);
1458 * @brief Process initiator IO completions
1461 * @param scsi_status did the IO complete successfully
1462 * @param rsp pointer to response buffer
1464 * @param arg application specific pointer provided in the call to ocs_target_io()
1468 static int32_t ocs_scsi_initiator_io_cb(ocs_io_t *io,
1469 ocs_scsi_io_status_e scsi_status,
1470 ocs_scsi_cmd_resp_t *rsp,
1471 uint32_t flags, void *arg)
1473 union ccb *ccb = arg;
1474 struct ccb_scsiio *csio = &ccb->csio;
1475 struct ocs_softc *ocs = csio->ccb_h.ccb_ocs_ptr;
1476 uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
1477 cam_status ccb_status= CAM_REQ_CMP_ERR;
1479 if (CAM_DIR_NONE != cam_dir) {
1480 bus_dmasync_op_t op;
1482 if (CAM_DIR_IN == cam_dir) {
1483 op = BUS_DMASYNC_POSTREAD;
1485 op = BUS_DMASYNC_POSTWRITE;
1487 /* Synchronize the DMA memory with the CPU and free the mapping */
1488 bus_dmamap_sync(ocs->buf_dmat, io->tgt_io.dmap, op);
1489 if (io->tgt_io.flags & OCS_CAM_IO_F_DMAPPED) {
1490 bus_dmamap_unload(ocs->buf_dmat, io->tgt_io.dmap);
1494 if (scsi_status == OCS_SCSI_STATUS_CHECK_RESPONSE) {
1495 csio->scsi_status = rsp->scsi_status;
1496 if (SCSI_STATUS_OK != rsp->scsi_status) {
1497 ccb_status = CAM_SCSI_STATUS_ERROR;
1500 csio->resid = rsp->residual;
1501 if (rsp->residual > 0) {
1502 uint32_t length = rsp->response_wire_length;
1504 if (csio->dxfer_len == (length + csio->resid)) {
1505 ccb_status = CAM_REQ_CMP;
1507 } else if (rsp->residual < 0) {
1508 ccb_status = CAM_DATA_RUN_ERR;
1511 if ((rsp->sense_data_length) &&
1512 !(ccb->ccb_h.flags & (CAM_SENSE_PHYS | CAM_SENSE_PTR))) {
1513 uint32_t sense_len = 0;
1515 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
1516 if (rsp->sense_data_length < csio->sense_len) {
1518 csio->sense_len - rsp->sense_data_length;
1519 sense_len = rsp->sense_data_length;
1521 csio->sense_resid = 0;
1522 sense_len = csio->sense_len;
1524 ocs_memcpy(&csio->sense_data, rsp->sense_data, sense_len);
1526 } else if (scsi_status != OCS_SCSI_STATUS_GOOD) {
1527 ccb_status = CAM_REQ_CMP_ERR;
1528 ocs_set_ccb_status(ccb, ccb_status);
1529 csio->ccb_h.status |= CAM_DEV_QFRZN;
1530 xpt_freeze_devq(csio->ccb_h.path, 1);
1533 ccb_status = CAM_REQ_CMP;
1536 ocs_set_ccb_status(ccb, ccb_status);
1538 ocs_scsi_io_free(io);
1540 csio->ccb_h.ccb_io_ptr = NULL;
1541 csio->ccb_h.ccb_ocs_ptr = NULL;
1542 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1550 * @brief Load scatter-gather list entries into an IO
1552 * This routine relies on the driver instance's software context pointer and
1553 * the IO object pointer having been already assigned to hooks in the CCB.
1554 * Although the routine does not return success/fail, callers can look at the
1555 * n_sge member to determine if the mapping failed (0 on failure).
1557 * @param arg pointer to the CAM ccb for this IO
1558 * @param seg DMA address/length pairs
1559 * @param nseg number of DMA address/length pairs
1560 * @param error any errors while mapping the IO
1563 ocs_scsi_dmamap_load(void *arg, bus_dma_segment_t *seg, int nseg, int error)
1565 ocs_dmamap_load_arg_t *sglarg = (ocs_dmamap_load_arg_t*) arg;
1568 printf("%s: seg=%p nseg=%d error=%d\n",
1569 __func__, seg, nseg, error);
1575 if ((sglarg->sgl_count + nseg) > sglarg->sgl_max) {
1576 printf("%s: sgl_count=%d nseg=%d max=%d\n", __func__,
1577 sglarg->sgl_count, nseg, sglarg->sgl_max);
1582 for (i = 0, c = sglarg->sgl_count; i < nseg; i++, c++) {
1583 sglarg->sgl[c].addr = seg[i].ds_addr;
1584 sglarg->sgl[c].len = seg[i].ds_len;
1587 sglarg->sgl_count = c;
1594 * @brief Build a scatter-gather list from a CAM CCB
1596 * @param ocs the driver instance's software context
1597 * @param ccb pointer to the CCB
1598 * @param io pointer to the previously allocated IO object
1599 * @param sgl pointer to SGL
1600 * @param sgl_max number of entries in sgl
1602 * @return 0 on success, non-zero otherwise
1605 ocs_build_scsi_sgl(struct ocs_softc *ocs, union ccb *ccb, ocs_io_t *io,
1606 ocs_scsi_sgl_t *sgl, uint32_t sgl_max)
1608 ocs_dmamap_load_arg_t dmaarg;
1611 if (!ocs || !ccb || !io || !sgl) {
1612 printf("%s: bad param o=%p c=%p i=%p s=%p\n", __func__,
1617 io->tgt_io.flags &= ~OCS_CAM_IO_F_DMAPPED;
1620 dmaarg.sgl_count = 0;
1621 dmaarg.sgl_max = sgl_max;
1624 err = bus_dmamap_load_ccb(ocs->buf_dmat, io->tgt_io.dmap, ccb,
1625 ocs_scsi_dmamap_load, &dmaarg, 0);
1627 if (err || dmaarg.rc) {
1629 ocs->dev, "%s: bus_dmamap_load_ccb error (%d %d)\n",
1630 __func__, err, dmaarg.rc);
1634 io->tgt_io.flags |= OCS_CAM_IO_F_DMAPPED;
1635 return dmaarg.sgl_count;
1640 * @brief Send a target IO
1642 * @param ocs the driver instance's software context
1643 * @param ccb pointer to the CCB
1645 * @return 0 on success, non-zero otherwise
1648 ocs_target_io(struct ocs_softc *ocs, union ccb *ccb)
1650 struct ccb_scsiio *csio = &ccb->csio;
1651 ocs_io_t *io = NULL;
1652 uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
1653 bool sendstatus = ccb->ccb_h.flags & CAM_SEND_STATUS;
1654 uint32_t xferlen = csio->dxfer_len;
1657 io = ocs_scsi_find_io(ocs, csio->tag_id);
1659 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
1660 panic("bad tag value");
1664 /* Received an ABORT TASK for this IO */
1665 if (io->tgt_io.flags & OCS_CAM_IO_F_ABORT_RECV) {
1666 /*device_printf(ocs->dev,
1667 "%s: XPT_CONT_TARGET_IO state=%d tag=%#x xid=%#x flags=%#x\n",
1668 __func__, io->tgt_io.state, io->tag, io->init_task_tag,
1669 io->tgt_io.flags);*/
1670 io->tgt_io.flags |= OCS_CAM_IO_F_ABORT_CAM;
1672 if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
1673 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
1674 ocs_target_io_free(io);
1678 ocs_set_ccb_status(ccb, CAM_REQ_ABORTED);
1683 io->tgt_io.app = ccb;
1685 ocs_set_ccb_status(ccb, CAM_REQ_INPROG);
1686 ccb->ccb_h.status |= CAM_SIM_QUEUED;
1688 csio->ccb_h.ccb_ocs_ptr = ocs;
1689 csio->ccb_h.ccb_io_ptr = io;
1691 if ((sendstatus && (xferlen == 0))) {
1692 ocs_scsi_cmd_resp_t resp = { 0 };
1694 ocs_assert(ccb->ccb_h.flags & CAM_SEND_STATUS, -1);
1696 io->tgt_io.state = OCS_CAM_IO_RESP;
1698 resp.scsi_status = csio->scsi_status;
1700 if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
1701 resp.sense_data = (uint8_t *)&csio->sense_data;
1702 resp.sense_data_length = csio->sense_len;
1705 resp.residual = io->exp_xfer_len - io->transferred;
1706 rc = ocs_scsi_send_resp(io, 0, &resp, ocs_scsi_target_io_cb, ccb);
1708 } else if (xferlen != 0) {
1709 ocs_scsi_sgl_t sgl[OCS_FC_MAX_SGL];
1710 int32_t sgl_count = 0;
1712 io->tgt_io.state = OCS_CAM_IO_DATA;
1715 io->tgt_io.sendresp = 1;
1717 sgl_count = ocs_build_scsi_sgl(ocs, ccb, io, sgl, ARRAY_SIZE(sgl));
1718 if (sgl_count > 0) {
1719 if (cam_dir == CAM_DIR_IN) {
1720 rc = ocs_scsi_send_rd_data(io, 0, NULL, sgl,
1721 sgl_count, csio->dxfer_len,
1722 ocs_scsi_target_io_cb, ccb);
1723 } else if (cam_dir == CAM_DIR_OUT) {
1724 rc = ocs_scsi_recv_wr_data(io, 0, NULL, sgl,
1725 sgl_count, csio->dxfer_len,
1726 ocs_scsi_target_io_cb, ccb);
1728 device_printf(ocs->dev, "%s:"
1729 " unknown CAM direction %#x\n",
1731 ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
1735 device_printf(ocs->dev, "%s: building SGL failed\n",
1737 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
1741 device_printf(ocs->dev, "%s: Wrong value xfer and sendstatus"
1742 " are 0 \n", __func__);
1743 ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
1749 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
1750 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1751 io->tgt_io.state = OCS_CAM_IO_DATA_DONE;
1752 device_printf(ocs->dev, "%s: CTIO state=%d tag=%#x\n",
1753 __func__, io->tgt_io.state, io->tag);
1754 if ((sendstatus && (xferlen == 0))) {
1755 ocs_target_io_free(io);
1763 ocs_target_tmf_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags,
1767 /*device_printf(io->ocs->dev, "%s: tag=%x io=%p s=%#x\n",
1768 __func__, io->tag, io, scsi_status);*/
1769 ocs_scsi_io_complete(io);
1776 * @brief Send an initiator IO
1778 * @param ocs the driver instance's software context
1779 * @param ccb pointer to the CCB
1781 * @return 0 on success, non-zero otherwise
1784 ocs_initiator_io(struct ocs_softc *ocs, union ccb *ccb)
1787 struct ccb_scsiio *csio = &ccb->csio;
1788 struct ccb_hdr *ccb_h = &csio->ccb_h;
1789 ocs_node_t *node = NULL;
1790 ocs_io_t *io = NULL;
1791 ocs_scsi_sgl_t sgl[OCS_FC_MAX_SGL];
1795 fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path)));
1797 if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_LOST) {
1798 device_printf(ocs->dev, "%s: device LOST %d\n", __func__,
1800 return CAM_REQUEUE_REQ;
1803 if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_NONE) {
1804 device_printf(ocs->dev, "%s: device not ready %d\n", __func__,
1806 return CAM_SEL_TIMEOUT;
1809 node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id);
1811 device_printf(ocs->dev, "%s: no device %d\n", __func__,
1813 return CAM_SEL_TIMEOUT;
1817 device_printf(ocs->dev, "%s: not target device %d\n", __func__,
1819 return CAM_SEL_TIMEOUT;
1822 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR);
1824 device_printf(ocs->dev, "%s: unable to alloc IO\n", __func__);
1828 /* eventhough this is INI, use target structure as ocs_build_scsi_sgl
1829 * only references the tgt_io part of an ocs_io_t */
1830 io->tgt_io.app = ccb;
1832 csio->ccb_h.ccb_ocs_ptr = ocs;
1833 csio->ccb_h.ccb_io_ptr = io;
1835 sgl_count = ocs_build_scsi_sgl(ocs, ccb, io, sgl, ARRAY_SIZE(sgl));
1836 if (sgl_count < 0) {
1837 ocs_scsi_io_free(io);
1838 device_printf(ocs->dev, "%s: building SGL failed\n", __func__);
1842 if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) {
1844 } else if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) {
1845 io->timeout = OCS_CAM_IO_TIMEOUT;
1847 io->timeout = ccb->ccb_h.timeout;
1850 switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
1852 rc = ocs_scsi_send_nodata_io(node, io, ccb_h->target_lun,
1853 ccb->ccb_h.flags & CAM_CDB_POINTER ?
1854 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes,
1856 ocs_scsi_initiator_io_cb, ccb);
1859 rc = ocs_scsi_send_rd_io(node, io, ccb_h->target_lun,
1860 ccb->ccb_h.flags & CAM_CDB_POINTER ?
1861 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes,
1864 sgl, sgl_count, csio->dxfer_len,
1865 ocs_scsi_initiator_io_cb, ccb);
1868 rc = ocs_scsi_send_wr_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,
1873 sgl, sgl_count, csio->dxfer_len,
1874 ocs_scsi_initiator_io_cb, ccb);
1877 panic("%s invalid data direction %08x\n", __func__,
1886 ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role)
1889 uint32_t rc = 0, was = 0, i = 0;
1890 ocs_vport_spec_t *vport = fcp->vport;
1892 for (was = 0, i = 0; i < (ocs->num_vports + 1); i++) {
1893 if (FCPORT(ocs, i)->role != KNOB_ROLE_NONE)
1898 if ((was == 0) || (vport == NULL)) {
1899 fcp->role = new_role;
1900 if (vport == NULL) {
1901 ocs->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
1902 ocs->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
1904 vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
1905 vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
1908 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
1910 ocs_log_debug(ocs, "port offline failed : %d\n", rc);
1913 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
1915 ocs_log_debug(ocs, "port online failed : %d\n", rc);
1921 if ((fcp->role != KNOB_ROLE_NONE)){
1922 fcp->role = new_role;
1923 vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
1924 vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
1925 /* New Sport will be created in sport deleted cb */
1926 return ocs_sport_vport_del(ocs, ocs->domain, vport->wwpn, vport->wwnn);
1929 fcp->role = new_role;
1931 vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
1932 vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
1934 if (fcp->role != KNOB_ROLE_NONE) {
1935 return ocs_sport_vport_alloc(ocs->domain, vport);
1943 * @brief Process CAM actions
1945 * The driver supplies this routine to the CAM during intialization and
1946 * is the main entry point for processing CAM Control Blocks (CCB)
1948 * @param sim pointer to the SCSI Interface Module
1949 * @param ccb CAM control block
1952 * - populate path inquiry data via info retrieved from SLI port
1955 ocs_action(struct cam_sim *sim, union ccb *ccb)
1957 struct ocs_softc *ocs = (struct ocs_softc *)cam_sim_softc(sim);
1958 struct ccb_hdr *ccb_h = &ccb->ccb_h;
1961 bus = cam_sim_bus(sim);
1963 switch (ccb_h->func_code) {
1966 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1967 if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
1968 ccb->ccb_h.status = CAM_REQ_INVALID;
1974 rc = ocs_initiator_io(ocs, ccb);
1976 ocs_set_ccb_status(ccb, CAM_REQ_INPROG | CAM_SIM_QUEUED);
1979 if (rc == CAM_REQUEUE_REQ) {
1980 cam_freeze_devq(ccb->ccb_h.path);
1981 cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 100, 0);
1982 ccb->ccb_h.status = CAM_REQUEUE_REQ;
1987 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1989 ocs_set_ccb_status(ccb, rc);
1991 ocs_set_ccb_status(ccb, CAM_SEL_TIMEOUT);
1998 struct ccb_pathinq *cpi = &ccb->cpi;
1999 struct ccb_pathinq_settings_fc *fc = &cpi->xport_specific.fc;
2000 ocs_fcport *fcp = FCPORT(ocs, bus);
2003 ocs_xport_stats_t value;
2005 cpi->version_num = 1;
2007 cpi->protocol = PROTO_SCSI;
2008 cpi->protocol_version = SCSI_REV_SPC;
2010 if (ocs->ocs_xport == OCS_XPORT_FC) {
2011 cpi->transport = XPORT_FC;
2013 cpi->transport = XPORT_UNKNOWN;
2016 cpi->transport_version = 0;
2018 /* Set the transport parameters of the SIM */
2019 ocs_xport_status(ocs->xport, OCS_XPORT_LINK_SPEED, &value);
2020 fc->bitrate = value.value * 1000; /* speed in Mbps */
2022 wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs, OCS_SCSI_WWPN));
2023 fc->wwpn = be64toh(wwn);
2025 wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs, OCS_SCSI_WWNN));
2026 fc->wwnn = be64toh(wwn);
2028 fc->port = fcp->fc_id;
2030 if (ocs->config_tgt) {
2032 PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
2035 cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
2036 cpi->hba_misc |= PIM_EXTLUNS | PIM_NOSCAN;
2038 cpi->hba_inquiry = PI_TAG_ABLE;
2039 cpi->max_target = OCS_MAX_TARGETS;
2040 cpi->initiator_id = ocs->max_remote_nodes + 1;
2042 if (!ocs->enable_ini) {
2043 cpi->hba_misc |= PIM_NOINITIATOR;
2046 cpi->max_lun = OCS_MAX_LUN;
2047 cpi->bus_id = cam_sim_bus(sim);
2049 /* Need to supply a base transfer speed prior to linking up
2050 * Worst case, this would be FC 1Gbps */
2051 cpi->base_transfer_speed = 1 * 1000 * 1000;
2053 /* Calculate the max IO supported
2054 * Worst case would be an OS page per SGL entry */
2055 cpi->maxio = PAGE_SIZE *
2056 (ocs_scsi_get_property(ocs, OCS_SCSI_MAX_SGL) - 1);
2058 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2059 strncpy(cpi->hba_vid, "Emulex", HBA_IDLEN);
2060 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2061 cpi->unit_number = cam_sim_unit(sim);
2063 cpi->ccb_h.status = CAM_REQ_CMP;
2067 case XPT_GET_TRAN_SETTINGS:
2069 struct ccb_trans_settings *cts = &ccb->cts;
2070 struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
2071 struct ccb_trans_settings_fc *fc = &cts->xport_specific.fc;
2072 ocs_xport_stats_t value;
2073 ocs_fcport *fcp = FCPORT(ocs, bus);
2074 ocs_fc_target_t *tgt = NULL;
2076 if (ocs->ocs_xport != OCS_XPORT_FC) {
2077 ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
2082 if (cts->ccb_h.target_id > OCS_MAX_TARGETS) {
2083 ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
2088 tgt = &fcp->tgt[cts->ccb_h.target_id];
2089 if (tgt->state == OCS_TGT_STATE_NONE) {
2090 ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
2095 cts->protocol = PROTO_SCSI;
2096 cts->protocol_version = SCSI_REV_SPC2;
2097 cts->transport = XPORT_FC;
2098 cts->transport_version = 2;
2100 scsi->valid = CTS_SCSI_VALID_TQ;
2101 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
2104 ocs_xport_status(ocs->xport, OCS_XPORT_LINK_SPEED, &value);
2105 fc->bitrate = value.value * 100;
2107 fc->wwpn = tgt->wwpn;
2109 fc->wwnn = tgt->wwnn;
2111 fc->port = tgt->port_id;
2113 fc->valid = CTS_FC_VALID_SPEED |
2118 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2122 case XPT_SET_TRAN_SETTINGS:
2123 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2127 case XPT_CALC_GEOMETRY:
2128 cam_calc_geometry(&ccb->ccg, TRUE);
2132 case XPT_GET_SIM_KNOB:
2134 struct ccb_sim_knob *knob = &ccb->knob;
2136 ocs_fcport *fcp = FCPORT(ocs, bus);
2138 if (ocs->ocs_xport != OCS_XPORT_FC) {
2139 ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
2145 wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs,
2147 knob->xport_specific.fc.wwnn = be64toh(wwn);
2149 wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs,
2151 knob->xport_specific.fc.wwpn = be64toh(wwn);
2153 knob->xport_specific.fc.wwnn = fcp->vport->wwnn;
2154 knob->xport_specific.fc.wwpn = fcp->vport->wwpn;
2157 knob->xport_specific.fc.role = fcp->role;
2158 knob->xport_specific.fc.valid = KNOB_VALID_ADDRESS |
2161 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2165 case XPT_SET_SIM_KNOB:
2167 struct ccb_sim_knob *knob = &ccb->knob;
2168 bool role_changed = FALSE;
2169 ocs_fcport *fcp = FCPORT(ocs, bus);
2171 if (ocs->ocs_xport != OCS_XPORT_FC) {
2172 ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
2177 if (knob->xport_specific.fc.valid & KNOB_VALID_ADDRESS) {
2178 device_printf(ocs->dev,
2179 "%s: XPT_SET_SIM_KNOB wwnn=%llx wwpn=%llx\n",
2181 (unsigned long long)knob->xport_specific.fc.wwnn,
2182 (unsigned long long)knob->xport_specific.fc.wwpn);
2185 if (knob->xport_specific.fc.valid & KNOB_VALID_ROLE) {
2186 switch (knob->xport_specific.fc.role) {
2187 case KNOB_ROLE_NONE:
2188 if (fcp->role != KNOB_ROLE_NONE) {
2189 role_changed = TRUE;
2192 case KNOB_ROLE_TARGET:
2193 if (fcp->role != KNOB_ROLE_TARGET) {
2194 role_changed = TRUE;
2197 case KNOB_ROLE_INITIATOR:
2198 if (fcp->role != KNOB_ROLE_INITIATOR) {
2199 role_changed = TRUE;
2202 case KNOB_ROLE_BOTH:
2203 if (fcp->role != KNOB_ROLE_BOTH) {
2204 role_changed = TRUE;
2208 device_printf(ocs->dev,
2209 "%s: XPT_SET_SIM_KNOB unsupported role: %d\n",
2210 __func__, knob->xport_specific.fc.role);
2214 device_printf(ocs->dev,
2215 "BUS:%d XPT_SET_SIM_KNOB old_role: %d new_role: %d\n",
2216 bus, fcp->role, knob->xport_specific.fc.role);
2218 ocs_fcp_change_role(ocs, fcp, knob->xport_specific.fc.role);
2224 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2230 union ccb *accb = ccb->cab.abort_ccb;
2232 switch (accb->ccb_h.func_code) {
2233 case XPT_ACCEPT_TARGET_IO:
2234 ocs_abort_atio(ocs, ccb);
2236 case XPT_IMMEDIATE_NOTIFY:
2237 ocs_abort_inot(ocs, ccb);
2240 rc = ocs_abort_initiator_io(ocs, accb);
2242 ccb->ccb_h.status = CAM_UA_ABORT;
2244 ccb->ccb_h.status = CAM_REQ_CMP;
2249 printf("abort of unknown func %#x\n",
2250 accb->ccb_h.func_code);
2251 ccb->ccb_h.status = CAM_REQ_INVALID;
2257 if (ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE) == 0) {
2258 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
2260 ocs_log_debug(ocs, "Failed to bring port online"
2263 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2265 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
2271 ocs_node_t *node = NULL;
2272 ocs_io_t *io = NULL;
2274 ocs_fcport *fcp = FCPORT(ocs, bus);
2276 node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id);
2278 device_printf(ocs->dev, "%s: no device %d\n",
2279 __func__, ccb_h->target_id);
2280 ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
2285 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR);
2287 device_printf(ocs->dev, "%s: unable to alloc IO\n",
2289 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
2294 rc = ocs_scsi_send_tmf(node, io, NULL, ccb_h->target_lun,
2295 OCS_SCSI_TMF_LOGICAL_UNIT_RESET,
2296 NULL, 0, 0, /* sgl, sgl_count, length */
2297 ocs_initiator_tmf_cb, NULL/*arg*/);
2300 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
2302 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2305 if (node->fcp2device) {
2306 ocs_reset_crn(node, ccb_h->target_lun);
2312 case XPT_EN_LUN: /* target support */
2314 ocs_tgt_resource_t *trsrc = NULL;
2315 uint32_t status = 0;
2316 ocs_fcport *fcp = FCPORT(ocs, bus);
2318 device_printf(ocs->dev, "XPT_EN_LUN %sable %d:%d\n",
2319 ccb->cel.enable ? "en" : "dis",
2320 ccb->ccb_h.target_id,
2321 (unsigned int)ccb->ccb_h.target_lun);
2323 trsrc = ocs_tgt_resource_get(fcp, &ccb->ccb_h, &status);
2325 trsrc->enabled = ccb->cel.enable;
2327 /* Abort all ATIO/INOT on LUN disable */
2328 if (trsrc->enabled == FALSE) {
2329 ocs_tgt_resource_abort(ocs, trsrc);
2331 STAILQ_INIT(&trsrc->atio);
2332 STAILQ_INIT(&trsrc->inot);
2334 status = CAM_REQ_CMP;
2337 ocs_set_ccb_status(ccb, status);
2342 * The flow of target IOs in CAM is:
2343 * - CAM supplies a number of CCBs to the driver used for received
2345 * - when the driver receives a command, it copies the relevant
2346 * information to the CCB and returns it to the CAM using xpt_done()
2347 * - after the target server processes the request, it creates
2348 * a new CCB containing information on how to continue the IO and
2349 * passes that to the driver
2350 * - the driver processes the "continue IO" (a.k.a CTIO) CCB
2351 * - once the IO completes, the driver returns the CTIO to the CAM
2354 case XPT_ACCEPT_TARGET_IO: /* used to inform upper layer of
2355 received CDB (a.k.a. ATIO) */
2356 case XPT_IMMEDIATE_NOTIFY: /* used to inform upper layer of other
2357 event (a.k.a. INOT) */
2359 ocs_tgt_resource_t *trsrc = NULL;
2360 uint32_t status = 0;
2361 ocs_fcport *fcp = FCPORT(ocs, bus);
2363 /*printf("XPT_%s %p\n", ccb_h->func_code == XPT_ACCEPT_TARGET_IO ?
2364 "ACCEPT_TARGET_IO" : "IMMEDIATE_NOTIFY", ccb);*/
2365 trsrc = ocs_tgt_resource_get(fcp, &ccb->ccb_h, &status);
2366 if (trsrc == NULL) {
2367 ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
2372 if (XPT_ACCEPT_TARGET_IO == ccb->ccb_h.func_code) {
2373 struct ccb_accept_tio *atio = NULL;
2375 atio = (struct ccb_accept_tio *)ccb;
2376 atio->init_id = 0x0badbeef;
2377 atio->tag_id = 0xdeadc0de;
2379 STAILQ_INSERT_TAIL(&trsrc->atio, &ccb->ccb_h,
2382 STAILQ_INSERT_TAIL(&trsrc->inot, &ccb->ccb_h,
2385 ccb->ccb_h.ccb_io_ptr = NULL;
2386 ccb->ccb_h.ccb_ocs_ptr = ocs;
2387 ocs_set_ccb_status(ccb, CAM_REQ_INPROG);
2389 * These actions give resources to the target driver.
2390 * If we didn't return here, this function would call
2391 * xpt_done(), signaling to the upper layers that an
2392 * IO or other event had arrived.
2396 case XPT_NOTIFY_ACKNOWLEDGE:
2398 ocs_io_t *io = NULL;
2399 ocs_io_t *abortio = NULL;
2401 /* Get the IO reference for this tag */
2402 io = ocs_scsi_find_io(ocs, ccb->cna2.tag_id);
2404 device_printf(ocs->dev,
2405 "%s: XPT_NOTIFY_ACKNOWLEDGE no IO with tag %#x\n",
2406 __func__, ccb->cna2.tag_id);
2407 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
2412 abortio = io->tgt_io.app;
2414 abortio->tgt_io.flags &= ~OCS_CAM_IO_F_ABORT_NOTIFY;
2415 device_printf(ocs->dev,
2416 "%s: XPT_NOTIFY_ACK state=%d tag=%#x xid=%#x"
2417 " flags=%#x\n", __func__, abortio->tgt_io.state,
2418 abortio->tag, abortio->init_task_tag,
2419 abortio->tgt_io.flags);
2420 /* TMF response was sent in abort callback */
2422 ocs_scsi_send_tmf_resp(io,
2423 OCS_SCSI_TMF_FUNCTION_COMPLETE,
2424 NULL, ocs_target_tmf_cb, NULL);
2427 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2431 case XPT_CONT_TARGET_IO: /* continue target IO, sending data/response (a.k.a. CTIO) */
2432 if (ocs_target_io(ocs, ccb)) {
2433 device_printf(ocs->dev,
2434 "XPT_CONT_TARGET_IO failed flags=%x tag=%#x\n",
2435 ccb->ccb_h.flags, ccb->csio.tag_id);
2440 device_printf(ocs->dev, "unhandled func_code = %#x\n",
2442 ccb_h->status = CAM_REQ_INVALID;
2450 * @brief Process events
2452 * @param sim pointer to the SCSI Interface Module
2456 ocs_poll(struct cam_sim *sim)
2458 printf("%s\n", __func__);
2462 ocs_initiator_tmf_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status,
2463 ocs_scsi_cmd_resp_t *rsp, uint32_t flags, void *arg)
2467 switch (scsi_status) {
2468 case OCS_SCSI_STATUS_GOOD:
2469 case OCS_SCSI_STATUS_NO_IO:
2471 case OCS_SCSI_STATUS_CHECK_RESPONSE:
2472 if (rsp->response_data_length == 0) {
2473 ocs_log_test(io->ocs, "check response without data?!?\n");
2478 if (rsp->response_data[3] != 0) {
2479 ocs_log_test(io->ocs, "TMF status %08x\n",
2480 be32toh(*((uint32_t *)rsp->response_data)));
2486 ocs_log_test(io->ocs, "status=%#x\n", scsi_status);
2490 ocs_scsi_io_free(io);
2496 * @brief lookup target resource structure
2498 * Arbitrarily support
2499 * - wildcard target ID + LU
2500 * - 0 target ID + non-wildcard LU
2502 * @param ocs the driver instance's software context
2503 * @param ccb_h pointer to the CCB header
2504 * @param status returned status value
2506 * @return pointer to the target resource, NULL if none available (e.g. if LU
2509 static ocs_tgt_resource_t *ocs_tgt_resource_get(ocs_fcport *fcp,
2510 struct ccb_hdr *ccb_h, uint32_t *status)
2512 target_id_t tid = ccb_h->target_id;
2513 lun_id_t lun = ccb_h->target_lun;
2515 if (CAM_TARGET_WILDCARD == tid) {
2516 if (CAM_LUN_WILDCARD != lun) {
2517 *status = CAM_LUN_INVALID;
2520 return &fcp->targ_rsrc_wildcard;
2522 if (lun < OCS_MAX_LUN) {
2523 return &fcp->targ_rsrc[lun];
2525 *status = CAM_LUN_INVALID;
2533 ocs_tgt_resource_abort(struct ocs_softc *ocs, ocs_tgt_resource_t *trsrc)
2535 union ccb *ccb = NULL;
2540 ccb = (union ccb *)STAILQ_FIRST(&trsrc->atio);
2542 STAILQ_REMOVE_HEAD(&trsrc->atio, sim_links.stqe);
2543 ccb->ccb_h.status = CAM_REQ_ABORTED;
2551 ccb = (union ccb *)STAILQ_FIRST(&trsrc->inot);
2553 STAILQ_REMOVE_HEAD(&trsrc->inot, sim_links.stqe);
2554 ccb->ccb_h.status = CAM_REQ_ABORTED;
2564 ocs_abort_atio(struct ocs_softc *ocs, union ccb *ccb)
2567 ocs_io_t *aio = NULL;
2568 ocs_tgt_resource_t *trsrc = NULL;
2569 uint32_t status = CAM_REQ_INVALID;
2570 struct ccb_hdr *cur = NULL;
2571 union ccb *accb = ccb->cab.abort_ccb;
2573 int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path));
2574 ocs_fcport *fcp = FCPORT(ocs, bus);
2576 trsrc = ocs_tgt_resource_get(fcp, &accb->ccb_h, &status);
2577 if (trsrc != NULL) {
2578 STAILQ_FOREACH(cur, &trsrc->atio, sim_links.stqe) {
2579 if (cur != &accb->ccb_h)
2582 STAILQ_REMOVE(&trsrc->atio, cur, ccb_hdr,
2584 accb->ccb_h.status = CAM_REQ_ABORTED;
2586 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2591 /* if the ATIO has a valid IO pointer, CAM is telling
2592 * the driver that the ATIO (which represents the entire
2593 * exchange) has been aborted. */
2595 aio = accb->ccb_h.ccb_io_ptr;
2597 ccb->ccb_h.status = CAM_UA_ABORT;
2601 device_printf(ocs->dev,
2602 "%s: XPT_ABORT ATIO state=%d tag=%#x"
2603 " xid=%#x flags=%#x\n", __func__,
2604 aio->tgt_io.state, aio->tag,
2605 aio->init_task_tag, aio->tgt_io.flags);
2606 /* Expectations are:
2607 * - abort task was received
2608 * - already aborted IO in the DEVICE
2609 * - already received NOTIFY ACKNOWLEDGE */
2611 if ((aio->tgt_io.flags & OCS_CAM_IO_F_ABORT_RECV) == 0) {
2612 device_printf(ocs->dev, "%s: abort not received or io completed \n", __func__);
2613 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2617 aio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_CAM;
2618 ocs_target_io_free(aio);
2619 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2625 ocs_abort_inot(struct ocs_softc *ocs, union ccb *ccb)
2627 ocs_tgt_resource_t *trsrc = NULL;
2628 uint32_t status = CAM_REQ_INVALID;
2629 struct ccb_hdr *cur = NULL;
2630 union ccb *accb = ccb->cab.abort_ccb;
2632 int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path));
2633 ocs_fcport *fcp = FCPORT(ocs, bus);
2635 trsrc = ocs_tgt_resource_get(fcp, &accb->ccb_h, &status);
2637 STAILQ_FOREACH(cur, &trsrc->inot, sim_links.stqe) {
2638 if (cur != &accb->ccb_h)
2641 STAILQ_REMOVE(&trsrc->inot, cur, ccb_hdr,
2643 accb->ccb_h.status = CAM_REQ_ABORTED;
2645 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2650 ocs_set_ccb_status(ccb, CAM_UA_ABORT);
2655 ocs_abort_initiator_io(struct ocs_softc *ocs, union ccb *accb)
2658 ocs_node_t *node = NULL;
2659 ocs_io_t *io = NULL;
2661 struct ccb_scsiio *csio = &accb->csio;
2663 ocs_fcport *fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((accb)->ccb_h.path)));
2664 node = ocs_node_get_instance(ocs, fcp->tgt[accb->ccb_h.target_id].node_id);
2666 device_printf(ocs->dev, "%s: no device %d\n",
2667 __func__, accb->ccb_h.target_id);
2668 ocs_set_ccb_status(accb, CAM_DEV_NOT_THERE);
2673 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR);
2675 device_printf(ocs->dev,
2676 "%s: unable to alloc IO\n", __func__);
2677 ocs_set_ccb_status(accb, CAM_REQ_CMP_ERR);
2682 rc = ocs_scsi_send_tmf(node, io,
2683 (ocs_io_t *)csio->ccb_h.ccb_io_ptr,
2684 accb->ccb_h.target_lun,
2685 OCS_SCSI_TMF_ABORT_TASK,
2687 ocs_initiator_tmf_cb, NULL/*arg*/);
2693 ocs_scsi_ini_ddump(ocs_textbuf_t *textbuf, ocs_scsi_ddump_type_e type, void *obj)
2696 case OCS_SCSI_DDUMP_DEVICE: {
2700 case OCS_SCSI_DDUMP_DOMAIN: {
2701 //ocs_domain_t *domain = obj;
2704 case OCS_SCSI_DDUMP_SPORT: {
2705 //ocs_sport_t *sport = obj;
2708 case OCS_SCSI_DDUMP_NODE: {
2709 //ocs_node_t *node = obj;
2712 case OCS_SCSI_DDUMP_IO: {
2713 //ocs_io_t *io = obj;
2723 ocs_scsi_tgt_ddump(ocs_textbuf_t *textbuf, ocs_scsi_ddump_type_e type, void *obj)
2726 case OCS_SCSI_DDUMP_DEVICE: {
2730 case OCS_SCSI_DDUMP_DOMAIN: {
2731 //ocs_domain_t *domain = obj;
2734 case OCS_SCSI_DDUMP_SPORT: {
2735 //ocs_sport_t *sport = obj;
2738 case OCS_SCSI_DDUMP_NODE: {
2739 //ocs_node_t *node = obj;
2742 case OCS_SCSI_DDUMP_IO: {
2744 char *state_str = NULL;
2746 switch (io->tgt_io.state) {
2747 case OCS_CAM_IO_FREE:
2750 case OCS_CAM_IO_COMMAND:
2751 state_str = "COMMAND";
2753 case OCS_CAM_IO_DATA:
2756 case OCS_CAM_IO_DATA_DONE:
2757 state_str = "DATA_DONE";
2759 case OCS_CAM_IO_RESP:
2763 state_str = "xxx BAD xxx";
2765 ocs_ddump_value(textbuf, "cam_st", "%s", state_str);
2766 if (io->tgt_io.app) {
2767 ocs_ddump_value(textbuf, "cam_flags", "%#x",
2768 ((union ccb *)(io->tgt_io.app))->ccb_h.flags);
2769 ocs_ddump_value(textbuf, "cam_status", "%#x",
2770 ((union ccb *)(io->tgt_io.app))->ccb_h.status);
2781 int32_t ocs_scsi_get_block_vaddr(ocs_io_t *io, uint64_t blocknumber,
2782 ocs_scsi_vaddr_len_t addrlen[],
2783 uint32_t max_addrlen, void **dif_vaddr)
2789 ocs_get_crn(ocs_node_t *node, uint8_t *crn, uint64_t lun)
2792 struct ocs_lun_crn *lcrn = NULL;
2793 idx = lun % OCS_MAX_LUN;
2795 lcrn = node->ini_node.lun_crn[idx];
2798 lcrn = ocs_malloc(node->ocs, sizeof(struct ocs_lun_crn),
2805 node->ini_node.lun_crn[idx] = lcrn;
2808 if (lcrn->lun != lun) {
2812 if (lcrn->crnseed == 0)
2815 *crn = lcrn->crnseed++;
2820 ocs_del_crn(ocs_node_t *node)
2823 struct ocs_lun_crn *lcrn = NULL;
2825 for(i = 0; i < OCS_MAX_LUN; i++) {
2826 lcrn = node->ini_node.lun_crn[i];
2828 ocs_free(node->ocs, lcrn, sizeof(*lcrn));
2836 ocs_reset_crn(ocs_node_t *node, uint64_t lun)
2839 struct ocs_lun_crn *lcrn = NULL;
2840 idx = lun % OCS_MAX_LUN;
2842 lcrn = node->ini_node.lun_crn[idx];