nrelease - fix/improve livecd
[dragonfly.git] / sys / bus / u4b / storage / ustorage_fs.c
CommitLineData
12bd3c8b
SW
1/* $FreeBSD$ */
2/*-
3 * Copyright (C) 2003-2005 Alan Stern
4 * Copyright (C) 2008 Hans Petter Selasky
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
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 * 3. The names of the above-listed copyright holders may not be used
17 * to endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/*
35 * NOTE: Much of the SCSI statemachine handling code derives from the
36 * Linux USB gadget stack.
37 */
38
39#include <sys/stdint.h>
12bd3c8b
SW
40#include <sys/param.h>
41#include <sys/queue.h>
42#include <sys/types.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>
45#include <sys/bus.h>
46#include <sys/module.h>
47#include <sys/lock.h>
12bd3c8b
SW
48#include <sys/condvar.h>
49#include <sys/sysctl.h>
12bd3c8b
SW
50#include <sys/unistd.h>
51#include <sys/callout.h>
52#include <sys/malloc.h>
2b3f93ea 53#include <sys/caps.h>
12bd3c8b 54
722d05c3
SW
55#include <bus/u4b/usb.h>
56#include <bus/u4b/usbdi.h>
ef4aa9ff 57#include "usbdevs.h"
12bd3c8b
SW
58#include "usb_if.h"
59
60#define USB_DEBUG_VAR ustorage_fs_debug
722d05c3 61#include <bus/u4b/usb_debug.h>
12bd3c8b
SW
62
63#ifdef USB_DEBUG
64static int ustorage_fs_debug = 0;
65
66SYSCTL_NODE(_hw_usb, OID_AUTO, ustorage_fs, CTLFLAG_RW, 0, "USB ustorage_fs");
a9b765b7 67SYSCTL_INT(_hw_usb_ustorage_fs, OID_AUTO, debug, CTLFLAG_RW,
12bd3c8b
SW
68 &ustorage_fs_debug, 0, "ustorage_fs debug level");
69#endif
70
71/* Define some limits */
72
73#ifndef USTORAGE_FS_BULK_SIZE
74#define USTORAGE_FS_BULK_SIZE (1UL << 17) /* bytes */
75#endif
76
77#ifndef USTORAGE_FS_MAX_LUN
78#define USTORAGE_FS_MAX_LUN 8 /* units */
79#endif
80
81#ifndef USTORAGE_QDATA_MAX
82#define USTORAGE_QDATA_MAX 40 /* bytes */
83#endif
84
85#define sc_cmd_data sc_cbw.CBWCDB
86
87/*
88 * The SCSI ID string must be exactly 28 characters long
89 * exluding the terminating zero.
90 */
91#ifndef USTORAGE_FS_ID_STRING
92#define USTORAGE_FS_ID_STRING \
93 "FreeBSD " /* 8 */ \
94 "File-Stor Gadget" /* 16 */ \
95 "0101" /* 4 */
96#endif
97
98/*
99 * The following macro defines the number of
100 * sectors to be allocated for the RAM disk:
101 */
102#ifndef USTORAGE_FS_RAM_SECT
103#define USTORAGE_FS_RAM_SECT (1UL << 13)
104#endif
105
106static uint8_t *ustorage_fs_ramdisk;
107
108/* USB transfer definitions */
109
110#define USTORAGE_FS_T_BBB_COMMAND 0
111#define USTORAGE_FS_T_BBB_DATA_DUMP 1
112#define USTORAGE_FS_T_BBB_DATA_READ 2
113#define USTORAGE_FS_T_BBB_DATA_WRITE 3
114#define USTORAGE_FS_T_BBB_STATUS 4
115#define USTORAGE_FS_T_BBB_MAX 5
116
117/* USB data stage direction */
118
119#define DIR_NONE 0
120#define DIR_READ 1
121#define DIR_WRITE 2
122
123/* USB interface specific control request */
124
125#define UR_BBB_RESET 0xff /* Bulk-Only reset */
126#define UR_BBB_GET_MAX_LUN 0xfe /* Get maximum lun */
127
128/* Command Block Wrapper */
129typedef struct {
130 uDWord dCBWSignature;
131#define CBWSIGNATURE 0x43425355
132 uDWord dCBWTag;
133 uDWord dCBWDataTransferLength;
134 uByte bCBWFlags;
135#define CBWFLAGS_OUT 0x00
136#define CBWFLAGS_IN 0x80
137 uByte bCBWLUN;
138 uByte bCDBLength;
139#define CBWCDBLENGTH 16
140 uByte CBWCDB[CBWCDBLENGTH];
141} __packed ustorage_fs_bbb_cbw_t;
142
143#define USTORAGE_FS_BBB_CBW_SIZE 31
144
145/* Command Status Wrapper */
146typedef struct {
147 uDWord dCSWSignature;
148#define CSWSIGNATURE 0x53425355
149 uDWord dCSWTag;
150 uDWord dCSWDataResidue;
151 uByte bCSWStatus;
152#define CSWSTATUS_GOOD 0x0
153#define CSWSTATUS_FAILED 0x1
154#define CSWSTATUS_PHASE 0x2
155} __packed ustorage_fs_bbb_csw_t;
156
157#define USTORAGE_FS_BBB_CSW_SIZE 13
158
159struct ustorage_fs_lun {
160
161 uint8_t *memory_image;
162
163 uint32_t num_sectors;
164 uint32_t sense_data;
165 uint32_t sense_data_info;
166 uint32_t unit_attention_data;
167
168 uint8_t read_only:1;
169 uint8_t prevent_medium_removal:1;
170 uint8_t info_valid:1;
171 uint8_t removable:1;
172};
173
174struct ustorage_fs_softc {
175
a41b1dd4
MP
176 ustorage_fs_bbb_cbw_t *sc_cbw; /* Command Wrapper Block */
177 ustorage_fs_bbb_csw_t *sc_csw; /* Command Status Block */
178 void *sc_dma_ptr; /* Main data buffer */
12bd3c8b 179
722d05c3 180 struct lock sc_lock;
12bd3c8b
SW
181
182 struct ustorage_fs_lun sc_lun[USTORAGE_FS_MAX_LUN];
183
184 struct {
185 uint8_t *data_ptr;
186 struct ustorage_fs_lun *currlun;
187
188 uint32_t data_rem; /* bytes, as reported by the command
189 * block wrapper */
190 uint32_t offset; /* bytes */
191
192 uint8_t cbw_dir;
193 uint8_t cmd_dir;
194 uint8_t lun;
195 uint8_t cmd_len;
196 uint8_t data_short:1;
197 uint8_t data_error:1;
198 } sc_transfer;
199
200 device_t sc_dev;
201 struct usb_device *sc_udev;
202 struct usb_xfer *sc_xfer[USTORAGE_FS_T_BBB_MAX];
203
204 uint8_t sc_iface_no; /* interface number */
205 uint8_t sc_last_lun;
206 uint8_t sc_last_xfer_index;
207 uint8_t sc_qdata[USTORAGE_QDATA_MAX];
208};
209
210/* prototypes */
211
212static device_probe_t ustorage_fs_probe;
213static device_attach_t ustorage_fs_attach;
214static device_detach_t ustorage_fs_detach;
215static device_suspend_t ustorage_fs_suspend;
216static device_resume_t ustorage_fs_resume;
217static usb_handle_request_t ustorage_fs_handle_request;
218
219static usb_callback_t ustorage_fs_t_bbb_command_callback;
220static usb_callback_t ustorage_fs_t_bbb_data_dump_callback;
221static usb_callback_t ustorage_fs_t_bbb_data_read_callback;
222static usb_callback_t ustorage_fs_t_bbb_data_write_callback;
223static usb_callback_t ustorage_fs_t_bbb_status_callback;
224
225static void ustorage_fs_transfer_start(struct ustorage_fs_softc *sc, uint8_t xfer_index);
226static void ustorage_fs_transfer_stop(struct ustorage_fs_softc *sc);
227
228static uint8_t ustorage_fs_verify(struct ustorage_fs_softc *sc);
229static uint8_t ustorage_fs_inquiry(struct ustorage_fs_softc *sc);
230static uint8_t ustorage_fs_request_sense(struct ustorage_fs_softc *sc);
231static uint8_t ustorage_fs_read_capacity(struct ustorage_fs_softc *sc);
232static uint8_t ustorage_fs_mode_sense(struct ustorage_fs_softc *sc);
233static uint8_t ustorage_fs_start_stop(struct ustorage_fs_softc *sc);
234static uint8_t ustorage_fs_prevent_allow(struct ustorage_fs_softc *sc);
235static uint8_t ustorage_fs_read_format_capacities(struct ustorage_fs_softc *sc);
236static uint8_t ustorage_fs_mode_select(struct ustorage_fs_softc *sc);
237static uint8_t ustorage_fs_min_len(struct ustorage_fs_softc *sc, uint32_t len, uint32_t mask);
238static uint8_t ustorage_fs_read(struct ustorage_fs_softc *sc);
239static uint8_t ustorage_fs_write(struct ustorage_fs_softc *sc);
240static uint8_t ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t cmd_size, uint16_t mask, uint8_t needs_medium);
241static uint8_t ustorage_fs_do_cmd(struct ustorage_fs_softc *sc);
242
243static device_method_t ustorage_fs_methods[] = {
244 /* USB interface */
245 DEVMETHOD(usb_handle_request, ustorage_fs_handle_request),
246
247 /* Device interface */
248 DEVMETHOD(device_probe, ustorage_fs_probe),
249 DEVMETHOD(device_attach, ustorage_fs_attach),
250 DEVMETHOD(device_detach, ustorage_fs_detach),
251 DEVMETHOD(device_suspend, ustorage_fs_suspend),
252 DEVMETHOD(device_resume, ustorage_fs_resume),
253
d3c9c58e 254 DEVMETHOD_END
12bd3c8b
SW
255};
256
257static driver_t ustorage_fs_driver = {
258 .name = "ustorage_fs",
259 .methods = ustorage_fs_methods,
260 .size = sizeof(struct ustorage_fs_softc),
261};
262
263static devclass_t ustorage_fs_devclass;
264
15f415f6 265DRIVER_MODULE(ustorage_fs, uhub, ustorage_fs_driver, ustorage_fs_devclass, NULL, NULL);
12bd3c8b
SW
266MODULE_VERSION(ustorage_fs, 0);
267MODULE_DEPEND(ustorage_fs, usb, 1, 1, 1);
268
269static struct usb_config ustorage_fs_bbb_config[USTORAGE_FS_T_BBB_MAX] = {
270
271 [USTORAGE_FS_T_BBB_COMMAND] = {
272 .type = UE_BULK,
273 .endpoint = UE_ADDR_ANY,
274 .direction = UE_DIR_OUT,
275 .bufsize = sizeof(ustorage_fs_bbb_cbw_t),
12bd3c8b
SW
276 .callback = &ustorage_fs_t_bbb_command_callback,
277 .usb_mode = USB_MODE_DEVICE,
278 },
279
280 [USTORAGE_FS_T_BBB_DATA_DUMP] = {
281 .type = UE_BULK,
282 .endpoint = UE_ADDR_ANY,
283 .direction = UE_DIR_OUT,
284 .bufsize = 0, /* use wMaxPacketSize */
285 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
286 .callback = &ustorage_fs_t_bbb_data_dump_callback,
287 .usb_mode = USB_MODE_DEVICE,
288 },
289
290 [USTORAGE_FS_T_BBB_DATA_READ] = {
291 .type = UE_BULK,
292 .endpoint = UE_ADDR_ANY,
293 .direction = UE_DIR_OUT,
294 .bufsize = USTORAGE_FS_BULK_SIZE,
a41b1dd4 295 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1},
12bd3c8b
SW
296 .callback = &ustorage_fs_t_bbb_data_read_callback,
297 .usb_mode = USB_MODE_DEVICE,
298 },
299
300 [USTORAGE_FS_T_BBB_DATA_WRITE] = {
301 .type = UE_BULK,
302 .endpoint = UE_ADDR_ANY,
303 .direction = UE_DIR_IN,
304 .bufsize = USTORAGE_FS_BULK_SIZE,
305 .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
306 .callback = &ustorage_fs_t_bbb_data_write_callback,
307 .usb_mode = USB_MODE_DEVICE,
308 },
309
310 [USTORAGE_FS_T_BBB_STATUS] = {
311 .type = UE_BULK,
312 .endpoint = UE_ADDR_ANY,
313 .direction = UE_DIR_IN,
314 .bufsize = sizeof(ustorage_fs_bbb_csw_t),
a41b1dd4 315 .flags = {.short_xfer_ok = 1},
12bd3c8b
SW
316 .callback = &ustorage_fs_t_bbb_status_callback,
317 .usb_mode = USB_MODE_DEVICE,
318 },
319};
320
321/*
322 * USB device probe/attach/detach
323 */
324
325static int
326ustorage_fs_probe(device_t dev)
327{
328 struct usb_attach_arg *uaa = device_get_ivars(dev);
329 struct usb_interface_descriptor *id;
330
331 if (uaa->usb_mode != USB_MODE_DEVICE) {
332 return (ENXIO);
333 }
334 /* Check for a standards compliant device */
335 id = usbd_get_interface_descriptor(uaa->iface);
336 if ((id == NULL) ||
337 (id->bInterfaceClass != UICLASS_MASS) ||
338 (id->bInterfaceSubClass != UISUBCLASS_SCSI) ||
339 (id->bInterfaceProtocol != UIPROTO_MASS_BBB)) {
340 return (ENXIO);
341 }
342 return (BUS_PROBE_GENERIC);
343}
344
345static int
346ustorage_fs_attach(device_t dev)
347{
348 struct ustorage_fs_softc *sc = device_get_softc(dev);
349 struct usb_attach_arg *uaa = device_get_ivars(dev);
350 struct usb_interface_descriptor *id;
351 int err;
352 int unit;
353
354 /*
355 * NOTE: the softc struct is cleared in device_set_driver.
356 * We can safely call ustorage_fs_detach without specifically
357 * initializing the struct.
358 */
359
360 sc->sc_dev = dev;
361 sc->sc_udev = uaa->device;
362 unit = device_get_unit(dev);
363
364 /* enable power saving mode */
365 usbd_set_power_mode(uaa->device, USB_POWER_MODE_SAVE);
366
367 if (unit == 0) {
368 if (ustorage_fs_ramdisk == NULL) {
369 /*
370 * allocate a memory image for our ramdisk until
371 * further
372 */
373 ustorage_fs_ramdisk =
722d05c3 374 kmalloc(USTORAGE_FS_RAM_SECT << 9, M_USB,
12bd3c8b 375 M_ZERO | M_WAITOK);
a41b1dd4
MP
376
377 if (ustorage_fs_ramdisk == NULL) {
378 return (ENOMEM);
379 }
12bd3c8b
SW
380 }
381 sc->sc_lun[0].memory_image = ustorage_fs_ramdisk;
382 sc->sc_lun[0].num_sectors = USTORAGE_FS_RAM_SECT;
383 sc->sc_lun[0].removable = 1;
384 }
385
386 device_set_usb_desc(dev);
387
63da4a34
SW
388 lockinit(&sc->sc_lock, "USTORAGE_FS lock", 0, LK_CANRECURSE);
389
12bd3c8b
SW
390 /* get interface index */
391
392 id = usbd_get_interface_descriptor(uaa->iface);
393 if (id == NULL) {
394 device_printf(dev, "failed to get "
395 "interface number\n");
396 goto detach;
397 }
398 sc->sc_iface_no = id->bInterfaceNumber;
399
400 err = usbd_transfer_setup(uaa->device,
401 &uaa->info.bIfaceIndex, sc->sc_xfer, ustorage_fs_bbb_config,
722d05c3 402 USTORAGE_FS_T_BBB_MAX, sc, &sc->sc_lock);
12bd3c8b
SW
403 if (err) {
404 device_printf(dev, "could not setup required "
405 "transfers, %s\n", usbd_errstr(err));
406 goto detach;
407 }
a41b1dd4
MP
408
409 sc->sc_cbw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
410 USTORAGE_FS_T_BBB_COMMAND], 0);
411 sc->sc_csw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
412 USTORAGE_FS_T_BBB_STATUS], 0);
413 sc->sc_dma_ptr = usbd_xfer_get_frame_buffer(sc->sc_xfer[
414 USTORAGE_FS_T_BBB_DATA_READ], 0);
415
12bd3c8b
SW
416 /* start Mass Storage State Machine */
417
63da4a34 418 lockmgr(&sc->sc_lock, LK_EXCLUSIVE);
12bd3c8b 419 ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_COMMAND);
63da4a34 420 lockmgr(&sc->sc_lock, LK_RELEASE);
12bd3c8b
SW
421
422 return (0); /* success */
423
424detach:
425 ustorage_fs_detach(dev);
426 return (ENXIO); /* failure */
427}
428
429static int
430ustorage_fs_detach(device_t dev)
431{
432 struct ustorage_fs_softc *sc = device_get_softc(dev);
433
434 /* teardown our statemachine */
435
436 usbd_transfer_unsetup(sc->sc_xfer, USTORAGE_FS_T_BBB_MAX);
437
722d05c3 438 lockuninit(&sc->sc_lock);
12bd3c8b
SW
439
440 return (0); /* success */
441}
442
443static int
444ustorage_fs_suspend(device_t dev)
445{
446 device_printf(dev, "suspending\n");
447 return (0); /* success */
448}
449
450static int
451ustorage_fs_resume(device_t dev)
452{
453 device_printf(dev, "resuming\n");
454 return (0); /* success */
455}
456
457/*
458 * Generic functions to handle transfers
459 */
460
461static void
462ustorage_fs_transfer_start(struct ustorage_fs_softc *sc, uint8_t xfer_index)
463{
464 if (sc->sc_xfer[xfer_index]) {
465 sc->sc_last_xfer_index = xfer_index;
466 usbd_transfer_start(sc->sc_xfer[xfer_index]);
467 }
468}
469
470static void
471ustorage_fs_transfer_stop(struct ustorage_fs_softc *sc)
472{
473 usbd_transfer_stop(sc->sc_xfer[sc->sc_last_xfer_index]);
63da4a34 474 lockmgr(&sc->sc_lock, LK_RELEASE);
12bd3c8b 475 usbd_transfer_drain(sc->sc_xfer[sc->sc_last_xfer_index]);
63da4a34 476 lockmgr(&sc->sc_lock, LK_EXCLUSIVE);
12bd3c8b
SW
477}
478
479static int
480ustorage_fs_handle_request(device_t dev,
481 const void *preq, void **pptr, uint16_t *plen,
482 uint16_t offset, uint8_t *pstate)
483{
484 struct ustorage_fs_softc *sc = device_get_softc(dev);
485 const struct usb_device_request *req = preq;
486 uint8_t is_complete = *pstate;
487
488 if (!is_complete) {
489 if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
490 (req->bRequest == UR_BBB_RESET)) {
491 *plen = 0;
63da4a34 492 lockmgr(&sc->sc_lock, LK_EXCLUSIVE);
12bd3c8b
SW
493 ustorage_fs_transfer_stop(sc);
494 sc->sc_transfer.data_error = 1;
495 ustorage_fs_transfer_start(sc,
496 USTORAGE_FS_T_BBB_COMMAND);
63da4a34 497 lockmgr(&sc->sc_lock, LK_RELEASE);
12bd3c8b
SW
498 return (0);
499 } else if ((req->bmRequestType == UT_READ_CLASS_INTERFACE) &&
500 (req->bRequest == UR_BBB_GET_MAX_LUN)) {
501 if (offset == 0) {
502 *plen = 1;
503 *pptr = &sc->sc_last_lun;
504 } else {
505 *plen = 0;
506 }
507 return (0);
508 }
509 }
510 return (ENXIO); /* use builtin handler */
511}
512
513static void
514ustorage_fs_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
515{
516 struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
517 uint32_t tag;
518 uint8_t err = 0;
519
520 DPRINTF("\n");
521
522 switch (USB_GET_STATE(xfer)) {
523 case USB_ST_TRANSFERRED:
524
a41b1dd4 525 tag = UGETDW(sc->sc_cbw->dCBWSignature);
12bd3c8b
SW
526
527 if (tag != CBWSIGNATURE) {
528 /* do nothing */
529 DPRINTF("invalid signature 0x%08x\n", tag);
530 break;
531 }
a41b1dd4 532 tag = UGETDW(sc->sc_cbw->dCBWTag);
12bd3c8b
SW
533
534 /* echo back tag */
a41b1dd4 535 USETDW(sc->sc_csw->dCSWTag, tag);
12bd3c8b
SW
536
537 /* reset status */
a41b1dd4 538 sc->sc_csw->bCSWStatus = 0;
12bd3c8b
SW
539
540 /* reset data offset, data length and data remainder */
541 sc->sc_transfer.offset = 0;
542 sc->sc_transfer.data_rem =
a41b1dd4 543 UGETDW(sc->sc_cbw->dCBWDataTransferLength);
12bd3c8b
SW
544
545 /* reset data flags */
546 sc->sc_transfer.data_short = 0;
547
548 /* extract LUN */
a41b1dd4 549 sc->sc_transfer.lun = sc->sc_cbw->bCBWLUN;
12bd3c8b
SW
550
551 if (sc->sc_transfer.data_rem == 0) {
552 sc->sc_transfer.cbw_dir = DIR_NONE;
553 } else {
a41b1dd4 554 if (sc->sc_cbw->bCBWFlags & CBWFLAGS_IN) {
12bd3c8b
SW
555 sc->sc_transfer.cbw_dir = DIR_WRITE;
556 } else {
557 sc->sc_transfer.cbw_dir = DIR_READ;
558 }
559 }
560
a41b1dd4
MP
561 sc->sc_transfer.cmd_len = sc->sc_cbw->bCDBLength;
562 if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw->CBWCDB)) ||
12bd3c8b
SW
563 (sc->sc_transfer.cmd_len == 0)) {
564 /* just halt - this is invalid */
565 DPRINTF("invalid command length %d bytes\n",
566 sc->sc_transfer.cmd_len);
567 break;
568 }
569
570 err = ustorage_fs_do_cmd(sc);
571 if (err) {
572 /* got an error */
573 DPRINTF("command failed\n");
574 break;
575 }
576 if ((sc->sc_transfer.data_rem > 0) &&
577 (sc->sc_transfer.cbw_dir != sc->sc_transfer.cmd_dir)) {
578 /* contradicting data transfer direction */
579 err = 1;
580 DPRINTF("data direction mismatch\n");
581 break;
582 }
583 switch (sc->sc_transfer.cbw_dir) {
584 case DIR_READ:
585 ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_DATA_READ);
586 break;
587 case DIR_WRITE:
588 ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_DATA_WRITE);
589 break;
590 default:
591 ustorage_fs_transfer_start(sc,
592 USTORAGE_FS_T_BBB_STATUS);
593 break;
594 }
595 break;
596
597 case USB_ST_SETUP:
598tr_setup:
599 if (sc->sc_transfer.data_error) {
600 sc->sc_transfer.data_error = 0;
601 usbd_xfer_set_stall(xfer);
602 DPRINTF("stall pipe\n");
603 }
a41b1dd4
MP
604 usbd_xfer_set_frame_len(xfer, 0,
605 sizeof(ustorage_fs_bbb_cbw_t));
12bd3c8b
SW
606 usbd_transfer_submit(xfer);
607 break;
608
609 default: /* Error */
610 DPRINTF("error\n");
611 if (error == USB_ERR_CANCELLED) {
612 break;
613 }
614 /* If the pipe is already stalled, don't do another stall */
615 if (!usbd_xfer_is_stalled(xfer))
616 sc->sc_transfer.data_error = 1;
617
618 /* try again */
619 goto tr_setup;
620 }
621 if (err) {
a41b1dd4 622 if (sc->sc_csw->bCSWStatus == 0) {
12bd3c8b 623 /* set some default error code */
a41b1dd4 624 sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
12bd3c8b
SW
625 }
626 if (sc->sc_transfer.cbw_dir == DIR_READ) {
627 /* dump all data */
628 ustorage_fs_transfer_start(sc,
629 USTORAGE_FS_T_BBB_DATA_DUMP);
630 return;
631 }
632 if (sc->sc_transfer.cbw_dir == DIR_WRITE) {
633 /* need to stall before status */
634 sc->sc_transfer.data_error = 1;
635 }
636 ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_STATUS);
637 }
638}
639
640static void
641ustorage_fs_t_bbb_data_dump_callback(struct usb_xfer *xfer, usb_error_t error)
642{
643 struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
644 uint32_t max_bulk = usbd_xfer_max_len(xfer);
645 int actlen, sumlen;
646
647 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
648
649 DPRINTF("\n");
650
651 switch (USB_GET_STATE(xfer)) {
652 case USB_ST_TRANSFERRED:
653 sc->sc_transfer.data_rem -= actlen;
654 sc->sc_transfer.offset += actlen;
655
656 if (actlen != sumlen || sc->sc_transfer.data_rem == 0) {
657 /* short transfer or end of data */
658 ustorage_fs_transfer_start(sc,
659 USTORAGE_FS_T_BBB_STATUS);
660 break;
661 }
662 /* Fallthrough */
663
664 case USB_ST_SETUP:
665tr_setup:
666 if (max_bulk > sc->sc_transfer.data_rem) {
667 max_bulk = sc->sc_transfer.data_rem;
668 }
669 if (sc->sc_transfer.data_error) {
670 sc->sc_transfer.data_error = 0;
671 usbd_xfer_set_stall(xfer);
672 }
673 usbd_xfer_set_frame_len(xfer, 0, max_bulk);
674 usbd_transfer_submit(xfer);
675 break;
676
677 default: /* Error */
678 if (error == USB_ERR_CANCELLED) {
679 break;
680 }
681 /*
682 * If the pipe is already stalled, don't do another stall:
683 */
684 if (!usbd_xfer_is_stalled(xfer))
685 sc->sc_transfer.data_error = 1;
686
687 /* try again */
688 goto tr_setup;
689 }
690}
691
692static void
693ustorage_fs_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
694{
695 struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
696 uint32_t max_bulk = usbd_xfer_max_len(xfer);
697 int actlen, sumlen;
698
699 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
700
701 DPRINTF("\n");
702
703 switch (USB_GET_STATE(xfer)) {
704 case USB_ST_TRANSFERRED:
a41b1dd4
MP
705 /* XXX copy data from DMA buffer */
706 memcpy(sc->sc_transfer.data_ptr, sc->sc_dma_ptr, actlen);
707
12bd3c8b
SW
708 sc->sc_transfer.data_rem -= actlen;
709 sc->sc_transfer.data_ptr += actlen;
710 sc->sc_transfer.offset += actlen;
711
712 if (actlen != sumlen || sc->sc_transfer.data_rem == 0) {
713 /* short transfer or end of data */
714 ustorage_fs_transfer_start(sc,
715 USTORAGE_FS_T_BBB_STATUS);
716 break;
717 }
718 /* Fallthrough */
719
720 case USB_ST_SETUP:
721tr_setup:
722 if (max_bulk > sc->sc_transfer.data_rem) {
723 max_bulk = sc->sc_transfer.data_rem;
724 }
725 if (sc->sc_transfer.data_error) {
726 sc->sc_transfer.data_error = 0;
727 usbd_xfer_set_stall(xfer);
728 }
729
a41b1dd4 730 usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
12bd3c8b
SW
731 usbd_transfer_submit(xfer);
732 break;
733
734 default: /* Error */
735 if (error == USB_ERR_CANCELLED) {
736 break;
737 }
738 /* If the pipe is already stalled, don't do another stall */
739 if (!usbd_xfer_is_stalled(xfer))
740 sc->sc_transfer.data_error = 1;
741
742 /* try again */
743 goto tr_setup;
744 }
745}
746
747static void
748ustorage_fs_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
749{
750 struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
751 uint32_t max_bulk = usbd_xfer_max_len(xfer);
752 int actlen, sumlen;
753
754 usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
755
756 DPRINTF("\n");
757
758 switch (USB_GET_STATE(xfer)) {
759 case USB_ST_TRANSFERRED:
760 sc->sc_transfer.data_rem -= actlen;
761 sc->sc_transfer.data_ptr += actlen;
762 sc->sc_transfer.offset += actlen;
763
764 if (actlen != sumlen || sc->sc_transfer.data_rem == 0) {
765 /* short transfer or end of data */
766 ustorage_fs_transfer_start(sc,
767 USTORAGE_FS_T_BBB_STATUS);
768 break;
769 }
770 case USB_ST_SETUP:
771tr_setup:
772 if (max_bulk >= sc->sc_transfer.data_rem) {
773 max_bulk = sc->sc_transfer.data_rem;
774 if (sc->sc_transfer.data_short)
775 usbd_xfer_set_flag(xfer, USB_FORCE_SHORT_XFER);
776 else
777 usbd_xfer_clr_flag(xfer, USB_FORCE_SHORT_XFER);
778 } else
779 usbd_xfer_clr_flag(xfer, USB_FORCE_SHORT_XFER);
780
781 if (sc->sc_transfer.data_error) {
782 sc->sc_transfer.data_error = 0;
783 usbd_xfer_set_stall(xfer);
784 }
785
a41b1dd4
MP
786 /* XXX copy data to DMA buffer */
787 memcpy(sc->sc_dma_ptr, sc->sc_transfer.data_ptr, max_bulk);
788
789 usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
12bd3c8b
SW
790 usbd_transfer_submit(xfer);
791 break;
792
793 default: /* Error */
794 if (error == USB_ERR_CANCELLED) {
795 break;
796 }
797 /*
798 * If the pipe is already stalled, don't do another
799 * stall
800 */
801 if (!usbd_xfer_is_stalled(xfer))
802 sc->sc_transfer.data_error = 1;
803
804 /* try again */
805 goto tr_setup;
806 }
807}
808
809static void
810ustorage_fs_t_bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
811{
812 struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
813
814 DPRINTF("\n");
815
816 switch (USB_GET_STATE(xfer)) {
817 case USB_ST_TRANSFERRED:
818 ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_COMMAND);
819 break;
820
821 case USB_ST_SETUP:
822tr_setup:
a41b1dd4
MP
823 USETDW(sc->sc_csw->dCSWSignature, CSWSIGNATURE);
824 USETDW(sc->sc_csw->dCSWDataResidue, sc->sc_transfer.data_rem);
12bd3c8b
SW
825
826 if (sc->sc_transfer.data_error) {
827 sc->sc_transfer.data_error = 0;
828 usbd_xfer_set_stall(xfer);
829 }
a41b1dd4
MP
830 usbd_xfer_set_frame_len(xfer, 0,
831 sizeof(ustorage_fs_bbb_csw_t));
12bd3c8b
SW
832 usbd_transfer_submit(xfer);
833 break;
834
835 default:
836 if (error == USB_ERR_CANCELLED) {
837 break;
838 }
839 /* If the pipe is already stalled, don't do another stall */
840 if (!usbd_xfer_is_stalled(xfer))
841 sc->sc_transfer.data_error = 1;
842
843 /* try again */
844 goto tr_setup;
845 }
846}
847
848/* SCSI commands that we recognize */
849#define SC_FORMAT_UNIT 0x04
850#define SC_INQUIRY 0x12
851#define SC_MODE_SELECT_6 0x15
852#define SC_MODE_SELECT_10 0x55
853#define SC_MODE_SENSE_6 0x1a
854#define SC_MODE_SENSE_10 0x5a
855#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
856#define SC_READ_6 0x08
857#define SC_READ_10 0x28
858#define SC_READ_12 0xa8
859#define SC_READ_CAPACITY 0x25
860#define SC_READ_FORMAT_CAPACITIES 0x23
861#define SC_RELEASE 0x17
862#define SC_REQUEST_SENSE 0x03
863#define SC_RESERVE 0x16
864#define SC_SEND_DIAGNOSTIC 0x1d
865#define SC_START_STOP_UNIT 0x1b
866#define SC_SYNCHRONIZE_CACHE 0x35
867#define SC_TEST_UNIT_READY 0x00
868#define SC_VERIFY 0x2f
869#define SC_WRITE_6 0x0a
870#define SC_WRITE_10 0x2a
871#define SC_WRITE_12 0xaa
872
873/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
874#define SS_NO_SENSE 0
875#define SS_COMMUNICATION_FAILURE 0x040800
876#define SS_INVALID_COMMAND 0x052000
877#define SS_INVALID_FIELD_IN_CDB 0x052400
878#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100
879#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500
880#define SS_MEDIUM_NOT_PRESENT 0x023a00
881#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302
882#define SS_NOT_READY_TO_READY_TRANSITION 0x062800
883#define SS_RESET_OCCURRED 0x062900
884#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900
885#define SS_UNRECOVERED_READ_ERROR 0x031100
886#define SS_WRITE_ERROR 0x030c02
887#define SS_WRITE_PROTECTED 0x072700
888
889#define SK(x) ((uint8_t) ((x) >> 16)) /* Sense Key byte, etc. */
890#define ASC(x) ((uint8_t) ((x) >> 8))
891#define ASCQ(x) ((uint8_t) (x))
892
893/* Routines for unaligned data access */
894
895static uint16_t
896get_be16(uint8_t *buf)
897{
898 return ((uint16_t)buf[0] << 8) | ((uint16_t)buf[1]);
899}
900
901static uint32_t
902get_be32(uint8_t *buf)
903{
904 return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
905 ((uint32_t)buf[2] << 8) | ((uint32_t)buf[3]);
906}
907
908static void
909put_be16(uint8_t *buf, uint16_t val)
910{
911 buf[0] = val >> 8;
912 buf[1] = val;
913}
914
915static void
916put_be32(uint8_t *buf, uint32_t val)
917{
918 buf[0] = val >> 24;
919 buf[1] = val >> 16;
920 buf[2] = val >> 8;
921 buf[3] = val & 0xff;
922}
923
924/*------------------------------------------------------------------------*
925 * ustorage_fs_verify
926 *
927 * Returns:
928 * 0: Success
929 * Else: Failure
930 *------------------------------------------------------------------------*/
931static uint8_t
932ustorage_fs_verify(struct ustorage_fs_softc *sc)
933{
934 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
935 uint32_t lba;
936 uint32_t vlen;
937 uint64_t file_offset;
938 uint64_t amount_left;
939
940 /*
941 * Get the starting Logical Block Address
942 */
a41b1dd4 943 lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
12bd3c8b
SW
944
945 /*
946 * We allow DPO (Disable Page Out = don't save data in the cache)
947 * but we don't implement it.
948 */
a41b1dd4 949 if ((sc->sc_cbw->CBWCDB[1] & ~0x10) != 0) {
12bd3c8b
SW
950 currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
951 return (1);
952 }
a41b1dd4 953 vlen = get_be16(&sc->sc_cbw->CBWCDB[7]);
12bd3c8b
SW
954 if (vlen == 0) {
955 goto done;
956 }
957 /* No default reply */
958
959 /* Prepare to carry out the file verify */
960 amount_left = vlen;
961 amount_left <<= 9;
962 file_offset = lba;
963 file_offset <<= 9;
964
965 /* Range check */
966 vlen += lba;
967
968 if ((vlen < lba) ||
969 (vlen > currlun->num_sectors) ||
970 (lba >= currlun->num_sectors)) {
971 currlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
972 return (1);
973 }
974 /* XXX TODO: verify that data is readable */
975done:
a41b1dd4 976 return (ustorage_fs_min_len(sc, 0, -1U));
12bd3c8b
SW
977}
978
979/*------------------------------------------------------------------------*
980 * ustorage_fs_inquiry
981 *
982 * Returns:
983 * 0: Success
984 * Else: Failure
985 *------------------------------------------------------------------------*/
986static uint8_t
987ustorage_fs_inquiry(struct ustorage_fs_softc *sc)
988{
989 uint8_t *buf = sc->sc_transfer.data_ptr;
990
991 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
992
993 if (!sc->sc_transfer.currlun) {
994 /* Unsupported LUNs are okay */
995 memset(buf, 0, 36);
996 buf[0] = 0x7f;
997 /* Unsupported, no device - type */
a41b1dd4 998 return (ustorage_fs_min_len(sc, 36, -1U));
12bd3c8b
SW
999 }
1000 memset(buf, 0, 8);
1001 /* Non - removable, direct - access device */
1002 if (currlun->removable)
1003 buf[1] = 0x80;
1004 buf[2] = 2;
1005 /* ANSI SCSI level 2 */
1006 buf[3] = 2;
1007 /* SCSI - 2 INQUIRY data format */
1008 buf[4] = 31;
1009 /* Additional length */
1010 /* No special options */
1011 /* Copy in ID string */
1012 memcpy(buf + 8, USTORAGE_FS_ID_STRING, 28);
1013
1014#if (USTORAGE_QDATA_MAX < 36)
1015#error "(USTORAGE_QDATA_MAX < 36)"
1016#endif
a41b1dd4 1017 return (ustorage_fs_min_len(sc, 36, -1U));
12bd3c8b
SW
1018}
1019
1020/*------------------------------------------------------------------------*
1021 * ustorage_fs_request_sense
1022 *
1023 * Returns:
1024 * 0: Success
1025 * Else: Failure
1026 *------------------------------------------------------------------------*/
1027static uint8_t
1028ustorage_fs_request_sense(struct ustorage_fs_softc *sc)
1029{
1030 uint8_t *buf = sc->sc_transfer.data_ptr;
1031 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1032 uint32_t sd;
1033 uint32_t sdinfo;
1034 uint8_t valid;
1035
1036 /*
1037 * From the SCSI-2 spec., section 7.9 (Unit attention condition):
1038 *
1039 * If a REQUEST SENSE command is received from an initiator
1040 * with a pending unit attention condition (before the target
1041 * generates the contingent allegiance condition), then the
1042 * target shall either:
1043 * a) report any pending sense data and preserve the unit
1044 * attention condition on the logical unit, or,
1045 * b) report the unit attention condition, may discard any
1046 * pending sense data, and clear the unit attention
1047 * condition on the logical unit for that initiator.
1048 *
1049 * FSG normally uses option a); enable this code to use option b).
1050 */
1051#if 0
1052 if (currlun && currlun->unit_attention_data != SS_NO_SENSE) {
1053 currlun->sense_data = currlun->unit_attention_data;
1054 currlun->unit_attention_data = SS_NO_SENSE;
1055 }
1056#endif
1057
1058 if (!currlun) {
1059 /* Unsupported LUNs are okay */
1060 sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
1061 sdinfo = 0;
1062 valid = 0;
1063 } else {
1064 sd = currlun->sense_data;
1065 sdinfo = currlun->sense_data_info;
1066 valid = currlun->info_valid << 7;
1067 currlun->sense_data = SS_NO_SENSE;
1068 currlun->sense_data_info = 0;
1069 currlun->info_valid = 0;
1070 }
1071
1072 memset(buf, 0, 18);
1073 buf[0] = valid | 0x70;
1074 /* Valid, current error */
1075 buf[2] = SK(sd);
1076 put_be32(&buf[3], sdinfo);
1077 /* Sense information */
1078 buf[7] = 18 - 8;
1079 /* Additional sense length */
1080 buf[12] = ASC(sd);
1081 buf[13] = ASCQ(sd);
1082
1083#if (USTORAGE_QDATA_MAX < 18)
1084#error "(USTORAGE_QDATA_MAX < 18)"
1085#endif
a41b1dd4 1086 return (ustorage_fs_min_len(sc, 18, -1U));
12bd3c8b
SW
1087}
1088
1089/*------------------------------------------------------------------------*
1090 * ustorage_fs_read_capacity
1091 *
1092 * Returns:
1093 * 0: Success
1094 * Else: Failure
1095 *------------------------------------------------------------------------*/
1096static uint8_t
1097ustorage_fs_read_capacity(struct ustorage_fs_softc *sc)
1098{
1099 uint8_t *buf = sc->sc_transfer.data_ptr;
1100 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
a41b1dd4
MP
1101 uint32_t lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
1102 uint8_t pmi = sc->sc_cbw->CBWCDB[8];
12bd3c8b
SW
1103
1104 /* Check the PMI and LBA fields */
1105 if ((pmi > 1) || ((pmi == 0) && (lba != 0))) {
1106 currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1107 return (1);
1108 }
1109 /* Max logical block */
1110 put_be32(&buf[0], currlun->num_sectors - 1);
1111 /* Block length */
1112 put_be32(&buf[4], 512);
1113
1114#if (USTORAGE_QDATA_MAX < 8)
1115#error "(USTORAGE_QDATA_MAX < 8)"
1116#endif
a41b1dd4 1117 return (ustorage_fs_min_len(sc, 8, -1U));
12bd3c8b
SW
1118}
1119
1120/*------------------------------------------------------------------------*
1121 * ustorage_fs_mode_sense
1122 *
1123 * Returns:
1124 * 0: Success
1125 * Else: Failure
1126 *------------------------------------------------------------------------*/
1127static uint8_t
1128ustorage_fs_mode_sense(struct ustorage_fs_softc *sc)
1129{
1130 uint8_t *buf = sc->sc_transfer.data_ptr;
1131 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1132 uint8_t *buf0;
1133 uint16_t len;
1134 uint16_t limit;
a41b1dd4 1135 uint8_t mscmnd = sc->sc_cbw->CBWCDB[0];
12bd3c8b
SW
1136 uint8_t pc;
1137 uint8_t page_code;
1138 uint8_t changeable_values;
1139 uint8_t all_pages;
1140
1141 buf0 = buf;
1142
a41b1dd4 1143 if ((sc->sc_cbw->CBWCDB[1] & ~0x08) != 0) {
12bd3c8b
SW
1144 /* Mask away DBD */
1145 currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1146 return (1);
1147 }
a41b1dd4
MP
1148 pc = sc->sc_cbw->CBWCDB[2] >> 6;
1149 page_code = sc->sc_cbw->CBWCDB[2] & 0x3f;
12bd3c8b
SW
1150 if (pc == 3) {
1151 currlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
1152 return (1);
1153 }
1154 changeable_values = (pc == 1);
1155 all_pages = (page_code == 0x3f);
1156
1157 /*
1158 * Write the mode parameter header. Fixed values are: default
1159 * medium type, no cache control (DPOFUA), and no block descriptors.
1160 * The only variable value is the WriteProtect bit. We will fill in
1161 * the mode data length later.
1162 */
1163 memset(buf, 0, 8);
1164 if (mscmnd == SC_MODE_SENSE_6) {
1165 buf[2] = (currlun->read_only ? 0x80 : 0x00);
1166 /* WP, DPOFUA */
1167 buf += 4;
1168 limit = 255;
1169 } else {
1170 /* SC_MODE_SENSE_10 */
1171 buf[3] = (currlun->read_only ? 0x80 : 0x00);
1172 /* WP, DPOFUA */
1173 buf += 8;
1174 limit = 65535;
1175 /* Should really be mod_data.buflen */
1176 }
1177
1178 /* No block descriptors */
1179
1180 /*
1181 * The mode pages, in numerical order.
1182 */
1183 if ((page_code == 0x08) || all_pages) {
1184 buf[0] = 0x08;
1185 /* Page code */
1186 buf[1] = 10;
1187 /* Page length */
1188 memset(buf + 2, 0, 10);
1189 /* None of the fields are changeable */
1190
1191 if (!changeable_values) {
1192 buf[2] = 0x04;
1193 /* Write cache enable, */
1194 /* Read cache not disabled */
1195 /* No cache retention priorities */
1196 put_be16(&buf[4], 0xffff);
1197 /* Don 't disable prefetch */
1198 /* Minimum prefetch = 0 */
1199 put_be16(&buf[8], 0xffff);
1200 /* Maximum prefetch */
1201 put_be16(&buf[10], 0xffff);
1202 /* Maximum prefetch ceiling */
1203 }
1204 buf += 12;
1205 }
1206 /*
1207 * Check that a valid page was requested and the mode data length
1208 * isn't too long.
1209 */
1210 len = buf - buf0;
1211 if (len > limit) {
1212 currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1213 return (1);
1214 }
1215 /* Store the mode data length */
1216 if (mscmnd == SC_MODE_SENSE_6)
1217 buf0[0] = len - 1;
1218 else
1219 put_be16(buf0, len - 2);
1220
1221#if (USTORAGE_QDATA_MAX < 24)
1222#error "(USTORAGE_QDATA_MAX < 24)"
1223#endif
a41b1dd4 1224 return (ustorage_fs_min_len(sc, len, -1U));
12bd3c8b
SW
1225}
1226
1227/*------------------------------------------------------------------------*
1228 * ustorage_fs_start_stop
1229 *
1230 * Returns:
1231 * 0: Success
1232 * Else: Failure
1233 *------------------------------------------------------------------------*/
1234static uint8_t
1235ustorage_fs_start_stop(struct ustorage_fs_softc *sc)
1236{
1237 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1238 uint8_t loej;
1239 uint8_t start;
1240 uint8_t immed;
1241
1242 if (!currlun->removable) {
1243 currlun->sense_data = SS_INVALID_COMMAND;
1244 return (1);
1245 }
a41b1dd4
MP
1246 immed = sc->sc_cbw->CBWCDB[1] & 0x01;
1247 loej = sc->sc_cbw->CBWCDB[4] & 0x02;
1248 start = sc->sc_cbw->CBWCDB[4] & 0x01;
12bd3c8b
SW
1249
1250 if (immed || loej || start) {
1251 /* compile fix */
1252 }
1253 return (0);
1254}
1255
1256/*------------------------------------------------------------------------*
1257 * ustorage_fs_prevent_allow
1258 *
1259 * Returns:
1260 * 0: Success
1261 * Else: Failure
1262 *------------------------------------------------------------------------*/
1263static uint8_t
1264ustorage_fs_prevent_allow(struct ustorage_fs_softc *sc)
1265{
1266 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1267 uint8_t prevent;
1268
1269 if (!currlun->removable) {
1270 currlun->sense_data = SS_INVALID_COMMAND;
1271 return (1);
1272 }
a41b1dd4
MP
1273 prevent = sc->sc_cbw->CBWCDB[4] & 0x01;
1274 if ((sc->sc_cbw->CBWCDB[4] & ~0x01) != 0) {
12bd3c8b
SW
1275 /* Mask away Prevent */
1276 currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1277 return (1);
1278 }
1279 if (currlun->prevent_medium_removal && !prevent) {
1280 //fsync_sub(currlun);
1281 }
1282 currlun->prevent_medium_removal = prevent;
1283 return (0);
1284}
1285
1286/*------------------------------------------------------------------------*
1287 * ustorage_fs_read_format_capacities
1288 *
1289 * Returns:
1290 * 0: Success
1291 * Else: Failure
1292 *------------------------------------------------------------------------*/
1293static uint8_t
1294ustorage_fs_read_format_capacities(struct ustorage_fs_softc *sc)
1295{
1296 uint8_t *buf = sc->sc_transfer.data_ptr;
1297 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1298
1299 buf[0] = buf[1] = buf[2] = 0;
1300 buf[3] = 8;
1301 /* Only the Current / Maximum Capacity Descriptor */
1302 buf += 4;
1303
1304 /* Number of blocks */
1305 put_be32(&buf[0], currlun->num_sectors);
1306 /* Block length */
1307 put_be32(&buf[4], 512);
1308 /* Current capacity */
1309 buf[4] = 0x02;
1310
1311#if (USTORAGE_QDATA_MAX < 12)
1312#error "(USTORAGE_QDATA_MAX < 12)"
1313#endif
a41b1dd4 1314 return (ustorage_fs_min_len(sc, 12, -1U));
12bd3c8b
SW
1315}
1316
1317/*------------------------------------------------------------------------*
1318 * ustorage_fs_mode_select
1319 *
1320 * Return values:
1321 * 0: Success
1322 * Else: Failure
1323 *------------------------------------------------------------------------*/
1324static uint8_t
1325ustorage_fs_mode_select(struct ustorage_fs_softc *sc)
1326{
1327 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1328
1329 /* We don't support MODE SELECT */
1330 currlun->sense_data = SS_INVALID_COMMAND;
1331 return (1);
1332}
1333
1334/*------------------------------------------------------------------------*
1335 * ustorage_fs_synchronize_cache
1336 *
1337 * Return values:
1338 * 0: Success
1339 * Else: Failure
1340 *------------------------------------------------------------------------*/
1341static uint8_t
1342ustorage_fs_synchronize_cache(struct ustorage_fs_softc *sc)
1343{
1344#if 0
1345 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1346 uint8_t rc;
1347
1348 /*
1349 * We ignore the requested LBA and write out all dirty data buffers.
1350 */
1351 rc = 0;
1352 if (rc) {
1353 currlun->sense_data = SS_WRITE_ERROR;
1354 }
1355#endif
1356 return (0);
1357}
1358
1359/*------------------------------------------------------------------------*
1360 * ustorage_fs_read - read data from disk
1361 *
1362 * Return values:
1363 * 0: Success
1364 * Else: Failure
1365 *------------------------------------------------------------------------*/
1366static uint8_t
1367ustorage_fs_read(struct ustorage_fs_softc *sc)
1368{
1369 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1370 uint64_t file_offset;
1371 uint32_t lba;
1372 uint32_t len;
1373
1374 /*
1375 * Get the starting Logical Block Address and check that it's not
1376 * too big
1377 */
a41b1dd4
MP
1378 if (sc->sc_cbw->CBWCDB[0] == SC_READ_6) {
1379 lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
1380 get_be16(&sc->sc_cbw->CBWCDB[2]);
12bd3c8b 1381 } else {
a41b1dd4 1382 lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
12bd3c8b
SW
1383
1384 /*
1385 * We allow DPO (Disable Page Out = don't save data in the
1386 * cache) and FUA (Force Unit Access = don't read from the
1387 * cache), but we don't implement them.
1388 */
a41b1dd4 1389 if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
12bd3c8b
SW
1390 currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1391 return (1);
1392 }
1393 }
1394 len = sc->sc_transfer.data_rem >> 9;
1395 len += lba;
1396
1397 if ((len < lba) ||
1398 (len > currlun->num_sectors) ||
1399 (lba >= currlun->num_sectors)) {
1400 currlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1401 return (1);
1402 }
1403 file_offset = lba;
1404 file_offset <<= 9;
1405
1406 sc->sc_transfer.data_ptr = currlun->memory_image + file_offset;
1407
1408 return (0);
1409}
1410
1411/*------------------------------------------------------------------------*
1412 * ustorage_fs_write - write data to disk
1413 *
1414 * Return values:
1415 * 0: Success
1416 * Else: Failure
1417 *------------------------------------------------------------------------*/
1418static uint8_t
1419ustorage_fs_write(struct ustorage_fs_softc *sc)
1420{
1421 struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1422 uint64_t file_offset;
1423 uint32_t lba;
1424 uint32_t len;
1425
1426 if (currlun->read_only) {
1427 currlun->sense_data = SS_WRITE_PROTECTED;
1428 return (1);
1429 }
1430 /* XXX clear SYNC */
1431
1432 /*
1433 * Get the starting Logical Block Address and check that it's not
1434 * too big.
1435 */
a41b1dd4
MP
1436 if (sc->sc_cbw->CBWCDB[0] == SC_WRITE_6)
1437 lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
1438 get_be16(&sc->sc_cbw->CBWCDB[2]);
12bd3c8b 1439 else {
a41b1dd4 1440 lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
12bd3c8b
SW
1441
1442 /*
1443 * We allow DPO (Disable Page Out = don't save data in the
1444 * cache) and FUA (Force Unit Access = write directly to the
1445 * medium). We don't implement DPO; we implement FUA by
1446 * performing synchronous output.
1447 */
a41b1dd4 1448 if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
12bd3c8b
SW
1449 currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1450 return (1);
1451 }
a41b1dd4 1452 if (sc->sc_cbw->CBWCDB[1] & 0x08) {
12bd3c8b
SW
1453 /* FUA */
1454 /* XXX set SYNC flag here */
1455 }
1456 }
1457
1458 len = sc->sc_transfer.data_rem >> 9;
1459 len += lba;
1460
1461 if ((len < lba) ||
1462 (len > currlun->num_sectors) ||
1463 (lba >= currlun->num_sectors)) {
1464 currlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1465 return (1);
1466 }
1467 file_offset = lba;
1468 file_offset <<= 9;
1469
1470 sc->sc_transfer.data_ptr = currlun->memory_image + file_offset;
1471
1472 return (0);
1473}
1474
1475/*------------------------------------------------------------------------*
1476 * ustorage_fs_min_len
1477 *
1478 * Return values:
1479 * 0: Success
1480 * Else: Failure
1481 *------------------------------------------------------------------------*/
1482static uint8_t
1483ustorage_fs_min_len(struct ustorage_fs_softc *sc, uint32_t len, uint32_t mask)
1484{
1485 if (len != sc->sc_transfer.data_rem) {
1486
1487 if (sc->sc_transfer.cbw_dir == DIR_READ) {
1488 /*
1489 * there must be something wrong about this SCSI
1490 * command
1491 */
a41b1dd4 1492 sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
12bd3c8b
SW
1493 return (1);
1494 }
1495 /* compute the minimum length */
1496
1497 if (sc->sc_transfer.data_rem > len) {
1498 /* data ends prematurely */
1499 sc->sc_transfer.data_rem = len;
1500 sc->sc_transfer.data_short = 1;
1501 }
1502 /* check length alignment */
1503
1504 if (sc->sc_transfer.data_rem & ~mask) {
1505 /* data ends prematurely */
1506 sc->sc_transfer.data_rem &= mask;
1507 sc->sc_transfer.data_short = 1;
1508 }
1509 }
1510 return (0);
1511}
1512
1513/*------------------------------------------------------------------------*
1514 * ustorage_fs_check_cmd - check command routine
1515 *
1516 * Check whether the command is properly formed and whether its data
1517 * size and direction agree with the values we already have.
1518 *
1519 * Return values:
1520 * 0: Success
1521 * Else: Failure
1522 *------------------------------------------------------------------------*/
1523static uint8_t
1524ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
1525 uint16_t mask, uint8_t needs_medium)
1526{
1527 struct ustorage_fs_lun *currlun;
a41b1dd4 1528 uint8_t lun = (sc->sc_cbw->CBWCDB[1] >> 5);
12bd3c8b
SW
1529 uint8_t i;
1530
1531 /* Verify the length of the command itself */
1532 if (min_cmd_size > sc->sc_transfer.cmd_len) {
1533 DPRINTF("%u > %u\n",
1534 min_cmd_size, sc->sc_transfer.cmd_len);
a41b1dd4 1535 sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
12bd3c8b
SW
1536 return (1);
1537 }
1538 /* Mask away the LUN */
a41b1dd4 1539 sc->sc_cbw->CBWCDB[1] &= 0x1f;
12bd3c8b
SW
1540
1541 /* Check if LUN is correct */
1542 if (lun != sc->sc_transfer.lun) {
1543
1544 }
1545 /* Check the LUN */
1546 if (sc->sc_transfer.lun <= sc->sc_last_lun) {
1547 sc->sc_transfer.currlun = currlun =
1548 sc->sc_lun + sc->sc_transfer.lun;
a41b1dd4 1549 if (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE) {
12bd3c8b
SW
1550 currlun->sense_data = SS_NO_SENSE;
1551 currlun->sense_data_info = 0;
1552 currlun->info_valid = 0;
1553 }
1554 /*
1555 * If a unit attention condition exists, only INQUIRY
1556 * and REQUEST SENSE commands are allowed. Anything
1557 * else must fail!
1558 */
1559 if ((currlun->unit_attention_data != SS_NO_SENSE) &&
a41b1dd4
MP
1560 (sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
1561 (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
12bd3c8b
SW
1562 currlun->sense_data = currlun->unit_attention_data;
1563 currlun->unit_attention_data = SS_NO_SENSE;
1564 return (1);
1565 }
1566 } else {
1567 sc->sc_transfer.currlun = currlun = NULL;
1568
1569 /*
1570 * INQUIRY and REQUEST SENSE commands are explicitly allowed
1571 * to use unsupported LUNs; all others may not.
1572 */
a41b1dd4
MP
1573 if ((sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
1574 (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
12bd3c8b
SW
1575 return (1);
1576 }
1577 }
1578
1579 /*
1580 * Check that only command bytes listed in the mask are
1581 * non-zero.
1582 */
1583 for (i = 0; i != min_cmd_size; i++) {
a41b1dd4 1584 if (sc->sc_cbw->CBWCDB[i] && !(mask & (1UL << i))) {
12bd3c8b
SW
1585 if (currlun) {
1586 currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1587 }
1588 return (1);
1589 }
1590 }
1591
1592 /*
1593 * If the medium isn't mounted and the command needs to access
1594 * it, return an error.
1595 */
1596 if (currlun && (!currlun->memory_image) && needs_medium) {
1597 currlun->sense_data = SS_MEDIUM_NOT_PRESENT;
1598 return (1);
1599 }
1600 return (0);
1601}
1602
1603/*------------------------------------------------------------------------*
1604 * ustorage_fs_do_cmd - do command
1605 *
1606 * Return values:
1607 * 0: Success
1608 * Else: Failure
1609 *------------------------------------------------------------------------*/
1610static uint8_t
1611ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
1612{
1613 uint8_t error = 1;
1614 uint8_t i;
1615 uint32_t temp;
1616 const uint32_t mask9 = (0xFFFFFFFFUL >> 9) << 9;
1617
1618 /* set default data transfer pointer */
1619 sc->sc_transfer.data_ptr = sc->sc_qdata;
1620
1621 DPRINTF("cmd_data[0]=0x%02x, data_rem=0x%08x\n",
a41b1dd4 1622 sc->sc_cbw->CBWCDB[0], sc->sc_transfer.data_rem);
12bd3c8b 1623
a41b1dd4 1624 switch (sc->sc_cbw->CBWCDB[0]) {
12bd3c8b
SW
1625 case SC_INQUIRY:
1626 sc->sc_transfer.cmd_dir = DIR_WRITE;
a41b1dd4 1627 error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
12bd3c8b
SW
1628 if (error) {
1629 break;
1630 }
1631 error = ustorage_fs_check_cmd(sc, 6,
1632 (1UL << 4) | 1, 0);
1633 if (error) {
1634 break;
1635 }
1636 error = ustorage_fs_inquiry(sc);
1637
1638 break;
1639
1640 case SC_MODE_SELECT_6:
1641 sc->sc_transfer.cmd_dir = DIR_READ;
a41b1dd4 1642 error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
12bd3c8b
SW
1643 if (error) {
1644 break;
1645 }
1646 error = ustorage_fs_check_cmd(sc, 6,
1647 (1UL << 1) | (1UL << 4) | 1, 0);
1648 if (error) {
1649 break;
1650 }
1651 error = ustorage_fs_mode_select(sc);
1652
1653 break;
1654
1655 case SC_MODE_SELECT_10:
1656 sc->sc_transfer.cmd_dir = DIR_READ;
1657 error = ustorage_fs_min_len(sc,
a41b1dd4 1658 get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
12bd3c8b
SW
1659 if (error) {
1660 break;
1661 }
1662 error = ustorage_fs_check_cmd(sc, 10,
1663 (1UL << 1) | (3UL << 7) | 1, 0);
1664 if (error) {
1665 break;
1666 }
1667 error = ustorage_fs_mode_select(sc);
1668
1669 break;
1670
1671 case SC_MODE_SENSE_6:
1672 sc->sc_transfer.cmd_dir = DIR_WRITE;
a41b1dd4 1673 error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
12bd3c8b
SW
1674 if (error) {
1675 break;
1676 }
1677 error = ustorage_fs_check_cmd(sc, 6,
1678 (1UL << 1) | (1UL << 2) | (1UL << 4) | 1, 0);
1679 if (error) {
1680 break;
1681 }
1682 error = ustorage_fs_mode_sense(sc);
1683
1684 break;
1685
1686 case SC_MODE_SENSE_10:
1687 sc->sc_transfer.cmd_dir = DIR_WRITE;
1688 error = ustorage_fs_min_len(sc,
a41b1dd4 1689 get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
12bd3c8b
SW
1690 if (error) {
1691 break;
1692 }
1693 error = ustorage_fs_check_cmd(sc, 10,
1694 (1UL << 1) | (1UL << 2) | (3UL << 7) | 1, 0);
1695 if (error) {
1696 break;
1697 }
1698 error = ustorage_fs_mode_sense(sc);
1699
1700 break;
1701
1702 case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
a41b1dd4 1703 error = ustorage_fs_min_len(sc, 0, -1U);
12bd3c8b
SW
1704 if (error) {
1705 break;
1706 }
1707 error = ustorage_fs_check_cmd(sc, 6,
1708 (1UL << 4) | 1, 0);
1709 if (error) {
1710 break;
1711 }
1712 error = ustorage_fs_prevent_allow(sc);
1713
1714 break;
1715
1716 case SC_READ_6:
a41b1dd4 1717 i = sc->sc_cbw->CBWCDB[4];
12bd3c8b
SW
1718 sc->sc_transfer.cmd_dir = DIR_WRITE;
1719 temp = ((i == 0) ? 256UL : i);
1720 error = ustorage_fs_min_len(sc, temp << 9, mask9);
1721 if (error) {
1722 break;
1723 }
1724 error = ustorage_fs_check_cmd(sc, 6,
1725 (7UL << 1) | (1UL << 4) | 1, 1);
1726 if (error) {
1727 break;
1728 }
1729 error = ustorage_fs_read(sc);
1730
1731 break;
1732
1733 case SC_READ_10:
1734 sc->sc_transfer.cmd_dir = DIR_WRITE;
a41b1dd4 1735 temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
12bd3c8b
SW
1736 error = ustorage_fs_min_len(sc, temp << 9, mask9);
1737 if (error) {
1738 break;
1739 }
1740 error = ustorage_fs_check_cmd(sc, 10,
1741 (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
1742 if (error) {
1743 break;
1744 }
1745 error = ustorage_fs_read(sc);
1746
1747 break;
1748
1749 case SC_READ_12:
1750 sc->sc_transfer.cmd_dir = DIR_WRITE;
a41b1dd4 1751 temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
12bd3c8b
SW
1752 if (temp >= (1UL << (32 - 9))) {
1753 /* numerical overflow */
a41b1dd4 1754 sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
12bd3c8b
SW
1755 error = 1;
1756 break;
1757 }
1758 error = ustorage_fs_min_len(sc, temp << 9, mask9);
1759 if (error) {
1760 break;
1761 }
1762 error = ustorage_fs_check_cmd(sc, 12,
1763 (1UL << 1) | (0xfUL << 2) | (0xfUL << 6) | 1, 1);
1764 if (error) {
1765 break;
1766 }
1767 error = ustorage_fs_read(sc);
1768
1769 break;
1770
1771 case SC_READ_CAPACITY:
1772 sc->sc_transfer.cmd_dir = DIR_WRITE;
1773 error = ustorage_fs_check_cmd(sc, 10,
1774 (0xfUL << 2) | (1UL << 8) | 1, 1);
1775 if (error) {
1776 break;
1777 }
1778 error = ustorage_fs_read_capacity(sc);
1779
1780 break;
1781
1782 case SC_READ_FORMAT_CAPACITIES:
1783 sc->sc_transfer.cmd_dir = DIR_WRITE;
1784 error = ustorage_fs_min_len(sc,
a41b1dd4 1785 get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
12bd3c8b
SW
1786 if (error) {
1787 break;
1788 }
1789 error = ustorage_fs_check_cmd(sc, 10,
1790 (3UL << 7) | 1, 1);
1791 if (error) {
1792 break;
1793 }
1794 error = ustorage_fs_read_format_capacities(sc);
1795
1796 break;
1797
1798 case SC_REQUEST_SENSE:
1799 sc->sc_transfer.cmd_dir = DIR_WRITE;
a41b1dd4 1800 error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
12bd3c8b
SW
1801 if (error) {
1802 break;
1803 }
1804 error = ustorage_fs_check_cmd(sc, 6,
1805 (1UL << 4) | 1, 0);
1806 if (error) {
1807 break;
1808 }
1809 error = ustorage_fs_request_sense(sc);
1810
1811 break;
1812
1813 case SC_START_STOP_UNIT:
a41b1dd4 1814 error = ustorage_fs_min_len(sc, 0, -1U);
12bd3c8b
SW
1815 if (error) {
1816 break;
1817 }
1818 error = ustorage_fs_check_cmd(sc, 6,
1819 (1UL << 1) | (1UL << 4) | 1, 0);
1820 if (error) {
1821 break;
1822 }
1823 error = ustorage_fs_start_stop(sc);
1824
1825 break;
1826
1827 case SC_SYNCHRONIZE_CACHE:
a41b1dd4 1828 error = ustorage_fs_min_len(sc, 0, -1U);
12bd3c8b
SW
1829 if (error) {
1830 break;
1831 }
1832 error = ustorage_fs_check_cmd(sc, 10,
1833 (0xfUL << 2) | (3UL << 7) | 1, 1);
1834 if (error) {
1835 break;
1836 }
1837 error = ustorage_fs_synchronize_cache(sc);
1838
1839 break;
1840
1841 case SC_TEST_UNIT_READY:
a41b1dd4 1842 error = ustorage_fs_min_len(sc, 0, -1U);
12bd3c8b
SW
1843 if (error) {
1844 break;
1845 }
1846 error = ustorage_fs_check_cmd(sc, 6,
1847 0 | 1, 1);
1848 break;
1849
1850 /*
1851 * Although optional, this command is used by MS-Windows.
1852 * We support a minimal version: BytChk must be 0.
1853 */
1854 case SC_VERIFY:
a41b1dd4 1855 error = ustorage_fs_min_len(sc, 0, -1U);
12bd3c8b
SW
1856 if (error) {
1857 break;
1858 }
1859 error = ustorage_fs_check_cmd(sc, 10,
1860 (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
1861 if (error) {
1862 break;
1863 }
1864 error = ustorage_fs_verify(sc);
1865
1866 break;
1867
1868 case SC_WRITE_6:
a41b1dd4 1869 i = sc->sc_cbw->CBWCDB[4];
12bd3c8b
SW
1870 sc->sc_transfer.cmd_dir = DIR_READ;
1871 temp = ((i == 0) ? 256UL : i);
1872 error = ustorage_fs_min_len(sc, temp << 9, mask9);
1873 if (error) {
1874 break;
1875 }
1876 error = ustorage_fs_check_cmd(sc, 6,
1877 (7UL << 1) | (1UL << 4) | 1, 1);
1878 if (error) {
1879 break;
1880 }
1881 error = ustorage_fs_write(sc);
1882
1883 break;
1884
1885 case SC_WRITE_10:
1886 sc->sc_transfer.cmd_dir = DIR_READ;
a41b1dd4 1887 temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
12bd3c8b
SW
1888 error = ustorage_fs_min_len(sc, temp << 9, mask9);
1889 if (error) {
1890 break;
1891 }
1892 error = ustorage_fs_check_cmd(sc, 10,
1893 (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
1894 if (error) {
1895 break;
1896 }
1897 error = ustorage_fs_write(sc);
1898
1899 break;
1900
1901 case SC_WRITE_12:
1902 sc->sc_transfer.cmd_dir = DIR_READ;
a41b1dd4 1903 temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
12bd3c8b
SW
1904 if (temp > (mask9 >> 9)) {
1905 /* numerical overflow */
a41b1dd4 1906 sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
12bd3c8b
SW
1907 error = 1;
1908 break;
1909 }
1910 error = ustorage_fs_min_len(sc, temp << 9, mask9);
1911 if (error) {
1912 break;
1913 }
1914 error = ustorage_fs_check_cmd(sc, 12,
1915 (1UL << 1) | (0xfUL << 2) | (0xfUL << 6) | 1, 1);
1916 if (error) {
1917 break;
1918 }
1919 error = ustorage_fs_write(sc);
1920
1921 break;
1922
1923 /*
1924 * Some mandatory commands that we recognize but don't
1925 * implement. They don't mean much in this setting.
1926 * It's left as an exercise for anyone interested to
1927 * implement RESERVE and RELEASE in terms of Posix
1928 * locks.
1929 */
1930 case SC_FORMAT_UNIT:
1931 case SC_RELEASE:
1932 case SC_RESERVE:
1933 case SC_SEND_DIAGNOSTIC:
1934 /* Fallthrough */
1935
1936 default:
a41b1dd4 1937 error = ustorage_fs_min_len(sc, 0, -1U);
12bd3c8b
SW
1938 if (error) {
1939 break;
1940 }
1941 error = ustorage_fs_check_cmd(sc, sc->sc_transfer.cmd_len,
1942 0xff, 0);
1943 if (error) {
1944 break;
1945 }
1946 sc->sc_transfer.currlun->sense_data =
1947 SS_INVALID_COMMAND;
1948 error = 1;
1949
1950 break;
1951 }
1952 return (error);
1953}