scsi_ctl.c revision 313369
11553Srgrimes/*-
21553Srgrimes * Copyright (c) 2008, 2009 Silicon Graphics International Corp.
31553Srgrimes * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org>
41553Srgrimes * All rights reserved.
51553Srgrimes *
61553Srgrimes * Redistribution and use in source and binary forms, with or without
71553Srgrimes * modification, are permitted provided that the following conditions
81553Srgrimes * are met:
91553Srgrimes * 1. Redistributions of source code must retain the above copyright
101553Srgrimes *    notice, this list of conditions, and the following disclaimer,
111553Srgrimes *    without modification.
121553Srgrimes * 2. Redistributions in binary form must reproduce at minimum a disclaimer
13121300Sphk *    substantially similar to the "NO WARRANTY" disclaimer below
141553Srgrimes *    ("Disclaimer") and any redistribution must be conditioned upon
151553Srgrimes *    including a substantially similar Disclaimer requirement for further
161553Srgrimes *    binary redistribution.
171553Srgrimes *
181553Srgrimes * NO WARRANTY
191553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
201553Srgrimes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
211553Srgrimes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
221553Srgrimes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
231553Srgrimes * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
241553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
251553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
261553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
271553Srgrimes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
281553Srgrimes * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291553Srgrimes * POSSIBILITY OF SUCH DAMAGES.
30114601Sobrien *
311553Srgrimes * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/scsi_ctl.c#4 $
321553Srgrimes */
33114601Sobrien/*
3430027Scharnier * Peripheral driver interface between CAM and CTL (CAM Target Layer).
35114601Sobrien *
36114601Sobrien * Author: Ken Merry <ken@FreeBSD.org>
371553Srgrimes */
381553Srgrimes
391553Srgrimes#include <sys/cdefs.h>
4030027Scharnier__FBSDID("$FreeBSD: stable/10/sys/cam/ctl/scsi_ctl.c 313369 2017-02-07 01:56:26Z mav $");
4130027Scharnier
4230027Scharnier#include <sys/param.h>
431553Srgrimes#include <sys/queue.h>
441553Srgrimes#include <sys/systm.h>
451553Srgrimes#include <sys/kernel.h>
4644303Swollman#include <sys/lock.h>
4730027Scharnier#include <sys/mutex.h>
4844303Swollman#include <sys/condvar.h>
4944303Swollman#include <sys/malloc.h>
5044303Swollman#include <sys/bus.h>
5144303Swollman#include <sys/endian.h>
5244303Swollman#include <sys/sbuf.h>
5344303Swollman#include <sys/sysctl.h>
5444303Swollman#include <sys/types.h>
55144295Stobez#include <sys/systm.h>
56144295Stobez#include <machine/bus.h>
57144295Stobez
581553Srgrimes#include <cam/cam.h>
59100070Sdes#include <cam/cam_ccb.h>
6030027Scharnier#include <cam/cam_periph.h>
6130027Scharnier#include <cam/cam_queue.h>
621553Srgrimes#include <cam/cam_xpt_periph.h>
6342561Sjkoshy#include <cam/cam_debug.h>
641553Srgrimes#include <cam/cam_sim.h>
651553Srgrimes#include <cam/cam_xpt.h>
661553Srgrimes
671553Srgrimes#include <cam/scsi/scsi_all.h>
681553Srgrimes#include <cam/scsi/scsi_message.h>
691553Srgrimes
701553Srgrimes#include <cam/ctl/ctl_io.h>
711553Srgrimes#include <cam/ctl/ctl.h>
721553Srgrimes#include <cam/ctl/ctl_frontend.h>
7366584Sphk#include <cam/ctl/ctl_util.h>
741553Srgrimes#include <cam/ctl/ctl_error.h>
75103726Swollman
7699800Salfredstruct ctlfe_softc {
7799800Salfred	struct ctl_port	port;
7899800Salfred	path_id_t	path_id;
791553Srgrimes	target_id_t	target_id;
801553Srgrimes	uint32_t	hba_misc;
81121299Sphk	u_int		maxio;
821553Srgrimes	struct cam_sim *sim;
83121299Sphk	char		port_name[DEV_IDLEN];
84121299Sphk	struct mtx	lun_softc_mtx;
8599802Salfred	STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list;
861553Srgrimes	STAILQ_ENTRY(ctlfe_softc) links;
8799802Salfred};
882860Srgrimes
891553SrgrimesSTAILQ_HEAD(, ctlfe_softc) ctlfe_softc_list;
90124265Sphkstruct mtx ctlfe_list_mtx;
91124265Sphkstatic char ctlfe_mtx_desc[] = "ctlfelist";
92124265Sphk#ifdef CTLFE_INIT_ENABLE
93124265Sphkstatic int ctlfe_max_targets = 1;
94124265Sphkstatic int ctlfe_num_targets = 0;
95124265Sphk#endif
96124265Sphk
97124265Sphktypedef enum {
98124265Sphk	CTLFE_LUN_NONE		= 0x00,
99124265Sphk	CTLFE_LUN_WILDCARD	= 0x01
1001553Srgrimes} ctlfe_lun_flags;
10199802Salfred
1021553Srgrimesstruct ctlfe_lun_softc {
1031553Srgrimes	struct ctlfe_softc *parent_softc;
104124389Sphk	struct cam_periph *periph;
1052860Srgrimes	ctlfe_lun_flags flags;
1062860Srgrimes	uint64_t ccbs_alloced;
1072860Srgrimes	uint64_t ccbs_freed;
10860418Swollman	uint64_t ctios_sent;
10960418Swollman	uint64_t ctios_returned;
11060418Swollman	uint64_t atios_alloced;
11160418Swollman	uint64_t atios_freed;
1121553Srgrimes	uint64_t inots_alloced;
1131553Srgrimes	uint64_t inots_freed;
1142860Srgrimes	/* bus_dma_tag_t dma_tag; */
1152860Srgrimes	TAILQ_HEAD(, ccb_hdr) work_queue;
1162860Srgrimes	STAILQ_ENTRY(ctlfe_lun_softc) links;
1172860Srgrimes};
11854375Sjoe
1192860Srgrimestypedef enum {
1201553Srgrimes	CTLFE_CMD_NONE		= 0x00,
1211553Srgrimes	CTLFE_CMD_PIECEWISE	= 0x01
1222860Srgrimes} ctlfe_cmd_flags;
1232860Srgrimes
1242860Srgrimesstruct ctlfe_cmd_info {
1252860Srgrimes	int cur_transfer_index;
1262860Srgrimes	size_t cur_transfer_off;
1271553Srgrimes	ctlfe_cmd_flags flags;
1281553Srgrimes	/*
1291553Srgrimes	 * XXX KDM struct bus_dma_segment is 8 bytes on i386, and 16
1301553Srgrimes	 * bytes on amd64.  So with 32 elements, this is 256 bytes on
13130027Scharnier	 * i386 and 512 bytes on amd64.
1321553Srgrimes	 */
1331553Srgrimes#define CTLFE_MAX_SEGS	32
1341553Srgrimes	bus_dma_segment_t cam_sglist[CTLFE_MAX_SEGS];
1352860Srgrimes};
1361553Srgrimes
1378857Srgrimes/*
1381553Srgrimes * When we register the adapter/bus, request that this many ctl_ios be
1392860Srgrimes * allocated.  This should be the maximum supported by the adapter, but we
1401553Srgrimes * currently don't have a way to get that back from the path inquiry.
1411553Srgrimes * XXX KDM add that to the path inquiry.
142112214Srobert */
1431553Srgrimes#define	CTLFE_REQ_CTL_IO	4096
1441553Srgrimes/*
1451553Srgrimes * Number of Accept Target I/O CCBs to allocate and queue down to the
146121299Sphk * adapter per LUN.
1471553Srgrimes * XXX KDM should this be controlled by CTL?
1481553Srgrimes */
1491553Srgrimes#define	CTLFE_ATIO_PER_LUN	1024
150112214Srobert/*
151112214Srobert * Number of Immediate Notify CCBs (used for aborts, resets, etc.) to
1522860Srgrimes * allocate and queue down to the adapter per LUN.
15361749Sjoe * XXX KDM should this be controlled by CTL?
15442561Sjkoshy */
1551553Srgrimes#define	CTLFE_IN_PER_LUN	1024
15642561Sjkoshy
15742561Sjkoshy/*
15842561Sjkoshy * Timeout (in seconds) on CTIO CCB allocation for doing a DMA or sending
159121731Sphk * status to the initiator.  The SIM is expected to have its own timeouts,
16042561Sjkoshy * so we're not putting this timeout around the CCB execution time.  The
1612860Srgrimes * SIM should timeout and let us know if it has an issue.
16242561Sjkoshy */
1631553Srgrimes#define	CTLFE_DMA_TIMEOUT	60
16442561Sjkoshy
165121300Sphk/*
16642561Sjkoshy * Turn this on to enable extra debugging prints.
1671553Srgrimes */
1682860Srgrimes#if 0
1692860Srgrimes#define	CTLFE_DEBUG
1701553Srgrimes#endif
1712860Srgrimes
1721553Srgrimes/*
1732860Srgrimes * Use randomly assigned WWNN/WWPN values.  This is to work around an issue
1742860Srgrimes * in the FreeBSD initiator that makes it unable to rescan the target if
1752860Srgrimes * the target gets rebooted and the WWNN/WWPN stay the same.
1762860Srgrimes */
177124389Sphk#if 0
178124389Sphk#define	RANDOM_WWNN
179124389Sphk#endif
180124389Sphk
181124389SphkMALLOC_DEFINE(M_CTLFE, "CAM CTL FE", "CAM CTL FE interface");
182124389Sphk
183124389Sphk#define	io_ptr		ppriv_ptr0
18430027Scharnier
185124389Sphk/* This is only used in the CTIO */
186124389Sphk#define	ccb_atio	ppriv_ptr1
1872860Srgrimes
1882860Srgrimes#define PRIV_CCB(io)	((io)->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptrs[0])
1892860Srgrimes#define PRIV_INFO(io)	((io)->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptrs[1])
1902860Srgrimes
1912860Srgrimesstatic int		ctlfeinitialize(void);
1922860Srgrimesstatic int		ctlfeshutdown(void);
193124389Sphkstatic periph_init_t	ctlfeperiphinit;
194124389Sphkstatic void		ctlfeasync(void *callback_arg, uint32_t code,
195124389Sphk				   struct cam_path *path, void *arg);
196124389Sphkstatic periph_ctor_t	ctlferegister;
197124389Sphkstatic periph_oninv_t	ctlfeoninvalidate;
198124389Sphkstatic periph_dtor_t	ctlfecleanup;
199124389Sphkstatic periph_start_t	ctlfestart;
20030027Scharnierstatic void		ctlfedone(struct cam_periph *periph,
201124389Sphk				  union ccb *done_ccb);
202124389Sphk
2032860Srgrimesstatic void 		ctlfe_onoffline(void *arg, int online);
2042860Srgrimesstatic void 		ctlfe_online(void *arg);
2052860Srgrimesstatic void 		ctlfe_offline(void *arg);
2062860Srgrimesstatic int 		ctlfe_lun_enable(void *arg, int lun_id);
2071553Srgrimesstatic int 		ctlfe_lun_disable(void *arg, int lun_id);
2082860Srgrimesstatic void		ctlfe_dump_sim(struct cam_sim *sim);
2091553Srgrimesstatic void		ctlfe_dump_queue(struct ctlfe_lun_softc *softc);
2102860Srgrimesstatic void 		ctlfe_datamove(union ctl_io *io);
211255483Sdelphijstatic void 		ctlfe_done(union ctl_io *io);
212100070Sdesstatic void 		ctlfe_dump(void);
213100070Sdes
2141553Srgrimesstatic struct periph_driver ctlfe_driver =
215187940Skientzle{
216205793Sed	ctlfeperiphinit, "ctl",
217205793Sed	TAILQ_HEAD_INITIALIZER(ctlfe_driver.units), /*generation*/ 0,
2181553Srgrimes	CAM_PERIPH_DRV_EARLY
2191553Srgrimes};
2201553Srgrimes
221124389Sphkstatic struct ctl_frontend ctlfe_frontend =
2221553Srgrimes{
223112214Srobert	.name = "camtgt",
2241553Srgrimes	.init = ctlfeinitialize,
22544303Swollman	.fe_dump = ctlfe_dump,
2266286Swollman	.shutdown = ctlfeshutdown,
22744303Swollman};
2286286SwollmanCTL_FRONTEND_DECLARE(ctlfe, ctlfe_frontend);
22944303Swollman
230122134Sphkstatic int
231124389Sphkctlfeshutdown(void)
232122134Sphk{
2336286Swollman
23444303Swollman	/* CAM does not support periph driver unregister now. */
23544303Swollman	return (EBUSY);
23644303Swollman}
23744303Swollman
23844303Swollmanstatic int
23944303Swollmanctlfeinitialize(void)
240122134Sphk{
241124389Sphk
242122134Sphk	STAILQ_INIT(&ctlfe_softc_list);
24344303Swollman	mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF);
24444303Swollman	periphdriver_register(&ctlfe_driver);
24544303Swollman	return (0);
24644303Swollman}
24744303Swollman
24844303Swollmanstatic void
24944303Swollmanctlfeperiphinit(void)
250122134Sphk{
251124389Sphk	cam_status status;
252122134Sphk
25344303Swollman	status = xpt_register_async(AC_PATH_REGISTERED | AC_PATH_DEREGISTERED |
25444303Swollman				    AC_CONTRACT, ctlfeasync, NULL, NULL);
255144295Stobez	if (status != CAM_REQ_CMP) {
256144295Stobez		printf("ctl: Failed to attach async callback due to CAM "
257144295Stobez		       "status 0x%x!\n", status);
258144295Stobez	}
259144295Stobez}
260144295Stobez
261144295Stobezstatic void
262144295Stobezctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
263144295Stobez{
264144295Stobez	struct ctlfe_softc *softc;
2651553Srgrimes
2661553Srgrimes#ifdef CTLFEDEBUG
2672860Srgrimes	printf("%s: entered\n", __func__);
26861749Sjoe#endif
26961749Sjoe
27061749Sjoe	mtx_lock(&ctlfe_list_mtx);
27161749Sjoe	STAILQ_FOREACH(softc, &ctlfe_softc_list, links) {
27261749Sjoe		if (softc->path_id == xpt_path_path_id(path))
2731553Srgrimes			break;
2741553Srgrimes	}
2751553Srgrimes	mtx_unlock(&ctlfe_list_mtx);
2761553Srgrimes
2771553Srgrimes	/*
2781553Srgrimes	 * When a new path gets registered, and it is capable of target
27954375Sjoe	 * mode, go ahead and attach.  Later on, we may need to be more
28054375Sjoe	 * selective, but for now this will be sufficient.
2811553Srgrimes 	 */
2821553Srgrimes	switch (code) {
283121299Sphk	case AC_PATH_REGISTERED: {
2841553Srgrimes		struct ctl_port *port;
285121299Sphk		struct ccb_pathinq *cpi;
286121299Sphk		int retval;
287121299Sphk
288121299Sphk		cpi = (struct ccb_pathinq *)arg;
289121299Sphk
2901553Srgrimes		/* Don't attach if it doesn't support target mode */
2911553Srgrimes		if ((cpi->target_sprt & PIT_PROCESSOR) == 0) {
2922860Srgrimes#ifdef CTLFEDEBUG
2932860Srgrimes			printf("%s: SIM %s%d doesn't support target mode\n",
2942860Srgrimes			       __func__, cpi->dev_name, cpi->unit_number);
29566584Sphk#endif
29654375Sjoe			break;
29754375Sjoe		}
29861749Sjoe
2992877Srgrimes		if (softc != NULL) {
3001553Srgrimes#ifdef CTLFEDEBUG
3011553Srgrimes			printf("%s: CTL port for CAM path %u already exists\n",
3021553Srgrimes			       __func__, xpt_path_path_id(path));
303124389Sphk#endif
3041553Srgrimes			break;
3051553Srgrimes		}
3061553Srgrimes
3071553Srgrimes#ifdef CTLFE_INIT_ENABLE
3081553Srgrimes		if (ctlfe_num_targets >= ctlfe_max_targets) {
3091553Srgrimes			union ccb *ccb;
31054375Sjoe
3111553Srgrimes			ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP,
31254375Sjoe						  M_NOWAIT | M_ZERO);
3131553Srgrimes			if (ccb == NULL) {
3142860Srgrimes				printf("%s: unable to malloc CCB!\n", __func__);
3152860Srgrimes				return;
3162860Srgrimes			}
3172860Srgrimes			xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
3182860Srgrimes
3192860Srgrimes			ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
3202860Srgrimes			ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
3212860Srgrimes			ccb->knob.xport_specific.fc.role = KNOB_ROLE_INITIATOR;
3222860Srgrimes
3232860Srgrimes			xpt_action(ccb);
3242860Srgrimes
3252860Srgrimes			if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
3262860Srgrimes			     CAM_REQ_CMP) {
3272860Srgrimes				printf("%s: SIM %s%d (path id %d) initiator "
3282860Srgrimes				       "enable failed with status %#x\n",
3292860Srgrimes				       __func__, cpi->dev_name,
33054375Sjoe				       cpi->unit_number, cpi->ccb_h.path_id,
33154375Sjoe				       ccb->ccb_h.status);
33254375Sjoe			} else {
33354375Sjoe				printf("%s: SIM %s%d (path id %d) initiator "
33454375Sjoe				       "enable succeeded\n",
33554375Sjoe				       __func__, cpi->dev_name,
33654375Sjoe				       cpi->unit_number, cpi->ccb_h.path_id);
33754375Sjoe			}
33854375Sjoe
33954375Sjoe			free(ccb, M_TEMP);
34054375Sjoe
34154375Sjoe			break;
34266584Sphk		} else {
34354375Sjoe			ctlfe_num_targets++;
3441553Srgrimes		}
3451553Srgrimes
3462860Srgrimes		printf("%s: ctlfe_num_targets = %d\n", __func__,
3472860Srgrimes		       ctlfe_num_targets);
3482877Srgrimes#endif /* CTLFE_INIT_ENABLE */
3492877Srgrimes
3502860Srgrimes		/*
3512860Srgrimes		 * We're in an interrupt context here, so we have to
3522860Srgrimes		 * use M_NOWAIT.  Of course this means trouble if we
353121300Sphk		 * can't allocate memory.
35466584Sphk		 */
35566584Sphk		softc = malloc(sizeof(*softc), M_CTLFE, M_NOWAIT | M_ZERO);
3562877Srgrimes		if (softc == NULL) {
3572860Srgrimes			printf("%s: unable to malloc %zd bytes for softc\n",
3582860Srgrimes			       __func__, sizeof(*softc));
3591553Srgrimes			return;
3602860Srgrimes		}
36151705Sbillf
362124389Sphk		softc->path_id = cpi->ccb_h.path_id;
363124389Sphk		softc->target_id = cpi->initiator_id;
3642860Srgrimes		softc->sim = xpt_path_sim(path);
365124389Sphk		softc->hba_misc = cpi->hba_misc;
366124389Sphk		if (cpi->maxio != 0)
3672860Srgrimes			softc->maxio = cpi->maxio;
368124389Sphk		else
36951705Sbillf			softc->maxio = DFLTPHYS;
3702860Srgrimes		mtx_init(&softc->lun_softc_mtx, "LUN softc mtx", NULL, MTX_DEF);
37138020Sbde		STAILQ_INIT(&softc->lun_softc_list);
37251705Sbillf
373124389Sphk		port = &softc->port;
374124389Sphk		port->frontend = &ctlfe_frontend;
3752860Srgrimes
376124389Sphk		/*
377124389Sphk		 * XXX KDM should we be more accurate here ?
3782860Srgrimes		 */
379124389Sphk		if (cpi->transport == XPORT_FC)
38051705Sbillf			port->port_type = CTL_PORT_FC;
3812860Srgrimes		else if (cpi->transport == XPORT_SAS)
38238020Sbde			port->port_type = CTL_PORT_SAS;
3832860Srgrimes		else
3842860Srgrimes			port->port_type = CTL_PORT_SCSI;
3852860Srgrimes
3862860Srgrimes		/* XXX KDM what should the real number be here? */
38766584Sphk		port->num_requested_ctl_io = 4096;
38861749Sjoe		snprintf(softc->port_name, sizeof(softc->port_name),
38961749Sjoe			 "%s%d", cpi->dev_name, cpi->unit_number);
39061749Sjoe		/*
39161749Sjoe		 * XXX KDM it would be nice to allocate storage in the
3922860Srgrimes		 * frontend structure itself.
3932860Srgrimes	 	 */
3942860Srgrimes		port->port_name = softc->port_name;
3952860Srgrimes		port->physical_port = cpi->bus_id;
39654375Sjoe		port->virtual_port = 0;
3972860Srgrimes		port->port_online = ctlfe_online;
3981553Srgrimes		port->port_offline = ctlfe_offline;
3991553Srgrimes		port->onoff_arg = softc;
4001553Srgrimes		port->lun_enable = ctlfe_lun_enable;
4011553Srgrimes		port->lun_disable = ctlfe_lun_disable;
402121299Sphk		port->targ_lun_arg = softc;
4031553Srgrimes		port->fe_datamove = ctlfe_datamove;
4041553Srgrimes		port->fe_done = ctlfe_done;
4051553Srgrimes		/*
4061553Srgrimes		 * XXX KDM the path inquiry doesn't give us the maximum
4071553Srgrimes		 * number of targets supported.
4081553Srgrimes		 */
4091553Srgrimes		port->max_targets = cpi->max_target;
4101553Srgrimes		port->max_target_id = cpi->max_target;
4111553Srgrimes		port->targ_port = -1;
4121553Srgrimes
4131553Srgrimes		/*
4141553Srgrimes		 * XXX KDM need to figure out whether we're the master or
4152860Srgrimes		 * slave.
4161553Srgrimes		 */
4171553Srgrimes#ifdef CTLFEDEBUG
4181553Srgrimes		printf("%s: calling ctl_port_register() for %s%d\n",
4191553Srgrimes		       __func__, cpi->dev_name, cpi->unit_number);
4201553Srgrimes#endif
4211553Srgrimes		retval = ctl_port_register(port);
4221553Srgrimes		if (retval != 0) {
4231553Srgrimes			printf("%s: ctl_port_register() failed with "
4242860Srgrimes			       "error %d!\n", __func__, retval);
4252860Srgrimes			mtx_destroy(&softc->lun_softc_mtx);
4261553Srgrimes			free(softc, M_CTLFE);
4271553Srgrimes			break;
4281553Srgrimes		} else {
429			mtx_lock(&ctlfe_list_mtx);
430			STAILQ_INSERT_TAIL(&ctlfe_softc_list, softc, links);
431			mtx_unlock(&ctlfe_list_mtx);
432		}
433
434		break;
435	}
436	case AC_PATH_DEREGISTERED: {
437
438		if (softc != NULL) {
439			/*
440			 * XXX KDM are we certain at this point that there
441			 * are no outstanding commands for this frontend?
442			 */
443			mtx_lock(&ctlfe_list_mtx);
444			STAILQ_REMOVE(&ctlfe_softc_list, softc, ctlfe_softc,
445			    links);
446			mtx_unlock(&ctlfe_list_mtx);
447			ctl_port_deregister(&softc->port);
448			mtx_destroy(&softc->lun_softc_mtx);
449			free(softc, M_CTLFE);
450		}
451		break;
452	}
453	case AC_CONTRACT: {
454		struct ac_contract *ac;
455
456		ac = (struct ac_contract *)arg;
457
458		switch (ac->contract_number) {
459		case AC_CONTRACT_DEV_CHG: {
460			struct ac_device_changed *dev_chg;
461			int retval;
462
463			dev_chg = (struct ac_device_changed *)ac->contract_data;
464
465			printf("%s: WWPN %#jx port 0x%06x path %u target %u %s\n",
466			       __func__, dev_chg->wwpn, dev_chg->port,
467			       xpt_path_path_id(path), dev_chg->target,
468			       (dev_chg->arrived == 0) ?  "left" : "arrived");
469
470			if (softc == NULL) {
471				printf("%s: CTL port for CAM path %u not "
472				       "found!\n", __func__,
473				       xpt_path_path_id(path));
474				break;
475			}
476			if (dev_chg->arrived != 0) {
477				retval = ctl_add_initiator(&softc->port,
478				    dev_chg->target, dev_chg->wwpn, NULL);
479			} else {
480				retval = ctl_remove_initiator(&softc->port,
481				    dev_chg->target);
482			}
483
484			if (retval < 0) {
485				printf("%s: could not %s port %d iid %u "
486				       "WWPN %#jx!\n", __func__,
487				       (dev_chg->arrived != 0) ? "add" :
488				       "remove", softc->port.targ_port,
489				       dev_chg->target,
490				       (uintmax_t)dev_chg->wwpn);
491			}
492			break;
493		}
494		default:
495			printf("%s: unsupported contract number %ju\n",
496			       __func__, (uintmax_t)ac->contract_number);
497			break;
498		}
499		break;
500	}
501	default:
502		break;
503	}
504}
505
506static cam_status
507ctlferegister(struct cam_periph *periph, void *arg)
508{
509	struct ctlfe_softc *bus_softc;
510	struct ctlfe_lun_softc *softc;
511	union ccb en_lun_ccb;
512	cam_status status;
513	int i;
514
515	softc = (struct ctlfe_lun_softc *)arg;
516	bus_softc = softc->parent_softc;
517
518	TAILQ_INIT(&softc->work_queue);
519	softc->periph = periph;
520	periph->softc = softc;
521
522	xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE);
523	en_lun_ccb.ccb_h.func_code = XPT_EN_LUN;
524	en_lun_ccb.cel.grp6_len = 0;
525	en_lun_ccb.cel.grp7_len = 0;
526	en_lun_ccb.cel.enable = 1;
527	xpt_action(&en_lun_ccb);
528	status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK);
529	if (status != CAM_REQ_CMP) {
530		xpt_print(periph->path, "%s: Enable LUN failed, status 0x%x\n",
531			  __func__, en_lun_ccb.ccb_h.status);
532		return (status);
533	}
534
535	status = CAM_REQ_CMP;
536
537	for (i = 0; i < CTLFE_ATIO_PER_LUN; i++) {
538		union ccb *new_ccb;
539		union ctl_io *new_io;
540		struct ctlfe_cmd_info *cmd_info;
541
542		new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
543					      M_ZERO|M_NOWAIT);
544		if (new_ccb == NULL) {
545			status = CAM_RESRC_UNAVAIL;
546			break;
547		}
548		new_io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref);
549		if (new_io == NULL) {
550			free(new_ccb, M_CTLFE);
551			status = CAM_RESRC_UNAVAIL;
552			break;
553		}
554		cmd_info = malloc(sizeof(*cmd_info), M_CTLFE,
555		    M_ZERO | M_NOWAIT);
556		if (cmd_info == NULL) {
557			ctl_free_io(new_io);
558			free(new_ccb, M_CTLFE);
559			status = CAM_RESRC_UNAVAIL;
560			break;
561		}
562		PRIV_INFO(new_io) = cmd_info;
563		softc->atios_alloced++;
564		new_ccb->ccb_h.io_ptr = new_io;
565
566		xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
567		new_ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
568		new_ccb->ccb_h.cbfcnp = ctlfedone;
569		new_ccb->ccb_h.flags |= CAM_UNLOCKED;
570		xpt_action(new_ccb);
571		status = new_ccb->ccb_h.status;
572		if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
573			free(cmd_info, M_CTLFE);
574			ctl_free_io(new_io);
575			free(new_ccb, M_CTLFE);
576			break;
577		}
578	}
579
580	status = cam_periph_acquire(periph);
581	if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
582		xpt_print(periph->path, "%s: could not acquire reference "
583			  "count, status = %#x\n", __func__, status);
584		return (status);
585	}
586
587	if (i == 0) {
588		xpt_print(periph->path, "%s: could not allocate ATIO CCBs, "
589			  "status 0x%x\n", __func__, status);
590		return (CAM_REQ_CMP_ERR);
591	}
592
593	for (i = 0; i < CTLFE_IN_PER_LUN; i++) {
594		union ccb *new_ccb;
595		union ctl_io *new_io;
596
597		new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
598					      M_ZERO|M_NOWAIT);
599		if (new_ccb == NULL) {
600			status = CAM_RESRC_UNAVAIL;
601			break;
602		}
603		new_io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref);
604		if (new_io == NULL) {
605			free(new_ccb, M_CTLFE);
606			status = CAM_RESRC_UNAVAIL;
607			break;
608		}
609		softc->inots_alloced++;
610		new_ccb->ccb_h.io_ptr = new_io;
611
612		xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
613		new_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
614		new_ccb->ccb_h.cbfcnp = ctlfedone;
615		new_ccb->ccb_h.flags |= CAM_UNLOCKED;
616		xpt_action(new_ccb);
617		status = new_ccb->ccb_h.status;
618		if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
619			/*
620			 * Note that we don't free the CCB here.  If the
621			 * status is not CAM_REQ_INPROG, then we're
622			 * probably talking to a SIM that says it is
623			 * target-capable but doesn't support the
624			 * XPT_IMMEDIATE_NOTIFY CCB.  i.e. it supports the
625			 * older API.  In that case, it'll call xpt_done()
626			 * on the CCB, and we need to free it in our done
627			 * routine as a result.
628			 */
629			break;
630		}
631	}
632	if ((i == 0)
633	 || (status != CAM_REQ_INPROG)) {
634		xpt_print(periph->path, "%s: could not allocate immediate "
635			  "notify CCBs, status 0x%x\n", __func__, status);
636		return (CAM_REQ_CMP_ERR);
637	}
638	mtx_lock(&bus_softc->lun_softc_mtx);
639	STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, softc, links);
640	mtx_unlock(&bus_softc->lun_softc_mtx);
641	return (CAM_REQ_CMP);
642}
643
644static void
645ctlfeoninvalidate(struct cam_periph *periph)
646{
647	union ccb en_lun_ccb;
648	cam_status status;
649	struct ctlfe_softc *bus_softc;
650	struct ctlfe_lun_softc *softc;
651
652	softc = (struct ctlfe_lun_softc *)periph->softc;
653
654	xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE);
655	en_lun_ccb.ccb_h.func_code = XPT_EN_LUN;
656	en_lun_ccb.cel.grp6_len = 0;
657	en_lun_ccb.cel.grp7_len = 0;
658	en_lun_ccb.cel.enable = 0;
659	xpt_action(&en_lun_ccb);
660	status = (en_lun_ccb.ccb_h.status & CAM_STATUS_MASK);
661	if (status != CAM_REQ_CMP) {
662		xpt_print(periph->path, "%s: Disable LUN failed, status 0x%x\n",
663			  __func__, en_lun_ccb.ccb_h.status);
664		/*
665		 * XXX KDM what do we do now?
666		 */
667	}
668
669	bus_softc = softc->parent_softc;
670	mtx_lock(&bus_softc->lun_softc_mtx);
671	STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links);
672	mtx_unlock(&bus_softc->lun_softc_mtx);
673}
674
675static void
676ctlfecleanup(struct cam_periph *periph)
677{
678	struct ctlfe_lun_softc *softc;
679
680	softc = (struct ctlfe_lun_softc *)periph->softc;
681
682	KASSERT(softc->ccbs_freed == softc->ccbs_alloced, ("%s: "
683		"ccbs_freed %ju != ccbs_alloced %ju", __func__,
684		softc->ccbs_freed, softc->ccbs_alloced));
685	KASSERT(softc->ctios_returned == softc->ctios_sent, ("%s: "
686		"ctios_returned %ju != ctios_sent %ju", __func__,
687		softc->ctios_returned, softc->ctios_sent));
688	KASSERT(softc->atios_freed == softc->atios_alloced, ("%s: "
689		"atios_freed %ju != atios_alloced %ju", __func__,
690		softc->atios_freed, softc->atios_alloced));
691	KASSERT(softc->inots_freed == softc->inots_alloced, ("%s: "
692		"inots_freed %ju != inots_alloced %ju", __func__,
693		softc->inots_freed, softc->inots_alloced));
694
695	free(softc, M_CTLFE);
696}
697
698static void
699ctlfedata(struct ctlfe_lun_softc *softc, union ctl_io *io,
700    ccb_flags *flags, uint8_t **data_ptr, uint32_t *dxfer_len,
701    u_int16_t *sglist_cnt)
702{
703	struct ctlfe_softc *bus_softc;
704	struct ctlfe_cmd_info *cmd_info;
705	struct ctl_sg_entry *ctl_sglist;
706	bus_dma_segment_t *cam_sglist;
707	size_t off;
708	int i, idx;
709
710	cmd_info = PRIV_INFO(io);
711	bus_softc = softc->parent_softc;
712
713	/*
714	 * Set the direction, relative to the initiator.
715	 */
716	*flags &= ~CAM_DIR_MASK;
717	if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN)
718		*flags |= CAM_DIR_IN;
719	else
720		*flags |= CAM_DIR_OUT;
721
722	*flags &= ~CAM_DATA_MASK;
723	idx = cmd_info->cur_transfer_index;
724	off = cmd_info->cur_transfer_off;
725	cmd_info->flags &= ~CTLFE_CMD_PIECEWISE;
726	if (io->scsiio.kern_sg_entries == 0) {	/* No S/G list. */
727
728		/* One time shift for SRR offset. */
729		off += io->scsiio.ext_data_filled;
730		io->scsiio.ext_data_filled = 0;
731
732		*data_ptr = io->scsiio.kern_data_ptr + off;
733		if (io->scsiio.kern_data_len - off <= bus_softc->maxio) {
734			*dxfer_len = io->scsiio.kern_data_len - off;
735		} else {
736			*dxfer_len = bus_softc->maxio;
737			cmd_info->cur_transfer_off += bus_softc->maxio;
738			cmd_info->flags |= CTLFE_CMD_PIECEWISE;
739		}
740		*sglist_cnt = 0;
741
742		if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
743			*flags |= CAM_DATA_PADDR;
744		else
745			*flags |= CAM_DATA_VADDR;
746	} else {	/* S/G list with physical or virtual pointers. */
747		ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
748
749		/* One time shift for SRR offset. */
750		while (io->scsiio.ext_data_filled >= ctl_sglist[idx].len - off) {
751			io->scsiio.ext_data_filled -= ctl_sglist[idx].len - off;
752			idx++;
753			off = 0;
754		}
755		off += io->scsiio.ext_data_filled;
756		io->scsiio.ext_data_filled = 0;
757
758		cam_sglist = cmd_info->cam_sglist;
759		*dxfer_len = 0;
760		for (i = 0; i < io->scsiio.kern_sg_entries - idx; i++) {
761			cam_sglist[i].ds_addr = (bus_addr_t)ctl_sglist[i + idx].addr + off;
762			if (ctl_sglist[i + idx].len - off <= bus_softc->maxio - *dxfer_len) {
763				cam_sglist[i].ds_len = ctl_sglist[idx + i].len - off;
764				*dxfer_len += cam_sglist[i].ds_len;
765			} else {
766				cam_sglist[i].ds_len = bus_softc->maxio - *dxfer_len;
767				cmd_info->cur_transfer_index = idx + i;
768				cmd_info->cur_transfer_off = cam_sglist[i].ds_len + off;
769				cmd_info->flags |= CTLFE_CMD_PIECEWISE;
770				*dxfer_len += cam_sglist[i].ds_len;
771				if (ctl_sglist[i].len != 0)
772					i++;
773				break;
774			}
775			if (i == (CTLFE_MAX_SEGS - 1) &&
776			    idx + i < (io->scsiio.kern_sg_entries - 1)) {
777				cmd_info->cur_transfer_index = idx + i + 1;
778				cmd_info->cur_transfer_off = 0;
779				cmd_info->flags |= CTLFE_CMD_PIECEWISE;
780				i++;
781				break;
782			}
783			off = 0;
784		}
785		*sglist_cnt = i;
786		if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR)
787			*flags |= CAM_DATA_SG_PADDR;
788		else
789			*flags |= CAM_DATA_SG;
790		*data_ptr = (uint8_t *)cam_sglist;
791	}
792}
793
794static void
795ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
796{
797	struct ctlfe_lun_softc *softc;
798	struct ctlfe_cmd_info *cmd_info;
799	struct ccb_hdr *ccb_h;
800	struct ccb_accept_tio *atio;
801	struct ccb_scsiio *csio;
802	uint8_t *data_ptr;
803	uint32_t dxfer_len;
804	ccb_flags flags;
805	union ctl_io *io;
806	uint8_t scsi_status;
807
808	softc = (struct ctlfe_lun_softc *)periph->softc;
809	softc->ccbs_alloced++;
810
811	ccb_h = TAILQ_FIRST(&softc->work_queue);
812	if (ccb_h == NULL) {
813		softc->ccbs_freed++;
814		xpt_release_ccb(start_ccb);
815		return;
816	}
817
818	/* Take the ATIO off the work queue */
819	TAILQ_REMOVE(&softc->work_queue, ccb_h, periph_links.tqe);
820	atio = (struct ccb_accept_tio *)ccb_h;
821	io = (union ctl_io *)ccb_h->io_ptr;
822	csio = &start_ccb->csio;
823
824	flags = atio->ccb_h.flags &
825		(CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK);
826	cmd_info = PRIV_INFO(io);
827	cmd_info->cur_transfer_index = 0;
828	cmd_info->cur_transfer_off = 0;
829	cmd_info->flags = 0;
830
831	if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) {
832		/*
833		 * Datamove call, we need to setup the S/G list.
834		 */
835		ctlfedata(softc, io, &flags, &data_ptr, &dxfer_len,
836		    &csio->sglist_cnt);
837	} else {
838		/*
839		 * We're done, send status back.
840		 */
841		if ((io->io_hdr.flags & CTL_FLAG_ABORT) &&
842		    (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) {
843			io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED;
844
845			/*
846			 * If this command was aborted, we don't
847			 * need to send status back to the SIM.
848			 * Just free the CTIO and ctl_io, and
849			 * recycle the ATIO back to the SIM.
850			 */
851			xpt_print(periph->path, "%s: aborted "
852				  "command 0x%04x discarded\n",
853				  __func__, io->scsiio.tag_num);
854			/*
855			 * For a wildcard attachment, commands can
856			 * come in with a specific target/lun.  Reset
857			 * the target and LUN fields back to the
858			 * wildcard values before we send them back
859			 * down to the SIM.  The SIM has a wildcard
860			 * LUN enabled, not whatever target/lun
861			 * these happened to be.
862			 */
863			if (softc->flags & CTLFE_LUN_WILDCARD) {
864				atio->ccb_h.target_id = CAM_TARGET_WILDCARD;
865				atio->ccb_h.target_lun = CAM_LUN_WILDCARD;
866			}
867
868			if (atio->ccb_h.func_code != XPT_ACCEPT_TARGET_IO) {
869				xpt_print(periph->path, "%s: func_code "
870					  "is %#x\n", __func__,
871					  atio->ccb_h.func_code);
872			}
873			start_ccb->ccb_h.func_code = XPT_ABORT;
874			start_ccb->cab.abort_ccb = (union ccb *)atio;
875
876			/* Tell the SIM that we've aborted this ATIO */
877			xpt_action(start_ccb);
878			softc->ccbs_freed++;
879			xpt_release_ccb(start_ccb);
880
881			/*
882			 * Send the ATIO back down to the SIM.
883			 */
884			xpt_action((union ccb *)atio);
885
886			/*
887			 * If we still have work to do, ask for
888			 * another CCB.  Otherwise, deactivate our
889			 * callout.
890			 */
891			if (!TAILQ_EMPTY(&softc->work_queue))
892				xpt_schedule(periph, /*priority*/ 1);
893			return;
894		}
895		data_ptr = NULL;
896		dxfer_len = 0;
897		csio->sglist_cnt = 0;
898	}
899	scsi_status = 0;
900	if ((io->io_hdr.flags & CTL_FLAG_STATUS_QUEUED) &&
901	    (cmd_info->flags & CTLFE_CMD_PIECEWISE) == 0 &&
902	    ((io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) == 0 ||
903	     io->io_hdr.status == CTL_SUCCESS)) {
904		flags |= CAM_SEND_STATUS;
905		scsi_status = io->scsiio.scsi_status;
906		csio->sense_len = io->scsiio.sense_len;
907#ifdef CTLFEDEBUG
908		printf("%s: tag %04x status %x\n", __func__,
909		       atio->tag_id, io->io_hdr.status);
910#endif
911		if (csio->sense_len != 0) {
912			csio->sense_data = io->scsiio.sense_data;
913			flags |= CAM_SEND_SENSE;
914		} else if (scsi_status == SCSI_STATUS_CHECK_COND) {
915			xpt_print(periph->path, "%s: check condition "
916				  "with no sense\n", __func__);
917		}
918	}
919
920#ifdef CTLFEDEBUG
921	printf("%s: %s: tag %04x flags %x ptr %p len %u\n", __func__,
922	       (flags & CAM_SEND_STATUS) ? "done" : "datamove",
923	       atio->tag_id, flags, data_ptr, dxfer_len);
924#endif
925
926	/*
927	 * Valid combinations:
928	 *  - CAM_SEND_STATUS, CAM_DATA_SG = 0, dxfer_len = 0,
929	 *    sglist_cnt = 0
930	 *  - CAM_SEND_STATUS = 0, CAM_DATA_SG = 0, dxfer_len != 0,
931	 *    sglist_cnt = 0
932	 *  - CAM_SEND_STATUS = 0, CAM_DATA_SG, dxfer_len != 0,
933	 *    sglist_cnt != 0
934	 */
935#ifdef CTLFEDEBUG
936	if (((flags & CAM_SEND_STATUS)
937	  && (((flags & CAM_DATA_SG) != 0)
938	   || (dxfer_len != 0)
939	   || (csio->sglist_cnt != 0)))
940	 || (((flags & CAM_SEND_STATUS) == 0)
941	  && (dxfer_len == 0))
942	 || ((flags & CAM_DATA_SG)
943	  && (csio->sglist_cnt == 0))
944	 || (((flags & CAM_DATA_SG) == 0)
945	  && (csio->sglist_cnt != 0))) {
946		printf("%s: tag %04x cdb %02x flags %#x dxfer_len "
947		       "%d sg %u\n", __func__, atio->tag_id,
948		       atio_cdb_ptr(atio)[0], flags, dxfer_len,
949		       csio->sglist_cnt);
950		printf("%s: tag %04x io status %#x\n", __func__,
951		       atio->tag_id, io->io_hdr.status);
952	}
953#endif
954	cam_fill_ctio(csio,
955		      /*retries*/ 2,
956		      ctlfedone,
957		      flags,
958		      (flags & CAM_TAG_ACTION_VALID) ? MSG_SIMPLE_Q_TAG : 0,
959		      atio->tag_id,
960		      atio->init_id,
961		      scsi_status,
962		      /*data_ptr*/ data_ptr,
963		      /*dxfer_len*/ dxfer_len,
964		      /*timeout*/ 5 * 1000);
965	start_ccb->ccb_h.flags |= CAM_UNLOCKED;
966	start_ccb->ccb_h.ccb_atio = atio;
967	if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED)
968		io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
969	io->io_hdr.flags &= ~(CTL_FLAG_DMA_QUEUED | CTL_FLAG_STATUS_QUEUED);
970
971	softc->ctios_sent++;
972
973	cam_periph_unlock(periph);
974	xpt_action(start_ccb);
975	cam_periph_lock(periph);
976
977	/*
978	 * If we still have work to do, ask for another CCB.
979	 */
980	if (!TAILQ_EMPTY(&softc->work_queue))
981		xpt_schedule(periph, /*priority*/ 1);
982}
983
984static void
985ctlfe_free_ccb(struct cam_periph *periph, union ccb *ccb)
986{
987	struct ctlfe_lun_softc *softc;
988	union ctl_io *io;
989	struct ctlfe_cmd_info *cmd_info;
990
991	softc = (struct ctlfe_lun_softc *)periph->softc;
992	io = ccb->ccb_h.io_ptr;
993
994	switch (ccb->ccb_h.func_code) {
995	case XPT_ACCEPT_TARGET_IO:
996		softc->atios_freed++;
997		cmd_info = PRIV_INFO(io);
998		free(cmd_info, M_CTLFE);
999		break;
1000	case XPT_IMMEDIATE_NOTIFY:
1001	case XPT_NOTIFY_ACKNOWLEDGE:
1002		softc->inots_freed++;
1003		break;
1004	default:
1005		break;
1006	}
1007
1008	ctl_free_io(io);
1009	free(ccb, M_CTLFE);
1010
1011	KASSERT(softc->atios_freed <= softc->atios_alloced, ("%s: "
1012		"atios_freed %ju > atios_alloced %ju", __func__,
1013		softc->atios_freed, softc->atios_alloced));
1014	KASSERT(softc->inots_freed <= softc->inots_alloced, ("%s: "
1015		"inots_freed %ju > inots_alloced %ju", __func__,
1016		softc->inots_freed, softc->inots_alloced));
1017
1018	/*
1019	 * If we have received all of our CCBs, we can release our
1020	 * reference on the peripheral driver.  It will probably go away
1021	 * now.
1022	 */
1023	if ((softc->atios_freed == softc->atios_alloced)
1024	 && (softc->inots_freed == softc->inots_alloced)) {
1025		cam_periph_release_locked(periph);
1026	}
1027}
1028
1029static int
1030ctlfe_adjust_cdb(struct ccb_accept_tio *atio, uint32_t offset)
1031{
1032	uint64_t lba;
1033	uint32_t num_blocks, nbc;
1034	uint8_t *cmdbyt = atio_cdb_ptr(atio);
1035
1036	nbc = offset >> 9;	/* ASSUMING 512 BYTE BLOCKS */
1037
1038	switch (cmdbyt[0]) {
1039	case READ_6:
1040	case WRITE_6:
1041	{
1042		struct scsi_rw_6 *cdb = (struct scsi_rw_6 *)cmdbyt;
1043		lba = scsi_3btoul(cdb->addr);
1044		lba &= 0x1fffff;
1045		num_blocks = cdb->length;
1046		if (num_blocks == 0)
1047			num_blocks = 256;
1048		lba += nbc;
1049		num_blocks -= nbc;
1050		scsi_ulto3b(lba, cdb->addr);
1051		cdb->length = num_blocks;
1052		break;
1053	}
1054	case READ_10:
1055	case WRITE_10:
1056	{
1057		struct scsi_rw_10 *cdb = (struct scsi_rw_10 *)cmdbyt;
1058		lba = scsi_4btoul(cdb->addr);
1059		num_blocks = scsi_2btoul(cdb->length);
1060		lba += nbc;
1061		num_blocks -= nbc;
1062		scsi_ulto4b(lba, cdb->addr);
1063		scsi_ulto2b(num_blocks, cdb->length);
1064		break;
1065	}
1066	case READ_12:
1067	case WRITE_12:
1068	{
1069		struct scsi_rw_12 *cdb = (struct scsi_rw_12 *)cmdbyt;
1070		lba = scsi_4btoul(cdb->addr);
1071		num_blocks = scsi_4btoul(cdb->length);
1072		lba += nbc;
1073		num_blocks -= nbc;
1074		scsi_ulto4b(lba, cdb->addr);
1075		scsi_ulto4b(num_blocks, cdb->length);
1076		break;
1077	}
1078	case READ_16:
1079	case WRITE_16:
1080	{
1081		struct scsi_rw_16 *cdb = (struct scsi_rw_16 *)cmdbyt;
1082		lba = scsi_8btou64(cdb->addr);
1083		num_blocks = scsi_4btoul(cdb->length);
1084		lba += nbc;
1085		num_blocks -= nbc;
1086		scsi_u64to8b(lba, cdb->addr);
1087		scsi_ulto4b(num_blocks, cdb->length);
1088		break;
1089	}
1090	default:
1091		return -1;
1092	}
1093	return (0);
1094}
1095
1096static void
1097ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
1098{
1099	struct ctlfe_lun_softc *softc;
1100	struct ctlfe_softc *bus_softc;
1101	struct ctlfe_cmd_info *cmd_info;
1102	struct ccb_accept_tio *atio = NULL;
1103	union ctl_io *io = NULL;
1104	struct mtx *mtx;
1105
1106	KASSERT((done_ccb->ccb_h.flags & CAM_UNLOCKED) != 0,
1107	    ("CCB in ctlfedone() without CAM_UNLOCKED flag"));
1108#ifdef CTLFE_DEBUG
1109	printf("%s: entered, func_code = %#x\n", __func__,
1110	       done_ccb->ccb_h.func_code);
1111#endif
1112
1113	/*
1114	 * At this point CTL has no known use case for device queue freezes.
1115	 * In case some SIM think different -- drop its freeze right here.
1116	 */
1117	if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
1118		cam_release_devq(periph->path,
1119				 /*relsim_flags*/0,
1120				 /*reduction*/0,
1121				 /*timeout*/0,
1122				 /*getcount_only*/0);
1123		done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
1124	}
1125
1126	softc = (struct ctlfe_lun_softc *)periph->softc;
1127	bus_softc = softc->parent_softc;
1128	mtx = cam_periph_mtx(periph);
1129	mtx_lock(mtx);
1130
1131	/*
1132	 * If the peripheral is invalid, ATIOs and immediate notify CCBs
1133	 * need to be freed.  Most of the ATIOs and INOTs that come back
1134	 * will be CCBs that are being returned from the SIM as a result of
1135	 * our disabling the LUN.
1136	 *
1137	 * Other CCB types are handled in their respective cases below.
1138	 */
1139	if (periph->flags & CAM_PERIPH_INVALID) {
1140		switch (done_ccb->ccb_h.func_code) {
1141		case XPT_ACCEPT_TARGET_IO:
1142		case XPT_IMMEDIATE_NOTIFY:
1143		case XPT_NOTIFY_ACKNOWLEDGE:
1144			ctlfe_free_ccb(periph, done_ccb);
1145			goto out;
1146		default:
1147			break;
1148		}
1149
1150	}
1151	switch (done_ccb->ccb_h.func_code) {
1152	case XPT_ACCEPT_TARGET_IO: {
1153
1154		atio = &done_ccb->atio;
1155
1156 resubmit:
1157		/*
1158		 * Allocate a ctl_io, pass it to CTL, and wait for the
1159		 * datamove or done.
1160		 */
1161		mtx_unlock(mtx);
1162		io = done_ccb->ccb_h.io_ptr;
1163		cmd_info = PRIV_INFO(io);
1164		ctl_zero_io(io);
1165
1166		/* Save pointers on both sides */
1167		PRIV_CCB(io) = done_ccb;
1168		PRIV_INFO(io) = cmd_info;
1169		done_ccb->ccb_h.io_ptr = io;
1170
1171		/*
1172		 * Only SCSI I/O comes down this path, resets, etc. come
1173		 * down the immediate notify path below.
1174		 */
1175		io->io_hdr.io_type = CTL_IO_SCSI;
1176		io->io_hdr.nexus.initid = atio->init_id;
1177		io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
1178		if (bus_softc->hba_misc & PIM_EXTLUNS) {
1179			io->io_hdr.nexus.targ_lun = ctl_decode_lun(
1180			    CAM_EXTLUN_BYTE_SWIZZLE(atio->ccb_h.target_lun));
1181		} else {
1182			io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun;
1183		}
1184		io->scsiio.tag_num = atio->tag_id;
1185		switch (atio->tag_action) {
1186		case CAM_TAG_ACTION_NONE:
1187			io->scsiio.tag_type = CTL_TAG_UNTAGGED;
1188			break;
1189		case MSG_SIMPLE_TASK:
1190			io->scsiio.tag_type = CTL_TAG_SIMPLE;
1191			break;
1192		case MSG_HEAD_OF_QUEUE_TASK:
1193        		io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE;
1194			break;
1195		case MSG_ORDERED_TASK:
1196        		io->scsiio.tag_type = CTL_TAG_ORDERED;
1197			break;
1198		case MSG_ACA_TASK:
1199			io->scsiio.tag_type = CTL_TAG_ACA;
1200			break;
1201		default:
1202			io->scsiio.tag_type = CTL_TAG_UNTAGGED;
1203			printf("%s: unhandled tag type %#x!!\n", __func__,
1204			       atio->tag_action);
1205			break;
1206		}
1207		if (atio->cdb_len > sizeof(io->scsiio.cdb)) {
1208			printf("%s: WARNING: CDB len %d > ctl_io space %zd\n",
1209			       __func__, atio->cdb_len, sizeof(io->scsiio.cdb));
1210		}
1211		io->scsiio.cdb_len = min(atio->cdb_len, sizeof(io->scsiio.cdb));
1212		bcopy(atio_cdb_ptr(atio), io->scsiio.cdb, io->scsiio.cdb_len);
1213
1214#ifdef CTLFEDEBUG
1215		printf("%s: %u:%u:%u: tag %04x CDB %02x\n", __func__,
1216		        io->io_hdr.nexus.initid,
1217		        io->io_hdr.nexus.targ_port,
1218		        io->io_hdr.nexus.targ_lun,
1219			io->scsiio.tag_num, io->scsiio.cdb[0]);
1220#endif
1221
1222		ctl_queue(io);
1223		return;
1224	}
1225	case XPT_CONT_TARGET_IO: {
1226		int srr = 0;
1227		uint32_t srr_off = 0;
1228
1229		atio = (struct ccb_accept_tio *)done_ccb->ccb_h.ccb_atio;
1230		io = (union ctl_io *)atio->ccb_h.io_ptr;
1231
1232		softc->ctios_returned++;
1233#ifdef CTLFEDEBUG
1234		printf("%s: got XPT_CONT_TARGET_IO tag %#x flags %#x\n",
1235		       __func__, atio->tag_id, done_ccb->ccb_h.flags);
1236#endif
1237		/*
1238		 * Handle SRR case were the data pointer is pushed back hack
1239		 */
1240		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_MESSAGE_RECV
1241		    && done_ccb->csio.msg_ptr != NULL
1242		    && done_ccb->csio.msg_ptr[0] == MSG_EXTENDED
1243		    && done_ccb->csio.msg_ptr[1] == 5
1244       		    && done_ccb->csio.msg_ptr[2] == 0) {
1245			srr = 1;
1246			srr_off =
1247			    (done_ccb->csio.msg_ptr[3] << 24)
1248			    | (done_ccb->csio.msg_ptr[4] << 16)
1249			    | (done_ccb->csio.msg_ptr[5] << 8)
1250			    | (done_ccb->csio.msg_ptr[6]);
1251		}
1252
1253		/*
1254		 * If we have an SRR and we're still sending data, we
1255		 * should be able to adjust offsets and cycle again.
1256		 * It is possible only if offset is from this datamove.
1257		 */
1258		if (srr && (io->io_hdr.flags & CTL_FLAG_DMA_INPROG) &&
1259		    srr_off >= io->scsiio.kern_rel_offset &&
1260		    srr_off < io->scsiio.kern_rel_offset +
1261		     io->scsiio.kern_data_len) {
1262			io->scsiio.kern_data_resid =
1263			    io->scsiio.kern_rel_offset +
1264			    io->scsiio.kern_data_len - srr_off;
1265			io->scsiio.ext_data_filled = srr_off;
1266			io->scsiio.io_hdr.status = CTL_STATUS_NONE;
1267			io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED;
1268			softc->ccbs_freed++;
1269			xpt_release_ccb(done_ccb);
1270			TAILQ_INSERT_HEAD(&softc->work_queue, &atio->ccb_h,
1271					  periph_links.tqe);
1272			xpt_schedule(periph, /*priority*/ 1);
1273			break;
1274		}
1275
1276		/*
1277		 * If status was being sent, the back end data is now history.
1278		 * Hack it up and resubmit a new command with the CDB adjusted.
1279		 * If the SIM does the right thing, all of the resid math
1280		 * should work.
1281		 */
1282		if (srr && (io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) {
1283			softc->ccbs_freed++;
1284			xpt_release_ccb(done_ccb);
1285			if (ctlfe_adjust_cdb(atio, srr_off) == 0) {
1286				done_ccb = (union ccb *)atio;
1287				goto resubmit;
1288			}
1289			/*
1290			 * Fall through to doom....
1291			 */
1292		}
1293
1294		if ((done_ccb->ccb_h.flags & CAM_SEND_STATUS) &&
1295		    (done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
1296			io->io_hdr.flags |= CTL_FLAG_STATUS_SENT;
1297
1298		/*
1299		 * If we were sending status back to the initiator, free up
1300		 * resources.  If we were doing a datamove, call the
1301		 * datamove done routine.
1302		 */
1303		if ((io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) {
1304			softc->ccbs_freed++;
1305			xpt_release_ccb(done_ccb);
1306			/*
1307			 * For a wildcard attachment, commands can come in
1308			 * with a specific target/lun.  Reset the target
1309			 * and LUN fields back to the wildcard values before
1310			 * we send them back down to the SIM.  The SIM has
1311			 * a wildcard LUN enabled, not whatever target/lun
1312			 * these happened to be.
1313			 */
1314			if (softc->flags & CTLFE_LUN_WILDCARD) {
1315				atio->ccb_h.target_id = CAM_TARGET_WILDCARD;
1316				atio->ccb_h.target_lun = CAM_LUN_WILDCARD;
1317			}
1318			if (periph->flags & CAM_PERIPH_INVALID) {
1319				ctlfe_free_ccb(periph, (union ccb *)atio);
1320			} else {
1321				mtx_unlock(mtx);
1322				xpt_action((union ccb *)atio);
1323				return;
1324			}
1325		} else {
1326			struct ctlfe_cmd_info *cmd_info;
1327			struct ccb_scsiio *csio;
1328
1329			csio = &done_ccb->csio;
1330			cmd_info = PRIV_INFO(io);
1331
1332			io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG;
1333
1334			/*
1335			 * Translate CAM status to CTL status.  Success
1336			 * does not change the overall, ctl_io status.  In
1337			 * that case we just set port_status to 0.  If we
1338			 * have a failure, though, set a data phase error
1339			 * for the overall ctl_io.
1340			 */
1341			switch (done_ccb->ccb_h.status & CAM_STATUS_MASK) {
1342			case CAM_REQ_CMP:
1343				io->scsiio.kern_data_resid -= csio->dxfer_len;
1344				io->io_hdr.port_status = 0;
1345				break;
1346			default:
1347				/*
1348				 * XXX KDM we probably need to figure out a
1349				 * standard set of errors that the SIM
1350				 * drivers should return in the event of a
1351				 * data transfer failure.  A data phase
1352				 * error will at least point the user to a
1353				 * data transfer error of some sort.
1354				 * Hopefully the SIM printed out some
1355				 * additional information to give the user
1356				 * a clue what happened.
1357				 */
1358				io->io_hdr.port_status = 0xbad1;
1359				ctl_set_data_phase_error(&io->scsiio);
1360				/*
1361				 * XXX KDM figure out residual.
1362				 */
1363				break;
1364			}
1365			/*
1366			 * If we had to break this S/G list into multiple
1367			 * pieces, figure out where we are in the list, and
1368			 * continue sending pieces if necessary.
1369			 */
1370			if ((cmd_info->flags & CTLFE_CMD_PIECEWISE)
1371			 && (io->io_hdr.port_status == 0)) {
1372				ccb_flags flags;
1373				uint8_t *data_ptr;
1374				uint32_t dxfer_len;
1375
1376				flags = atio->ccb_h.flags &
1377					(CAM_DIS_DISCONNECT|
1378					 CAM_TAG_ACTION_VALID);
1379
1380				ctlfedata(softc, io, &flags, &data_ptr,
1381				    &dxfer_len, &csio->sglist_cnt);
1382
1383				if (((flags & CAM_SEND_STATUS) == 0)
1384				 && (dxfer_len == 0)) {
1385					printf("%s: tag %04x no status or "
1386					       "len cdb = %02x\n", __func__,
1387					       atio->tag_id,
1388					       atio_cdb_ptr(atio)[0]);
1389					printf("%s: tag %04x io status %#x\n",
1390					       __func__, atio->tag_id,
1391					       io->io_hdr.status);
1392				}
1393
1394				cam_fill_ctio(csio,
1395					      /*retries*/ 2,
1396					      ctlfedone,
1397					      flags,
1398					      (flags & CAM_TAG_ACTION_VALID) ?
1399					       MSG_SIMPLE_Q_TAG : 0,
1400					      atio->tag_id,
1401					      atio->init_id,
1402					      0,
1403					      /*data_ptr*/ data_ptr,
1404					      /*dxfer_len*/ dxfer_len,
1405					      /*timeout*/ 5 * 1000);
1406
1407				csio->ccb_h.flags |= CAM_UNLOCKED;
1408				csio->resid = 0;
1409				csio->ccb_h.ccb_atio = atio;
1410				io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
1411				softc->ctios_sent++;
1412				mtx_unlock(mtx);
1413				xpt_action((union ccb *)csio);
1414			} else {
1415				/*
1416				 * Release the CTIO.  The ATIO will be sent back
1417				 * down to the SIM once we send status.
1418				 */
1419				softc->ccbs_freed++;
1420				xpt_release_ccb(done_ccb);
1421				mtx_unlock(mtx);
1422
1423				/* Call the backend move done callback */
1424				io->scsiio.be_move_done(io);
1425			}
1426			return;
1427		}
1428		break;
1429	}
1430	case XPT_IMMEDIATE_NOTIFY: {
1431		union ctl_io *io;
1432		struct ccb_immediate_notify *inot;
1433		cam_status status;
1434		int send_ctl_io;
1435
1436		inot = &done_ccb->cin1;
1437		printf("%s: got XPT_IMMEDIATE_NOTIFY status %#x tag %#x "
1438		       "seq %#x\n", __func__, inot->ccb_h.status,
1439		       inot->tag_id, inot->seq_id);
1440
1441		io = done_ccb->ccb_h.io_ptr;
1442		ctl_zero_io(io);
1443
1444		send_ctl_io = 1;
1445
1446		io->io_hdr.io_type = CTL_IO_TASK;
1447		PRIV_CCB(io) = done_ccb;
1448		inot->ccb_h.io_ptr = io;
1449		io->io_hdr.nexus.initid = inot->initiator_id;
1450		io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
1451		if (bus_softc->hba_misc & PIM_EXTLUNS) {
1452			io->io_hdr.nexus.targ_lun = ctl_decode_lun(
1453			    CAM_EXTLUN_BYTE_SWIZZLE(inot->ccb_h.target_lun));
1454		} else {
1455			io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun;
1456		}
1457		/* XXX KDM should this be the tag_id? */
1458		io->taskio.tag_num = inot->seq_id;
1459
1460		status = inot->ccb_h.status & CAM_STATUS_MASK;
1461		switch (status) {
1462		case CAM_SCSI_BUS_RESET:
1463			io->taskio.task_action = CTL_TASK_BUS_RESET;
1464			break;
1465		case CAM_BDR_SENT:
1466			io->taskio.task_action = CTL_TASK_TARGET_RESET;
1467			break;
1468		case CAM_MESSAGE_RECV:
1469			switch (inot->arg) {
1470			case MSG_ABORT_TASK_SET:
1471				io->taskio.task_action =
1472				    CTL_TASK_ABORT_TASK_SET;
1473				break;
1474			case MSG_TARGET_RESET:
1475				io->taskio.task_action = CTL_TASK_TARGET_RESET;
1476				break;
1477			case MSG_ABORT_TASK:
1478				io->taskio.task_action = CTL_TASK_ABORT_TASK;
1479				break;
1480			case MSG_LOGICAL_UNIT_RESET:
1481				io->taskio.task_action = CTL_TASK_LUN_RESET;
1482				break;
1483			case MSG_CLEAR_TASK_SET:
1484				io->taskio.task_action =
1485				    CTL_TASK_CLEAR_TASK_SET;
1486				break;
1487			case MSG_CLEAR_ACA:
1488				io->taskio.task_action = CTL_TASK_CLEAR_ACA;
1489				break;
1490			case MSG_QUERY_TASK:
1491				io->taskio.task_action = CTL_TASK_QUERY_TASK;
1492				break;
1493			case MSG_QUERY_TASK_SET:
1494				io->taskio.task_action =
1495				    CTL_TASK_QUERY_TASK_SET;
1496				break;
1497			case MSG_QUERY_ASYNC_EVENT:
1498				io->taskio.task_action =
1499				    CTL_TASK_QUERY_ASYNC_EVENT;
1500				break;
1501			case MSG_NOOP:
1502				send_ctl_io = 0;
1503				break;
1504			default:
1505				xpt_print(periph->path,
1506					  "%s: unsupported message 0x%x\n",
1507					  __func__, inot->arg);
1508				send_ctl_io = 0;
1509				break;
1510			}
1511			break;
1512		case CAM_REQ_ABORTED:
1513			/*
1514			 * This request was sent back by the driver.
1515			 * XXX KDM what do we do here?
1516			 */
1517			send_ctl_io = 0;
1518			break;
1519		case CAM_REQ_INVALID:
1520		case CAM_PROVIDE_FAIL:
1521		default:
1522			/*
1523			 * We should only get here if we're talking
1524			 * to a talking to a SIM that is target
1525			 * capable but supports the old API.  In
1526			 * that case, we need to just free the CCB.
1527			 * If we actually send a notify acknowledge,
1528			 * it will send that back with an error as
1529			 * well.
1530			 */
1531
1532			if ((status != CAM_REQ_INVALID)
1533			 && (status != CAM_PROVIDE_FAIL))
1534				xpt_print(periph->path,
1535					  "%s: unsupported CAM status 0x%x\n",
1536					  __func__, status);
1537
1538			ctlfe_free_ccb(periph, done_ccb);
1539
1540			goto out;
1541		}
1542		if (send_ctl_io != 0) {
1543			ctl_queue(io);
1544		} else {
1545			done_ccb->ccb_h.status = CAM_REQ_INPROG;
1546			done_ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
1547			xpt_action(done_ccb);
1548		}
1549		break;
1550	}
1551	case XPT_NOTIFY_ACKNOWLEDGE:
1552		/*
1553		 * Queue this back down to the SIM as an immediate notify.
1554		 */
1555		done_ccb->ccb_h.status = CAM_REQ_INPROG;
1556		done_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
1557		xpt_action(done_ccb);
1558		break;
1559	case XPT_SET_SIM_KNOB:
1560	case XPT_GET_SIM_KNOB:
1561		break;
1562	default:
1563		panic("%s: unexpected CCB type %#x", __func__,
1564		      done_ccb->ccb_h.func_code);
1565		break;
1566	}
1567
1568out:
1569	mtx_unlock(mtx);
1570}
1571
1572static void
1573ctlfe_onoffline(void *arg, int online)
1574{
1575	struct ctlfe_softc *bus_softc;
1576	union ccb *ccb;
1577	cam_status status;
1578	struct cam_path *path;
1579	int set_wwnn;
1580
1581	bus_softc = (struct ctlfe_softc *)arg;
1582
1583	set_wwnn = 0;
1584
1585	status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
1586		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
1587	if (status != CAM_REQ_CMP) {
1588		printf("%s: unable to create path!\n", __func__);
1589		return;
1590	}
1591	ccb = xpt_alloc_ccb();
1592	xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
1593	ccb->ccb_h.func_code = XPT_GET_SIM_KNOB;
1594	xpt_action(ccb);
1595
1596	/*
1597	 * Copan WWN format:
1598	 *
1599	 * Bits 63-60:	0x5		NAA, IEEE registered name
1600	 * Bits 59-36:	0x000ED5	IEEE Company name assigned to Copan
1601	 * Bits 35-12:			Copan SSN (Sequential Serial Number)
1602	 * Bits 11-8:			Type of port:
1603	 *					1 == N-Port
1604	 *					2 == F-Port
1605	 *					3 == NL-Port
1606	 * Bits 7-0:			0 == Node Name, >0 == Port Number
1607	 */
1608	if (online != 0) {
1609		if ((ccb->knob.xport_specific.valid & KNOB_VALID_ADDRESS) != 0){
1610#ifdef RANDOM_WWNN
1611			uint64_t random_bits;
1612#endif
1613
1614			printf("%s: %s current WWNN %#jx\n", __func__,
1615			       bus_softc->port_name,
1616			       ccb->knob.xport_specific.fc.wwnn);
1617			printf("%s: %s current WWPN %#jx\n", __func__,
1618			       bus_softc->port_name,
1619			       ccb->knob.xport_specific.fc.wwpn);
1620
1621#ifdef RANDOM_WWNN
1622			arc4rand(&random_bits, sizeof(random_bits), 0);
1623#endif
1624
1625			/*
1626			 * XXX KDM this is a bit of a kludge for now.  We
1627			 * take the current WWNN/WWPN from the card, and
1628			 * replace the company identifier and the NL-Port
1629			 * indicator and the port number (for the WWPN).
1630			 * This should be replaced later with ddb_GetWWNN,
1631			 * or possibly a more centralized scheme.  (It
1632			 * would be nice to have the WWNN/WWPN for each
1633			 * port stored in the ctl_port structure.)
1634			 */
1635#ifdef RANDOM_WWNN
1636			ccb->knob.xport_specific.fc.wwnn =
1637				(random_bits &
1638				0x0000000fffffff00ULL) |
1639				/* Company ID */ 0x5000ED5000000000ULL |
1640				/* NL-Port */    0x0300;
1641			ccb->knob.xport_specific.fc.wwpn =
1642				(random_bits &
1643				0x0000000fffffff00ULL) |
1644				/* Company ID */ 0x5000ED5000000000ULL |
1645				/* NL-Port */    0x3000 |
1646				/* Port Num */ (bus_softc->port.targ_port & 0xff);
1647
1648			/*
1649			 * This is a bit of an API break/reversal, but if
1650			 * we're doing the random WWNN that's a little
1651			 * different anyway.  So record what we're actually
1652			 * using with the frontend code so it's reported
1653			 * accurately.
1654			 */
1655			ctl_port_set_wwns(&bus_softc->port,
1656			    true, ccb->knob.xport_specific.fc.wwnn,
1657			    true, ccb->knob.xport_specific.fc.wwpn);
1658			set_wwnn = 1;
1659#else /* RANDOM_WWNN */
1660			/*
1661			 * If the user has specified a WWNN/WWPN, send them
1662			 * down to the SIM.  Otherwise, record what the SIM
1663			 * has reported.
1664			 */
1665			if (bus_softc->port.wwnn != 0 && bus_softc->port.wwnn
1666			    != ccb->knob.xport_specific.fc.wwnn) {
1667				ccb->knob.xport_specific.fc.wwnn =
1668				    bus_softc->port.wwnn;
1669				set_wwnn = 1;
1670			} else {
1671				ctl_port_set_wwns(&bus_softc->port,
1672				    true, ccb->knob.xport_specific.fc.wwnn,
1673				    false, 0);
1674			}
1675			if (bus_softc->port.wwpn != 0 && bus_softc->port.wwpn
1676			     != ccb->knob.xport_specific.fc.wwpn) {
1677				ccb->knob.xport_specific.fc.wwpn =
1678				    bus_softc->port.wwpn;
1679				set_wwnn = 1;
1680			} else {
1681				ctl_port_set_wwns(&bus_softc->port,
1682				    false, 0,
1683				    true, ccb->knob.xport_specific.fc.wwpn);
1684			}
1685#endif /* RANDOM_WWNN */
1686
1687
1688			if (set_wwnn != 0) {
1689				printf("%s: %s new WWNN %#jx\n", __func__,
1690				       bus_softc->port_name,
1691				ccb->knob.xport_specific.fc.wwnn);
1692				printf("%s: %s new WWPN %#jx\n", __func__,
1693				       bus_softc->port_name,
1694				       ccb->knob.xport_specific.fc.wwpn);
1695			}
1696		} else {
1697			printf("%s: %s has no valid WWNN/WWPN\n", __func__,
1698			       bus_softc->port_name);
1699		}
1700	}
1701	ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
1702	ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
1703	if (set_wwnn != 0)
1704		ccb->knob.xport_specific.valid |= KNOB_VALID_ADDRESS;
1705
1706	if (online != 0)
1707		ccb->knob.xport_specific.fc.role |= KNOB_ROLE_TARGET;
1708	else
1709		ccb->knob.xport_specific.fc.role &= ~KNOB_ROLE_TARGET;
1710
1711	xpt_action(ccb);
1712
1713	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1714		printf("%s: SIM %s (path id %d) target %s failed with "
1715		       "status %#x\n",
1716		       __func__, bus_softc->port_name, bus_softc->path_id,
1717		       (online != 0) ? "enable" : "disable",
1718		       ccb->ccb_h.status);
1719	} else {
1720		printf("%s: SIM %s (path id %d) target %s succeeded\n",
1721		       __func__, bus_softc->port_name, bus_softc->path_id,
1722		       (online != 0) ? "enable" : "disable");
1723	}
1724
1725	xpt_free_path(path);
1726	xpt_free_ccb(ccb);
1727}
1728
1729static void
1730ctlfe_online(void *arg)
1731{
1732	struct ctlfe_softc *bus_softc;
1733	struct cam_path *path;
1734	cam_status status;
1735	struct ctlfe_lun_softc *lun_softc;
1736	struct cam_periph *periph;
1737
1738	bus_softc = (struct ctlfe_softc *)arg;
1739
1740	/*
1741	 * Create the wildcard LUN before bringing the port online.
1742	 */
1743	status = xpt_create_path(&path, /*periph*/ NULL,
1744				 bus_softc->path_id, CAM_TARGET_WILDCARD,
1745				 CAM_LUN_WILDCARD);
1746	if (status != CAM_REQ_CMP) {
1747		printf("%s: unable to create path for wildcard periph\n",
1748				__func__);
1749		return;
1750	}
1751
1752	lun_softc = malloc(sizeof(*lun_softc), M_CTLFE, M_WAITOK | M_ZERO);
1753
1754	xpt_path_lock(path);
1755	periph = cam_periph_find(path, "ctl");
1756	if (periph != NULL) {
1757		/* We've already got a periph, no need to alloc a new one. */
1758		xpt_path_unlock(path);
1759		xpt_free_path(path);
1760		free(lun_softc, M_CTLFE);
1761		return;
1762	}
1763	lun_softc->parent_softc = bus_softc;
1764	lun_softc->flags |= CTLFE_LUN_WILDCARD;
1765
1766	status = cam_periph_alloc(ctlferegister,
1767				  ctlfeoninvalidate,
1768				  ctlfecleanup,
1769				  ctlfestart,
1770				  "ctl",
1771				  CAM_PERIPH_BIO,
1772				  path,
1773				  ctlfeasync,
1774				  0,
1775				  lun_softc);
1776
1777	if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1778		const struct cam_status_entry *entry;
1779
1780		entry = cam_fetch_status_entry(status);
1781		printf("%s: CAM error %s (%#x) returned from "
1782		       "cam_periph_alloc()\n", __func__, (entry != NULL) ?
1783		       entry->status_text : "Unknown", status);
1784		free(lun_softc, M_CTLFE);
1785	}
1786
1787	xpt_path_unlock(path);
1788	ctlfe_onoffline(arg, /*online*/ 1);
1789	xpt_free_path(path);
1790}
1791
1792static void
1793ctlfe_offline(void *arg)
1794{
1795	struct ctlfe_softc *bus_softc;
1796	struct cam_path *path;
1797	cam_status status;
1798	struct cam_periph *periph;
1799
1800	bus_softc = (struct ctlfe_softc *)arg;
1801
1802	ctlfe_onoffline(arg, /*online*/ 0);
1803
1804	/*
1805	 * Disable the wildcard LUN for this port now that we have taken
1806	 * the port offline.
1807	 */
1808	status = xpt_create_path(&path, /*periph*/ NULL,
1809				 bus_softc->path_id, CAM_TARGET_WILDCARD,
1810				 CAM_LUN_WILDCARD);
1811	if (status != CAM_REQ_CMP) {
1812		printf("%s: unable to create path for wildcard periph\n",
1813		       __func__);
1814		return;
1815	}
1816	xpt_path_lock(path);
1817	if ((periph = cam_periph_find(path, "ctl")) != NULL)
1818		cam_periph_invalidate(periph);
1819	xpt_path_unlock(path);
1820	xpt_free_path(path);
1821}
1822
1823/*
1824 * This will get called to enable a LUN on every bus that is attached to
1825 * CTL.  So we only need to create a path/periph for this particular bus.
1826 */
1827static int
1828ctlfe_lun_enable(void *arg, int lun_id)
1829{
1830	struct ctlfe_softc *bus_softc;
1831	struct ctlfe_lun_softc *softc;
1832	struct cam_path *path;
1833	struct cam_periph *periph;
1834	cam_status status;
1835
1836	bus_softc = (struct ctlfe_softc *)arg;
1837	if (bus_softc->hba_misc & PIM_EXTLUNS)
1838		lun_id = CAM_EXTLUN_BYTE_SWIZZLE(ctl_encode_lun(lun_id));
1839
1840	status = xpt_create_path(&path, /*periph*/ NULL,
1841	    bus_softc->path_id, bus_softc->target_id, lun_id);
1842	/* XXX KDM need some way to return status to CTL here? */
1843	if (status != CAM_REQ_CMP) {
1844		printf("%s: could not create path, status %#x\n", __func__,
1845		       status);
1846		return (1);
1847	}
1848
1849	softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO);
1850	xpt_path_lock(path);
1851	periph = cam_periph_find(path, "ctl");
1852	if (periph != NULL) {
1853		/* We've already got a periph, no need to alloc a new one. */
1854		xpt_path_unlock(path);
1855		xpt_free_path(path);
1856		free(softc, M_CTLFE);
1857		return (0);
1858	}
1859	softc->parent_softc = bus_softc;
1860
1861	status = cam_periph_alloc(ctlferegister,
1862				  ctlfeoninvalidate,
1863				  ctlfecleanup,
1864				  ctlfestart,
1865				  "ctl",
1866				  CAM_PERIPH_BIO,
1867				  path,
1868				  ctlfeasync,
1869				  0,
1870				  softc);
1871
1872	if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1873		const struct cam_status_entry *entry;
1874
1875		entry = cam_fetch_status_entry(status);
1876		printf("%s: CAM error %s (%#x) returned from "
1877		       "cam_periph_alloc()\n", __func__, (entry != NULL) ?
1878		       entry->status_text : "Unknown", status);
1879		free(softc, M_CTLFE);
1880	}
1881
1882	xpt_path_unlock(path);
1883	xpt_free_path(path);
1884	return (0);
1885}
1886
1887/*
1888 * This will get called when the user removes a LUN to disable that LUN
1889 * on every bus that is attached to CTL.
1890 */
1891static int
1892ctlfe_lun_disable(void *arg, int lun_id)
1893{
1894	struct ctlfe_softc *softc;
1895	struct ctlfe_lun_softc *lun_softc;
1896
1897	softc = (struct ctlfe_softc *)arg;
1898	if (softc->hba_misc & PIM_EXTLUNS)
1899		lun_id = CAM_EXTLUN_BYTE_SWIZZLE(ctl_encode_lun(lun_id));
1900
1901	mtx_lock(&softc->lun_softc_mtx);
1902	STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {
1903		struct cam_path *path;
1904
1905		path = lun_softc->periph->path;
1906
1907		if ((xpt_path_target_id(path) == softc->target_id)
1908		 && (xpt_path_lun_id(path) == lun_id)) {
1909			break;
1910		}
1911	}
1912	if (lun_softc == NULL) {
1913		mtx_unlock(&softc->lun_softc_mtx);
1914		printf("%s: can't find lun %d\n", __func__, lun_id);
1915		return (1);
1916	}
1917	cam_periph_acquire(lun_softc->periph);
1918	mtx_unlock(&softc->lun_softc_mtx);
1919
1920	cam_periph_lock(lun_softc->periph);
1921	cam_periph_invalidate(lun_softc->periph);
1922	cam_periph_unlock(lun_softc->periph);
1923	cam_periph_release(lun_softc->periph);
1924	return (0);
1925}
1926
1927static void
1928ctlfe_dump_sim(struct cam_sim *sim)
1929{
1930
1931	printf("%s%d: max tagged openings: %d, max dev openings: %d\n",
1932	       sim->sim_name, sim->unit_number,
1933	       sim->max_tagged_dev_openings, sim->max_dev_openings);
1934}
1935
1936/*
1937 * Assumes that the SIM lock is held.
1938 */
1939static void
1940ctlfe_dump_queue(struct ctlfe_lun_softc *softc)
1941{
1942	struct ccb_hdr *hdr;
1943	struct cam_periph *periph;
1944	int num_items;
1945
1946	periph = softc->periph;
1947	num_items = 0;
1948
1949	TAILQ_FOREACH(hdr, &softc->work_queue, periph_links.tqe) {
1950		union ctl_io *io = hdr->io_ptr;
1951
1952		num_items++;
1953
1954		/*
1955		 * Only regular SCSI I/O is put on the work
1956		 * queue, so we can print sense here.  There may be no
1957		 * sense if it's no the queue for a DMA, but this serves to
1958		 * print out the CCB as well.
1959		 *
1960		 * XXX KDM switch this over to scsi_sense_print() when
1961		 * CTL is merged in with CAM.
1962		 */
1963		ctl_io_error_print(io, NULL);
1964
1965		/*
1966		 * Print DMA status if we are DMA_QUEUED.
1967		 */
1968		if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) {
1969			xpt_print(periph->path,
1970			    "Total %u, Current %u, Resid %u\n",
1971			    io->scsiio.kern_total_len,
1972			    io->scsiio.kern_data_len,
1973			    io->scsiio.kern_data_resid);
1974		}
1975	}
1976
1977	xpt_print(periph->path, "%d requests total waiting for CCBs\n",
1978		  num_items);
1979	xpt_print(periph->path, "%ju CCBs outstanding (%ju allocated, %ju "
1980		  "freed)\n", (uintmax_t)(softc->ccbs_alloced -
1981		  softc->ccbs_freed), (uintmax_t)softc->ccbs_alloced,
1982		  (uintmax_t)softc->ccbs_freed);
1983	xpt_print(periph->path, "%ju CTIOs outstanding (%ju sent, %ju "
1984		  "returned\n", (uintmax_t)(softc->ctios_sent -
1985		  softc->ctios_returned), softc->ctios_sent,
1986		  softc->ctios_returned);
1987}
1988
1989/*
1990 * Datamove/done routine called by CTL.  Put ourselves on the queue to
1991 * receive a CCB from CAM so we can queue the continue I/O request down
1992 * to the adapter.
1993 */
1994static void
1995ctlfe_datamove(union ctl_io *io)
1996{
1997	union ccb *ccb;
1998	struct cam_periph *periph;
1999	struct ctlfe_lun_softc *softc;
2000
2001	KASSERT(io->io_hdr.io_type == CTL_IO_SCSI,
2002	    ("Unexpected io_type (%d) in ctlfe_datamove", io->io_hdr.io_type));
2003
2004	io->scsiio.ext_data_filled = 0;
2005	ccb = PRIV_CCB(io);
2006	periph = xpt_path_periph(ccb->ccb_h.path);
2007	cam_periph_lock(periph);
2008	softc = (struct ctlfe_lun_softc *)periph->softc;
2009	io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED;
2010	if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE)
2011		io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED;
2012	TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h,
2013			  periph_links.tqe);
2014	xpt_schedule(periph, /*priority*/ 1);
2015	cam_periph_unlock(periph);
2016}
2017
2018static void
2019ctlfe_done(union ctl_io *io)
2020{
2021	union ccb *ccb;
2022	struct cam_periph *periph;
2023	struct ctlfe_lun_softc *softc;
2024
2025	ccb = PRIV_CCB(io);
2026	periph = xpt_path_periph(ccb->ccb_h.path);
2027	cam_periph_lock(periph);
2028	softc = (struct ctlfe_lun_softc *)periph->softc;
2029
2030	if (io->io_hdr.io_type == CTL_IO_TASK) {
2031		/*
2032		 * Task management commands don't require any further
2033		 * communication back to the adapter.  Requeue the CCB
2034		 * to the adapter, and free the CTL I/O.
2035		 */
2036		xpt_print(ccb->ccb_h.path, "%s: returning task I/O "
2037			  "tag %#x seq %#x\n", __func__,
2038			  ccb->cin1.tag_id, ccb->cin1.seq_id);
2039		/*
2040		 * Send the notify acknowledge down to the SIM, to let it
2041		 * know we processed the task management command.
2042		 */
2043		ccb->ccb_h.status = CAM_REQ_INPROG;
2044		ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
2045		switch (io->taskio.task_status) {
2046		case CTL_TASK_FUNCTION_COMPLETE:
2047			ccb->cna2.arg = CAM_RSP_TMF_COMPLETE;
2048			break;
2049		case CTL_TASK_FUNCTION_SUCCEEDED:
2050			ccb->cna2.arg = CAM_RSP_TMF_SUCCEEDED;
2051			ccb->ccb_h.flags |= CAM_SEND_STATUS;
2052			break;
2053		case CTL_TASK_FUNCTION_REJECTED:
2054			ccb->cna2.arg = CAM_RSP_TMF_REJECTED;
2055			ccb->ccb_h.flags |= CAM_SEND_STATUS;
2056			break;
2057		case CTL_TASK_LUN_DOES_NOT_EXIST:
2058			ccb->cna2.arg = CAM_RSP_TMF_INCORRECT_LUN;
2059			ccb->ccb_h.flags |= CAM_SEND_STATUS;
2060			break;
2061		case CTL_TASK_FUNCTION_NOT_SUPPORTED:
2062			ccb->cna2.arg = CAM_RSP_TMF_FAILED;
2063			ccb->ccb_h.flags |= CAM_SEND_STATUS;
2064			break;
2065		}
2066		ccb->cna2.arg |= scsi_3btoul(io->taskio.task_resp) << 8;
2067		xpt_action(ccb);
2068	} else if (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) {
2069		if (softc->flags & CTLFE_LUN_WILDCARD) {
2070			ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
2071			ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
2072		}
2073		if (periph->flags & CAM_PERIPH_INVALID) {
2074			ctlfe_free_ccb(periph, ccb);
2075		} else {
2076			cam_periph_unlock(periph);
2077			xpt_action(ccb);
2078			return;
2079		}
2080	} else {
2081		io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED;
2082		TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h,
2083				  periph_links.tqe);
2084		xpt_schedule(periph, /*priority*/ 1);
2085	}
2086
2087	cam_periph_unlock(periph);
2088}
2089
2090static void
2091ctlfe_dump(void)
2092{
2093	struct ctlfe_softc *bus_softc;
2094	struct ctlfe_lun_softc *lun_softc;
2095
2096	STAILQ_FOREACH(bus_softc, &ctlfe_softc_list, links) {
2097		ctlfe_dump_sim(bus_softc->sim);
2098		STAILQ_FOREACH(lun_softc, &bus_softc->lun_softc_list, links)
2099			ctlfe_dump_queue(lun_softc);
2100	}
2101}
2102