ustorage_fs.c revision 244503
1217806Slstewart/* $FreeBSD: head/sys/dev/usb/storage/ustorage_fs.c 244503 2012-12-20 18:38:02Z hselasky $ */
2217806Slstewart/*-
3217806Slstewart * Copyright (C) 2003-2005 Alan Stern
4217806Slstewart * Copyright (C) 2008 Hans Petter Selasky
5217806Slstewart * All rights reserved.
6217806Slstewart *
7217806Slstewart * Redistribution and use in source and binary forms, with or without
8217806Slstewart * modification, are permitted provided that the following conditions
9220560Slstewart * are met:
10220560Slstewart * 1. Redistributions of source code must retain the above copyright
11220560Slstewart *    notice, this list of conditions, and the following disclaimer,
12217806Slstewart *    without modification.
13217806Slstewart * 2. Redistributions in binary form must reproduce the above copyright
14217806Slstewart *    notice, this list of conditions and the following disclaimer in the
15217806Slstewart *    documentation and/or other materials provided with the distribution.
16217806Slstewart * 3. The names of the above-listed copyright holders may not be used
17217806Slstewart *    to endorse or promote products derived from this software without
18217806Slstewart *    specific prior written permission.
19217806Slstewart *
20217806Slstewart *
21217806Slstewart * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22217806Slstewart * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23217806Slstewart * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24217806Slstewart * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25217806Slstewart * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26217806Slstewart * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27217806Slstewart * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28217806Slstewart * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29217806Slstewart * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30217806Slstewart * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31217806Slstewart * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32217806Slstewart */
33217806Slstewart
34217806Slstewart/*
35217806Slstewart * NOTE: Much of the SCSI statemachine handling code derives from the
36217806Slstewart * Linux USB gadget stack.
37217806Slstewart */
38217806Slstewart
39217806Slstewart#include <sys/stdint.h>
40217806Slstewart#include <sys/stddef.h>
41217806Slstewart#include <sys/param.h>
42217806Slstewart#include <sys/queue.h>
43217806Slstewart#include <sys/types.h>
44217806Slstewart#include <sys/systm.h>
45217806Slstewart#include <sys/kernel.h>
46217806Slstewart#include <sys/bus.h>
47217806Slstewart#include <sys/module.h>
48217806Slstewart#include <sys/lock.h>
49217806Slstewart#include <sys/mutex.h>
50217806Slstewart#include <sys/condvar.h>
51217806Slstewart#include <sys/sysctl.h>
52217806Slstewart#include <sys/sx.h>
53217806Slstewart#include <sys/unistd.h>
54217806Slstewart#include <sys/callout.h>
55217806Slstewart#include <sys/malloc.h>
56217806Slstewart#include <sys/priv.h>
57217806Slstewart
58217806Slstewart#include <dev/usb/usb.h>
59217806Slstewart#include <dev/usb/usbdi.h>
60217806Slstewart#include "usbdevs.h"
61217806Slstewart#include "usb_if.h"
62217806Slstewart
63217806Slstewart#define	USB_DEBUG_VAR ustorage_fs_debug
64217806Slstewart#include <dev/usb/usb_debug.h>
65217806Slstewart
66217806Slstewart#ifdef USB_DEBUG
67217806Slstewartstatic int ustorage_fs_debug = 0;
68217806Slstewart
69217806SlstewartSYSCTL_NODE(_hw_usb, OID_AUTO, ustorage_fs, CTLFLAG_RW, 0, "USB ustorage_fs");
70217806SlstewartSYSCTL_INT(_hw_usb_ustorage_fs, OID_AUTO, debug, CTLFLAG_RW,
71217806Slstewart    &ustorage_fs_debug, 0, "ustorage_fs debug level");
72217806Slstewart#endif
73217806Slstewart
74217806Slstewart/* Define some limits */
75217806Slstewart
76217806Slstewart#ifndef USTORAGE_FS_BULK_SIZE
77217806Slstewart#define	USTORAGE_FS_BULK_SIZE	(1U << 17)	/* bytes */
78217806Slstewart#endif
79217806Slstewart
80217806Slstewart#ifndef	USTORAGE_FS_MAX_LUN
81217806Slstewart#define	USTORAGE_FS_MAX_LUN	8	/* units */
82217806Slstewart#endif
83217806Slstewart
84217806Slstewart#ifndef USTORAGE_QDATA_MAX
85217806Slstewart#define	USTORAGE_QDATA_MAX	40	/* bytes */
86217806Slstewart#endif
87217806Slstewart
88217806Slstewart/*
89217806Slstewart * The SCSI ID string must be exactly 28 characters long
90217806Slstewart * exluding the terminating zero.
91217806Slstewart */
92217806Slstewart#ifndef USTORAGE_FS_ID_STRING
93217806Slstewart#define	USTORAGE_FS_ID_STRING \
94217806Slstewart	"FreeBSD " /* 8 */ \
95217806Slstewart	"File-Stor Gadget" /* 16 */ \
96217806Slstewart	"0101" /* 4 */
97217806Slstewart#endif
98217806Slstewart
99217806Slstewart/*
100217806Slstewart * The following macro defines the number of
101217806Slstewart * sectors to be allocated for the RAM disk:
102217806Slstewart */
103217806Slstewart#ifndef USTORAGE_FS_RAM_SECT
104217806Slstewart#define	USTORAGE_FS_RAM_SECT (1UL << 13)
105217806Slstewart#endif
106217806Slstewart
107217806Slstewartstatic uint8_t *ustorage_fs_ramdisk;
108217806Slstewart
109217806Slstewart/* USB transfer definitions */
110217806Slstewart
111217806Slstewart#define	USTORAGE_FS_T_BBB_COMMAND     0
112217806Slstewart#define	USTORAGE_FS_T_BBB_DATA_DUMP   1
113217806Slstewart#define	USTORAGE_FS_T_BBB_DATA_READ   2
114217806Slstewart#define	USTORAGE_FS_T_BBB_DATA_WRITE  3
115217806Slstewart#define	USTORAGE_FS_T_BBB_STATUS      4
116217806Slstewart#define	USTORAGE_FS_T_BBB_MAX         5
117217806Slstewart
118217806Slstewart/* USB data stage direction */
119217806Slstewart
120217806Slstewart#define	DIR_NONE	0
121217806Slstewart#define	DIR_READ	1
122217806Slstewart#define	DIR_WRITE	2
123217806Slstewart
124217806Slstewart/* USB interface specific control request */
125217806Slstewart
126217806Slstewart#define	UR_BBB_RESET		0xff	/* Bulk-Only reset */
127217806Slstewart#define	UR_BBB_GET_MAX_LUN	0xfe	/* Get maximum lun */
128217806Slstewart
129217806Slstewart/* Command Block Wrapper */
130217806Slstewarttypedef struct {
131217806Slstewart	uDWord	dCBWSignature;
132217806Slstewart#define	CBWSIGNATURE	0x43425355
133217806Slstewart	uDWord	dCBWTag;
134217806Slstewart	uDWord	dCBWDataTransferLength;
135217806Slstewart	uByte	bCBWFlags;
136217806Slstewart#define	CBWFLAGS_OUT	0x00
137217806Slstewart#define	CBWFLAGS_IN	0x80
138217806Slstewart	uByte	bCBWLUN;
139217806Slstewart	uByte	bCDBLength;
140217806Slstewart#define	CBWCDBLENGTH	16
141217806Slstewart	uByte	CBWCDB[CBWCDBLENGTH];
142217806Slstewart} __packed ustorage_fs_bbb_cbw_t;
143217806Slstewart
144217806Slstewart#define	USTORAGE_FS_BBB_CBW_SIZE	31
145217806Slstewart
146217806Slstewart/* Command Status Wrapper */
147217806Slstewarttypedef struct {
148217806Slstewart	uDWord	dCSWSignature;
149217806Slstewart#define	CSWSIGNATURE	0x53425355
150217806Slstewart	uDWord	dCSWTag;
151217806Slstewart	uDWord	dCSWDataResidue;
152217806Slstewart	uByte	bCSWStatus;
153217806Slstewart#define	CSWSTATUS_GOOD	0x0
154239346Slstewart#define	CSWSTATUS_FAILED	0x1
155239346Slstewart#define	CSWSTATUS_PHASE	0x2
156217806Slstewart} __packed ustorage_fs_bbb_csw_t;
157217806Slstewart
158217806Slstewart#define	USTORAGE_FS_BBB_CSW_SIZE	13
159239346Slstewart
160239346Slstewartstruct ustorage_fs_lun {
161217806Slstewart
162217806Slstewart	uint8_t	*memory_image;
163217806Slstewart
164217806Slstewart	uint32_t num_sectors;
165217806Slstewart	uint32_t sense_data;
166217806Slstewart	uint32_t sense_data_info;
167217806Slstewart	uint32_t unit_attention_data;
168217806Slstewart
169217806Slstewart	uint8_t	read_only:1;
170217806Slstewart	uint8_t	prevent_medium_removal:1;
171217806Slstewart	uint8_t	info_valid:1;
172217806Slstewart	uint8_t	removable:1;
173217806Slstewart};
174217806Slstewart
175217806Slstewartstruct ustorage_fs_softc {
176217806Slstewart
177217806Slstewart	ustorage_fs_bbb_cbw_t *sc_cbw;	/* Command Wrapper Block */
178217806Slstewart	ustorage_fs_bbb_csw_t *sc_csw;	/* Command Status Block */
179217806Slstewart	void *sc_dma_ptr;		/* Main data buffer */
180217806Slstewart
181217806Slstewart	struct mtx sc_mtx;
182217806Slstewart
183217806Slstewart	struct ustorage_fs_lun sc_lun[USTORAGE_FS_MAX_LUN];
184217806Slstewart
185217806Slstewart	struct {
186217806Slstewart		uint8_t *data_ptr;
187217806Slstewart		struct ustorage_fs_lun *currlun;
188217806Slstewart
189217806Slstewart		uint32_t data_rem;	/* bytes, as reported by the command
190217806Slstewart					 * block wrapper */
191217806Slstewart		uint32_t offset;	/* bytes */
192217806Slstewart
193217806Slstewart		uint8_t	cbw_dir;
194217806Slstewart		uint8_t	cmd_dir;
195217806Slstewart		uint8_t	lun;
196217806Slstewart		uint8_t	cmd_len;
197217806Slstewart		uint8_t	data_short:1;
198217806Slstewart		uint8_t	data_error:1;
199217806Slstewart	}	sc_transfer;
200217806Slstewart
201217806Slstewart	device_t sc_dev;
202217806Slstewart	struct usb_device *sc_udev;
203217806Slstewart	struct usb_xfer *sc_xfer[USTORAGE_FS_T_BBB_MAX];
204217806Slstewart
205217806Slstewart	uint8_t	sc_iface_no;		/* interface number */
206217806Slstewart	uint8_t	sc_last_lun;
207217806Slstewart	uint8_t	sc_last_xfer_index;
208217806Slstewart	uint8_t	sc_qdata[USTORAGE_QDATA_MAX];
209217806Slstewart};
210217806Slstewart
211217806Slstewart/* prototypes */
212217806Slstewart
213217806Slstewartstatic device_probe_t ustorage_fs_probe;
214217806Slstewartstatic device_attach_t ustorage_fs_attach;
215217806Slstewartstatic device_detach_t ustorage_fs_detach;
216217806Slstewartstatic device_suspend_t ustorage_fs_suspend;
217217806Slstewartstatic device_resume_t ustorage_fs_resume;
218217806Slstewartstatic usb_handle_request_t ustorage_fs_handle_request;
219217806Slstewart
220217806Slstewartstatic usb_callback_t ustorage_fs_t_bbb_command_callback;
221217806Slstewartstatic usb_callback_t ustorage_fs_t_bbb_data_dump_callback;
222217806Slstewartstatic usb_callback_t ustorage_fs_t_bbb_data_read_callback;
223217806Slstewartstatic usb_callback_t ustorage_fs_t_bbb_data_write_callback;
224217806Slstewartstatic usb_callback_t ustorage_fs_t_bbb_status_callback;
225217806Slstewart
226217806Slstewartstatic void ustorage_fs_transfer_start(struct ustorage_fs_softc *sc, uint8_t xfer_index);
227217806Slstewartstatic void ustorage_fs_transfer_stop(struct ustorage_fs_softc *sc);
228217806Slstewart
229217806Slstewartstatic uint8_t ustorage_fs_verify(struct ustorage_fs_softc *sc);
230217806Slstewartstatic uint8_t ustorage_fs_inquiry(struct ustorage_fs_softc *sc);
231217806Slstewartstatic uint8_t ustorage_fs_request_sense(struct ustorage_fs_softc *sc);
232217806Slstewartstatic uint8_t ustorage_fs_read_capacity(struct ustorage_fs_softc *sc);
233217806Slstewartstatic uint8_t ustorage_fs_mode_sense(struct ustorage_fs_softc *sc);
234217806Slstewartstatic uint8_t ustorage_fs_start_stop(struct ustorage_fs_softc *sc);
235217806Slstewartstatic uint8_t ustorage_fs_prevent_allow(struct ustorage_fs_softc *sc);
236217806Slstewartstatic uint8_t ustorage_fs_read_format_capacities(struct ustorage_fs_softc *sc);
237217806Slstewartstatic uint8_t ustorage_fs_mode_select(struct ustorage_fs_softc *sc);
238217806Slstewartstatic uint8_t ustorage_fs_min_len(struct ustorage_fs_softc *sc, uint32_t len, uint32_t mask);
239217806Slstewartstatic uint8_t ustorage_fs_read(struct ustorage_fs_softc *sc);
240217806Slstewartstatic uint8_t ustorage_fs_write(struct ustorage_fs_softc *sc);
241217806Slstewartstatic uint8_t ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t cmd_size, uint16_t mask, uint8_t needs_medium);
242217806Slstewartstatic uint8_t ustorage_fs_do_cmd(struct ustorage_fs_softc *sc);
243217806Slstewart
244217806Slstewartstatic device_method_t ustorage_fs_methods[] = {
245217806Slstewart	/* USB interface */
246217806Slstewart	DEVMETHOD(usb_handle_request, ustorage_fs_handle_request),
247217806Slstewart
248217806Slstewart	/* Device interface */
249217806Slstewart	DEVMETHOD(device_probe, ustorage_fs_probe),
250217806Slstewart	DEVMETHOD(device_attach, ustorage_fs_attach),
251217806Slstewart	DEVMETHOD(device_detach, ustorage_fs_detach),
252217806Slstewart	DEVMETHOD(device_suspend, ustorage_fs_suspend),
253217806Slstewart	DEVMETHOD(device_resume, ustorage_fs_resume),
254217806Slstewart
255217806Slstewart	{0, 0}
256217806Slstewart};
257217806Slstewart
258217806Slstewartstatic driver_t ustorage_fs_driver = {
259217806Slstewart	.name = "ustorage_fs",
260217806Slstewart	.methods = ustorage_fs_methods,
261217806Slstewart	.size = sizeof(struct ustorage_fs_softc),
262217806Slstewart};
263217806Slstewart
264217806Slstewartstatic devclass_t ustorage_fs_devclass;
265217806Slstewart
266217806SlstewartDRIVER_MODULE(ustorage_fs, uhub, ustorage_fs_driver, ustorage_fs_devclass, NULL, 0);
267217806SlstewartMODULE_VERSION(ustorage_fs, 0);
268217806SlstewartMODULE_DEPEND(ustorage_fs, usb, 1, 1, 1);
269217806Slstewart
270217806Slstewartstatic struct usb_config ustorage_fs_bbb_config[USTORAGE_FS_T_BBB_MAX] = {
271217806Slstewart
272217806Slstewart	[USTORAGE_FS_T_BBB_COMMAND] = {
273217806Slstewart		.type = UE_BULK,
274217806Slstewart		.endpoint = UE_ADDR_ANY,
275217806Slstewart		.direction = UE_DIR_OUT,
276217806Slstewart		.bufsize = sizeof(ustorage_fs_bbb_cbw_t),
277217806Slstewart		.callback = &ustorage_fs_t_bbb_command_callback,
278217806Slstewart		.usb_mode = USB_MODE_DEVICE,
279217806Slstewart	},
280217806Slstewart
281217806Slstewart	[USTORAGE_FS_T_BBB_DATA_DUMP] = {
282217806Slstewart		.type = UE_BULK,
283217806Slstewart		.endpoint = UE_ADDR_ANY,
284217806Slstewart		.direction = UE_DIR_OUT,
285217806Slstewart		.bufsize = 0,	/* use wMaxPacketSize */
286217806Slstewart		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
287217806Slstewart		.callback = &ustorage_fs_t_bbb_data_dump_callback,
288217806Slstewart		.usb_mode = USB_MODE_DEVICE,
289217806Slstewart	},
290217806Slstewart
291217806Slstewart	[USTORAGE_FS_T_BBB_DATA_READ] = {
292217806Slstewart		.type = UE_BULK,
293217806Slstewart		.endpoint = UE_ADDR_ANY,
294217806Slstewart		.direction = UE_DIR_OUT,
295217806Slstewart		.bufsize = USTORAGE_FS_BULK_SIZE,
296217806Slstewart		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1},
297217806Slstewart		.callback = &ustorage_fs_t_bbb_data_read_callback,
298217806Slstewart		.usb_mode = USB_MODE_DEVICE,
299217806Slstewart	},
300217806Slstewart
301217806Slstewart	[USTORAGE_FS_T_BBB_DATA_WRITE] = {
302217806Slstewart		.type = UE_BULK,
303217806Slstewart		.endpoint = UE_ADDR_ANY,
304217806Slstewart		.direction = UE_DIR_IN,
305217806Slstewart		.bufsize = USTORAGE_FS_BULK_SIZE,
306217806Slstewart		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
307217806Slstewart		.callback = &ustorage_fs_t_bbb_data_write_callback,
308217806Slstewart		.usb_mode = USB_MODE_DEVICE,
309217806Slstewart	},
310217806Slstewart
311217806Slstewart	[USTORAGE_FS_T_BBB_STATUS] = {
312217806Slstewart		.type = UE_BULK,
313217806Slstewart		.endpoint = UE_ADDR_ANY,
314217806Slstewart		.direction = UE_DIR_IN,
315217806Slstewart		.bufsize = sizeof(ustorage_fs_bbb_csw_t),
316217806Slstewart		.flags = {.short_xfer_ok = 1},
317217806Slstewart		.callback = &ustorage_fs_t_bbb_status_callback,
318217806Slstewart		.usb_mode = USB_MODE_DEVICE,
319217806Slstewart	},
320217806Slstewart};
321217806Slstewart
322217806Slstewart/*
323217806Slstewart * USB device probe/attach/detach
324217806Slstewart */
325217806Slstewart
326217806Slstewartstatic int
327217806Slstewartustorage_fs_probe(device_t dev)
328217806Slstewart{
329217806Slstewart	struct usb_attach_arg *uaa = device_get_ivars(dev);
330217806Slstewart	struct usb_interface_descriptor *id;
331217806Slstewart
332217806Slstewart	if (uaa->usb_mode != USB_MODE_DEVICE) {
333217806Slstewart		return (ENXIO);
334217806Slstewart	}
335217806Slstewart	/* Check for a standards compliant device */
336217806Slstewart	id = usbd_get_interface_descriptor(uaa->iface);
337217806Slstewart	if ((id == NULL) ||
338217806Slstewart	    (id->bInterfaceClass != UICLASS_MASS) ||
339217806Slstewart	    (id->bInterfaceSubClass != UISUBCLASS_SCSI) ||
340217806Slstewart	    (id->bInterfaceProtocol != UIPROTO_MASS_BBB)) {
341217806Slstewart		return (ENXIO);
342217806Slstewart	}
343217806Slstewart	return (BUS_PROBE_GENERIC);
344217806Slstewart}
345217806Slstewart
346217806Slstewartstatic int
347217806Slstewartustorage_fs_attach(device_t dev)
348217806Slstewart{
349217806Slstewart	struct ustorage_fs_softc *sc = device_get_softc(dev);
350217806Slstewart	struct usb_attach_arg *uaa = device_get_ivars(dev);
351217806Slstewart	struct usb_interface_descriptor *id;
352217806Slstewart	int err;
353217806Slstewart	int unit;
354239346Slstewart
355217806Slstewart	/*
356217806Slstewart	 * NOTE: the softc struct is cleared in device_set_driver.
357217806Slstewart	 * We can safely call ustorage_fs_detach without specifically
358217806Slstewart	 * initializing the struct.
359217806Slstewart	 */
360217806Slstewart
361217806Slstewart	sc->sc_dev = dev;
362217806Slstewart	sc->sc_udev = uaa->device;
363217806Slstewart	unit = device_get_unit(dev);
364217806Slstewart
365217806Slstewart	/* enable power saving mode */
366217806Slstewart	usbd_set_power_mode(uaa->device, USB_POWER_MODE_SAVE);
367217806Slstewart
368217806Slstewart	if (unit == 0) {
369217806Slstewart		if (ustorage_fs_ramdisk == NULL) {
370217806Slstewart			/*
371217806Slstewart			 * allocate a memory image for our ramdisk until
372217806Slstewart			 * further
373217806Slstewart			 */
374217806Slstewart			ustorage_fs_ramdisk =
375217806Slstewart			    malloc(USTORAGE_FS_RAM_SECT << 9, M_USB,
376217806Slstewart			    M_ZERO | M_WAITOK);
377217806Slstewart
378217806Slstewart			if (ustorage_fs_ramdisk == NULL) {
379217806Slstewart				return (ENOMEM);
380217806Slstewart			}
381217806Slstewart		}
382217806Slstewart		sc->sc_lun[0].memory_image = ustorage_fs_ramdisk;
383217806Slstewart		sc->sc_lun[0].num_sectors = USTORAGE_FS_RAM_SECT;
384217806Slstewart		sc->sc_lun[0].removable = 1;
385217806Slstewart	}
386217806Slstewart
387217806Slstewart	device_set_usb_desc(dev);
388217806Slstewart
389217806Slstewart	mtx_init(&sc->sc_mtx, "USTORAGE_FS lock",
390217806Slstewart	    NULL, (MTX_DEF | MTX_RECURSE));
391217806Slstewart
392217806Slstewart	/* get interface index */
393217806Slstewart
394217806Slstewart	id = usbd_get_interface_descriptor(uaa->iface);
395217806Slstewart	if (id == NULL) {
396217806Slstewart		device_printf(dev, "failed to get "
397217806Slstewart		    "interface number\n");
398217806Slstewart		goto detach;
399217806Slstewart	}
400217806Slstewart	sc->sc_iface_no = id->bInterfaceNumber;
401217806Slstewart
402217806Slstewart	err = usbd_transfer_setup(uaa->device,
403217806Slstewart	    &uaa->info.bIfaceIndex, sc->sc_xfer, ustorage_fs_bbb_config,
404217806Slstewart	    USTORAGE_FS_T_BBB_MAX, sc, &sc->sc_mtx);
405217806Slstewart	if (err) {
406217806Slstewart		device_printf(dev, "could not setup required "
407217806Slstewart		    "transfers, %s\n", usbd_errstr(err));
408217806Slstewart		goto detach;
409217806Slstewart	}
410217806Slstewart
411217806Slstewart	sc->sc_cbw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
412217806Slstewart	    USTORAGE_FS_T_BBB_COMMAND], 0);
413217806Slstewart	sc->sc_csw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
414217806Slstewart	    USTORAGE_FS_T_BBB_STATUS], 0);
415217806Slstewart 	sc->sc_dma_ptr = usbd_xfer_get_frame_buffer(sc->sc_xfer[
416217806Slstewart	    USTORAGE_FS_T_BBB_DATA_READ], 0);
417217806Slstewart
418217806Slstewart	/* start Mass Storage State Machine */
419217806Slstewart
420217806Slstewart	mtx_lock(&sc->sc_mtx);
421217806Slstewart	ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_COMMAND);
422217806Slstewart	mtx_unlock(&sc->sc_mtx);
423217806Slstewart
424217806Slstewart	return (0);			/* success */
425217806Slstewart
426217806Slstewartdetach:
427217806Slstewart	ustorage_fs_detach(dev);
428217806Slstewart	return (ENXIO);			/* failure */
429217806Slstewart}
430217806Slstewart
431217806Slstewartstatic int
432217806Slstewartustorage_fs_detach(device_t dev)
433217806Slstewart{
434217806Slstewart	struct ustorage_fs_softc *sc = device_get_softc(dev);
435217806Slstewart
436217806Slstewart	/* teardown our statemachine */
437217806Slstewart
438217806Slstewart	usbd_transfer_unsetup(sc->sc_xfer, USTORAGE_FS_T_BBB_MAX);
439217806Slstewart
440217806Slstewart	mtx_destroy(&sc->sc_mtx);
441217806Slstewart
442217806Slstewart	return (0);			/* success */
443217806Slstewart}
444217806Slstewart
445217806Slstewartstatic int
446217806Slstewartustorage_fs_suspend(device_t dev)
447217806Slstewart{
448217806Slstewart	device_printf(dev, "suspending\n");
449217806Slstewart	return (0);			/* success */
450217806Slstewart}
451217806Slstewart
452217806Slstewartstatic int
453217806Slstewartustorage_fs_resume(device_t dev)
454217806Slstewart{
455217806Slstewart	device_printf(dev, "resuming\n");
456217806Slstewart	return (0);			/* success */
457217806Slstewart}
458217806Slstewart
459217806Slstewart/*
460217806Slstewart * Generic functions to handle transfers
461217806Slstewart */
462217806Slstewart
463217806Slstewartstatic void
464217806Slstewartustorage_fs_transfer_start(struct ustorage_fs_softc *sc, uint8_t xfer_index)
465217806Slstewart{
466217806Slstewart	if (sc->sc_xfer[xfer_index]) {
467217806Slstewart		sc->sc_last_xfer_index = xfer_index;
468217806Slstewart		usbd_transfer_start(sc->sc_xfer[xfer_index]);
469217806Slstewart	}
470217806Slstewart}
471217806Slstewart
472217806Slstewartstatic void
473217806Slstewartustorage_fs_transfer_stop(struct ustorage_fs_softc *sc)
474217806Slstewart{
475217806Slstewart	usbd_transfer_stop(sc->sc_xfer[sc->sc_last_xfer_index]);
476217806Slstewart	mtx_unlock(&sc->sc_mtx);
477217806Slstewart	usbd_transfer_drain(sc->sc_xfer[sc->sc_last_xfer_index]);
478217806Slstewart	mtx_lock(&sc->sc_mtx);
479217806Slstewart}
480217806Slstewart
481217806Slstewartstatic int
482239346Slstewartustorage_fs_handle_request(device_t dev,
483217806Slstewart    const void *preq, void **pptr, uint16_t *plen,
484217806Slstewart    uint16_t offset, uint8_t *pstate)
485217806Slstewart{
486217806Slstewart	struct ustorage_fs_softc *sc = device_get_softc(dev);
487217806Slstewart	const struct usb_device_request *req = preq;
488217806Slstewart	uint8_t is_complete = *pstate;
489217806Slstewart
490217806Slstewart	if (!is_complete) {
491217806Slstewart		if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
492217806Slstewart		    (req->bRequest == UR_BBB_RESET)) {
493217806Slstewart			*plen = 0;
494217806Slstewart			mtx_lock(&sc->sc_mtx);
495217806Slstewart			ustorage_fs_transfer_stop(sc);
496217806Slstewart			sc->sc_transfer.data_error = 1;
497217806Slstewart			ustorage_fs_transfer_start(sc,
498217806Slstewart			    USTORAGE_FS_T_BBB_COMMAND);
499217806Slstewart			mtx_unlock(&sc->sc_mtx);
500217806Slstewart			return (0);
501217806Slstewart		} else if ((req->bmRequestType == UT_READ_CLASS_INTERFACE) &&
502217806Slstewart			   (req->bRequest == UR_BBB_GET_MAX_LUN)) {
503217806Slstewart			if (offset == 0) {
504217806Slstewart				*plen = 1;
505217806Slstewart				*pptr = &sc->sc_last_lun;
506217806Slstewart			} else {
507217806Slstewart				*plen = 0;
508217806Slstewart			}
509217806Slstewart			return (0);
510217806Slstewart		}
511217806Slstewart	}
512217806Slstewart	return (ENXIO);			/* use builtin handler */
513217806Slstewart}
514217806Slstewart
515217806Slstewartstatic void
516217806Slstewartustorage_fs_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
517217806Slstewart{
518217806Slstewart	struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
519217806Slstewart	uint32_t tag;
520217806Slstewart	uint8_t err = 0;
521217806Slstewart
522217806Slstewart	DPRINTF("\n");
523217806Slstewart
524217806Slstewart	switch (USB_GET_STATE(xfer)) {
525217806Slstewart	case USB_ST_TRANSFERRED:
526217806Slstewart
527217806Slstewart		tag = UGETDW(sc->sc_cbw->dCBWSignature);
528217806Slstewart
529217806Slstewart		if (tag != CBWSIGNATURE) {
530217806Slstewart			/* do nothing */
531217806Slstewart			DPRINTF("invalid signature 0x%08x\n", tag);
532217806Slstewart			break;
533217806Slstewart		}
534217806Slstewart		tag = UGETDW(sc->sc_cbw->dCBWTag);
535217806Slstewart
536217806Slstewart		/* echo back tag */
537217806Slstewart		USETDW(sc->sc_csw->dCSWTag, tag);
538217806Slstewart
539217806Slstewart		/* reset status */
540217806Slstewart		sc->sc_csw->bCSWStatus = 0;
541217806Slstewart
542217806Slstewart		/* reset data offset, data length and data remainder */
543217806Slstewart		sc->sc_transfer.offset = 0;
544217806Slstewart		sc->sc_transfer.data_rem =
545217806Slstewart		    UGETDW(sc->sc_cbw->dCBWDataTransferLength);
546217806Slstewart
547217806Slstewart		/* reset data flags */
548		sc->sc_transfer.data_short = 0;
549
550		/* extract LUN */
551		sc->sc_transfer.lun = sc->sc_cbw->bCBWLUN;
552
553		if (sc->sc_transfer.data_rem == 0) {
554			sc->sc_transfer.cbw_dir = DIR_NONE;
555		} else {
556			if (sc->sc_cbw->bCBWFlags & CBWFLAGS_IN) {
557				sc->sc_transfer.cbw_dir = DIR_WRITE;
558			} else {
559				sc->sc_transfer.cbw_dir = DIR_READ;
560			}
561		}
562
563		sc->sc_transfer.cmd_len = sc->sc_cbw->bCDBLength;
564		if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw->CBWCDB)) ||
565		    (sc->sc_transfer.cmd_len == 0)) {
566			/* just halt - this is invalid */
567			DPRINTF("invalid command length %d bytes\n",
568			    sc->sc_transfer.cmd_len);
569			break;
570		}
571
572		err = ustorage_fs_do_cmd(sc);
573		if (err) {
574			/* got an error */
575			DPRINTF("command failed\n");
576			break;
577		}
578		if ((sc->sc_transfer.data_rem > 0) &&
579		    (sc->sc_transfer.cbw_dir != sc->sc_transfer.cmd_dir)) {
580			/* contradicting data transfer direction */
581			err = 1;
582			DPRINTF("data direction mismatch\n");
583			break;
584		}
585		switch (sc->sc_transfer.cbw_dir) {
586		case DIR_READ:
587			ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_DATA_READ);
588			break;
589		case DIR_WRITE:
590			ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_DATA_WRITE);
591			break;
592		default:
593			ustorage_fs_transfer_start(sc,
594			    USTORAGE_FS_T_BBB_STATUS);
595			break;
596		}
597		break;
598
599	case USB_ST_SETUP:
600tr_setup:
601		if (sc->sc_transfer.data_error) {
602			sc->sc_transfer.data_error = 0;
603			usbd_xfer_set_stall(xfer);
604			DPRINTF("stall pipe\n");
605		}
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) {
622		if (sc->sc_csw->bCSWStatus == 0) {
623			/* set some default error code */
624			sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
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:
705		/* XXX copy data from DMA buffer */
706		memcpy(sc->sc_transfer.data_ptr, sc->sc_dma_ptr, actlen);
707
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
730		usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
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
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);
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:
823		USETDW(sc->sc_csw->dCSWSignature, CSWSIGNATURE);
824		USETDW(sc->sc_csw->dCSWDataResidue, sc->sc_transfer.data_rem);
825
826		if (sc->sc_transfer.data_error) {
827			sc->sc_transfer.data_error = 0;
828			usbd_xfer_set_stall(xfer);
829		}
830		usbd_transfer_submit(xfer);
831		break;
832
833	default:
834		if (error == USB_ERR_CANCELLED) {
835			break;
836		}
837		/* If the pipe is already stalled, don't do another stall */
838		if (!usbd_xfer_is_stalled(xfer))
839			sc->sc_transfer.data_error = 1;
840
841		/* try again */
842		goto tr_setup;
843	}
844}
845
846/* SCSI commands that we recognize */
847#define	SC_FORMAT_UNIT			0x04
848#define	SC_INQUIRY			0x12
849#define	SC_MODE_SELECT_6		0x15
850#define	SC_MODE_SELECT_10		0x55
851#define	SC_MODE_SENSE_6			0x1a
852#define	SC_MODE_SENSE_10		0x5a
853#define	SC_PREVENT_ALLOW_MEDIUM_REMOVAL	0x1e
854#define	SC_READ_6			0x08
855#define	SC_READ_10			0x28
856#define	SC_READ_12			0xa8
857#define	SC_READ_CAPACITY		0x25
858#define	SC_READ_FORMAT_CAPACITIES	0x23
859#define	SC_RELEASE			0x17
860#define	SC_REQUEST_SENSE		0x03
861#define	SC_RESERVE			0x16
862#define	SC_SEND_DIAGNOSTIC		0x1d
863#define	SC_START_STOP_UNIT		0x1b
864#define	SC_SYNCHRONIZE_CACHE		0x35
865#define	SC_TEST_UNIT_READY		0x00
866#define	SC_VERIFY			0x2f
867#define	SC_WRITE_6			0x0a
868#define	SC_WRITE_10			0x2a
869#define	SC_WRITE_12			0xaa
870
871/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
872#define	SS_NO_SENSE				0
873#define	SS_COMMUNICATION_FAILURE		0x040800
874#define	SS_INVALID_COMMAND			0x052000
875#define	SS_INVALID_FIELD_IN_CDB			0x052400
876#define	SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE	0x052100
877#define	SS_LOGICAL_UNIT_NOT_SUPPORTED		0x052500
878#define	SS_MEDIUM_NOT_PRESENT			0x023a00
879#define	SS_MEDIUM_REMOVAL_PREVENTED		0x055302
880#define	SS_NOT_READY_TO_READY_TRANSITION	0x062800
881#define	SS_RESET_OCCURRED			0x062900
882#define	SS_SAVING_PARAMETERS_NOT_SUPPORTED	0x053900
883#define	SS_UNRECOVERED_READ_ERROR		0x031100
884#define	SS_WRITE_ERROR				0x030c02
885#define	SS_WRITE_PROTECTED			0x072700
886
887#define	SK(x)		((uint8_t) ((x) >> 16))	/* Sense Key byte, etc. */
888#define	ASC(x)		((uint8_t) ((x) >> 8))
889#define	ASCQ(x)		((uint8_t) (x))
890
891/* Routines for unaligned data access */
892
893static uint16_t
894get_be16(uint8_t *buf)
895{
896	return ((uint16_t)buf[0] << 8) | ((uint16_t)buf[1]);
897}
898
899static uint32_t
900get_be32(uint8_t *buf)
901{
902	return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
903	((uint32_t)buf[2] << 8) | ((uint32_t)buf[3]);
904}
905
906static void
907put_be16(uint8_t *buf, uint16_t val)
908{
909	buf[0] = val >> 8;
910	buf[1] = val;
911}
912
913static void
914put_be32(uint8_t *buf, uint32_t val)
915{
916	buf[0] = val >> 24;
917	buf[1] = val >> 16;
918	buf[2] = val >> 8;
919	buf[3] = val & 0xff;
920}
921
922/*------------------------------------------------------------------------*
923 *	ustorage_fs_verify
924 *
925 * Returns:
926 *    0: Success
927 * Else: Failure
928 *------------------------------------------------------------------------*/
929static uint8_t
930ustorage_fs_verify(struct ustorage_fs_softc *sc)
931{
932	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
933	uint32_t lba;
934	uint32_t vlen;
935	uint64_t file_offset;
936	uint64_t amount_left;
937
938	/*
939	 * Get the starting Logical Block Address
940	 */
941	lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
942
943	/*
944	 * We allow DPO (Disable Page Out = don't save data in the cache)
945	 * but we don't implement it.
946	 */
947	if ((sc->sc_cbw->CBWCDB[1] & ~0x10) != 0) {
948		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
949		return (1);
950	}
951	vlen = get_be16(&sc->sc_cbw->CBWCDB[7]);
952	if (vlen == 0) {
953		goto done;
954	}
955	/* No default reply */
956
957	/* Prepare to carry out the file verify */
958	amount_left = vlen;
959	amount_left <<= 9;
960	file_offset = lba;
961	file_offset <<= 9;
962
963	/* Range check */
964	vlen += lba;
965
966	if ((vlen < lba) ||
967	    (vlen > currlun->num_sectors) ||
968	    (lba >= currlun->num_sectors)) {
969		currlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
970		return (1);
971	}
972	/* XXX TODO: verify that data is readable */
973done:
974	return (ustorage_fs_min_len(sc, 0, -1U));
975}
976
977/*------------------------------------------------------------------------*
978 *	ustorage_fs_inquiry
979 *
980 * Returns:
981 *    0: Success
982 * Else: Failure
983 *------------------------------------------------------------------------*/
984static uint8_t
985ustorage_fs_inquiry(struct ustorage_fs_softc *sc)
986{
987	uint8_t *buf = sc->sc_transfer.data_ptr;
988
989	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
990
991	if (!sc->sc_transfer.currlun) {
992		/* Unsupported LUNs are okay */
993		memset(buf, 0, 36);
994		buf[0] = 0x7f;
995		/* Unsupported, no device - type */
996		return (ustorage_fs_min_len(sc, 36, -1U));
997	}
998	memset(buf, 0, 8);
999	/* Non - removable, direct - access device */
1000	if (currlun->removable)
1001		buf[1] = 0x80;
1002	buf[2] = 2;
1003	/* ANSI SCSI level 2 */
1004	buf[3] = 2;
1005	/* SCSI - 2 INQUIRY data format */
1006	buf[4] = 31;
1007	/* Additional length */
1008	/* No special options */
1009	/* Copy in ID string */
1010	memcpy(buf + 8, USTORAGE_FS_ID_STRING, 28);
1011
1012#if (USTORAGE_QDATA_MAX < 36)
1013#error "(USTORAGE_QDATA_MAX < 36)"
1014#endif
1015	return (ustorage_fs_min_len(sc, 36, -1U));
1016}
1017
1018/*------------------------------------------------------------------------*
1019 *	ustorage_fs_request_sense
1020 *
1021 * Returns:
1022 *    0: Success
1023 * Else: Failure
1024 *------------------------------------------------------------------------*/
1025static uint8_t
1026ustorage_fs_request_sense(struct ustorage_fs_softc *sc)
1027{
1028	uint8_t *buf = sc->sc_transfer.data_ptr;
1029	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1030	uint32_t sd;
1031	uint32_t sdinfo;
1032	uint8_t valid;
1033
1034	/*
1035	 * From the SCSI-2 spec., section 7.9 (Unit attention condition):
1036	 *
1037	 * If a REQUEST SENSE command is received from an initiator
1038	 * with a pending unit attention condition (before the target
1039	 * generates the contingent allegiance condition), then the
1040	 * target shall either:
1041	 *   a) report any pending sense data and preserve the unit
1042	 *	attention condition on the logical unit, or,
1043	 *   b) report the unit attention condition, may discard any
1044	 *	pending sense data, and clear the unit attention
1045	 *	condition on the logical unit for that initiator.
1046	 *
1047	 * FSG normally uses option a); enable this code to use option b).
1048	 */
1049#if 0
1050	if (currlun && currlun->unit_attention_data != SS_NO_SENSE) {
1051		currlun->sense_data = currlun->unit_attention_data;
1052		currlun->unit_attention_data = SS_NO_SENSE;
1053	}
1054#endif
1055
1056	if (!currlun) {
1057		/* Unsupported LUNs are okay */
1058		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
1059		sdinfo = 0;
1060		valid = 0;
1061	} else {
1062		sd = currlun->sense_data;
1063		sdinfo = currlun->sense_data_info;
1064		valid = currlun->info_valid << 7;
1065		currlun->sense_data = SS_NO_SENSE;
1066		currlun->sense_data_info = 0;
1067		currlun->info_valid = 0;
1068	}
1069
1070	memset(buf, 0, 18);
1071	buf[0] = valid | 0x70;
1072	/* Valid, current error */
1073	buf[2] = SK(sd);
1074	put_be32(&buf[3], sdinfo);
1075	/* Sense information */
1076	buf[7] = 18 - 8;
1077	/* Additional sense length */
1078	buf[12] = ASC(sd);
1079	buf[13] = ASCQ(sd);
1080
1081#if (USTORAGE_QDATA_MAX < 18)
1082#error "(USTORAGE_QDATA_MAX < 18)"
1083#endif
1084	return (ustorage_fs_min_len(sc, 18, -1U));
1085}
1086
1087/*------------------------------------------------------------------------*
1088 *	ustorage_fs_read_capacity
1089 *
1090 * Returns:
1091 *    0: Success
1092 * Else: Failure
1093 *------------------------------------------------------------------------*/
1094static uint8_t
1095ustorage_fs_read_capacity(struct ustorage_fs_softc *sc)
1096{
1097	uint8_t *buf = sc->sc_transfer.data_ptr;
1098	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1099	uint32_t lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
1100	uint8_t pmi = sc->sc_cbw->CBWCDB[8];
1101
1102	/* Check the PMI and LBA fields */
1103	if ((pmi > 1) || ((pmi == 0) && (lba != 0))) {
1104		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1105		return (1);
1106	}
1107	/* Max logical block */
1108	put_be32(&buf[0], currlun->num_sectors - 1);
1109	/* Block length */
1110	put_be32(&buf[4], 512);
1111
1112#if (USTORAGE_QDATA_MAX < 8)
1113#error "(USTORAGE_QDATA_MAX < 8)"
1114#endif
1115	return (ustorage_fs_min_len(sc, 8, -1U));
1116}
1117
1118/*------------------------------------------------------------------------*
1119 *	ustorage_fs_mode_sense
1120 *
1121 * Returns:
1122 *    0: Success
1123 * Else: Failure
1124 *------------------------------------------------------------------------*/
1125static uint8_t
1126ustorage_fs_mode_sense(struct ustorage_fs_softc *sc)
1127{
1128	uint8_t *buf = sc->sc_transfer.data_ptr;
1129	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1130	uint8_t *buf0;
1131	uint16_t len;
1132	uint16_t limit;
1133	uint8_t mscmnd = sc->sc_cbw->CBWCDB[0];
1134	uint8_t pc;
1135	uint8_t page_code;
1136	uint8_t changeable_values;
1137	uint8_t all_pages;
1138
1139	buf0 = buf;
1140
1141	if ((sc->sc_cbw->CBWCDB[1] & ~0x08) != 0) {
1142		/* Mask away DBD */
1143		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1144		return (1);
1145	}
1146	pc = sc->sc_cbw->CBWCDB[2] >> 6;
1147	page_code = sc->sc_cbw->CBWCDB[2] & 0x3f;
1148	if (pc == 3) {
1149		currlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
1150		return (1);
1151	}
1152	changeable_values = (pc == 1);
1153	all_pages = (page_code == 0x3f);
1154
1155	/*
1156	 * Write the mode parameter header.  Fixed values are: default
1157	 * medium type, no cache control (DPOFUA), and no block descriptors.
1158	 * The only variable value is the WriteProtect bit.  We will fill in
1159	 * the mode data length later.
1160	 */
1161	memset(buf, 0, 8);
1162	if (mscmnd == SC_MODE_SENSE_6) {
1163		buf[2] = (currlun->read_only ? 0x80 : 0x00);
1164		/* WP, DPOFUA */
1165		buf += 4;
1166		limit = 255;
1167	} else {
1168		/* SC_MODE_SENSE_10 */
1169		buf[3] = (currlun->read_only ? 0x80 : 0x00);
1170		/* WP, DPOFUA */
1171		buf += 8;
1172		limit = 65535;
1173		/* Should really be mod_data.buflen */
1174	}
1175
1176	/* No block descriptors */
1177
1178	/*
1179	 * The mode pages, in numerical order.
1180	 */
1181	if ((page_code == 0x08) || all_pages) {
1182		buf[0] = 0x08;
1183		/* Page code */
1184		buf[1] = 10;
1185		/* Page length */
1186		memset(buf + 2, 0, 10);
1187		/* None of the fields are changeable */
1188
1189		if (!changeable_values) {
1190			buf[2] = 0x04;
1191			/* Write cache enable, */
1192			/* Read cache not disabled */
1193			/* No cache retention priorities */
1194			put_be16(&buf[4], 0xffff);
1195			/* Don 't disable prefetch */
1196			/* Minimum prefetch = 0 */
1197			put_be16(&buf[8], 0xffff);
1198			/* Maximum prefetch */
1199			put_be16(&buf[10], 0xffff);
1200			/* Maximum prefetch ceiling */
1201		}
1202		buf += 12;
1203	}
1204	/*
1205	 * Check that a valid page was requested and the mode data length
1206	 * isn't too long.
1207	 */
1208	len = buf - buf0;
1209	if (len > limit) {
1210		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1211		return (1);
1212	}
1213	/* Store the mode data length */
1214	if (mscmnd == SC_MODE_SENSE_6)
1215		buf0[0] = len - 1;
1216	else
1217		put_be16(buf0, len - 2);
1218
1219#if (USTORAGE_QDATA_MAX < 24)
1220#error "(USTORAGE_QDATA_MAX < 24)"
1221#endif
1222	return (ustorage_fs_min_len(sc, len, -1U));
1223}
1224
1225/*------------------------------------------------------------------------*
1226 *	ustorage_fs_start_stop
1227 *
1228 * Returns:
1229 *    0: Success
1230 * Else: Failure
1231 *------------------------------------------------------------------------*/
1232static uint8_t
1233ustorage_fs_start_stop(struct ustorage_fs_softc *sc)
1234{
1235	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1236	uint8_t loej;
1237	uint8_t start;
1238	uint8_t immed;
1239
1240	if (!currlun->removable) {
1241		currlun->sense_data = SS_INVALID_COMMAND;
1242		return (1);
1243	}
1244	immed = sc->sc_cbw->CBWCDB[1] & 0x01;
1245	loej = sc->sc_cbw->CBWCDB[4] & 0x02;
1246	start = sc->sc_cbw->CBWCDB[4] & 0x01;
1247
1248	if (immed || loej || start) {
1249		/* compile fix */
1250	}
1251	return (0);
1252}
1253
1254/*------------------------------------------------------------------------*
1255 *	ustorage_fs_prevent_allow
1256 *
1257 * Returns:
1258 *    0: Success
1259 * Else: Failure
1260 *------------------------------------------------------------------------*/
1261static uint8_t
1262ustorage_fs_prevent_allow(struct ustorage_fs_softc *sc)
1263{
1264	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1265	uint8_t prevent;
1266
1267	if (!currlun->removable) {
1268		currlun->sense_data = SS_INVALID_COMMAND;
1269		return (1);
1270	}
1271	prevent = sc->sc_cbw->CBWCDB[4] & 0x01;
1272	if ((sc->sc_cbw->CBWCDB[4] & ~0x01) != 0) {
1273		/* Mask away Prevent */
1274		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1275		return (1);
1276	}
1277	if (currlun->prevent_medium_removal && !prevent) {
1278		//fsync_sub(currlun);
1279	}
1280	currlun->prevent_medium_removal = prevent;
1281	return (0);
1282}
1283
1284/*------------------------------------------------------------------------*
1285 *	ustorage_fs_read_format_capacities
1286 *
1287 * Returns:
1288 *    0: Success
1289 * Else: Failure
1290 *------------------------------------------------------------------------*/
1291static uint8_t
1292ustorage_fs_read_format_capacities(struct ustorage_fs_softc *sc)
1293{
1294	uint8_t *buf = sc->sc_transfer.data_ptr;
1295	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1296
1297	buf[0] = buf[1] = buf[2] = 0;
1298	buf[3] = 8;
1299	/* Only the Current / Maximum Capacity Descriptor */
1300	buf += 4;
1301
1302	/* Number of blocks */
1303	put_be32(&buf[0], currlun->num_sectors);
1304	/* Block length */
1305	put_be32(&buf[4], 512);
1306	/* Current capacity */
1307	buf[4] = 0x02;
1308
1309#if (USTORAGE_QDATA_MAX < 12)
1310#error "(USTORAGE_QDATA_MAX < 12)"
1311#endif
1312	return (ustorage_fs_min_len(sc, 12, -1U));
1313}
1314
1315/*------------------------------------------------------------------------*
1316 *	ustorage_fs_mode_select
1317 *
1318 * Return values:
1319 *    0: Success
1320 * Else: Failure
1321 *------------------------------------------------------------------------*/
1322static uint8_t
1323ustorage_fs_mode_select(struct ustorage_fs_softc *sc)
1324{
1325	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1326
1327	/* We don't support MODE SELECT */
1328	currlun->sense_data = SS_INVALID_COMMAND;
1329	return (1);
1330}
1331
1332/*------------------------------------------------------------------------*
1333 *	ustorage_fs_synchronize_cache
1334 *
1335 * Return values:
1336 *    0: Success
1337 * Else: Failure
1338 *------------------------------------------------------------------------*/
1339static uint8_t
1340ustorage_fs_synchronize_cache(struct ustorage_fs_softc *sc)
1341{
1342#if 0
1343	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1344	uint8_t rc;
1345
1346	/*
1347	 * We ignore the requested LBA and write out all dirty data buffers.
1348	 */
1349	rc = 0;
1350	if (rc) {
1351		currlun->sense_data = SS_WRITE_ERROR;
1352	}
1353#endif
1354	return (0);
1355}
1356
1357/*------------------------------------------------------------------------*
1358 *	ustorage_fs_read - read data from disk
1359 *
1360 * Return values:
1361 *    0: Success
1362 * Else: Failure
1363 *------------------------------------------------------------------------*/
1364static uint8_t
1365ustorage_fs_read(struct ustorage_fs_softc *sc)
1366{
1367	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1368	uint64_t file_offset;
1369	uint32_t lba;
1370	uint32_t len;
1371
1372	/*
1373	 * Get the starting Logical Block Address and check that it's not
1374	 * too big
1375	 */
1376	if (sc->sc_cbw->CBWCDB[0] == SC_READ_6) {
1377		lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
1378		    get_be16(&sc->sc_cbw->CBWCDB[2]);
1379	} else {
1380		lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
1381
1382		/*
1383		 * We allow DPO (Disable Page Out = don't save data in the
1384		 * cache) and FUA (Force Unit Access = don't read from the
1385		 * cache), but we don't implement them.
1386		 */
1387		if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
1388			currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1389			return (1);
1390		}
1391	}
1392	len = sc->sc_transfer.data_rem >> 9;
1393	len += lba;
1394
1395	if ((len < lba) ||
1396	    (len > currlun->num_sectors) ||
1397	    (lba >= currlun->num_sectors)) {
1398		currlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1399		return (1);
1400	}
1401	file_offset = lba;
1402	file_offset <<= 9;
1403
1404	sc->sc_transfer.data_ptr = currlun->memory_image + file_offset;
1405
1406	return (0);
1407}
1408
1409/*------------------------------------------------------------------------*
1410 *	ustorage_fs_write - write data to disk
1411 *
1412 * Return values:
1413 *    0: Success
1414 * Else: Failure
1415 *------------------------------------------------------------------------*/
1416static uint8_t
1417ustorage_fs_write(struct ustorage_fs_softc *sc)
1418{
1419	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1420	uint64_t file_offset;
1421	uint32_t lba;
1422	uint32_t len;
1423
1424	if (currlun->read_only) {
1425		currlun->sense_data = SS_WRITE_PROTECTED;
1426		return (1);
1427	}
1428	/* XXX clear SYNC */
1429
1430	/*
1431	 * Get the starting Logical Block Address and check that it's not
1432	 * too big.
1433	 */
1434	if (sc->sc_cbw->CBWCDB[0] == SC_WRITE_6)
1435		lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
1436		    get_be16(&sc->sc_cbw->CBWCDB[2]);
1437	else {
1438		lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
1439
1440		/*
1441		 * We allow DPO (Disable Page Out = don't save data in the
1442		 * cache) and FUA (Force Unit Access = write directly to the
1443		 * medium).  We don't implement DPO; we implement FUA by
1444		 * performing synchronous output.
1445		 */
1446		if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
1447			currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1448			return (1);
1449		}
1450		if (sc->sc_cbw->CBWCDB[1] & 0x08) {
1451			/* FUA */
1452			/* XXX set SYNC flag here */
1453		}
1454	}
1455
1456	len = sc->sc_transfer.data_rem >> 9;
1457	len += lba;
1458
1459	if ((len < lba) ||
1460	    (len > currlun->num_sectors) ||
1461	    (lba >= currlun->num_sectors)) {
1462		currlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1463		return (1);
1464	}
1465	file_offset = lba;
1466	file_offset <<= 9;
1467
1468	sc->sc_transfer.data_ptr = currlun->memory_image + file_offset;
1469
1470	return (0);
1471}
1472
1473/*------------------------------------------------------------------------*
1474 *	ustorage_fs_min_len
1475 *
1476 * Return values:
1477 *    0: Success
1478 * Else: Failure
1479 *------------------------------------------------------------------------*/
1480static uint8_t
1481ustorage_fs_min_len(struct ustorage_fs_softc *sc, uint32_t len, uint32_t mask)
1482{
1483	if (len != sc->sc_transfer.data_rem) {
1484
1485		if (sc->sc_transfer.cbw_dir == DIR_READ) {
1486			/*
1487			 * there must be something wrong about this SCSI
1488			 * command
1489			 */
1490			sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
1491			return (1);
1492		}
1493		/* compute the minimum length */
1494
1495		if (sc->sc_transfer.data_rem > len) {
1496			/* data ends prematurely */
1497			sc->sc_transfer.data_rem = len;
1498			sc->sc_transfer.data_short = 1;
1499		}
1500		/* check length alignment */
1501
1502		if (sc->sc_transfer.data_rem & ~mask) {
1503			/* data ends prematurely */
1504			sc->sc_transfer.data_rem &= mask;
1505			sc->sc_transfer.data_short = 1;
1506		}
1507	}
1508	return (0);
1509}
1510
1511/*------------------------------------------------------------------------*
1512 *	ustorage_fs_check_cmd - check command routine
1513 *
1514 * Check whether the command is properly formed and whether its data
1515 * size and direction agree with the values we already have.
1516 *
1517 * Return values:
1518 *    0: Success
1519 * Else: Failure
1520 *------------------------------------------------------------------------*/
1521static uint8_t
1522ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
1523    uint16_t mask, uint8_t needs_medium)
1524{
1525	struct ustorage_fs_lun *currlun;
1526	uint8_t lun = (sc->sc_cbw->CBWCDB[1] >> 5);
1527	uint8_t i;
1528
1529	/* Verify the length of the command itself */
1530	if (min_cmd_size > sc->sc_transfer.cmd_len) {
1531		DPRINTF("%u > %u\n",
1532		    min_cmd_size, sc->sc_transfer.cmd_len);
1533		sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
1534		return (1);
1535	}
1536	/* Mask away the LUN */
1537	sc->sc_cbw->CBWCDB[1] &= 0x1f;
1538
1539	/* Check if LUN is correct */
1540	if (lun != sc->sc_transfer.lun) {
1541
1542	}
1543	/* Check the LUN */
1544	if (sc->sc_transfer.lun <= sc->sc_last_lun) {
1545		sc->sc_transfer.currlun = currlun =
1546		    sc->sc_lun + sc->sc_transfer.lun;
1547		if (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE) {
1548			currlun->sense_data = SS_NO_SENSE;
1549			currlun->sense_data_info = 0;
1550			currlun->info_valid = 0;
1551		}
1552		/*
1553		 * If a unit attention condition exists, only INQUIRY
1554		 * and REQUEST SENSE commands are allowed. Anything
1555		 * else must fail!
1556		 */
1557		if ((currlun->unit_attention_data != SS_NO_SENSE) &&
1558		    (sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
1559		    (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
1560			currlun->sense_data = currlun->unit_attention_data;
1561			currlun->unit_attention_data = SS_NO_SENSE;
1562			return (1);
1563		}
1564	} else {
1565		sc->sc_transfer.currlun = currlun = NULL;
1566
1567		/*
1568		 * INQUIRY and REQUEST SENSE commands are explicitly allowed
1569		 * to use unsupported LUNs; all others may not.
1570		 */
1571		if ((sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
1572		    (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
1573			return (1);
1574		}
1575	}
1576
1577	/*
1578	 * Check that only command bytes listed in the mask are
1579	 * non-zero.
1580	 */
1581	for (i = 0; i != min_cmd_size; i++) {
1582		if (sc->sc_cbw->CBWCDB[i] && !(mask & (1UL << i))) {
1583			if (currlun) {
1584				currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1585			}
1586			return (1);
1587		}
1588	}
1589
1590	/*
1591	 * If the medium isn't mounted and the command needs to access
1592	 * it, return an error.
1593	 */
1594	if (currlun && (!currlun->memory_image) && needs_medium) {
1595		currlun->sense_data = SS_MEDIUM_NOT_PRESENT;
1596		return (1);
1597	}
1598	return (0);
1599}
1600
1601/*------------------------------------------------------------------------*
1602 *	ustorage_fs_do_cmd - do command
1603 *
1604 * Return values:
1605 *    0: Success
1606 * Else: Failure
1607 *------------------------------------------------------------------------*/
1608static uint8_t
1609ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
1610{
1611	uint8_t error = 1;
1612	uint8_t i;
1613	uint32_t temp;
1614	const uint32_t mask9 = (0xFFFFFFFFUL >> 9) << 9;
1615
1616	/* set default data transfer pointer */
1617	sc->sc_transfer.data_ptr = sc->sc_qdata;
1618
1619	DPRINTF("cmd_data[0]=0x%02x, data_rem=0x%08x\n",
1620	    sc->sc_cbw->CBWCDB[0], sc->sc_transfer.data_rem);
1621
1622	switch (sc->sc_cbw->CBWCDB[0]) {
1623	case SC_INQUIRY:
1624		sc->sc_transfer.cmd_dir = DIR_WRITE;
1625		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
1626		if (error) {
1627			break;
1628		}
1629		error = ustorage_fs_check_cmd(sc, 6,
1630		    (1UL << 4) | 1, 0);
1631		if (error) {
1632			break;
1633		}
1634		error = ustorage_fs_inquiry(sc);
1635
1636		break;
1637
1638	case SC_MODE_SELECT_6:
1639		sc->sc_transfer.cmd_dir = DIR_READ;
1640		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
1641		if (error) {
1642			break;
1643		}
1644		error = ustorage_fs_check_cmd(sc, 6,
1645		    (1UL << 1) | (1UL << 4) | 1, 0);
1646		if (error) {
1647			break;
1648		}
1649		error = ustorage_fs_mode_select(sc);
1650
1651		break;
1652
1653	case SC_MODE_SELECT_10:
1654		sc->sc_transfer.cmd_dir = DIR_READ;
1655		error = ustorage_fs_min_len(sc,
1656		    get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
1657		if (error) {
1658			break;
1659		}
1660		error = ustorage_fs_check_cmd(sc, 10,
1661		    (1UL << 1) | (3UL << 7) | 1, 0);
1662		if (error) {
1663			break;
1664		}
1665		error = ustorage_fs_mode_select(sc);
1666
1667		break;
1668
1669	case SC_MODE_SENSE_6:
1670		sc->sc_transfer.cmd_dir = DIR_WRITE;
1671		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
1672		if (error) {
1673			break;
1674		}
1675		error = ustorage_fs_check_cmd(sc, 6,
1676		    (1UL << 1) | (1UL << 2) | (1UL << 4) | 1, 0);
1677		if (error) {
1678			break;
1679		}
1680		error = ustorage_fs_mode_sense(sc);
1681
1682		break;
1683
1684	case SC_MODE_SENSE_10:
1685		sc->sc_transfer.cmd_dir = DIR_WRITE;
1686		error = ustorage_fs_min_len(sc,
1687		    get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
1688		if (error) {
1689			break;
1690		}
1691		error = ustorage_fs_check_cmd(sc, 10,
1692		    (1UL << 1) | (1UL << 2) | (3UL << 7) | 1, 0);
1693		if (error) {
1694			break;
1695		}
1696		error = ustorage_fs_mode_sense(sc);
1697
1698		break;
1699
1700	case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
1701		error = ustorage_fs_min_len(sc, 0, -1U);
1702		if (error) {
1703			break;
1704		}
1705		error = ustorage_fs_check_cmd(sc, 6,
1706		    (1UL << 4) | 1, 0);
1707		if (error) {
1708			break;
1709		}
1710		error = ustorage_fs_prevent_allow(sc);
1711
1712		break;
1713
1714	case SC_READ_6:
1715		i = sc->sc_cbw->CBWCDB[4];
1716		sc->sc_transfer.cmd_dir = DIR_WRITE;
1717		temp = ((i == 0) ? 256UL : i);
1718		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1719		if (error) {
1720			break;
1721		}
1722		error = ustorage_fs_check_cmd(sc, 6,
1723		    (7UL << 1) | (1UL << 4) | 1, 1);
1724		if (error) {
1725			break;
1726		}
1727		error = ustorage_fs_read(sc);
1728
1729		break;
1730
1731	case SC_READ_10:
1732		sc->sc_transfer.cmd_dir = DIR_WRITE;
1733		temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
1734		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1735		if (error) {
1736			break;
1737		}
1738		error = ustorage_fs_check_cmd(sc, 10,
1739		    (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
1740		if (error) {
1741			break;
1742		}
1743		error = ustorage_fs_read(sc);
1744
1745		break;
1746
1747	case SC_READ_12:
1748		sc->sc_transfer.cmd_dir = DIR_WRITE;
1749		temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
1750		if (temp >= (1UL << (32 - 9))) {
1751			/* numerical overflow */
1752			sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
1753			error = 1;
1754			break;
1755		}
1756		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1757		if (error) {
1758			break;
1759		}
1760		error = ustorage_fs_check_cmd(sc, 12,
1761		    (1UL << 1) | (0xfUL << 2) | (0xfUL << 6) | 1, 1);
1762		if (error) {
1763			break;
1764		}
1765		error = ustorage_fs_read(sc);
1766
1767		break;
1768
1769	case SC_READ_CAPACITY:
1770		sc->sc_transfer.cmd_dir = DIR_WRITE;
1771		error = ustorage_fs_check_cmd(sc, 10,
1772		    (0xfUL << 2) | (1UL << 8) | 1, 1);
1773		if (error) {
1774			break;
1775		}
1776		error = ustorage_fs_read_capacity(sc);
1777
1778		break;
1779
1780	case SC_READ_FORMAT_CAPACITIES:
1781		sc->sc_transfer.cmd_dir = DIR_WRITE;
1782		error = ustorage_fs_min_len(sc,
1783		    get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
1784		if (error) {
1785			break;
1786		}
1787		error = ustorage_fs_check_cmd(sc, 10,
1788		    (3UL << 7) | 1, 1);
1789		if (error) {
1790			break;
1791		}
1792		error = ustorage_fs_read_format_capacities(sc);
1793
1794		break;
1795
1796	case SC_REQUEST_SENSE:
1797		sc->sc_transfer.cmd_dir = DIR_WRITE;
1798		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
1799		if (error) {
1800			break;
1801		}
1802		error = ustorage_fs_check_cmd(sc, 6,
1803		    (1UL << 4) | 1, 0);
1804		if (error) {
1805			break;
1806		}
1807		error = ustorage_fs_request_sense(sc);
1808
1809		break;
1810
1811	case SC_START_STOP_UNIT:
1812		error = ustorage_fs_min_len(sc, 0, -1U);
1813		if (error) {
1814			break;
1815		}
1816		error = ustorage_fs_check_cmd(sc, 6,
1817		    (1UL << 1) | (1UL << 4) | 1, 0);
1818		if (error) {
1819			break;
1820		}
1821		error = ustorage_fs_start_stop(sc);
1822
1823		break;
1824
1825	case SC_SYNCHRONIZE_CACHE:
1826		error = ustorage_fs_min_len(sc, 0, -1U);
1827		if (error) {
1828			break;
1829		}
1830		error = ustorage_fs_check_cmd(sc, 10,
1831		    (0xfUL << 2) | (3UL << 7) | 1, 1);
1832		if (error) {
1833			break;
1834		}
1835		error = ustorage_fs_synchronize_cache(sc);
1836
1837		break;
1838
1839	case SC_TEST_UNIT_READY:
1840		error = ustorage_fs_min_len(sc, 0, -1U);
1841		if (error) {
1842			break;
1843		}
1844		error = ustorage_fs_check_cmd(sc, 6,
1845		    0 | 1, 1);
1846		break;
1847
1848		/*
1849		 * Although optional, this command is used by MS-Windows.
1850		 * We support a minimal version: BytChk must be 0.
1851		 */
1852	case SC_VERIFY:
1853		error = ustorage_fs_min_len(sc, 0, -1U);
1854		if (error) {
1855			break;
1856		}
1857		error = ustorage_fs_check_cmd(sc, 10,
1858		    (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
1859		if (error) {
1860			break;
1861		}
1862		error = ustorage_fs_verify(sc);
1863
1864		break;
1865
1866	case SC_WRITE_6:
1867		i = sc->sc_cbw->CBWCDB[4];
1868		sc->sc_transfer.cmd_dir = DIR_READ;
1869		temp = ((i == 0) ? 256UL : i);
1870		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1871		if (error) {
1872			break;
1873		}
1874		error = ustorage_fs_check_cmd(sc, 6,
1875		    (7UL << 1) | (1UL << 4) | 1, 1);
1876		if (error) {
1877			break;
1878		}
1879		error = ustorage_fs_write(sc);
1880
1881		break;
1882
1883	case SC_WRITE_10:
1884		sc->sc_transfer.cmd_dir = DIR_READ;
1885		temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
1886		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1887		if (error) {
1888			break;
1889		}
1890		error = ustorage_fs_check_cmd(sc, 10,
1891		    (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
1892		if (error) {
1893			break;
1894		}
1895		error = ustorage_fs_write(sc);
1896
1897		break;
1898
1899	case SC_WRITE_12:
1900		sc->sc_transfer.cmd_dir = DIR_READ;
1901		temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
1902		if (temp > (mask9 >> 9)) {
1903			/* numerical overflow */
1904			sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
1905			error = 1;
1906			break;
1907		}
1908		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1909		if (error) {
1910			break;
1911		}
1912		error = ustorage_fs_check_cmd(sc, 12,
1913		    (1UL << 1) | (0xfUL << 2) | (0xfUL << 6) | 1, 1);
1914		if (error) {
1915			break;
1916		}
1917		error = ustorage_fs_write(sc);
1918
1919		break;
1920
1921		/*
1922		 * Some mandatory commands that we recognize but don't
1923		 * implement.  They don't mean much in this setting.
1924		 * It's left as an exercise for anyone interested to
1925		 * implement RESERVE and RELEASE in terms of Posix
1926		 * locks.
1927		 */
1928	case SC_FORMAT_UNIT:
1929	case SC_RELEASE:
1930	case SC_RESERVE:
1931	case SC_SEND_DIAGNOSTIC:
1932		/* Fallthrough */
1933
1934	default:
1935		error = ustorage_fs_min_len(sc, 0, -1U);
1936		if (error) {
1937			break;
1938		}
1939		error = ustorage_fs_check_cmd(sc, sc->sc_transfer.cmd_len,
1940		    0xff, 0);
1941		if (error) {
1942			break;
1943		}
1944		sc->sc_transfer.currlun->sense_data =
1945		    SS_INVALID_COMMAND;
1946		error = 1;
1947
1948		break;
1949	}
1950	return (error);
1951}
1952