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