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