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