ustorage_fs.c revision 235000
1139743Simp/* $FreeBSD: stable/9/sys/dev/usb/storage/ustorage_fs.c 235000 2012-05-04 15:05:30Z hselasky $ */
265577Sdes/*-
365577Sdes * Copyright (C) 2003-2005 Alan Stern
459412Smsmith * Copyright (C) 2008 Hans Petter Selasky
559412Smsmith * All rights reserved.
659412Smsmith *
759412Smsmith * Redistribution and use in source and binary forms, with or without
859412Smsmith * modification, are permitted provided that the following conditions
959412Smsmith * are met:
1059412Smsmith * 1. Redistributions of source code must retain the above copyright
1159412Smsmith *    notice, this list of conditions, and the following disclaimer,
1259412Smsmith *    without modification.
1359412Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1459412Smsmith *    notice, this list of conditions and the following disclaimer in the
1559412Smsmith *    documentation and/or other materials provided with the distribution.
1659412Smsmith * 3. The names of the above-listed copyright holders may not be used
1759412Smsmith *    to endorse or promote products derived from this software without
1859412Smsmith *    specific prior written permission.
1959412Smsmith *
2059412Smsmith *
2159412Smsmith * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
2259412Smsmith * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2359412Smsmith * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2459412Smsmith * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2559412Smsmith * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2659412Smsmith * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2759412Smsmith * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2859412Smsmith * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2959412Smsmith * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3059412Smsmith * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3159412Smsmith * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3259412Smsmith */
3359412Smsmith
3459412Smsmith/*
3559412Smsmith * NOTE: Much of the SCSI statemachine handling code derives from the
3659412Smsmith * Linux USB gadget stack.
3759412Smsmith */
3859412Smsmith
3959412Smsmith#include <sys/stdint.h>
4059412Smsmith#include <sys/stddef.h>
4159412Smsmith#include <sys/param.h>
42116173Sobrien#include <sys/queue.h>
43116173Sobrien#include <sys/types.h>
44116173Sobrien#include <sys/systm.h>
4559412Smsmith#include <sys/kernel.h>
4683926Sdes#include <sys/bus.h>
4776166Smarkm#include <sys/module.h>
4874135Sjlemon#include <sys/lock.h>
4983926Sdes#include <sys/mutex.h>
50119911Sdes#include <sys/condvar.h>
5176166Smarkm#include <sys/sysctl.h>
5265633Sdes#include <sys/sx.h>
5383926Sdes#include <sys/unistd.h>
5476166Smarkm#include <sys/callout.h>
5574135Sjlemon#include <sys/malloc.h>
5678025Sdes#include <sys/priv.h>
57168067Sjkim
5876827Salfred#include <dev/usb/usb.h>
5985289Sdes#include <dev/usb/usbdi.h>
6065633Sdes#include "usbdevs.h"
6165633Sdes#include "usb_if.h"
6269995Sdes
63168067Sjkim#define	USB_DEBUG_VAR ustorage_fs_debug
64123246Sdes#include <dev/usb/usb_debug.h>
6583926Sdes
6676839Sjlemon#ifdef USB_DEBUG
6783926Sdesstatic int ustorage_fs_debug = 0;
68159995Snetchild
6965633SdesSYSCTL_NODE(_hw_usb, OID_AUTO, ustorage_fs, CTLFLAG_RW, 0, "USB ustorage_fs");
7083926SdesSYSCTL_INT(_hw_usb_ustorage_fs, OID_AUTO, debug, CTLFLAG_RW,
7183926Sdes    &ustorage_fs_debug, 0, "ustorage_fs debug level");
7259412Smsmith#endif
7359412Smsmith
7483926Sdes/* Define some limits */
7583926Sdes
7659412Smsmith#ifndef USTORAGE_FS_BULK_SIZE
7759412Smsmith#define	USTORAGE_FS_BULK_SIZE (1UL << 17)	/* bytes */
7867588Sdes#endif
7959412Smsmith
8060860Sdes#ifndef	USTORAGE_FS_MAX_LUN
8159412Smsmith#define	USTORAGE_FS_MAX_LUN	8	/* units */
8269799Sdes#endif
8367589Sdes
8478113Sdes#ifndef USTORAGE_QDATA_MAX
85133822Stjr#define	USTORAGE_QDATA_MAX	40	/* bytes */
8667589Sdes#endif
8759412Smsmith
88133822Stjr#define sc_cmd_data sc_cbw.CBWCDB
8959412Smsmith
90133822Stjr/*
91140214Sobrien * The SCSI ID string must be exactly 28 characters long
92140214Sobrien * exluding the terminating zero.
93140214Sobrien */
9487275Srwatson#ifndef USTORAGE_FS_ID_STRING
95133822Stjr#define	USTORAGE_FS_ID_STRING \
9685129Sdes	"FreeBSD " /* 8 */ \
9769995Sdes	"File-Stor Gadget" /* 16 */ \
9885289Sdes	"0101" /* 4 */
9978025Sdes#endif
10084248Sdes
10159412Smsmith/*
10267588Sdes * The following macro defines the number of
10367588Sdes * sectors to be allocated for the RAM disk:
10467588Sdes */
10576405Sdes#ifndef USTORAGE_FS_RAM_SECT
10667588Sdes#define	USTORAGE_FS_RAM_SECT (1UL << 13)
10767588Sdes#endif
10869799Sdes
10967588Sdesstatic uint8_t *ustorage_fs_ramdisk;
11067588Sdes
11174135Sjlemon/* USB transfer definitions */
112159995Snetchild
113159995Snetchild#define	USTORAGE_FS_T_BBB_COMMAND     0
114159995Snetchild#define	USTORAGE_FS_T_BBB_DATA_DUMP   1
115159995Snetchild#define	USTORAGE_FS_T_BBB_DATA_READ   2
116159995Snetchild#define	USTORAGE_FS_T_BBB_DATA_WRITE  3
117159995Snetchild#define	USTORAGE_FS_T_BBB_STATUS      4
118159995Snetchild#define	USTORAGE_FS_T_BBB_MAX         5
119159995Snetchild
120159995Snetchild/* USB data stage direction */
121159995Snetchild
122159995Snetchild#define	DIR_NONE	0
123159995Snetchild#define	DIR_READ	1
124159995Snetchild#define	DIR_WRITE	2
125159995Snetchild
126166140Snetchild/* USB interface specific control request */
127159995Snetchild
12878113Sdes#define	UR_BBB_RESET		0xff	/* Bulk-Only reset */
12978113Sdes#define	UR_BBB_GET_MAX_LUN	0xfe	/* Get maximum lun */
13078113Sdes
13178025Sdes/* Command Block Wrapper */
13278025Sdestypedef struct {
13359412Smsmith	uDWord	dCBWSignature;
13459412Smsmith#define	CBWSIGNATURE	0x43425355
13559412Smsmith	uDWord	dCBWTag;
13659412Smsmith	uDWord	dCBWDataTransferLength;
13759412Smsmith	uByte	bCBWFlags;
13859412Smsmith#define	CBWFLAGS_OUT	0x00
139113574Sjhb#define	CBWFLAGS_IN	0x80
140113574Sjhb	uByte	bCBWLUN;
141113574Sjhb	uByte	bCDBLength;
14260860Sdes#define	CBWCDBLENGTH	16
143117723Sphk	uByte	CBWCDB[CBWCDBLENGTH];
14459412Smsmith} __packed ustorage_fs_bbb_cbw_t;
14559412Smsmith
14659412Smsmith#define	USTORAGE_FS_BBB_CBW_SIZE	31
14759412Smsmith
14859412Smsmith/* Command Status Wrapper */
149170170Sattiliotypedef struct {
15059412Smsmith	uDWord	dCSWSignature;
15159412Smsmith#define	CSWSIGNATURE	0x53425355
15259412Smsmith	uDWord	dCSWTag;
15359412Smsmith	uDWord	dCSWDataResidue;
15459412Smsmith	uByte	bCSWStatus;
15559412Smsmith#define	CSWSTATUS_GOOD	0x0
156170170Sattilio#define	CSWSTATUS_FAILED	0x1
15759412Smsmith#define	CSWSTATUS_PHASE	0x2
158117723Sphk} __packed ustorage_fs_bbb_csw_t;
159153310Smlaier
160153310Smlaier#define	USTORAGE_FS_BBB_CSW_SIZE	13
161117723Sphk
16260860Sdesstruct ustorage_fs_lun {
163124082Salc
16471471Sjhb	uint8_t	*memory_image;
16560860Sdes
16660860Sdes	uint32_t num_sectors;
167124082Salc	uint32_t sense_data;
16860860Sdes	uint32_t sense_data_info;
16959412Smsmith	uint32_t unit_attention_data;
17059412Smsmith
17159412Smsmith	uint8_t	read_only:1;
17259412Smsmith	uint8_t	prevent_medium_removal:1;
17359412Smsmith	uint8_t	info_valid:1;
17459412Smsmith	uint8_t	removable:1;
17559412Smsmith};
17659412Smsmith
17759412Smsmithstruct ustorage_fs_softc {
178170170Sattilio
17959412Smsmith	ustorage_fs_bbb_cbw_t sc_cbw;	/* Command Wrapper Block */
18078025Sdes	ustorage_fs_bbb_csw_t sc_csw;	/* Command Status Block */
18178031Sdes
18269799Sdes	struct mtx sc_mtx;
18376839Sjlemon
18469799Sdes	struct ustorage_fs_lun sc_lun[USTORAGE_FS_MAX_LUN];
18569799Sdes
18669799Sdes	struct {
18769799Sdes		uint8_t *data_ptr;
18869799Sdes		struct ustorage_fs_lun *currlun;
18976839Sjlemon
19076839Sjlemon		uint32_t data_rem;	/* bytes, as reported by the command
19169799Sdes					 * block wrapper */
19269799Sdes		uint32_t offset;	/* bytes */
19369799Sdes
19469799Sdes		uint8_t	cbw_dir;
19569799Sdes		uint8_t	cmd_dir;
19659412Smsmith		uint8_t	lun;
19778025Sdes		uint8_t	cmd_len;
19859412Smsmith		uint8_t	data_short:1;
19959412Smsmith		uint8_t	data_error:1;
200133822Stjr	}	sc_transfer;
20178113Sdes
202133822Stjr	device_t sc_dev;
20378113Sdes	struct usb_device *sc_udev;
20478113Sdes	struct usb_xfer *sc_xfer[USTORAGE_FS_T_BBB_MAX];
20578113Sdes
20678113Sdes	uint8_t	sc_iface_no;		/* interface number */
207159544Sdes	uint8_t	sc_last_lun;
208159544Sdes	uint8_t	sc_last_xfer_index;
209159544Sdes	uint8_t	sc_qdata[USTORAGE_QDATA_MAX];
210123246Sdes};
211118421Sdes
21259412Smsmith/* prototypes */
21369799Sdes
21478031Sdesstatic device_probe_t ustorage_fs_probe;
21578031Sdesstatic device_attach_t ustorage_fs_attach;
21669799Sdesstatic device_detach_t ustorage_fs_detach;
21778031Sdesstatic device_suspend_t ustorage_fs_suspend;
21878031Sdesstatic device_resume_t ustorage_fs_resume;
21978031Sdesstatic usb_handle_request_t ustorage_fs_handle_request;
22078031Sdes
22178031Sdesstatic usb_callback_t ustorage_fs_t_bbb_command_callback;
22278031Sdesstatic usb_callback_t ustorage_fs_t_bbb_data_dump_callback;
22378031Sdesstatic usb_callback_t ustorage_fs_t_bbb_data_read_callback;
22467589Sdesstatic usb_callback_t ustorage_fs_t_bbb_data_write_callback;
22567589Sdesstatic usb_callback_t ustorage_fs_t_bbb_status_callback;
22667589Sdes
22759412Smsmithstatic void ustorage_fs_transfer_start(struct ustorage_fs_softc *sc, uint8_t xfer_index);
228133822Stjrstatic void ustorage_fs_transfer_stop(struct ustorage_fs_softc *sc);
22959412Smsmith
23067589Sdesstatic uint8_t ustorage_fs_verify(struct ustorage_fs_softc *sc);
23159412Smsmithstatic uint8_t ustorage_fs_inquiry(struct ustorage_fs_softc *sc);
23259412Smsmithstatic uint8_t ustorage_fs_request_sense(struct ustorage_fs_softc *sc);
23367589Sdesstatic uint8_t ustorage_fs_read_capacity(struct ustorage_fs_softc *sc);
23459412Smsmithstatic uint8_t ustorage_fs_mode_sense(struct ustorage_fs_softc *sc);
23559412Smsmithstatic uint8_t ustorage_fs_start_stop(struct ustorage_fs_softc *sc);
23667589Sdesstatic uint8_t ustorage_fs_prevent_allow(struct ustorage_fs_softc *sc);
23759412Smsmithstatic uint8_t ustorage_fs_read_format_capacities(struct ustorage_fs_softc *sc);
23859412Smsmithstatic uint8_t ustorage_fs_mode_select(struct ustorage_fs_softc *sc);
23967589Sdesstatic uint8_t ustorage_fs_min_len(struct ustorage_fs_softc *sc, uint32_t len, uint32_t mask);
24059412Smsmithstatic uint8_t ustorage_fs_read(struct ustorage_fs_softc *sc);
24159412Smsmithstatic uint8_t ustorage_fs_write(struct ustorage_fs_softc *sc);
24267589Sdesstatic uint8_t ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t cmd_size, uint16_t mask, uint8_t needs_medium);
24359412Smsmithstatic uint8_t ustorage_fs_do_cmd(struct ustorage_fs_softc *sc);
24459412Smsmith
24578031Sdesstatic device_method_t ustorage_fs_methods[] = {
24659412Smsmith	/* USB interface */
247159170Sdes	DEVMETHOD(usb_handle_request, ustorage_fs_handle_request),
248133822Stjr
249159170Sdes	/* Device interface */
250133822Stjr	DEVMETHOD(device_probe, ustorage_fs_probe),
251133822Stjr	DEVMETHOD(device_attach, ustorage_fs_attach),
25259412Smsmith	DEVMETHOD(device_detach, ustorage_fs_detach),
25359412Smsmith	DEVMETHOD(device_suspend, ustorage_fs_suspend),
254159544Sdes	DEVMETHOD(device_resume, ustorage_fs_resume),
255159544Sdes
256159544Sdes	{0, 0}
257159544Sdes};
258159544Sdes
259159544Sdesstatic driver_t ustorage_fs_driver = {
260123246Sdes	.name = "ustorage_fs",
261118421Sdes	.methods = ustorage_fs_methods,
262118421Sdes	.size = sizeof(struct ustorage_fs_softc),
263118421Sdes};
264118421Sdes
265118421Sdesstatic devclass_t ustorage_fs_devclass;
266159544Sdes
267118421SdesDRIVER_MODULE(ustorage_fs, uhub, ustorage_fs_driver, ustorage_fs_devclass, NULL, 0);
268159544SdesMODULE_VERSION(ustorage_fs, 0);
269159544SdesMODULE_DEPEND(ustorage_fs, usb, 1, 1, 1);
270118421Sdes
27159412Smsmithstatic struct usb_config ustorage_fs_bbb_config[USTORAGE_FS_T_BBB_MAX] = {
27278031Sdes
27378031Sdes	[USTORAGE_FS_T_BBB_COMMAND] = {
27467589Sdes		.type = UE_BULK,
27578031Sdes		.endpoint = UE_ADDR_ANY,
27667589Sdes		.direction = UE_DIR_OUT,
27778031Sdes		.bufsize = sizeof(ustorage_fs_bbb_cbw_t),
27867589Sdes		.flags = {.ext_buffer = 1,},
27978031Sdes		.callback = &ustorage_fs_t_bbb_command_callback,
280119068Sdes		.usb_mode = USB_MODE_DEVICE,
28178031Sdes	},
28267589Sdes
28378025Sdes	[USTORAGE_FS_T_BBB_DATA_DUMP] = {
28478025Sdes		.type = UE_BULK,
28578031Sdes		.endpoint = UE_ADDR_ANY,
28669799Sdes		.direction = UE_DIR_OUT,
28769799Sdes		.bufsize = 0,	/* use wMaxPacketSize */
28878025Sdes		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
28969799Sdes		.callback = &ustorage_fs_t_bbb_data_dump_callback,
29069799Sdes		.usb_mode = USB_MODE_DEVICE,
29169799Sdes	},
29278031Sdes
29369995Sdes	[USTORAGE_FS_T_BBB_DATA_READ] = {
29478025Sdes		.type = UE_BULK,
29559412Smsmith		.endpoint = UE_ADDR_ANY,
296133822Stjr		.direction = UE_DIR_OUT,
29765633Sdes		.bufsize = USTORAGE_FS_BULK_SIZE,
29878113Sdes		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
29985289Sdes		.callback = &ustorage_fs_t_bbb_data_read_callback,
30085289Sdes		.usb_mode = USB_MODE_DEVICE,
30185289Sdes	},
30285289Sdes
30385289Sdes	[USTORAGE_FS_T_BBB_DATA_WRITE] = {
30485289Sdes		.type = UE_BULK,
30585289Sdes		.endpoint = UE_ADDR_ANY,
30685289Sdes		.direction = UE_DIR_IN,
30785289Sdes		.bufsize = USTORAGE_FS_BULK_SIZE,
30885289Sdes		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
30991334Sjulian		.callback = &ustorage_fs_t_bbb_data_write_callback,
31091334Sjulian		.usb_mode = USB_MODE_DEVICE,
31185289Sdes	},
31285289Sdes
31385289Sdes	[USTORAGE_FS_T_BBB_STATUS] = {
31485289Sdes		.type = UE_BULK,
315168942Sdes		.endpoint = UE_ADDR_ANY,
31685289Sdes		.direction = UE_DIR_IN,
317168942Sdes		.bufsize = sizeof(ustorage_fs_bbb_csw_t),
318168942Sdes		.flags = {.short_xfer_ok = 1,.ext_buffer = 1,},
319168942Sdes		.callback = &ustorage_fs_t_bbb_status_callback,
32085289Sdes		.usb_mode = USB_MODE_DEVICE,
32191334Sjulian	},
32291334Sjulian};
32385289Sdes
324119068Sdes/*
32585289Sdes * USB device probe/attach/detach
32685289Sdes */
32785289Sdes
32885289Sdesstatic int
32985289Sdesustorage_fs_probe(device_t dev)
330119068Sdes{
33185289Sdes	struct usb_attach_arg *uaa = device_get_ivars(dev);
33285289Sdes	struct usb_interface_descriptor *id;
33385289Sdes
33485289Sdes	if (uaa->usb_mode != USB_MODE_DEVICE) {
33585289Sdes		return (ENXIO);
33685289Sdes	}
33785289Sdes	/* Check for a standards compliant device */
33885289Sdes	id = usbd_get_interface_descriptor(uaa->iface);
33985289Sdes	if ((id == NULL) ||
34085289Sdes	    (id->bInterfaceClass != UICLASS_MASS) ||
34185289Sdes	    (id->bInterfaceSubClass != UISUBCLASS_SCSI) ||
34285289Sdes	    (id->bInterfaceProtocol != UIPROTO_MASS_BBB)) {
343119068Sdes		return (ENXIO);
344158311Sambrisko	}
345158311Sambrisko	return (BUS_PROBE_GENERIC);
346158311Sambrisko}
347158311Sambrisko
348158311Sambriskostatic int
349158311Sambriskoustorage_fs_attach(device_t dev)
350158311Sambrisko{
35185289Sdes	struct ustorage_fs_softc *sc = device_get_softc(dev);
35285289Sdes	struct usb_attach_arg *uaa = device_get_ivars(dev);
35385289Sdes	struct usb_interface_descriptor *id;
35485289Sdes	int err;
35585289Sdes	int unit;
35685289Sdes
35785289Sdes	/*
35885289Sdes	 * NOTE: the softc struct is cleared in device_set_driver.
35985289Sdes	 * We can safely call ustorage_fs_detach without specifically
36085289Sdes	 * initializing the struct.
36185289Sdes	 */
36285289Sdes
36385289Sdes	sc->sc_dev = dev;
36485289Sdes	sc->sc_udev = uaa->device;
36585289Sdes	unit = device_get_unit(dev);
36685289Sdes
36785289Sdes	/* enable power saving mode */
36885289Sdes	usbd_set_power_mode(uaa->device, USB_POWER_MODE_SAVE);
36985289Sdes
37085289Sdes	if (unit == 0) {
37185289Sdes		if (ustorage_fs_ramdisk == NULL) {
37278113Sdes			/*
37378113Sdes			 * allocate a memory image for our ramdisk until
37478025Sdes			 * further
37578025Sdes			 */
37665633Sdes			ustorage_fs_ramdisk =
377123246Sdes			    malloc(USTORAGE_FS_RAM_SECT << 9, M_USB,
378120339Sdes			    M_ZERO | M_WAITOK);
379120339Sdes
380120339Sdes			if (ustorage_fs_ramdisk == NULL) {
381120339Sdes				return (ENOMEM);
382120339Sdes			}
383120339Sdes		}
384143194Ssobomax		sc->sc_lun[0].memory_image = ustorage_fs_ramdisk;
385143194Ssobomax		sc->sc_lun[0].num_sectors = USTORAGE_FS_RAM_SECT;
386143194Ssobomax		sc->sc_lun[0].removable = 1;
387143194Ssobomax	}
388143194Ssobomax
389143194Ssobomax	device_set_usb_desc(dev);
39078025Sdes
39169799Sdes	mtx_init(&sc->sc_mtx, "USTORAGE_FS lock",
39269799Sdes	    NULL, (MTX_DEF | MTX_RECURSE));
39369799Sdes
39469799Sdes	/* get interface index */
39569799Sdes
39685657Sdillon	id = usbd_get_interface_descriptor(uaa->iface);
397170170Sattilio	if (id == NULL) {
398170170Sattilio		device_printf(dev, "failed to get "
399170170Sattilio		    "interface number\n");
400170170Sattilio		goto detach;
401170170Sattilio	}
402170170Sattilio	sc->sc_iface_no = id->bInterfaceNumber;
403113574Sjhb
40478025Sdes	err = usbd_transfer_setup(uaa->device,
40565633Sdes	    &uaa->info.bIfaceIndex, sc->sc_xfer, ustorage_fs_bbb_config,
40665633Sdes	    USTORAGE_FS_T_BBB_MAX, sc, &sc->sc_mtx);
40778113Sdes	if (err) {
40878113Sdes		device_printf(dev, "could not setup required "
40978113Sdes		    "transfers, %s\n", usbd_errstr(err));
41078025Sdes		goto detach;
41178025Sdes	}
41265633Sdes	/* start Mass Storage State Machine */
41365633Sdes
41465633Sdes	mtx_lock(&sc->sc_mtx);
41565633Sdes	ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_COMMAND);
41685657Sdillon	mtx_unlock(&sc->sc_mtx);
417113574Sjhb
41869799Sdes	return (0);			/* success */
41978025Sdes
42065633Sdesdetach:
42165633Sdes	ustorage_fs_detach(dev);
42278113Sdes	return (ENXIO);			/* failure */
423167159Sjkim}
424167159Sjkim
425167159Sjkimstatic int
426167159Sjkimustorage_fs_detach(device_t dev)
427167159Sjkim{
428167159Sjkim	struct ustorage_fs_softc *sc = device_get_softc(dev);
429167159Sjkim
430167159Sjkim	/* teardown our statemachine */
431167159Sjkim
432167159Sjkim	usbd_transfer_unsetup(sc->sc_xfer, USTORAGE_FS_T_BBB_MAX);
433167159Sjkim
434167159Sjkim	mtx_destroy(&sc->sc_mtx);
435167159Sjkim
436167159Sjkim	return (0);			/* success */
437167159Sjkim}
438167159Sjkim
439167159Sjkimstatic int
440167159Sjkimustorage_fs_suspend(device_t dev)
441167159Sjkim{
442167159Sjkim	device_printf(dev, "suspending\n");
443167159Sjkim	return (0);			/* success */
444167159Sjkim}
445167159Sjkim
446167159Sjkimstatic int
447167159Sjkimustorage_fs_resume(device_t dev)
448167159Sjkim{
449167159Sjkim	device_printf(dev, "resuming\n");
450167159Sjkim	return (0);			/* success */
451167159Sjkim}
452167159Sjkim
453167159Sjkim/*
454168762Sdes * Generic functions to handle transfers
455167159Sjkim */
456167159Sjkim
457167159Sjkimstatic void
458167159Sjkimustorage_fs_transfer_start(struct ustorage_fs_softc *sc, uint8_t xfer_index)
459167159Sjkim{
460167159Sjkim	if (sc->sc_xfer[xfer_index]) {
461167159Sjkim		sc->sc_last_xfer_index = xfer_index;
462167159Sjkim		usbd_transfer_start(sc->sc_xfer[xfer_index]);
463167159Sjkim	}
464167159Sjkim}
465167159Sjkim
466167159Sjkimstatic void
467167159Sjkimustorage_fs_transfer_stop(struct ustorage_fs_softc *sc)
468167159Sjkim{
469168762Sdes	usbd_transfer_stop(sc->sc_xfer[sc->sc_last_xfer_index]);
470167159Sjkim	mtx_unlock(&sc->sc_mtx);
471167159Sjkim	usbd_transfer_drain(sc->sc_xfer[sc->sc_last_xfer_index]);
472167159Sjkim	mtx_lock(&sc->sc_mtx);
473167159Sjkim}
47478113Sdes
47578113Sdesstatic int
47678025Sdesustorage_fs_handle_request(device_t dev,
47778025Sdes    const void *preq, void **pptr, uint16_t *plen,
47865633Sdes    uint16_t offset, uint8_t *pstate)
47987275Srwatson{
48087275Srwatson	struct ustorage_fs_softc *sc = device_get_softc(dev);
48187275Srwatson	const struct usb_device_request *req = preq;
482112206Sjhb	uint8_t is_complete = *pstate;
483112206Sjhb
484167159Sjkim	if (!is_complete) {
485167159Sjkim		if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
486167159Sjkim		    (req->bRequest == UR_BBB_RESET)) {
487167159Sjkim			*plen = 0;
488167159Sjkim			mtx_lock(&sc->sc_mtx);
48987275Srwatson			ustorage_fs_transfer_stop(sc);
49078025Sdes			sc->sc_transfer.data_error = 1;
49165633Sdes			ustorage_fs_transfer_start(sc,
49265633Sdes			    USTORAGE_FS_T_BBB_COMMAND);
49378113Sdes			mtx_unlock(&sc->sc_mtx);
49478113Sdes			return (0);
49578113Sdes		} else if ((req->bmRequestType == UT_READ_CLASS_INTERFACE) &&
49678025Sdes			   (req->bRequest == UR_BBB_GET_MAX_LUN)) {
49778025Sdes			if (offset == 0) {
49876839Sjlemon				*plen = 1;
499168762Sdes				*pptr = &sc->sc_last_lun;
50078025Sdes			} else {
50176839Sjlemon				*plen = 0;
50276839Sjlemon			}
50376839Sjlemon			return (0);
50476839Sjlemon		}
50576839Sjlemon	}
50676839Sjlemon	return (ENXIO);			/* use builtin handler */
50776839Sjlemon}
50876839Sjlemon
50976839Sjlemonstatic void
51078116Sdesustorage_fs_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
51176839Sjlemon{
51278025Sdes	struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
51376839Sjlemon	uint32_t tag;
51476839Sjlemon	uint8_t err = 0;
51578113Sdes
51678113Sdes	DPRINTF("\n");
51778113Sdes
51878025Sdes	switch (USB_GET_STATE(xfer)) {
51978025Sdes	case USB_ST_TRANSFERRED:
52067588Sdes
52169995Sdes		tag = UGETDW(sc->sc_cbw.dCBWSignature);
522166140Snetchild
523166140Snetchild		if (tag != CBWSIGNATURE) {
52467588Sdes			/* do nothing */
52594307Sjhb			DPRINTF("invalid signature 0x%08x\n", tag);
52669995Sdes			break;
52778025Sdes		}
52878025Sdes		tag = UGETDW(sc->sc_cbw.dCBWTag);
52967588Sdes
530166140Snetchild		/* echo back tag */
531166140Snetchild		USETDW(sc->sc_csw.dCSWTag, tag);
532166140Snetchild
533166141Snetchild		/* reset status */
534166162Snetchild		sc->sc_csw.bCSWStatus = 0;
535166162Snetchild
536166141Snetchild		/* reset data offset, data length and data remainder */
537166141Snetchild		sc->sc_transfer.offset = 0;
538166140Snetchild		sc->sc_transfer.data_rem =
539166140Snetchild		    UGETDW(sc->sc_cbw.dCBWDataTransferLength);
540166140Snetchild
54173923Sjhb		/* reset data flags */
54267588Sdes		sc->sc_transfer.data_short = 0;
54367588Sdes
54491140Stanimura		/* extract LUN */
54567588Sdes		sc->sc_transfer.lun = sc->sc_cbw.bCBWLUN;
546159995Snetchild
54767588Sdes		if (sc->sc_transfer.data_rem == 0) {
548159995Snetchild			sc->sc_transfer.cbw_dir = DIR_NONE;
549159995Snetchild		} else {
550159995Snetchild			if (sc->sc_cbw.bCBWFlags & CBWFLAGS_IN) {
551159995Snetchild				sc->sc_transfer.cbw_dir = DIR_WRITE;
552159995Snetchild			} else {
553159995Snetchild				sc->sc_transfer.cbw_dir = DIR_READ;
554159995Snetchild			}
555159995Snetchild		}
556159995Snetchild
557159995Snetchild		sc->sc_transfer.cmd_len = sc->sc_cbw.bCDBLength;
558159995Snetchild		if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw.CBWCDB)) ||
559159995Snetchild		    (sc->sc_transfer.cmd_len == 0)) {
560159995Snetchild			/* just halt - this is invalid */
561159995Snetchild			DPRINTF("invalid command length %d bytes\n",
562159995Snetchild			    sc->sc_transfer.cmd_len);
563159995Snetchild			break;
564159995Snetchild		}
565159995Snetchild
566159995Snetchild		err = ustorage_fs_do_cmd(sc);
56769995Sdes		if (err) {
56867588Sdes			/* got an error */
56967588Sdes			DPRINTF("command failed\n");
570159995Snetchild			break;
571159995Snetchild		}
572159995Snetchild		if ((sc->sc_transfer.data_rem > 0) &&
573159995Snetchild		    (sc->sc_transfer.cbw_dir != sc->sc_transfer.cmd_dir)) {
574159995Snetchild			/* contradicting data transfer direction */
575159995Snetchild			err = 1;
57667588Sdes			DPRINTF("data direction mismatch\n");
577159995Snetchild			break;
578159995Snetchild		}
57969799Sdes		switch (sc->sc_transfer.cbw_dir) {
580159995Snetchild		case DIR_READ:
581159995Snetchild			ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_DATA_READ);
582159995Snetchild			break;
58367588Sdes		case DIR_WRITE:
58478025Sdes			ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_DATA_WRITE);
585119068Sdes			break;
58678025Sdes		default:
58767588Sdes			ustorage_fs_transfer_start(sc,
58867588Sdes			    USTORAGE_FS_T_BBB_STATUS);
58967588Sdes			break;
590119911Sdes		}
591119911Sdes		break;
592119911Sdes
593119911Sdes	case USB_ST_SETUP:
594119911Sdestr_setup:
595119911Sdes		if (sc->sc_transfer.data_error) {
596119911Sdes			sc->sc_transfer.data_error = 0;
597120340Sdes			usbd_xfer_set_stall(xfer);
598119911Sdes			DPRINTF("stall pipe\n");
599119911Sdes		}
600119911Sdes
601119911Sdes		usbd_xfer_set_frame_data(xfer, 0, &sc->sc_cbw,
602119911Sdes		    sizeof(sc->sc_cbw));
603119911Sdes		usbd_transfer_submit(xfer);
604119911Sdes		break;
605119911Sdes
606119911Sdes	default:			/* Error */
607119911Sdes		DPRINTF("error\n");
608119911Sdes		if (error == USB_ERR_CANCELLED) {
609119911Sdes			break;
610119911Sdes		}
611119911Sdes		/* If the pipe is already stalled, don't do another stall */
612119911Sdes		if (!usbd_xfer_is_stalled(xfer))
613119911Sdes			sc->sc_transfer.data_error = 1;
614119911Sdes
615119911Sdes		/* try again */
616119911Sdes		goto tr_setup;
617119911Sdes	}
618119911Sdes	if (err) {
619119911Sdes		if (sc->sc_csw.bCSWStatus == 0) {
620119911Sdes			/* set some default error code */
62178113Sdes			sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
62278113Sdes		}
62378025Sdes		if (sc->sc_transfer.cbw_dir == DIR_READ) {
62478025Sdes			/* dump all data */
62567588Sdes			ustorage_fs_transfer_start(sc,
62669995Sdes			    USTORAGE_FS_T_BBB_DATA_DUMP);
62767588Sdes			return;
62869799Sdes		}
62999072Sjulian		if (sc->sc_transfer.cbw_dir == DIR_WRITE) {
630114983Sjhb			/* need to stall before status */
63174135Sjlemon			sc->sc_transfer.data_error = 1;
63267588Sdes		}
633113611Sjhb		ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_STATUS);
63499072Sjulian	}
63599072Sjulian}
63699072Sjulian
63799072Sjulianstatic void
63899072Sjulianustorage_fs_t_bbb_data_dump_callback(struct usb_xfer *xfer, usb_error_t error)
639113611Sjhb{
64099072Sjulian	struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
64199072Sjulian	uint32_t max_bulk = usbd_xfer_max_len(xfer);
64299072Sjulian	int actlen, sumlen;
64399072Sjulian
64499072Sjulian	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
64599072Sjulian
64699072Sjulian	DPRINTF("\n");
64799072Sjulian
64899072Sjulian	switch (USB_GET_STATE(xfer)) {
64999072Sjulian	case USB_ST_TRANSFERRED:
650103216Sjulian		sc->sc_transfer.data_rem -= actlen;
65199072Sjulian		sc->sc_transfer.offset += actlen;
65299072Sjulian
65399072Sjulian		if (actlen != sumlen || sc->sc_transfer.data_rem == 0) {
65499072Sjulian			/* short transfer or end of data */
65599072Sjulian			ustorage_fs_transfer_start(sc,
65699072Sjulian			    USTORAGE_FS_T_BBB_STATUS);
65799072Sjulian			break;
65899072Sjulian		}
65999072Sjulian		/* Fallthrough */
66099072Sjulian
66199072Sjulian	case USB_ST_SETUP:
66299072Sjuliantr_setup:
66399072Sjulian		if (max_bulk > sc->sc_transfer.data_rem) {
66499072Sjulian			max_bulk = sc->sc_transfer.data_rem;
66599072Sjulian		}
66699072Sjulian		if (sc->sc_transfer.data_error) {
66799072Sjulian			sc->sc_transfer.data_error = 0;
66899072Sjulian			usbd_xfer_set_stall(xfer);
669113611Sjhb		}
67099072Sjulian		usbd_xfer_set_frame_len(xfer, 0, max_bulk);
67167588Sdes		usbd_transfer_submit(xfer);
67269995Sdes		break;
67378025Sdes
67478031Sdes	default:			/* Error */
67567588Sdes		if (error == USB_ERR_CANCELLED) {
67667588Sdes			break;
67767588Sdes		}
67867588Sdes		/*
67978025Sdes		 * If the pipe is already stalled, don't do another stall:
68078025Sdes		 */
68173923Sjhb		if (!usbd_xfer_is_stalled(xfer))
68278031Sdes			sc->sc_transfer.data_error = 1;
68378031Sdes
68478031Sdes		/* try again */
68578031Sdes		goto tr_setup;
68678031Sdes	}
68778031Sdes}
68878031Sdes
68978031Sdesstatic void
69078031Sdesustorage_fs_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
69178031Sdes{
69278025Sdes	struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
69367588Sdes	uint32_t max_bulk = usbd_xfer_max_len(xfer);
69478031Sdes	int actlen, sumlen;
69571471Sjhb
69678025Sdes	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
697119068Sdes
69867588Sdes	DPRINTF("\n");
69967588Sdes
70069799Sdes	switch (USB_GET_STATE(xfer)) {
70169799Sdes	case USB_ST_TRANSFERRED:
70269799Sdes		sc->sc_transfer.data_rem -= actlen;
70369799Sdes		sc->sc_transfer.data_ptr += actlen;
70469799Sdes		sc->sc_transfer.offset += actlen;
70569799Sdes
70669799Sdes		if (actlen != sumlen || sc->sc_transfer.data_rem == 0) {
70769799Sdes			/* short transfer or end of data */
70867588Sdes			ustorage_fs_transfer_start(sc,
709113574Sjhb			    USTORAGE_FS_T_BBB_STATUS);
71078025Sdes			break;
711113574Sjhb		}
712113574Sjhb		/* Fallthrough */
713113574Sjhb
714113574Sjhb	case USB_ST_SETUP:
71569995Sdestr_setup:
71669995Sdes		if (max_bulk > sc->sc_transfer.data_rem) {
717113574Sjhb			max_bulk = sc->sc_transfer.data_rem;
71867588Sdes		}
71967588Sdes		if (sc->sc_transfer.data_error) {
72067588Sdes			sc->sc_transfer.data_error = 0;
72167588Sdes			usbd_xfer_set_stall(xfer);
72267588Sdes		}
72367588Sdes
72467588Sdes		usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
72567588Sdes		    max_bulk);
72667588Sdes		usbd_transfer_submit(xfer);
72767588Sdes		break;
72867588Sdes
72967588Sdes	default:			/* Error */
73071471Sjhb		if (error == USB_ERR_CANCELLED) {
731104306Sjmallett			break;
73269799Sdes		}
73369799Sdes		/* If the pipe is already stalled, don't do another stall */
73469799Sdes		if (!usbd_xfer_is_stalled(xfer))
73569799Sdes			sc->sc_transfer.data_error = 1;
73678025Sdes
737114983Sjhb		/* try again */
738114983Sjhb		goto tr_setup;
739114983Sjhb	}
740114983Sjhb}
741114983Sjhb
74271471Sjhbstatic void
743119068Sdesustorage_fs_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
74467588Sdes{
74567588Sdes	struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
74667588Sdes	uint32_t max_bulk = usbd_xfer_max_len(xfer);
74767588Sdes	int actlen, sumlen;
74867588Sdes
74978025Sdes	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
75078025Sdes
75178025Sdes	DPRINTF("\n");
752119068Sdes
75378025Sdes	switch (USB_GET_STATE(xfer)) {
75467588Sdes	case USB_ST_TRANSFERRED:
75574135Sjlemon		sc->sc_transfer.data_rem -= actlen;
756119911Sdes		sc->sc_transfer.data_ptr += actlen;
75778113Sdes		sc->sc_transfer.offset += actlen;
758119911Sdes
759119911Sdes		if (actlen != sumlen || sc->sc_transfer.data_rem == 0) {
760119911Sdes			/* short transfer or end of data */
761119911Sdes			ustorage_fs_transfer_start(sc,
762119911Sdes			    USTORAGE_FS_T_BBB_STATUS);
763119911Sdes			break;
764119911Sdes		}
765119911Sdes	case USB_ST_SETUP:
766119911Sdestr_setup:
767119911Sdes		if (max_bulk >= sc->sc_transfer.data_rem) {
768119911Sdes			max_bulk = sc->sc_transfer.data_rem;
769119911Sdes			if (sc->sc_transfer.data_short)
770119911Sdes				usbd_xfer_set_flag(xfer, USB_FORCE_SHORT_XFER);
771119911Sdes			else
772119911Sdes				usbd_xfer_clr_flag(xfer, USB_FORCE_SHORT_XFER);
773119911Sdes		} else
774119911Sdes			usbd_xfer_clr_flag(xfer, USB_FORCE_SHORT_XFER);
775119911Sdes
776119911Sdes		if (sc->sc_transfer.data_error) {
777119911Sdes			sc->sc_transfer.data_error = 0;
778119911Sdes			usbd_xfer_set_stall(xfer);
779119911Sdes		}
780119911Sdes
781119911Sdes		usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
782119911Sdes		    max_bulk);
783119911Sdes		usbd_transfer_submit(xfer);
784119911Sdes		break;
785119911Sdes
786119911Sdes	default:			/* Error */
787119911Sdes		if (error == USB_ERR_CANCELLED) {
788119911Sdes			break;
789119911Sdes		}
790119911Sdes		/*
791119911Sdes		 * If the pipe is already stalled, don't do another
79278113Sdes		 * stall
79378113Sdes		 */
79478025Sdes		if (!usbd_xfer_is_stalled(xfer))
79578113Sdes			sc->sc_transfer.data_error = 1;
79678113Sdes
79778113Sdes		/* try again */
798138281Scperciva		goto tr_setup;
79978113Sdes	}
80078113Sdes}
80178113Sdes
80278113Sdesstatic void
80378113Sdesustorage_fs_t_bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
80478113Sdes{
80578113Sdes	struct ustorage_fs_softc *sc = usbd_xfer_softc(xfer);
80678113Sdes
80778113Sdes	DPRINTF("\n");
80878113Sdes
80978113Sdes	switch (USB_GET_STATE(xfer)) {
81078113Sdes	case USB_ST_TRANSFERRED:
81194620Sjhb		ustorage_fs_transfer_start(sc, USTORAGE_FS_T_BBB_COMMAND);
812127694Spjd		break;
81394620Sjhb
81494620Sjhb	case USB_ST_SETUP:
81594620Sjhbtr_setup:
81694620Sjhb		USETDW(sc->sc_csw.dCSWSignature, CSWSIGNATURE);
81794620Sjhb		USETDW(sc->sc_csw.dCSWDataResidue, sc->sc_transfer.data_rem);
81894620Sjhb
81994620Sjhb		if (sc->sc_transfer.data_error) {
820103767Sjake			sc->sc_transfer.data_error = 0;
821103767Sjake			usbd_xfer_set_stall(xfer);
82294620Sjhb		}
82394620Sjhb
824138281Scperciva		usbd_xfer_set_frame_data(xfer, 0, &sc->sc_csw,
825138281Scperciva		    sizeof(sc->sc_csw));
826138281Scperciva		usbd_transfer_submit(xfer);
827138281Scperciva		break;
828138281Scperciva
829138281Scperciva	default:
830138281Scperciva		if (error == USB_ERR_CANCELLED) {
831138281Scperciva			break;
832138281Scperciva		}
833138281Scperciva		/* If the pipe is already stalled, don't do another stall */
83494620Sjhb		if (!usbd_xfer_is_stalled(xfer))
835138281Scperciva			sc->sc_transfer.data_error = 1;
83694620Sjhb
83778113Sdes		/* try again */
838138281Scperciva		goto tr_setup;
83978113Sdes	}
84078113Sdes}
84178113Sdes
84278113Sdes/* SCSI commands that we recognize */
84378113Sdes#define	SC_FORMAT_UNIT			0x04
84478113Sdes#define	SC_INQUIRY			0x12
845116173Sobrien#define	SC_MODE_SELECT_6		0x15
846116173Sobrien#define	SC_MODE_SELECT_10		0x55
847116173Sobrien#define	SC_MODE_SENSE_6			0x1a
848116173Sobrien#define	SC_MODE_SENSE_10		0x5a
849116173Sobrien#define	SC_PREVENT_ALLOW_MEDIUM_REMOVAL	0x1e
850168762Sdes#define	SC_READ_6			0x08
851116173Sobrien#define	SC_READ_10			0x28
852116173Sobrien#define	SC_READ_12			0xa8
853116173Sobrien#define	SC_READ_CAPACITY		0x25
854116173Sobrien#define	SC_READ_FORMAT_CAPACITIES	0x23
855116173Sobrien#define	SC_RELEASE			0x17
856116173Sobrien#define	SC_REQUEST_SENSE		0x03
857116173Sobrien#define	SC_RESERVE			0x16
858116173Sobrien#define	SC_SEND_DIAGNOSTIC		0x1d
859116173Sobrien#define	SC_START_STOP_UNIT		0x1b
860116173Sobrien#define	SC_SYNCHRONIZE_CACHE		0x35
861121265Scognet#define	SC_TEST_UNIT_READY		0x00
862121246Scognet#define	SC_VERIFY			0x2f
863169156Salc#define	SC_WRITE_6			0x0a
864121265Scognet#define	SC_WRITE_10			0x2a
865169156Salc#define	SC_WRITE_12			0xaa
866121265Scognet
867121265Scognet/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
868121265Scognet#define	SS_NO_SENSE				0
869121265Scognet#define	SS_COMMUNICATION_FAILURE		0x040800
870169156Salc#define	SS_INVALID_COMMAND			0x052000
871121265Scognet#define	SS_INVALID_FIELD_IN_CDB			0x052400
872121265Scognet#define	SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE	0x052100
873137507Sphk#define	SS_LOGICAL_UNIT_NOT_SUPPORTED		0x052500
874137507Sphk#define	SS_MEDIUM_NOT_PRESENT			0x023a00
875161094Skib#define	SS_MEDIUM_REMOVAL_PREVENTED		0x055302
876168762Sdes#define	SS_NOT_READY_TO_READY_TRANSITION	0x062800
877121246Scognet#define	SS_RESET_OCCURRED			0x062900
878121246Scognet#define	SS_SAVING_PARAMETERS_NOT_SUPPORTED	0x053900
879121246Scognet#define	SS_UNRECOVERED_READ_ERROR		0x031100
880121246Scognet#define	SS_WRITE_ERROR				0x030c02
881121246Scognet#define	SS_WRITE_PROTECTED			0x072700
882168762Sdes
883121246Scognet#define	SK(x)		((uint8_t) ((x) >> 16))	/* Sense Key byte, etc. */
884121246Scognet#define	ASC(x)		((uint8_t) ((x) >> 8))
885168762Sdes#define	ASCQ(x)		((uint8_t) (x))
886121246Scognet
887121246Scognet/* Routines for unaligned data access */
888168762Sdes
889121246Scognetstatic uint16_t
890169156Salcget_be16(uint8_t *buf)
891168762Sdes{
892121246Scognet	return ((uint16_t)buf[0] << 8) | ((uint16_t)buf[1]);
893121246Scognet}
894121265Scognet
895121265Scognetstatic uint32_t
896121246Scognetget_be32(uint8_t *buf)
897121246Scognet{
898169156Salc	return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
899121246Scognet	((uint32_t)buf[2] << 8) | ((uint32_t)buf[3]);
900169156Salc}
901169156Salc
902169156Salcstatic void
903169156Salcput_be16(uint8_t *buf, uint16_t val)
904121246Scognet{
905169156Salc	buf[0] = val >> 8;
906121246Scognet	buf[1] = val;
907121246Scognet}
908121246Scognet
909161094Skibstatic void
910161094Skibput_be32(uint8_t *buf, uint32_t val)
911161094Skib{
912161094Skib	buf[0] = val >> 24;
913121246Scognet	buf[1] = val >> 16;
914161094Skib	buf[2] = val >> 8;
915161094Skib	buf[3] = val & 0xff;
916169156Salc}
917169156Salc
918121246Scognet/*------------------------------------------------------------------------*
919121246Scognet *	ustorage_fs_verify
920121246Scognet *
921169156Salc * Returns:
922161094Skib *    0: Success
923161094Skib * Else: Failure
924161094Skib *------------------------------------------------------------------------*/
925161094Skibstatic uint8_t
926161094Skibustorage_fs_verify(struct ustorage_fs_softc *sc)
927161094Skib{
928161094Skib	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
929161094Skib	uint32_t lba;
930161094Skib	uint32_t vlen;
931121246Scognet	uint64_t file_offset;
932121246Scognet	uint64_t amount_left;
933121246Scognet
934121246Scognet	/*
935121246Scognet	 * Get the starting Logical Block Address
936168762Sdes	 */
937121246Scognet	lba = get_be32(&sc->sc_cmd_data[2]);
938168762Sdes
939121246Scognet	/*
940121246Scognet	 * We allow DPO (Disable Page Out = don't save data in the cache)
941121246Scognet	 * but we don't implement it.
942121246Scognet	 */
943121246Scognet	if ((sc->sc_cmd_data[1] & ~0x10) != 0) {
944121246Scognet		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
945121246Scognet		return (1);
946121246Scognet	}
947121246Scognet	vlen = get_be16(&sc->sc_cmd_data[7]);
948121265Scognet	if (vlen == 0) {
949121246Scognet		goto done;
950121246Scognet	}
951121265Scognet	/* No default reply */
952121246Scognet
953121246Scognet	/* Prepare to carry out the file verify */
954121246Scognet	amount_left = vlen;
955121246Scognet	amount_left <<= 9;
956121246Scognet	file_offset = lba;
957121246Scognet	file_offset <<= 9;
958121246Scognet
959121246Scognet	/* Range check */
960121246Scognet	vlen += lba;
961121246Scognet
962121246Scognet	if ((vlen < lba) ||
963169156Salc	    (vlen > currlun->num_sectors) ||
964169156Salc	    (lba >= currlun->num_sectors)) {
965121246Scognet		currlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
966169156Salc		return (1);
967121246Scognet	}
968121246Scognet	/* XXX TODO: verify that data is readable */
969169156Salcdone:
970169156Salc	return (ustorage_fs_min_len(sc, 0, -1U));
971169156Salc}
972169156Salc
973169156Salc/*------------------------------------------------------------------------*
974169156Salc *	ustorage_fs_inquiry
975169156Salc *
976169156Salc * Returns:
977169156Salc *    0: Success
978121246Scognet * Else: Failure
979169156Salc *------------------------------------------------------------------------*/
980168762Sdesstatic uint8_t
981121246Scognetustorage_fs_inquiry(struct ustorage_fs_softc *sc)
982168762Sdes{
983168762Sdes	uint8_t *buf = sc->sc_transfer.data_ptr;
984116173Sobrien
98578113Sdes	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
98678113Sdes
98778025Sdes	if (!sc->sc_transfer.currlun) {
98878025Sdes		/* Unsupported LUNs are okay */
98974135Sjlemon		memset(buf, 0, 36);
99085129Sdes		buf[0] = 0x7f;
99174135Sjlemon		/* Unsupported, no device - type */
99274135Sjlemon		return (ustorage_fs_min_len(sc, 36, -1U));
99385129Sdes	}
99483926Sdes	memset(buf, 0, 8);
99585129Sdes	/* Non - removable, direct - access device */
99683926Sdes	if (currlun->removable)
99774135Sjlemon		buf[1] = 0x80;
998108172Shsu	buf[2] = 2;
99974135Sjlemon	/* ANSI SCSI level 2 */
100085129Sdes	buf[3] = 2;
100185129Sdes	/* SCSI - 2 INQUIRY data format */
100283926Sdes	buf[4] = 31;
100383926Sdes	/* Additional length */
100483926Sdes	/* No special options */
100583926Sdes	/* Copy in ID string */
100674135Sjlemon	memcpy(buf + 8, USTORAGE_FS_ID_STRING, 28);
1007108172Shsu
1008119068Sdes#if (USTORAGE_QDATA_MAX < 36)
100978025Sdes#error "(USTORAGE_QDATA_MAX < 36)"
101074135Sjlemon#endif
101174135Sjlemon	return (ustorage_fs_min_len(sc, 36, -1U));
1012158311Sambrisko}
1013167159Sjkim
1014167159Sjkim/*------------------------------------------------------------------------*
1015167159Sjkim *	ustorage_fs_request_sense
1016167159Sjkim *
1017167159Sjkim * Returns:
1018167159Sjkim *    0: Success
1019167159Sjkim * Else: Failure
1020167159Sjkim *------------------------------------------------------------------------*/
1021167159Sjkimstatic uint8_t
1022167159Sjkimustorage_fs_request_sense(struct ustorage_fs_softc *sc)
1023167159Sjkim{
1024167159Sjkim	uint8_t *buf = sc->sc_transfer.data_ptr;
1025167159Sjkim	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1026167159Sjkim	uint32_t sd;
1027167159Sjkim	uint32_t sdinfo;
1028167159Sjkim	uint8_t valid;
1029167159Sjkim
1030167159Sjkim	/*
1031167159Sjkim	 * From the SCSI-2 spec., section 7.9 (Unit attention condition):
1032167159Sjkim	 *
1033167159Sjkim	 * If a REQUEST SENSE command is received from an initiator
1034167159Sjkim	 * with a pending unit attention condition (before the target
1035167159Sjkim	 * generates the contingent allegiance condition), then the
1036167159Sjkim	 * target shall either:
1037167159Sjkim	 *   a) report any pending sense data and preserve the unit
1038167159Sjkim	 *	attention condition on the logical unit, or,
1039167159Sjkim	 *   b) report the unit attention condition, may discard any
1040167159Sjkim	 *	pending sense data, and clear the unit attention
1041167159Sjkim	 *	condition on the logical unit for that initiator.
1042167159Sjkim	 *
1043167159Sjkim	 * FSG normally uses option a); enable this code to use option b).
1044167159Sjkim	 */
1045167159Sjkim#if 0
1046168762Sdes	if (currlun && currlun->unit_attention_data != SS_NO_SENSE) {
1047167159Sjkim		currlun->sense_data = currlun->unit_attention_data;
1048167159Sjkim		currlun->unit_attention_data = SS_NO_SENSE;
1049167159Sjkim	}
1050167159Sjkim#endif
1051167159Sjkim
1052167159Sjkim	if (!currlun) {
1053164692Sjkim		/* Unsupported LUNs are okay */
1054164692Sjkim		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
1055164692Sjkim		sdinfo = 0;
1056164692Sjkim		valid = 0;
1057164692Sjkim	} else {
1058164692Sjkim		sd = currlun->sense_data;
1059168067Sjkim		sdinfo = currlun->sense_data_info;
1060164692Sjkim		valid = currlun->info_valid << 7;
1061164692Sjkim		currlun->sense_data = SS_NO_SENSE;
1062164692Sjkim		currlun->sense_data_info = 0;
1063164692Sjkim		currlun->info_valid = 0;
1064163251Skeramida	}
1065163129Snetchild
1066163129Snetchild	memset(buf, 0, 18);
1067163129Snetchild	buf[0] = valid | 0x70;
1068163129Snetchild	/* Valid, current error */
1069163757Snetchild	buf[2] = SK(sd);
1070163129Snetchild	put_be32(&buf[3], sdinfo);
1071163129Snetchild	/* Sense information */
1072163129Snetchild	buf[7] = 18 - 8;
1073163129Snetchild	/* Additional sense length */
1074163129Snetchild	buf[12] = ASC(sd);
1075164692Sjkim	buf[13] = ASCQ(sd);
1076164692Sjkim
1077164692Sjkim#if (USTORAGE_QDATA_MAX < 18)
1078164692Sjkim#error "(USTORAGE_QDATA_MAX < 18)"
1079164692Sjkim#endif
1080164692Sjkim	return (ustorage_fs_min_len(sc, 18, -1U));
1081168067Sjkim}
1082168067Sjkim
1083164692Sjkim/*------------------------------------------------------------------------*
1084164692Sjkim *	ustorage_fs_read_capacity
1085164692Sjkim *
1086164692Sjkim * Returns:
1087158311Sambrisko *    0: Success
1088158311Sambrisko * Else: Failure
1089158311Sambrisko *------------------------------------------------------------------------*/
1090158311Sambriskostatic uint8_t
1091158311Sambriskoustorage_fs_read_capacity(struct ustorage_fs_softc *sc)
1092168762Sdes{
1093158311Sambrisko	uint8_t *buf = sc->sc_transfer.data_ptr;
1094158311Sambrisko	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1095158311Sambrisko	uint32_t lba = get_be32(&sc->sc_cmd_data[2]);
1096158311Sambrisko	uint8_t pmi = sc->sc_cmd_data[8];
1097158311Sambrisko
1098158311Sambrisko	/* Check the PMI and LBA fields */
1099158311Sambrisko	if ((pmi > 1) || ((pmi == 0) && (lba != 0))) {
1100158311Sambrisko		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1101158311Sambrisko		return (1);
1102168762Sdes	}
1103158311Sambrisko	/* Max logical block */
1104158311Sambrisko	put_be32(&buf[0], currlun->num_sectors - 1);
1105158311Sambrisko	/* Block length */
110685538Sphk	put_be32(&buf[4], 512);
110785538Sphk
110878113Sdes#if (USTORAGE_QDATA_MAX < 8)
110978113Sdes#error "(USTORAGE_QDATA_MAX < 8)"
111078113Sdes#endif
111178025Sdes	return (ustorage_fs_min_len(sc, 8, -1U));
111278025Sdes}
111374135Sjlemon
1114158311Sambrisko/*------------------------------------------------------------------------*
111578025Sdes *	ustorage_fs_mode_sense
111674135Sjlemon *
1117158311Sambrisko * Returns:
1118158311Sambrisko *    0: Success
1119158311Sambrisko * Else: Failure
112074135Sjlemon *------------------------------------------------------------------------*/
112178025Sdesstatic uint8_t
1122119068Sdesustorage_fs_mode_sense(struct ustorage_fs_softc *sc)
112378025Sdes{
112474135Sjlemon	uint8_t *buf = sc->sc_transfer.data_ptr;
112574135Sjlemon	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
112678113Sdes	uint8_t *buf0;
112778113Sdes	uint16_t len;
112878113Sdes	uint16_t limit;
112978025Sdes	uint8_t mscmnd = sc->sc_cmd_data[0];
113078025Sdes	uint8_t pc;
113174135Sjlemon	uint8_t page_code;
1132168762Sdes	uint8_t changeable_values;
113378025Sdes	uint8_t all_pages;
113478025Sdes
113578025Sdes	buf0 = buf;
113678025Sdes
113774135Sjlemon	if ((sc->sc_cmd_data[1] & ~0x08) != 0) {
113883926Sdes		/* Mask away DBD */
113978025Sdes		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
114083926Sdes		return (1);
114183926Sdes	}
114283926Sdes	pc = sc->sc_cmd_data[2] >> 6;
114383926Sdes	page_code = sc->sc_cmd_data[2] & 0x3f;
114483926Sdes	if (pc == 3) {
114583926Sdes		currlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
1146119068Sdes		return (1);
114783926Sdes	}
114883926Sdes	changeable_values = (pc == 1);
114983926Sdes	all_pages = (page_code == 0x3f);
115083926Sdes
115183926Sdes	/*
115283926Sdes	 * Write the mode parameter header.  Fixed values are: default
115383926Sdes	 * medium type, no cache control (DPOFUA), and no block descriptors.
115483926Sdes	 * The only variable value is the WriteProtect bit.  We will fill in
115583926Sdes	 * the mode data length later.
115685129Sdes	 */
115778025Sdes	memset(buf, 0, 8);
115885129Sdes	if (mscmnd == SC_MODE_SENSE_6) {
115985129Sdes		buf[2] = (currlun->read_only ? 0x80 : 0x00);
116085129Sdes		/* WP, DPOFUA */
116185129Sdes		buf += 4;
116285129Sdes		limit = 255;
116374135Sjlemon	} else {
116485129Sdes		/* SC_MODE_SENSE_10 */
116578025Sdes		buf[3] = (currlun->read_only ? 0x80 : 0x00);
1166119923Sdes		/* WP, DPOFUA */
1167119911Sdes		buf += 8;
1168167482Sdes		limit = 65535;
1169119911Sdes		/* Should really be mod_data.buflen */
1170167482Sdes	}
1171119911Sdes
1172167482Sdes	/* No block descriptors */
1173119911Sdes
1174167482Sdes	/*
1175119911Sdes	 * The mode pages, in numerical order.
1176167482Sdes	 */
117783926Sdes	if ((page_code == 0x08) || all_pages) {
1178119911Sdes		buf[0] = 0x08;
1179167482Sdes		/* Page code */
118083926Sdes		buf[1] = 10;
1181158311Sambrisko		/* Page length */
1182167482Sdes		memset(buf + 2, 0, 10);
1183119911Sdes		/* None of the fields are changeable */
1184167482Sdes
118587543Sdes		if (!changeable_values) {
1186167482Sdes			buf[2] = 0x04;
1187119911Sdes			/* Write cache enable, */
1188167482Sdes			/* Read cache not disabled */
1189119911Sdes			/* No cache retention priorities */
1190167482Sdes			put_be16(&buf[4], 0xffff);
1191119911Sdes			/* Don 't disable prefetch */
1192167482Sdes			/* Minimum prefetch = 0 */
119378025Sdes			put_be16(&buf[8], 0xffff);
1194119923Sdes			/* Maximum prefetch */
1195167482Sdes			put_be16(&buf[10], 0xffff);
119685129Sdes			/* Maximum prefetch ceiling */
1197167482Sdes		}
119878025Sdes		buf += 12;
1199119923Sdes	}
1200167482Sdes	/*
120185129Sdes	 * Check that a valid page was requested and the mode data length
1202167482Sdes	 * isn't too long.
1203119911Sdes	 */
1204167482Sdes	len = buf - buf0;
1205116173Sobrien	if (len > limit) {
1206167482Sdes		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
120787543Sdes		return (1);
1208167482Sdes	}
1209116173Sobrien	/* Store the mode data length */
1210167482Sdes	if (mscmnd == SC_MODE_SENSE_6)
121185129Sdes		buf0[0] = len - 1;
1212167482Sdes	else
1213119911Sdes		put_be16(buf0, len - 2);
1214167482Sdes
121585129Sdes#if (USTORAGE_QDATA_MAX < 24)
1216167482Sdes#error "(USTORAGE_QDATA_MAX < 24)"
1217119911Sdes#endif
1218167482Sdes	return (ustorage_fs_min_len(sc, len, -1U));
121985129Sdes}
1220167482Sdes
122185129Sdes/*------------------------------------------------------------------------*
1222158311Sambrisko *	ustorage_fs_start_stop
1223167482Sdes *
1224158311Sambrisko * Returns:
1225167482Sdes *    0: Success
1226158311Sambrisko * Else: Failure
1227167482Sdes *------------------------------------------------------------------------*/
1228163129Snetchildstatic uint8_t
1229163129Snetchildustorage_fs_start_stop(struct ustorage_fs_softc *sc)
1230167482Sdes{
1231163129Snetchild	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1232167482Sdes	uint8_t loej;
1233167159Sjkim	uint8_t start;
1234167482Sdes	uint8_t immed;
1235167159Sjkim
1236167482Sdes	if (!currlun->removable) {
1237167159Sjkim		currlun->sense_data = SS_INVALID_COMMAND;
1238167482Sdes		return (1);
1239164692Sjkim	}
1240167482Sdes	immed = sc->sc_cmd_data[1] & 0x01;
1241163129Snetchild	loej = sc->sc_cmd_data[4] & 0x02;
1242167482Sdes	start = sc->sc_cmd_data[4] & 0x01;
1243164692Sjkim
1244167482Sdes	if (immed || loej || start) {
1245163129Snetchild		/* compile fix */
124685129Sdes	}
124785129Sdes	return (0);
124885129Sdes}
124985129Sdes
125085129Sdes/*------------------------------------------------------------------------*
125185129Sdes *	ustorage_fs_prevent_allow
125285129Sdes *
125385129Sdes * Returns:
125485129Sdes *    0: Success
125585129Sdes * Else: Failure
125685129Sdes *------------------------------------------------------------------------*/
125785129Sdesstatic uint8_t
125885129Sdesustorage_fs_prevent_allow(struct ustorage_fs_softc *sc)
125985129Sdes{
126085129Sdes	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
126178025Sdes	uint8_t prevent;
126278025Sdes
1263168440Sjkim	if (!currlun->removable) {
1264168440Sjkim		currlun->sense_data = SS_INVALID_COMMAND;
1265		return (1);
1266	}
1267	prevent = sc->sc_cmd_data[4] & 0x01;
1268	if ((sc->sc_cmd_data[4] & ~0x01) != 0) {
1269		/* Mask away Prevent */
1270		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1271		return (1);
1272	}
1273	if (currlun->prevent_medium_removal && !prevent) {
1274		//fsync_sub(currlun);
1275	}
1276	currlun->prevent_medium_removal = prevent;
1277	return (0);
1278}
1279
1280/*------------------------------------------------------------------------*
1281 *	ustorage_fs_read_format_capacities
1282 *
1283 * Returns:
1284 *    0: Success
1285 * Else: Failure
1286 *------------------------------------------------------------------------*/
1287static uint8_t
1288ustorage_fs_read_format_capacities(struct ustorage_fs_softc *sc)
1289{
1290	uint8_t *buf = sc->sc_transfer.data_ptr;
1291	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1292
1293	buf[0] = buf[1] = buf[2] = 0;
1294	buf[3] = 8;
1295	/* Only the Current / Maximum Capacity Descriptor */
1296	buf += 4;
1297
1298	/* Number of blocks */
1299	put_be32(&buf[0], currlun->num_sectors);
1300	/* Block length */
1301	put_be32(&buf[4], 512);
1302	/* Current capacity */
1303	buf[4] = 0x02;
1304
1305#if (USTORAGE_QDATA_MAX < 12)
1306#error "(USTORAGE_QDATA_MAX < 12)"
1307#endif
1308	return (ustorage_fs_min_len(sc, 12, -1U));
1309}
1310
1311/*------------------------------------------------------------------------*
1312 *	ustorage_fs_mode_select
1313 *
1314 * Return values:
1315 *    0: Success
1316 * Else: Failure
1317 *------------------------------------------------------------------------*/
1318static uint8_t
1319ustorage_fs_mode_select(struct ustorage_fs_softc *sc)
1320{
1321	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1322
1323	/* We don't support MODE SELECT */
1324	currlun->sense_data = SS_INVALID_COMMAND;
1325	return (1);
1326}
1327
1328/*------------------------------------------------------------------------*
1329 *	ustorage_fs_synchronize_cache
1330 *
1331 * Return values:
1332 *    0: Success
1333 * Else: Failure
1334 *------------------------------------------------------------------------*/
1335static uint8_t
1336ustorage_fs_synchronize_cache(struct ustorage_fs_softc *sc)
1337{
1338#if 0
1339	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1340	uint8_t rc;
1341
1342	/*
1343	 * We ignore the requested LBA and write out all dirty data buffers.
1344	 */
1345	rc = 0;
1346	if (rc) {
1347		currlun->sense_data = SS_WRITE_ERROR;
1348	}
1349#endif
1350	return (0);
1351}
1352
1353/*------------------------------------------------------------------------*
1354 *	ustorage_fs_read - read data from disk
1355 *
1356 * Return values:
1357 *    0: Success
1358 * Else: Failure
1359 *------------------------------------------------------------------------*/
1360static uint8_t
1361ustorage_fs_read(struct ustorage_fs_softc *sc)
1362{
1363	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1364	uint64_t file_offset;
1365	uint32_t lba;
1366	uint32_t len;
1367
1368	/*
1369	 * Get the starting Logical Block Address and check that it's not
1370	 * too big
1371	 */
1372	if (sc->sc_cmd_data[0] == SC_READ_6) {
1373		lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
1374		    get_be16(&sc->sc_cmd_data[2]);
1375	} else {
1376		lba = get_be32(&sc->sc_cmd_data[2]);
1377
1378		/*
1379		 * We allow DPO (Disable Page Out = don't save data in the
1380		 * cache) and FUA (Force Unit Access = don't read from the
1381		 * cache), but we don't implement them.
1382		 */
1383		if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
1384			currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1385			return (1);
1386		}
1387	}
1388	len = sc->sc_transfer.data_rem >> 9;
1389	len += lba;
1390
1391	if ((len < lba) ||
1392	    (len > currlun->num_sectors) ||
1393	    (lba >= currlun->num_sectors)) {
1394		currlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1395		return (1);
1396	}
1397	file_offset = lba;
1398	file_offset <<= 9;
1399
1400	sc->sc_transfer.data_ptr = currlun->memory_image + file_offset;
1401
1402	return (0);
1403}
1404
1405/*------------------------------------------------------------------------*
1406 *	ustorage_fs_write - write data to disk
1407 *
1408 * Return values:
1409 *    0: Success
1410 * Else: Failure
1411 *------------------------------------------------------------------------*/
1412static uint8_t
1413ustorage_fs_write(struct ustorage_fs_softc *sc)
1414{
1415	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
1416	uint64_t file_offset;
1417	uint32_t lba;
1418	uint32_t len;
1419
1420	if (currlun->read_only) {
1421		currlun->sense_data = SS_WRITE_PROTECTED;
1422		return (1);
1423	}
1424	/* XXX clear SYNC */
1425
1426	/*
1427	 * Get the starting Logical Block Address and check that it's not
1428	 * too big.
1429	 */
1430	if (sc->sc_cmd_data[0] == SC_WRITE_6)
1431		lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
1432		    get_be16(&sc->sc_cmd_data[2]);
1433	else {
1434		lba = get_be32(&sc->sc_cmd_data[2]);
1435
1436		/*
1437		 * We allow DPO (Disable Page Out = don't save data in the
1438		 * cache) and FUA (Force Unit Access = write directly to the
1439		 * medium).  We don't implement DPO; we implement FUA by
1440		 * performing synchronous output.
1441		 */
1442		if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
1443			currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1444			return (1);
1445		}
1446		if (sc->sc_cmd_data[1] & 0x08) {
1447			/* FUA */
1448			/* XXX set SYNC flag here */
1449		}
1450	}
1451
1452	len = sc->sc_transfer.data_rem >> 9;
1453	len += lba;
1454
1455	if ((len < lba) ||
1456	    (len > currlun->num_sectors) ||
1457	    (lba >= currlun->num_sectors)) {
1458		currlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
1459		return (1);
1460	}
1461	file_offset = lba;
1462	file_offset <<= 9;
1463
1464	sc->sc_transfer.data_ptr = currlun->memory_image + file_offset;
1465
1466	return (0);
1467}
1468
1469/*------------------------------------------------------------------------*
1470 *	ustorage_fs_min_len
1471 *
1472 * Return values:
1473 *    0: Success
1474 * Else: Failure
1475 *------------------------------------------------------------------------*/
1476static uint8_t
1477ustorage_fs_min_len(struct ustorage_fs_softc *sc, uint32_t len, uint32_t mask)
1478{
1479	if (len != sc->sc_transfer.data_rem) {
1480
1481		if (sc->sc_transfer.cbw_dir == DIR_READ) {
1482			/*
1483			 * there must be something wrong about this SCSI
1484			 * command
1485			 */
1486			sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
1487			return (1);
1488		}
1489		/* compute the minimum length */
1490
1491		if (sc->sc_transfer.data_rem > len) {
1492			/* data ends prematurely */
1493			sc->sc_transfer.data_rem = len;
1494			sc->sc_transfer.data_short = 1;
1495		}
1496		/* check length alignment */
1497
1498		if (sc->sc_transfer.data_rem & ~mask) {
1499			/* data ends prematurely */
1500			sc->sc_transfer.data_rem &= mask;
1501			sc->sc_transfer.data_short = 1;
1502		}
1503	}
1504	return (0);
1505}
1506
1507/*------------------------------------------------------------------------*
1508 *	ustorage_fs_check_cmd - check command routine
1509 *
1510 * Check whether the command is properly formed and whether its data
1511 * size and direction agree with the values we already have.
1512 *
1513 * Return values:
1514 *    0: Success
1515 * Else: Failure
1516 *------------------------------------------------------------------------*/
1517static uint8_t
1518ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
1519    uint16_t mask, uint8_t needs_medium)
1520{
1521	struct ustorage_fs_lun *currlun;
1522	uint8_t lun = (sc->sc_cmd_data[1] >> 5);
1523	uint8_t i;
1524
1525	/* Verify the length of the command itself */
1526	if (min_cmd_size > sc->sc_transfer.cmd_len) {
1527		DPRINTF("%u > %u\n",
1528		    min_cmd_size, sc->sc_transfer.cmd_len);
1529		sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
1530		return (1);
1531	}
1532	/* Mask away the LUN */
1533	sc->sc_cmd_data[1] &= 0x1f;
1534
1535	/* Check if LUN is correct */
1536	if (lun != sc->sc_transfer.lun) {
1537
1538	}
1539	/* Check the LUN */
1540	if (sc->sc_transfer.lun <= sc->sc_last_lun) {
1541		sc->sc_transfer.currlun = currlun =
1542		    sc->sc_lun + sc->sc_transfer.lun;
1543		if (sc->sc_cmd_data[0] != SC_REQUEST_SENSE) {
1544			currlun->sense_data = SS_NO_SENSE;
1545			currlun->sense_data_info = 0;
1546			currlun->info_valid = 0;
1547		}
1548		/*
1549		 * If a unit attention condition exists, only INQUIRY
1550		 * and REQUEST SENSE commands are allowed. Anything
1551		 * else must fail!
1552		 */
1553		if ((currlun->unit_attention_data != SS_NO_SENSE) &&
1554		    (sc->sc_cmd_data[0] != SC_INQUIRY) &&
1555		    (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
1556			currlun->sense_data = currlun->unit_attention_data;
1557			currlun->unit_attention_data = SS_NO_SENSE;
1558			return (1);
1559		}
1560	} else {
1561		sc->sc_transfer.currlun = currlun = NULL;
1562
1563		/*
1564		 * INQUIRY and REQUEST SENSE commands are explicitly allowed
1565		 * to use unsupported LUNs; all others may not.
1566		 */
1567		if ((sc->sc_cmd_data[0] != SC_INQUIRY) &&
1568		    (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
1569			return (1);
1570		}
1571	}
1572
1573	/*
1574	 * Check that only command bytes listed in the mask are
1575	 * non-zero.
1576	 */
1577	for (i = 0; i != min_cmd_size; i++) {
1578		if (sc->sc_cmd_data[i] && !(mask & (1UL << i))) {
1579			if (currlun) {
1580				currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
1581			}
1582			return (1);
1583		}
1584	}
1585
1586	/*
1587	 * If the medium isn't mounted and the command needs to access
1588	 * it, return an error.
1589	 */
1590	if (currlun && (!currlun->memory_image) && needs_medium) {
1591		currlun->sense_data = SS_MEDIUM_NOT_PRESENT;
1592		return (1);
1593	}
1594	return (0);
1595}
1596
1597/*------------------------------------------------------------------------*
1598 *	ustorage_fs_do_cmd - do command
1599 *
1600 * Return values:
1601 *    0: Success
1602 * Else: Failure
1603 *------------------------------------------------------------------------*/
1604static uint8_t
1605ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
1606{
1607	uint8_t error = 1;
1608	uint8_t i;
1609	uint32_t temp;
1610	const uint32_t mask9 = (0xFFFFFFFFUL >> 9) << 9;
1611
1612	/* set default data transfer pointer */
1613	sc->sc_transfer.data_ptr = sc->sc_qdata;
1614
1615	DPRINTF("cmd_data[0]=0x%02x, data_rem=0x%08x\n",
1616	    sc->sc_cmd_data[0], sc->sc_transfer.data_rem);
1617
1618	switch (sc->sc_cmd_data[0]) {
1619	case SC_INQUIRY:
1620		sc->sc_transfer.cmd_dir = DIR_WRITE;
1621		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
1622		if (error) {
1623			break;
1624		}
1625		error = ustorage_fs_check_cmd(sc, 6,
1626		    (1UL << 4) | 1, 0);
1627		if (error) {
1628			break;
1629		}
1630		error = ustorage_fs_inquiry(sc);
1631
1632		break;
1633
1634	case SC_MODE_SELECT_6:
1635		sc->sc_transfer.cmd_dir = DIR_READ;
1636		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
1637		if (error) {
1638			break;
1639		}
1640		error = ustorage_fs_check_cmd(sc, 6,
1641		    (1UL << 1) | (1UL << 4) | 1, 0);
1642		if (error) {
1643			break;
1644		}
1645		error = ustorage_fs_mode_select(sc);
1646
1647		break;
1648
1649	case SC_MODE_SELECT_10:
1650		sc->sc_transfer.cmd_dir = DIR_READ;
1651		error = ustorage_fs_min_len(sc,
1652		    get_be16(&sc->sc_cmd_data[7]), -1U);
1653		if (error) {
1654			break;
1655		}
1656		error = ustorage_fs_check_cmd(sc, 10,
1657		    (1UL << 1) | (3UL << 7) | 1, 0);
1658		if (error) {
1659			break;
1660		}
1661		error = ustorage_fs_mode_select(sc);
1662
1663		break;
1664
1665	case SC_MODE_SENSE_6:
1666		sc->sc_transfer.cmd_dir = DIR_WRITE;
1667		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
1668		if (error) {
1669			break;
1670		}
1671		error = ustorage_fs_check_cmd(sc, 6,
1672		    (1UL << 1) | (1UL << 2) | (1UL << 4) | 1, 0);
1673		if (error) {
1674			break;
1675		}
1676		error = ustorage_fs_mode_sense(sc);
1677
1678		break;
1679
1680	case SC_MODE_SENSE_10:
1681		sc->sc_transfer.cmd_dir = DIR_WRITE;
1682		error = ustorage_fs_min_len(sc,
1683		    get_be16(&sc->sc_cmd_data[7]), -1U);
1684		if (error) {
1685			break;
1686		}
1687		error = ustorage_fs_check_cmd(sc, 10,
1688		    (1UL << 1) | (1UL << 2) | (3UL << 7) | 1, 0);
1689		if (error) {
1690			break;
1691		}
1692		error = ustorage_fs_mode_sense(sc);
1693
1694		break;
1695
1696	case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
1697		error = ustorage_fs_min_len(sc, 0, -1U);
1698		if (error) {
1699			break;
1700		}
1701		error = ustorage_fs_check_cmd(sc, 6,
1702		    (1UL << 4) | 1, 0);
1703		if (error) {
1704			break;
1705		}
1706		error = ustorage_fs_prevent_allow(sc);
1707
1708		break;
1709
1710	case SC_READ_6:
1711		i = sc->sc_cmd_data[4];
1712		sc->sc_transfer.cmd_dir = DIR_WRITE;
1713		temp = ((i == 0) ? 256UL : i);
1714		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1715		if (error) {
1716			break;
1717		}
1718		error = ustorage_fs_check_cmd(sc, 6,
1719		    (7UL << 1) | (1UL << 4) | 1, 1);
1720		if (error) {
1721			break;
1722		}
1723		error = ustorage_fs_read(sc);
1724
1725		break;
1726
1727	case SC_READ_10:
1728		sc->sc_transfer.cmd_dir = DIR_WRITE;
1729		temp = get_be16(&sc->sc_cmd_data[7]);
1730		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1731		if (error) {
1732			break;
1733		}
1734		error = ustorage_fs_check_cmd(sc, 10,
1735		    (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
1736		if (error) {
1737			break;
1738		}
1739		error = ustorage_fs_read(sc);
1740
1741		break;
1742
1743	case SC_READ_12:
1744		sc->sc_transfer.cmd_dir = DIR_WRITE;
1745		temp = get_be32(&sc->sc_cmd_data[6]);
1746		if (temp >= (1UL << (32 - 9))) {
1747			/* numerical overflow */
1748			sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
1749			error = 1;
1750			break;
1751		}
1752		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1753		if (error) {
1754			break;
1755		}
1756		error = ustorage_fs_check_cmd(sc, 12,
1757		    (1UL << 1) | (0xfUL << 2) | (0xfUL << 6) | 1, 1);
1758		if (error) {
1759			break;
1760		}
1761		error = ustorage_fs_read(sc);
1762
1763		break;
1764
1765	case SC_READ_CAPACITY:
1766		sc->sc_transfer.cmd_dir = DIR_WRITE;
1767		error = ustorage_fs_check_cmd(sc, 10,
1768		    (0xfUL << 2) | (1UL << 8) | 1, 1);
1769		if (error) {
1770			break;
1771		}
1772		error = ustorage_fs_read_capacity(sc);
1773
1774		break;
1775
1776	case SC_READ_FORMAT_CAPACITIES:
1777		sc->sc_transfer.cmd_dir = DIR_WRITE;
1778		error = ustorage_fs_min_len(sc,
1779		    get_be16(&sc->sc_cmd_data[7]), -1U);
1780		if (error) {
1781			break;
1782		}
1783		error = ustorage_fs_check_cmd(sc, 10,
1784		    (3UL << 7) | 1, 1);
1785		if (error) {
1786			break;
1787		}
1788		error = ustorage_fs_read_format_capacities(sc);
1789
1790		break;
1791
1792	case SC_REQUEST_SENSE:
1793		sc->sc_transfer.cmd_dir = DIR_WRITE;
1794		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
1795		if (error) {
1796			break;
1797		}
1798		error = ustorage_fs_check_cmd(sc, 6,
1799		    (1UL << 4) | 1, 0);
1800		if (error) {
1801			break;
1802		}
1803		error = ustorage_fs_request_sense(sc);
1804
1805		break;
1806
1807	case SC_START_STOP_UNIT:
1808		error = ustorage_fs_min_len(sc, 0, -1U);
1809		if (error) {
1810			break;
1811		}
1812		error = ustorage_fs_check_cmd(sc, 6,
1813		    (1UL << 1) | (1UL << 4) | 1, 0);
1814		if (error) {
1815			break;
1816		}
1817		error = ustorage_fs_start_stop(sc);
1818
1819		break;
1820
1821	case SC_SYNCHRONIZE_CACHE:
1822		error = ustorage_fs_min_len(sc, 0, -1U);
1823		if (error) {
1824			break;
1825		}
1826		error = ustorage_fs_check_cmd(sc, 10,
1827		    (0xfUL << 2) | (3UL << 7) | 1, 1);
1828		if (error) {
1829			break;
1830		}
1831		error = ustorage_fs_synchronize_cache(sc);
1832
1833		break;
1834
1835	case SC_TEST_UNIT_READY:
1836		error = ustorage_fs_min_len(sc, 0, -1U);
1837		if (error) {
1838			break;
1839		}
1840		error = ustorage_fs_check_cmd(sc, 6,
1841		    0 | 1, 1);
1842		break;
1843
1844		/*
1845		 * Although optional, this command is used by MS-Windows.
1846		 * We support a minimal version: BytChk must be 0.
1847		 */
1848	case SC_VERIFY:
1849		error = ustorage_fs_min_len(sc, 0, -1U);
1850		if (error) {
1851			break;
1852		}
1853		error = ustorage_fs_check_cmd(sc, 10,
1854		    (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
1855		if (error) {
1856			break;
1857		}
1858		error = ustorage_fs_verify(sc);
1859
1860		break;
1861
1862	case SC_WRITE_6:
1863		i = sc->sc_cmd_data[4];
1864		sc->sc_transfer.cmd_dir = DIR_READ;
1865		temp = ((i == 0) ? 256UL : i);
1866		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1867		if (error) {
1868			break;
1869		}
1870		error = ustorage_fs_check_cmd(sc, 6,
1871		    (7UL << 1) | (1UL << 4) | 1, 1);
1872		if (error) {
1873			break;
1874		}
1875		error = ustorage_fs_write(sc);
1876
1877		break;
1878
1879	case SC_WRITE_10:
1880		sc->sc_transfer.cmd_dir = DIR_READ;
1881		temp = get_be16(&sc->sc_cmd_data[7]);
1882		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1883		if (error) {
1884			break;
1885		}
1886		error = ustorage_fs_check_cmd(sc, 10,
1887		    (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
1888		if (error) {
1889			break;
1890		}
1891		error = ustorage_fs_write(sc);
1892
1893		break;
1894
1895	case SC_WRITE_12:
1896		sc->sc_transfer.cmd_dir = DIR_READ;
1897		temp = get_be32(&sc->sc_cmd_data[6]);
1898		if (temp > (mask9 >> 9)) {
1899			/* numerical overflow */
1900			sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
1901			error = 1;
1902			break;
1903		}
1904		error = ustorage_fs_min_len(sc, temp << 9, mask9);
1905		if (error) {
1906			break;
1907		}
1908		error = ustorage_fs_check_cmd(sc, 12,
1909		    (1UL << 1) | (0xfUL << 2) | (0xfUL << 6) | 1, 1);
1910		if (error) {
1911			break;
1912		}
1913		error = ustorage_fs_write(sc);
1914
1915		break;
1916
1917		/*
1918		 * Some mandatory commands that we recognize but don't
1919		 * implement.  They don't mean much in this setting.
1920		 * It's left as an exercise for anyone interested to
1921		 * implement RESERVE and RELEASE in terms of Posix
1922		 * locks.
1923		 */
1924	case SC_FORMAT_UNIT:
1925	case SC_RELEASE:
1926	case SC_RESERVE:
1927	case SC_SEND_DIAGNOSTIC:
1928		/* Fallthrough */
1929
1930	default:
1931		error = ustorage_fs_min_len(sc, 0, -1U);
1932		if (error) {
1933			break;
1934		}
1935		error = ustorage_fs_check_cmd(sc, sc->sc_transfer.cmd_len,
1936		    0xff, 0);
1937		if (error) {
1938			break;
1939		}
1940		sc->sc_transfer.currlun->sense_data =
1941		    SS_INVALID_COMMAND;
1942		error = 1;
1943
1944		break;
1945	}
1946	return (error);
1947}
1948