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