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