xref: /freebsd/sys/dev/usb/storage/cfumass.c (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
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 
71 SYSCTL_NODE(_hw_usb, OID_AUTO, cfumass, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
72     "CAM Target Layer USB Mass Storage Frontend");
73 static int debug = 1;
74 SYSCTL_INT(_hw_usb_cfumass, OID_AUTO, debug, CTLFLAG_RWTUN,
75     &debug, 1, "Enable debug messages");
76 static int max_lun = 0;
77 SYSCTL_INT(_hw_usb_cfumass, OID_AUTO, max_lun, CTLFLAG_RWTUN,
78     &max_lun, 1, "Maximum advertised LUN number");
79 static int ignore_stop = 1;
80 SYSCTL_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  */
89 struct ctl_port	cfumass_port;
90 bool		cfumass_port_online;
91 volatile 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  */
115 struct 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
130 CTASSERT(sizeof(struct cfumass_cbw_t) == CFUMASS_CBW_SIZE);
131 
132 /*
133  * Command Status Wrapper.
134  */
135 struct 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
147 CTASSERT(sizeof(struct cfumass_csw_t) == CFUMASS_CSW_SIZE);
148 
149 struct 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  */
196 static device_probe_t		cfumass_probe;
197 static device_attach_t		cfumass_attach;
198 static device_detach_t		cfumass_detach;
199 static device_suspend_t		cfumass_suspend;
200 static device_resume_t		cfumass_resume;
201 static usb_handle_request_t	cfumass_handle_request;
202 
203 static usb_callback_t		cfumass_t_command_callback;
204 static usb_callback_t		cfumass_t_data_callback;
205 static usb_callback_t		cfumass_t_status_callback;
206 
207 static 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 
221 static driver_t cfumass_driver = {
222 	.name = "cfumass",
223 	.methods = cfumass_methods,
224 	.size = sizeof(struct cfumass_softc),
225 };
226 
227 static devclass_t cfumass_devclass;
228 
229 DRIVER_MODULE(cfumass, uhub, cfumass_driver, cfumass_devclass, NULL, 0);
230 MODULE_VERSION(cfumass, 0);
231 MODULE_DEPEND(cfumass, usb, 1, 1, 1);
232 MODULE_DEPEND(cfumass, usb_template, 1, 1, 1);
233 
234 static 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  */
280 static int	cfumass_init(void);
281 static int	cfumass_shutdown(void);
282 static void	cfumass_online(void *arg);
283 static void	cfumass_offline(void *arg);
284 static void	cfumass_datamove(union ctl_io *io);
285 static void	cfumass_done(union ctl_io *io);
286 
287 static struct ctl_frontend cfumass_frontend = {
288 	.name = "umass",
289 	.init = cfumass_init,
290 	.shutdown = cfumass_shutdown,
291 };
292 CTL_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 
313 static void	cfumass_transfer_start(struct cfumass_softc *sc,
314 		    uint8_t xfer_index);
315 static void	cfumass_terminate(struct cfumass_softc *sc);
316 
317 static int
318 cfumass_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 
342 static int
343 cfumass_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 
396 static int
397 cfumass_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 
426 static int
427 cfumass_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 
437 static int
438 cfumass_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 
448 static void
449 cfumass_transfer_start(struct cfumass_softc *sc, uint8_t xfer_index)
450 {
451 
452 	usbd_transfer_start(sc->sc_xfer[xfer_index]);
453 }
454 
455 static void
456 cfumass_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 
465 static void
466 cfumass_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 			sc->sc_ctl_io->scsiio.be_move_done(sc->sc_ctl_io);
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 
495 static int
496 cfumass_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 
558 static int
559 cfumass_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 
608 static void
609 cfumass_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:
693 tr_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 
712 static void
713 cfumass_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 			io->scsiio.be_move_done(io);
734 			break;
735 		}
736 		/* FALLTHROUGH */
737 
738 	case USB_ST_SETUP:
739 tr_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 
785 static void
786 cfumass_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:
803 tr_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 
834 static void
835 cfumass_online(void *arg __unused)
836 {
837 
838 	cfumass_port_online = true;
839 }
840 
841 static void
842 cfumass_offline(void *arg __unused)
843 {
844 
845 	cfumass_port_online = false;
846 }
847 
848 static void
849 cfumass_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 
888 fail:
889 	ctl_set_data_phase_error(&io->scsiio);
890 	io->scsiio.be_move_done(io);
891 	sc->sc_ctl_io = NULL;
892 }
893 
894 static void
895 cfumass_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 
947 int
948 cfumass_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 
977 int
978 cfumass_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