1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2016 The FreeBSD Foundation
5 *
6 * This software was developed by Edward Tomasz Napierala under sponsorship
7 * from the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31/*
32 * USB Mass Storage Class Bulk-Only (BBB) Transport target.
33 *
34 * http://www.usb.org/developers/docs/devclass_docs/usbmassbulk_10.pdf
35 *
36 * This code implements the USB Mass Storage frontend driver for the CAM
37 * Target Layer (ctl(4)) subsystem.
38 */
39
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD$");
42
43#include <sys/param.h>
44#include <sys/bus.h>
45#include <sys/kernel.h>
46#include <sys/lock.h>
47#include <sys/module.h>
48#include <sys/mutex.h>
49#include <sys/refcount.h>
50#include <sys/stdint.h>
51#include <sys/sysctl.h>
52#include <sys/systm.h>
53
54#include <dev/usb/usb.h>
55#include <dev/usb/usbdi.h>
56#include "usbdevs.h"
57#include "usb_if.h"
58
59#include <cam/scsi/scsi_all.h>
60#include <cam/scsi/scsi_da.h>
61#include <cam/ctl/ctl_io.h>
62#include <cam/ctl/ctl.h>
63#include <cam/ctl/ctl_backend.h>
64#include <cam/ctl/ctl_error.h>
65#include <cam/ctl/ctl_frontend.h>
66#include <cam/ctl/ctl_debug.h>
67#include <cam/ctl/ctl_ha.h>
68#include <cam/ctl/ctl_ioctl.h>
69#include <cam/ctl/ctl_private.h>
70
71SYSCTL_NODE(_hw_usb, OID_AUTO, cfumass, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
72    "CAM Target Layer USB Mass Storage Frontend");
73static int debug = 1;
74SYSCTL_INT(_hw_usb_cfumass, OID_AUTO, debug, CTLFLAG_RWTUN,
75    &debug, 1, "Enable debug messages");
76static int max_lun = 0;
77SYSCTL_INT(_hw_usb_cfumass, OID_AUTO, max_lun, CTLFLAG_RWTUN,
78    &max_lun, 1, "Maximum advertised LUN number");
79static int ignore_stop = 1;
80SYSCTL_INT(_hw_usb_cfumass, OID_AUTO, ignore_stop, CTLFLAG_RWTUN,
81    &ignore_stop, 1, "Ignore START STOP UNIT with START and LOEJ bits cleared");
82
83/*
84 * The driver uses a single, global CTL port.  It could create its ports
85 * in cfumass_attach() instead, but that would make it impossible to specify
86 * "port cfumass0" in ctl.conf(5), as the port generally wouldn't exist
87 * at the time ctld(8) gets run.
88 */
89struct ctl_port	cfumass_port;
90bool		cfumass_port_online;
91volatile u_int	cfumass_refcount;
92
93#ifndef CFUMASS_BULK_SIZE
94#define	CFUMASS_BULK_SIZE	(1U << 17)	/* bytes */
95#endif
96
97/*
98 * USB transfer definitions.
99 */
100#define	CFUMASS_T_COMMAND	0
101#define	CFUMASS_T_DATA_OUT	1
102#define	CFUMASS_T_DATA_IN	2
103#define	CFUMASS_T_STATUS	3
104#define	CFUMASS_T_MAX		4
105
106/*
107 * USB interface specific control requests.
108 */
109#define	UR_RESET	0xff	/* Bulk-Only Mass Storage Reset */
110#define	UR_GET_MAX_LUN	0xfe	/* Get Max LUN */
111
112/*
113 * Command Block Wrapper.
114 */
115struct cfumass_cbw_t {
116	uDWord	dCBWSignature;
117#define	CBWSIGNATURE		0x43425355 /* "USBC" */
118	uDWord	dCBWTag;
119	uDWord	dCBWDataTransferLength;
120	uByte	bCBWFlags;
121#define	CBWFLAGS_OUT		0x00
122#define	CBWFLAGS_IN		0x80
123	uByte	bCBWLUN;
124	uByte	bCDBLength;
125#define	CBWCBLENGTH		16
126	uByte	CBWCB[CBWCBLENGTH];
127} __packed;
128
129#define	CFUMASS_CBW_SIZE	31
130CTASSERT(sizeof(struct cfumass_cbw_t) == CFUMASS_CBW_SIZE);
131
132/*
133 * Command Status Wrapper.
134 */
135struct cfumass_csw_t {
136	uDWord	dCSWSignature;
137#define	CSWSIGNATURE		0x53425355 /* "USBS" */
138	uDWord	dCSWTag;
139	uDWord	dCSWDataResidue;
140	uByte	bCSWStatus;
141#define	CSWSTATUS_GOOD		0x0
142#define	CSWSTATUS_FAILED	0x1
143#define	CSWSTATUS_PHASE		0x2
144} __packed;
145
146#define	CFUMASS_CSW_SIZE	13
147CTASSERT(sizeof(struct cfumass_csw_t) == CFUMASS_CSW_SIZE);
148
149struct cfumass_softc {
150	device_t		sc_dev;
151	struct usb_device	*sc_udev;
152	struct usb_xfer		*sc_xfer[CFUMASS_T_MAX];
153
154	struct cfumass_cbw_t *sc_cbw;
155	struct cfumass_csw_t *sc_csw;
156
157	struct mtx	sc_mtx;
158	int		sc_online;
159	int		sc_ctl_initid;
160
161	/*
162	 * This is used to communicate between CTL callbacks
163	 * and USB callbacks; basically, it holds the state
164	 * for the current command ("the" command, since there
165	 * is no queueing in USB Mass Storage).
166	 */
167	bool		sc_current_stalled;
168
169	/*
170	 * The following are set upon receiving a SCSI command.
171	 */
172	int		sc_current_tag;
173	int		sc_current_transfer_length;
174	int		sc_current_flags;
175
176	/*
177	 * The following are set in ctl_datamove().
178	 */
179	int		sc_current_residue;
180	union ctl_io	*sc_ctl_io;
181
182	/*
183	 * The following is set in cfumass_done().
184	 */
185	int		sc_current_status;
186
187	/*
188	 * Number of requests queued to CTL.
189	 */
190	volatile u_int	sc_queued;
191};
192
193/*
194 * USB interface.
195 */
196static device_probe_t		cfumass_probe;
197static device_attach_t		cfumass_attach;
198static device_detach_t		cfumass_detach;
199static device_suspend_t		cfumass_suspend;
200static device_resume_t		cfumass_resume;
201static usb_handle_request_t	cfumass_handle_request;
202
203static usb_callback_t		cfumass_t_command_callback;
204static usb_callback_t		cfumass_t_data_callback;
205static usb_callback_t		cfumass_t_status_callback;
206
207static device_method_t cfumass_methods[] = {
208	/* USB interface. */
209	DEVMETHOD(usb_handle_request, cfumass_handle_request),
210
211	/* Device interface. */
212	DEVMETHOD(device_probe, cfumass_probe),
213	DEVMETHOD(device_attach, cfumass_attach),
214	DEVMETHOD(device_detach, cfumass_detach),
215	DEVMETHOD(device_suspend, cfumass_suspend),
216	DEVMETHOD(device_resume, cfumass_resume),
217
218	DEVMETHOD_END
219};
220
221static driver_t cfumass_driver = {
222	.name = "cfumass",
223	.methods = cfumass_methods,
224	.size = sizeof(struct cfumass_softc),
225};
226
227static devclass_t cfumass_devclass;
228
229DRIVER_MODULE(cfumass, uhub, cfumass_driver, cfumass_devclass, NULL, 0);
230MODULE_VERSION(cfumass, 0);
231MODULE_DEPEND(cfumass, usb, 1, 1, 1);
232MODULE_DEPEND(cfumass, usb_template, 1, 1, 1);
233
234static struct usb_config cfumass_config[CFUMASS_T_MAX] = {
235	[CFUMASS_T_COMMAND] = {
236		.type = UE_BULK,
237		.endpoint = UE_ADDR_ANY,
238		.direction = UE_DIR_OUT,
239		.bufsize = sizeof(struct cfumass_cbw_t),
240		.callback = &cfumass_t_command_callback,
241		.usb_mode = USB_MODE_DEVICE,
242	},
243
244	[CFUMASS_T_DATA_OUT] = {
245		.type = UE_BULK,
246		.endpoint = UE_ADDR_ANY,
247		.direction = UE_DIR_OUT,
248		.bufsize = CFUMASS_BULK_SIZE,
249		.flags = {.proxy_buffer = 1, .short_xfer_ok = 1,
250		    .ext_buffer = 1},
251		.callback = &cfumass_t_data_callback,
252		.usb_mode = USB_MODE_DEVICE,
253	},
254
255	[CFUMASS_T_DATA_IN] = {
256		.type = UE_BULK,
257		.endpoint = UE_ADDR_ANY,
258		.direction = UE_DIR_IN,
259		.bufsize = CFUMASS_BULK_SIZE,
260		.flags = {.proxy_buffer = 1, .short_xfer_ok = 1,
261		    .ext_buffer = 1},
262		.callback = &cfumass_t_data_callback,
263		.usb_mode = USB_MODE_DEVICE,
264	},
265
266	[CFUMASS_T_STATUS] = {
267		.type = UE_BULK,
268		.endpoint = UE_ADDR_ANY,
269		.direction = UE_DIR_IN,
270		.bufsize = sizeof(struct cfumass_csw_t),
271		.flags = {.short_xfer_ok = 1},
272		.callback = &cfumass_t_status_callback,
273		.usb_mode = USB_MODE_DEVICE,
274	},
275};
276
277/*
278 * CTL frontend interface.
279 */
280static int	cfumass_init(void);
281static int	cfumass_shutdown(void);
282static void	cfumass_online(void *arg);
283static void	cfumass_offline(void *arg);
284static void	cfumass_datamove(union ctl_io *io);
285static void	cfumass_done(union ctl_io *io);
286
287static struct ctl_frontend cfumass_frontend = {
288	.name = "umass",
289	.init = cfumass_init,
290	.shutdown = cfumass_shutdown,
291};
292CTL_FRONTEND_DECLARE(ctlcfumass, cfumass_frontend);
293
294#define	CFUMASS_DEBUG(S, X, ...)					\
295	do {								\
296		if (debug > 1) {					\
297			device_printf(S->sc_dev, "%s: " X "\n",		\
298			    __func__, ## __VA_ARGS__);			\
299		}							\
300	} while (0)
301
302#define	CFUMASS_WARN(S, X, ...)						\
303	do {								\
304		if (debug > 0) {					\
305			device_printf(S->sc_dev, "WARNING: %s: " X "\n",\
306			    __func__, ## __VA_ARGS__);			\
307		}							\
308	} while (0)
309
310#define CFUMASS_LOCK(X)		mtx_lock(&X->sc_mtx)
311#define CFUMASS_UNLOCK(X)	mtx_unlock(&X->sc_mtx)
312
313static void	cfumass_transfer_start(struct cfumass_softc *sc,
314		    uint8_t xfer_index);
315static void	cfumass_terminate(struct cfumass_softc *sc);
316
317static int
318cfumass_probe(device_t dev)
319{
320	struct usb_attach_arg *uaa;
321	struct usb_interface_descriptor *id;
322
323	uaa = device_get_ivars(dev);
324
325	if (uaa->usb_mode != USB_MODE_DEVICE)
326		return (ENXIO);
327
328	/*
329	 * Check for a compliant device.
330	 */
331	id = usbd_get_interface_descriptor(uaa->iface);
332	if ((id == NULL) ||
333	    (id->bInterfaceClass != UICLASS_MASS) ||
334	    (id->bInterfaceSubClass != UISUBCLASS_SCSI) ||
335	    (id->bInterfaceProtocol != UIPROTO_MASS_BBB)) {
336		return (ENXIO);
337	}
338
339	return (BUS_PROBE_GENERIC);
340}
341
342static int
343cfumass_attach(device_t dev)
344{
345	struct cfumass_softc *sc;
346	struct usb_attach_arg *uaa;
347	int error;
348
349	sc = device_get_softc(dev);
350	uaa = device_get_ivars(dev);
351
352	sc->sc_dev = dev;
353	sc->sc_udev = uaa->device;
354
355	CFUMASS_DEBUG(sc, "go");
356
357	usbd_set_power_mode(uaa->device, USB_POWER_MODE_SAVE);
358	device_set_usb_desc(dev);
359
360	mtx_init(&sc->sc_mtx, "cfumass", NULL, MTX_DEF);
361	refcount_acquire(&cfumass_refcount);
362
363	error = usbd_transfer_setup(uaa->device,
364	    &uaa->info.bIfaceIndex, sc->sc_xfer, cfumass_config,
365	    CFUMASS_T_MAX, sc, &sc->sc_mtx);
366	if (error != 0) {
367		CFUMASS_WARN(sc, "usbd_transfer_setup() failed: %s",
368		    usbd_errstr(error));
369		refcount_release(&cfumass_refcount);
370		return (ENXIO);
371	}
372
373	sc->sc_cbw =
374	    usbd_xfer_get_frame_buffer(sc->sc_xfer[CFUMASS_T_COMMAND], 0);
375	sc->sc_csw =
376	    usbd_xfer_get_frame_buffer(sc->sc_xfer[CFUMASS_T_STATUS], 0);
377
378	sc->sc_ctl_initid = ctl_add_initiator(&cfumass_port, -1, 0, NULL);
379	if (sc->sc_ctl_initid < 0) {
380		CFUMASS_WARN(sc, "ctl_add_initiator() failed with error %d",
381		    sc->sc_ctl_initid);
382		usbd_transfer_unsetup(sc->sc_xfer, CFUMASS_T_MAX);
383		refcount_release(&cfumass_refcount);
384		return (ENXIO);
385	}
386
387	refcount_init(&sc->sc_queued, 0);
388
389	CFUMASS_LOCK(sc);
390	cfumass_transfer_start(sc, CFUMASS_T_COMMAND);
391	CFUMASS_UNLOCK(sc);
392
393	return (0);
394}
395
396static int
397cfumass_detach(device_t dev)
398{
399	struct cfumass_softc *sc;
400	int error;
401
402	sc = device_get_softc(dev);
403
404	CFUMASS_DEBUG(sc, "go");
405
406	CFUMASS_LOCK(sc);
407	cfumass_terminate(sc);
408	CFUMASS_UNLOCK(sc);
409	usbd_transfer_unsetup(sc->sc_xfer, CFUMASS_T_MAX);
410
411	if (sc->sc_ctl_initid != -1) {
412		error = ctl_remove_initiator(&cfumass_port, sc->sc_ctl_initid);
413		if (error != 0) {
414			CFUMASS_WARN(sc, "ctl_remove_initiator() failed "
415			    "with error %d", error);
416		}
417		sc->sc_ctl_initid = -1;
418	}
419
420	mtx_destroy(&sc->sc_mtx);
421	refcount_release(&cfumass_refcount);
422
423	return (0);
424}
425
426static int
427cfumass_suspend(device_t dev)
428{
429	struct cfumass_softc *sc;
430
431	sc = device_get_softc(dev);
432	CFUMASS_DEBUG(sc, "go");
433
434	return (0);
435}
436
437static int
438cfumass_resume(device_t dev)
439{
440	struct cfumass_softc *sc;
441
442	sc = device_get_softc(dev);
443	CFUMASS_DEBUG(sc, "go");
444
445	return (0);
446}
447
448static void
449cfumass_transfer_start(struct cfumass_softc *sc, uint8_t xfer_index)
450{
451
452	usbd_transfer_start(sc->sc_xfer[xfer_index]);
453}
454
455static void
456cfumass_transfer_stop_and_drain(struct cfumass_softc *sc, uint8_t xfer_index)
457{
458
459	usbd_transfer_stop(sc->sc_xfer[xfer_index]);
460	CFUMASS_UNLOCK(sc);
461	usbd_transfer_drain(sc->sc_xfer[xfer_index]);
462	CFUMASS_LOCK(sc);
463}
464
465static void
466cfumass_terminate(struct cfumass_softc *sc)
467{
468	int last;
469
470	for (;;) {
471		cfumass_transfer_stop_and_drain(sc, CFUMASS_T_COMMAND);
472		cfumass_transfer_stop_and_drain(sc, CFUMASS_T_DATA_IN);
473		cfumass_transfer_stop_and_drain(sc, CFUMASS_T_DATA_OUT);
474
475		if (sc->sc_ctl_io != NULL) {
476			CFUMASS_DEBUG(sc, "terminating CTL transfer");
477			ctl_set_data_phase_error(&sc->sc_ctl_io->scsiio);
478			ctl_datamove_done(sc->sc_ctl_io, false);
479			sc->sc_ctl_io = NULL;
480		}
481
482		cfumass_transfer_stop_and_drain(sc, CFUMASS_T_STATUS);
483
484		refcount_acquire(&sc->sc_queued);
485		last = refcount_release(&sc->sc_queued);
486		if (last != 0)
487			break;
488
489		CFUMASS_DEBUG(sc, "%d CTL tasks pending", sc->sc_queued);
490		msleep(__DEVOLATILE(void *, &sc->sc_queued), &sc->sc_mtx,
491		    0, "cfumass_reset", hz / 100);
492	}
493}
494
495static int
496cfumass_handle_request(device_t dev,
497    const void *preq, void **pptr, uint16_t *plen,
498    uint16_t offset, uint8_t *pstate)
499{
500	static uint8_t max_lun_tmp;
501	struct cfumass_softc *sc;
502	const struct usb_device_request *req;
503	uint8_t is_complete;
504
505	sc = device_get_softc(dev);
506	req = preq;
507	is_complete = *pstate;
508
509	CFUMASS_DEBUG(sc, "go");
510
511	if (is_complete)
512		return (ENXIO);
513
514	if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
515	    (req->bRequest == UR_RESET)) {
516		CFUMASS_WARN(sc, "received Bulk-Only Mass Storage Reset");
517		*plen = 0;
518
519		CFUMASS_LOCK(sc);
520		cfumass_terminate(sc);
521		cfumass_transfer_start(sc, CFUMASS_T_COMMAND);
522		CFUMASS_UNLOCK(sc);
523
524		CFUMASS_DEBUG(sc, "Bulk-Only Mass Storage Reset done");
525		return (0);
526	}
527
528	if ((req->bmRequestType == UT_READ_CLASS_INTERFACE) &&
529	    (req->bRequest == UR_GET_MAX_LUN)) {
530		CFUMASS_DEBUG(sc, "received Get Max LUN");
531		if (offset == 0) {
532			*plen = 1;
533			/*
534			 * The protocol doesn't support LUN numbers higher
535			 * than 15.  Also, some initiators (namely Windows XP
536			 * SP3 Version 2002) can't properly query the number
537			 * of LUNs, resulting in inaccessible "fake" ones - thus
538			 * the default limit of one LUN.
539			 */
540			if (max_lun < 0 || max_lun > 15) {
541				CFUMASS_WARN(sc,
542				    "invalid hw.usb.cfumass.max_lun, must be "
543				    "between 0 and 15; defaulting to 0");
544				max_lun_tmp = 0;
545			} else {
546				max_lun_tmp = max_lun;
547			}
548			*pptr = &max_lun_tmp;
549		} else {
550			*plen = 0;
551		}
552		return (0);
553	}
554
555	return (ENXIO);
556}
557
558static int
559cfumass_quirk(struct cfumass_softc *sc, unsigned char *cdb, int cdb_len)
560{
561	struct scsi_start_stop_unit *sssu;
562
563	switch (cdb[0]) {
564	case START_STOP_UNIT:
565		/*
566		 * Some initiators - eg OSX, Darwin Kernel Version 15.6.0,
567		 * root:xnu-3248.60.11~2/RELEASE_X86_64 - attempt to stop
568		 * the unit on eject, but fail to start it when it's plugged
569		 * back.  Just ignore the command.
570		 */
571
572		if (cdb_len < sizeof(*sssu)) {
573			CFUMASS_DEBUG(sc, "received START STOP UNIT with "
574			    "bCDBLength %d, should be %zd",
575			    cdb_len, sizeof(*sssu));
576			break;
577		}
578
579		sssu = (struct scsi_start_stop_unit *)cdb;
580		if ((sssu->how & SSS_PC_MASK) != 0)
581			break;
582
583		if ((sssu->how & SSS_START) != 0)
584			break;
585
586		if ((sssu->how & SSS_LOEJ) != 0)
587			break;
588
589		if (ignore_stop == 0) {
590			break;
591		} else if (ignore_stop == 1) {
592			CFUMASS_WARN(sc, "ignoring START STOP UNIT request");
593		} else {
594			CFUMASS_DEBUG(sc, "ignoring START STOP UNIT request");
595		}
596
597		sc->sc_current_status = 0;
598		cfumass_transfer_start(sc, CFUMASS_T_STATUS);
599
600		return (1);
601	default:
602		break;
603	}
604
605	return (0);
606}
607
608static void
609cfumass_t_command_callback(struct usb_xfer *xfer, usb_error_t usb_error)
610{
611	struct cfumass_softc *sc;
612	uint32_t signature;
613	union ctl_io *io;
614	int error = 0;
615
616	sc = usbd_xfer_softc(xfer);
617
618	KASSERT(sc->sc_ctl_io == NULL,
619	    ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io));
620
621	switch (USB_GET_STATE(xfer)) {
622	case USB_ST_TRANSFERRED:
623		CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED");
624
625		signature = UGETDW(sc->sc_cbw->dCBWSignature);
626		if (signature != CBWSIGNATURE) {
627			CFUMASS_WARN(sc, "wrong dCBWSignature 0x%08x, "
628			    "should be 0x%08x", signature, CBWSIGNATURE);
629			break;
630		}
631
632		if (sc->sc_cbw->bCDBLength <= 0 ||
633		    sc->sc_cbw->bCDBLength > sizeof(sc->sc_cbw->CBWCB)) {
634			CFUMASS_WARN(sc, "invalid bCDBLength %d, should be <= %zd",
635			    sc->sc_cbw->bCDBLength, sizeof(sc->sc_cbw->CBWCB));
636			break;
637		}
638
639		sc->sc_current_stalled = false;
640		sc->sc_current_status = 0;
641		sc->sc_current_tag = UGETDW(sc->sc_cbw->dCBWTag);
642		sc->sc_current_transfer_length =
643		    UGETDW(sc->sc_cbw->dCBWDataTransferLength);
644		sc->sc_current_flags = sc->sc_cbw->bCBWFlags;
645
646		/*
647		 * Make sure to report proper residue if the datamove wasn't
648		 * required, or wasn't called due to SCSI error.
649		 */
650		sc->sc_current_residue = sc->sc_current_transfer_length;
651
652		if (cfumass_quirk(sc,
653		    sc->sc_cbw->CBWCB, sc->sc_cbw->bCDBLength) != 0)
654			break;
655
656		if (!cfumass_port_online) {
657			CFUMASS_DEBUG(sc, "cfumass port is offline; stalling");
658			usbd_xfer_set_stall(xfer);
659			break;
660		}
661
662		/*
663		 * Those CTL functions cannot be called with mutex held.
664		 */
665		CFUMASS_UNLOCK(sc);
666		io = ctl_alloc_io(cfumass_port.ctl_pool_ref);
667		ctl_zero_io(io);
668		io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = sc;
669		io->io_hdr.io_type = CTL_IO_SCSI;
670		io->io_hdr.nexus.initid = sc->sc_ctl_initid;
671		io->io_hdr.nexus.targ_port = cfumass_port.targ_port;
672		io->io_hdr.nexus.targ_lun = ctl_decode_lun(sc->sc_cbw->bCBWLUN);
673		io->scsiio.tag_num = UGETDW(sc->sc_cbw->dCBWTag);
674		io->scsiio.tag_type = CTL_TAG_UNTAGGED;
675		io->scsiio.cdb_len = sc->sc_cbw->bCDBLength;
676		memcpy(io->scsiio.cdb, sc->sc_cbw->CBWCB, sc->sc_cbw->bCDBLength);
677		refcount_acquire(&sc->sc_queued);
678		error = ctl_queue(io);
679		if (error != CTL_RETVAL_COMPLETE) {
680			CFUMASS_WARN(sc,
681			    "ctl_queue() failed; error %d; stalling", error);
682			ctl_free_io(io);
683			refcount_release(&sc->sc_queued);
684			CFUMASS_LOCK(sc);
685			usbd_xfer_set_stall(xfer);
686			break;
687		}
688
689		CFUMASS_LOCK(sc);
690		break;
691
692	case USB_ST_SETUP:
693tr_setup:
694		CFUMASS_DEBUG(sc, "USB_ST_SETUP");
695
696		usbd_xfer_set_frame_len(xfer, 0, sizeof(*sc->sc_cbw));
697		usbd_transfer_submit(xfer);
698		break;
699
700	default:
701		if (usb_error == USB_ERR_CANCELLED) {
702			CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED");
703			break;
704		}
705
706		CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error));
707
708		goto tr_setup;
709	}
710}
711
712static void
713cfumass_t_data_callback(struct usb_xfer *xfer, usb_error_t usb_error)
714{
715	struct cfumass_softc *sc = usbd_xfer_softc(xfer);
716	union ctl_io *io = sc->sc_ctl_io;
717	uint32_t max_bulk;
718	struct ctl_sg_entry sg_entry, *sglist;
719	int actlen, sumlen, sg_count;
720
721	switch (USB_GET_STATE(xfer)) {
722	case USB_ST_TRANSFERRED:
723		CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED");
724
725		usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
726		sc->sc_current_residue -= actlen;
727		io->scsiio.ext_data_filled += actlen;
728		io->scsiio.kern_data_resid -= actlen;
729		if (actlen < sumlen ||
730		    sc->sc_current_residue == 0 ||
731		    io->scsiio.kern_data_resid == 0) {
732			sc->sc_ctl_io = NULL;
733			ctl_datamove_done(io, false);
734			break;
735		}
736		/* FALLTHROUGH */
737
738	case USB_ST_SETUP:
739tr_setup:
740		CFUMASS_DEBUG(sc, "USB_ST_SETUP");
741
742		if (io->scsiio.kern_sg_entries > 0) {
743			sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
744			sg_count = io->scsiio.kern_sg_entries;
745		} else {
746			sglist = &sg_entry;
747			sglist->addr = io->scsiio.kern_data_ptr;
748			sglist->len = io->scsiio.kern_data_len;
749			sg_count = 1;
750		}
751
752		sumlen = io->scsiio.ext_data_filled -
753		    io->scsiio.kern_rel_offset;
754		while (sumlen >= sglist->len && sg_count > 0) {
755			sumlen -= sglist->len;
756			sglist++;
757			sg_count--;
758		}
759		KASSERT(sg_count > 0, ("Run out of S/G list entries"));
760
761		max_bulk = usbd_xfer_max_len(xfer);
762		actlen = min(sglist->len - sumlen, max_bulk);
763		actlen = min(actlen, sc->sc_current_transfer_length -
764		    io->scsiio.ext_data_filled);
765		CFUMASS_DEBUG(sc, "requested %d, done %d, max_bulk %d, "
766		    "segment %zd => transfer %d",
767		    sc->sc_current_transfer_length, io->scsiio.ext_data_filled,
768		    max_bulk, sglist->len - sumlen, actlen);
769
770		usbd_xfer_set_frame_data(xfer, 0,
771		    (uint8_t *)sglist->addr + sumlen, actlen);
772		usbd_transfer_submit(xfer);
773		break;
774
775	default:
776		if (usb_error == USB_ERR_CANCELLED) {
777			CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED");
778			break;
779		}
780		CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error));
781		goto tr_setup;
782	}
783}
784
785static void
786cfumass_t_status_callback(struct usb_xfer *xfer, usb_error_t usb_error)
787{
788	struct cfumass_softc *sc;
789
790	sc = usbd_xfer_softc(xfer);
791
792	KASSERT(sc->sc_ctl_io == NULL,
793	    ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io));
794
795	switch (USB_GET_STATE(xfer)) {
796	case USB_ST_TRANSFERRED:
797		CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED");
798
799		cfumass_transfer_start(sc, CFUMASS_T_COMMAND);
800		break;
801
802	case USB_ST_SETUP:
803tr_setup:
804		CFUMASS_DEBUG(sc, "USB_ST_SETUP");
805
806		if (sc->sc_current_residue > 0 && !sc->sc_current_stalled) {
807			CFUMASS_DEBUG(sc, "non-zero residue, stalling");
808			usbd_xfer_set_stall(xfer);
809			sc->sc_current_stalled = true;
810		}
811
812		USETDW(sc->sc_csw->dCSWSignature, CSWSIGNATURE);
813		USETDW(sc->sc_csw->dCSWTag, sc->sc_current_tag);
814		USETDW(sc->sc_csw->dCSWDataResidue, sc->sc_current_residue);
815		sc->sc_csw->bCSWStatus = sc->sc_current_status;
816
817		usbd_xfer_set_frame_len(xfer, 0, sizeof(*sc->sc_csw));
818		usbd_transfer_submit(xfer);
819		break;
820
821	default:
822		if (usb_error == USB_ERR_CANCELLED) {
823			CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED");
824			break;
825		}
826
827		CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s",
828		    usbd_errstr(usb_error));
829
830		goto tr_setup;
831	}
832}
833
834static void
835cfumass_online(void *arg __unused)
836{
837
838	cfumass_port_online = true;
839}
840
841static void
842cfumass_offline(void *arg __unused)
843{
844
845	cfumass_port_online = false;
846}
847
848static void
849cfumass_datamove(union ctl_io *io)
850{
851	struct cfumass_softc *sc;
852
853	sc = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
854
855	CFUMASS_DEBUG(sc, "go");
856
857	CFUMASS_LOCK(sc);
858
859	KASSERT(sc->sc_ctl_io == NULL,
860	    ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io));
861	sc->sc_ctl_io = io;
862
863	if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) {
864		/*
865		 * Verify that CTL wants us to send the data in the direction
866		 * expected by the initiator.
867		 */
868		if (sc->sc_current_flags != CBWFLAGS_IN) {
869			CFUMASS_WARN(sc, "wrong bCBWFlags 0x%x, should be 0x%x",
870			    sc->sc_current_flags, CBWFLAGS_IN);
871			goto fail;
872		}
873
874		cfumass_transfer_start(sc, CFUMASS_T_DATA_IN);
875	} else {
876		if (sc->sc_current_flags != CBWFLAGS_OUT) {
877			CFUMASS_WARN(sc, "wrong bCBWFlags 0x%x, should be 0x%x",
878			    sc->sc_current_flags, CBWFLAGS_OUT);
879			goto fail;
880		}
881
882		cfumass_transfer_start(sc, CFUMASS_T_DATA_OUT);
883	}
884
885	CFUMASS_UNLOCK(sc);
886	return;
887
888fail:
889	ctl_set_data_phase_error(&io->scsiio);
890	ctl_datamove_done(io, true);
891	sc->sc_ctl_io = NULL;
892}
893
894static void
895cfumass_done(union ctl_io *io)
896{
897	struct cfumass_softc *sc;
898
899	sc = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
900
901	CFUMASS_DEBUG(sc, "go");
902
903	KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE),
904	    ("invalid CTL status %#x", io->io_hdr.status));
905	KASSERT(sc->sc_ctl_io == NULL,
906	    ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io));
907
908	if (io->io_hdr.io_type == CTL_IO_TASK &&
909	    io->taskio.task_action == CTL_TASK_I_T_NEXUS_RESET) {
910		/*
911		 * Implicit task termination has just completed; nothing to do.
912		 */
913		ctl_free_io(io);
914		return;
915	}
916
917	/*
918	 * Do not return status for aborted commands.
919	 * There are exceptions, but none supported by CTL yet.
920	 */
921	if (((io->io_hdr.flags & CTL_FLAG_ABORT) &&
922	     (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) ||
923	    (io->io_hdr.flags & CTL_FLAG_STATUS_SENT)) {
924		ctl_free_io(io);
925		return;
926	}
927
928	if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)
929		sc->sc_current_status = 0;
930	else
931		sc->sc_current_status = 1;
932
933	/* XXX: How should we report BUSY, RESERVATION CONFLICT, etc? */
934	if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SCSI_ERROR &&
935	    io->scsiio.scsi_status == SCSI_STATUS_CHECK_COND)
936		ctl_queue_sense(io);
937	else
938		ctl_free_io(io);
939
940	CFUMASS_LOCK(sc);
941	cfumass_transfer_start(sc, CFUMASS_T_STATUS);
942	CFUMASS_UNLOCK(sc);
943
944	refcount_release(&sc->sc_queued);
945}
946
947int
948cfumass_init(void)
949{
950	int error;
951
952	cfumass_port.frontend = &cfumass_frontend;
953	cfumass_port.port_type = CTL_PORT_UMASS;
954	cfumass_port.num_requested_ctl_io = 1;
955	cfumass_port.port_name = "cfumass";
956	cfumass_port.physical_port = 0;
957	cfumass_port.virtual_port = 0;
958	cfumass_port.port_online = cfumass_online;
959	cfumass_port.port_offline = cfumass_offline;
960	cfumass_port.onoff_arg = NULL;
961	cfumass_port.fe_datamove = cfumass_datamove;
962	cfumass_port.fe_done = cfumass_done;
963	cfumass_port.targ_port = -1;
964
965	error = ctl_port_register(&cfumass_port);
966	if (error != 0) {
967		printf("%s: ctl_port_register() failed "
968		    "with error %d", __func__, error);
969	}
970
971	cfumass_port_online = true;
972	refcount_init(&cfumass_refcount, 0);
973
974	return (error);
975}
976
977int
978cfumass_shutdown(void)
979{
980	int error;
981
982	if (cfumass_refcount > 0) {
983		if (debug > 1) {
984			printf("%s: still have %u attachments; "
985			    "returning EBUSY\n", __func__, cfumass_refcount);
986		}
987		return (EBUSY);
988	}
989
990	error = ctl_port_deregister(&cfumass_port);
991	if (error != 0) {
992		printf("%s: ctl_port_deregister() failed "
993		    "with error %d\n", __func__, error);
994	}
995
996	return (error);
997}
998