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