cfumass.c revision 317336
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 317336 2017-04-23 09:00:26Z mav $");
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	io = sc->sc_ctl_io;
724
725	if (io->scsiio.kern_sg_entries > 0) {
726		ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
727		ctl_sg_count = io->scsiio.kern_sg_entries;
728	} else {
729		ctl_sglist = &ctl_sg_entry;
730		ctl_sglist->addr = io->scsiio.kern_data_ptr;
731		ctl_sglist->len = io->scsiio.kern_data_len;
732		ctl_sg_count = 1;
733	}
734
735	switch (USB_GET_STATE(xfer)) {
736	case USB_ST_TRANSFERRED:
737		CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED");
738
739		usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
740		if (actlen != ctl_sglist[0].len) {
741			KASSERT(actlen <= ctl_sglist[0].len,
742			    ("actlen %d > ctl_sglist.len %zd",
743			    actlen, ctl_sglist[0].len));
744			CFUMASS_DEBUG(sc, "host transferred %d bytes"
745			    "instead of expected %zd bytes",
746			    actlen, ctl_sglist[0].len);
747		}
748		sc->sc_current_residue -= actlen;
749		io->scsiio.kern_data_resid -= actlen;
750		io->scsiio.be_move_done(io);
751		sc->sc_ctl_io = NULL;
752		break;
753
754	case USB_ST_SETUP:
755tr_setup:
756		CFUMASS_DEBUG(sc, "USB_ST_SETUP");
757
758		CFUMASS_DEBUG(sc, "requested size %d, CTL segment size %zd",
759		    sc->sc_current_transfer_length, ctl_sglist[0].len);
760
761		usbd_xfer_set_frame_data(xfer, 0, ctl_sglist[0].addr, ctl_sglist[0].len);
762		usbd_transfer_submit(xfer);
763		break;
764
765	default:
766		if (usb_error == USB_ERR_CANCELLED) {
767			CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED");
768			break;
769		}
770
771		CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s",
772		    usbd_errstr(usb_error));
773
774		goto tr_setup;
775	}
776}
777
778static void
779cfumass_t_data_in_callback(struct usb_xfer *xfer, usb_error_t usb_error)
780{
781	struct cfumass_softc *sc;
782	union ctl_io *io;
783	uint32_t max_bulk;
784	struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
785	int actlen, ctl_sg_count;
786
787	sc = usbd_xfer_softc(xfer);
788	io = sc->sc_ctl_io;
789
790	switch (USB_GET_STATE(xfer)) {
791	case USB_ST_TRANSFERRED:
792		CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED");
793
794		usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
795		sc->sc_current_residue -= actlen;
796		io->scsiio.kern_data_resid -= actlen;
797		io->scsiio.be_move_done(io);
798		sc->sc_ctl_io = NULL;
799		break;
800
801	case USB_ST_SETUP:
802tr_setup:
803		CFUMASS_DEBUG(sc, "USB_ST_SETUP");
804
805		if (io->scsiio.kern_sg_entries > 0) {
806			ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
807			ctl_sg_count = io->scsiio.kern_sg_entries;
808		} else {
809			ctl_sglist = &ctl_sg_entry;
810			ctl_sglist->addr = io->scsiio.kern_data_ptr;
811			ctl_sglist->len = io->scsiio.kern_data_len;
812			ctl_sg_count = 1;
813		}
814
815		if (sc->sc_current_transfer_length > io->scsiio.kern_total_len) {
816			CFUMASS_DEBUG(sc, "initiator requested %d bytes, "
817			    "we will send %ju and stall",
818			    sc->sc_current_transfer_length,
819			    (uintmax_t)io->scsiio.kern_total_len);
820		}
821
822		max_bulk = usbd_xfer_max_len(xfer);
823		CFUMASS_DEBUG(sc, "max_bulk %d, requested size %d, "
824		    "CTL segment size %zd", max_bulk,
825		    sc->sc_current_transfer_length, ctl_sglist[0].len);
826
827		if (max_bulk >= ctl_sglist[0].len)
828			max_bulk = ctl_sglist[0].len;
829
830		usbd_xfer_set_frame_data(xfer, 0, ctl_sglist[0].addr, max_bulk);
831		usbd_transfer_submit(xfer);
832
833		break;
834
835	default:
836		if (usb_error == USB_ERR_CANCELLED) {
837			CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED");
838			break;
839		}
840
841		CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s", usbd_errstr(usb_error));
842
843		goto tr_setup;
844	}
845}
846
847static void
848cfumass_t_status_callback(struct usb_xfer *xfer, usb_error_t usb_error)
849{
850	struct cfumass_softc *sc;
851
852	sc = usbd_xfer_softc(xfer);
853
854	KASSERT(sc->sc_ctl_io == NULL,
855	    ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io));
856
857	switch (USB_GET_STATE(xfer)) {
858	case USB_ST_TRANSFERRED:
859		CFUMASS_DEBUG(sc, "USB_ST_TRANSFERRED");
860
861		cfumass_transfer_start(sc, CFUMASS_T_COMMAND);
862		break;
863
864	case USB_ST_SETUP:
865tr_setup:
866		CFUMASS_DEBUG(sc, "USB_ST_SETUP");
867
868		if (sc->sc_current_residue > 0 && !sc->sc_current_stalled) {
869			CFUMASS_DEBUG(sc, "non-zero residue, stalling");
870			usbd_xfer_set_stall(xfer);
871			sc->sc_current_stalled = true;
872		}
873
874		USETDW(sc->sc_csw->dCSWSignature, CSWSIGNATURE);
875		USETDW(sc->sc_csw->dCSWTag, sc->sc_current_tag);
876		USETDW(sc->sc_csw->dCSWDataResidue, sc->sc_current_residue);
877		sc->sc_csw->bCSWStatus = sc->sc_current_status;
878
879		usbd_xfer_set_frame_len(xfer, 0, sizeof(*sc->sc_csw));
880		usbd_transfer_submit(xfer);
881		break;
882
883	default:
884		if (usb_error == USB_ERR_CANCELLED) {
885			CFUMASS_DEBUG(sc, "USB_ERR_CANCELLED");
886			break;
887		}
888
889		CFUMASS_DEBUG(sc, "USB_ST_ERROR: %s",
890		    usbd_errstr(usb_error));
891
892		goto tr_setup;
893	}
894}
895
896static void
897cfumass_online(void *arg __unused)
898{
899
900	cfumass_port_online = true;
901}
902
903static void
904cfumass_offline(void *arg __unused)
905{
906
907	cfumass_port_online = false;
908}
909
910static void
911cfumass_datamove(union ctl_io *io)
912{
913	struct cfumass_softc *sc;
914
915	sc = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
916
917	CFUMASS_DEBUG(sc, "go");
918
919	CFUMASS_LOCK(sc);
920
921	KASSERT(sc->sc_ctl_io == NULL,
922	    ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io));
923	sc->sc_ctl_io = io;
924
925	if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) {
926		/*
927		 * Verify that CTL wants us to send the data in the direction
928		 * expected by the initiator.
929		 */
930		if (sc->sc_current_flags != CBWFLAGS_IN) {
931			CFUMASS_WARN(sc, "wrong bCBWFlags 0x%x, should be 0x%x",
932			    sc->sc_current_flags, CBWFLAGS_IN);
933			goto fail;
934		}
935
936		cfumass_transfer_start(sc, CFUMASS_T_DATA_IN);
937	} else {
938		if (sc->sc_current_flags != CBWFLAGS_OUT) {
939			CFUMASS_WARN(sc, "wrong bCBWFlags 0x%x, should be 0x%x",
940			    sc->sc_current_flags, CBWFLAGS_OUT);
941			goto fail;
942		}
943
944		cfumass_transfer_start(sc, CFUMASS_T_DATA_OUT);
945	}
946
947	CFUMASS_UNLOCK(sc);
948	return;
949
950fail:
951	ctl_set_data_phase_error(&io->scsiio);
952	io->scsiio.be_move_done(io);
953	sc->sc_ctl_io = NULL;
954}
955
956static void
957cfumass_done(union ctl_io *io)
958{
959	struct cfumass_softc *sc;
960
961	sc = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
962
963	CFUMASS_DEBUG(sc, "go");
964
965	KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE),
966	    ("invalid CTL status %#x", io->io_hdr.status));
967	KASSERT(sc->sc_ctl_io == NULL,
968	    ("sc_ctl_io is %p, should be NULL", sc->sc_ctl_io));
969
970	if (io->io_hdr.io_type == CTL_IO_TASK &&
971	    io->taskio.task_action == CTL_TASK_I_T_NEXUS_RESET) {
972		/*
973		 * Implicit task termination has just completed; nothing to do.
974		 */
975		ctl_free_io(io);
976		return;
977	}
978
979	/*
980	 * Do not return status for aborted commands.
981	 * There are exceptions, but none supported by CTL yet.
982	 */
983	if (((io->io_hdr.flags & CTL_FLAG_ABORT) &&
984	     (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) ||
985	    (io->io_hdr.flags & CTL_FLAG_STATUS_SENT)) {
986		ctl_free_io(io);
987		return;
988	}
989
990	switch (io->scsiio.scsi_status) {
991	case SCSI_STATUS_OK:
992		sc->sc_current_status = 0;
993		break;
994	default:
995		sc->sc_current_status = 1;
996		break;
997	}
998
999	CFUMASS_LOCK(sc);
1000	cfumass_transfer_start(sc, CFUMASS_T_STATUS);
1001	CFUMASS_UNLOCK(sc);
1002	ctl_free_io(io);
1003
1004	refcount_release(&sc->sc_queued);
1005}
1006
1007int
1008cfumass_init(void)
1009{
1010	int error;
1011
1012	cfumass_port.frontend = &cfumass_frontend;
1013	cfumass_port.port_type = CTL_PORT_UMASS;
1014	cfumass_port.num_requested_ctl_io = 1;
1015	cfumass_port.port_name = "cfumass";
1016	cfumass_port.physical_port = 0;
1017	cfumass_port.virtual_port = 0;
1018	cfumass_port.port_online = cfumass_online;
1019	cfumass_port.port_offline = cfumass_offline;
1020	cfumass_port.onoff_arg = NULL;
1021	cfumass_port.fe_datamove = cfumass_datamove;
1022	cfumass_port.fe_done = cfumass_done;
1023	cfumass_port.targ_port = -1;
1024
1025	error = ctl_port_register(&cfumass_port);
1026	if (error != 0) {
1027		printf("%s: ctl_port_register() failed "
1028		    "with error %d", __func__, error);
1029	}
1030
1031	cfumass_port_online = true;
1032	refcount_init(&cfumass_refcount, 0);
1033
1034	return (error);
1035}
1036
1037int
1038cfumass_shutdown(void)
1039{
1040	int error;
1041
1042	if (cfumass_refcount > 0) {
1043		if (debug > 1) {
1044			printf("%s: still have %u attachments; "
1045			    "returning EBUSY\n", __func__, cfumass_refcount);
1046		}
1047		return (EBUSY);
1048	}
1049
1050	error = ctl_port_deregister(&cfumass_port);
1051	if (error != 0) {
1052		printf("%s: ctl_port_deregister() failed "
1053		    "with error %d\n", __func__, error);
1054	}
1055
1056	return (error);
1057}
1058