PERFORCE change 106070 for review

Hans Petter Selasky hselasky at FreeBSD.org
Wed Sep 13 09:58:18 PDT 2006


http://perforce.freebsd.org/chv.cgi?CH=106070

Change 106070 by hselasky at hselasky_mini_itx on 2006/09/13 16:58:00

	Finished reworking "umass". There are lots of changes again.
	Please test!

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/umass.c#5 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/umass.c#5 (text+ko) ====

@@ -1,0 +1,3219 @@
+/*-
+ * Copyright (c) 1999 MAEKAWA Masahide <bishop at rr.iij4u.or.jp>,
+ *		      Nick Hibma <n_hibma at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	$FreeBSD: src/sys/dev/usb/umass.c,v 1.135 2006/03/17 18:16:22 iedowse Exp $
+ *	$NetBSD: umass.c,v 1.28 2000/04/02 23:46:53 augustss Exp $
+ */
+
+/* Also already merged from NetBSD:
+ *	$NetBSD: umass.c,v 1.67 2001/11/25 19:05:22 augustss Exp $
+ *	$NetBSD: umass.c,v 1.90 2002/11/04 19:17:33 pooka Exp $
+ *	$NetBSD: umass.c,v 1.108 2003/11/07 17:03:25 wiz Exp $
+ *	$NetBSD: umass.c,v 1.109 2003/12/04 13:57:31 keihan Exp $
+ */
+
+/*
+ * Universal Serial Bus Mass Storage Class specs:
+ * http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf
+ * http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf
+ * http://www.usb.org/developers/devclass_docs/usb_msc_cbi_1.1.pdf
+ * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf
+ */
+
+/*
+ * Ported to NetBSD by Lennart Augustsson <augustss at NetBSD.org>.
+ * Parts of the code written by Jason R. Thorpe <thorpej at shagadelic.org>.
+ */
+
+/*
+ * The driver handles 3 Wire Protocols
+ * - Command/Bulk/Interrupt (CBI)
+ * - Command/Bulk/Interrupt with Command Completion Interrupt (CBI with CCI)
+ * - Mass Storage Bulk-Only (BBB)
+ *   (BBB refers Bulk/Bulk/Bulk for Command/Data/Status phases)
+ *
+ * Over these wire protocols it handles the following command protocols
+ * - SCSI
+ * - UFI (floppy command set)
+ * - 8070i (ATAPI)
+ *
+ * UFI and 8070i (ATAPI) are transformed versions of the SCSI command set. The
+ * sc->sc_transform method is used to convert the commands into the appropriate
+ * format (if at all necessary). For example, UFI requires all commands to be
+ * 12 bytes in length amongst other things.
+ *
+ * The source code below is marked and can be split into a number of pieces
+ * (in this order):
+ *
+ * - probe/attach/detach
+ * - generic transfer routines
+ * - BBB
+ * - CBI
+ * - CBI_I (in addition to functions from CBI)
+ * - CAM (Common Access Method)
+ * - SCSI
+ * - UFI
+ * - 8070i (ATAPI)
+ *
+ * The protocols are implemented using a state machine, for the transfers as
+ * well as for the resets. The state machine is contained in umass_t_*_callback.
+ * The state machine is started through either umass_command_start() or
+ * umass_reset().
+ *
+ * The reason for doing this is a) CAM performs a lot better this way and b) it
+ * avoids using tsleep from interrupt context (for example after a failed
+ * transfer).
+ */
+
+/*
+ * The SCSI related part of this driver has been derived from the
+ * dev/ppbus/vpo.c driver, by Nicolas Souchu (nsouch at freebsd.org).
+ *
+ * The CAM layer uses so called actions which are messages sent to the host
+ * adapter for completion. The actions come in through umass_cam_action. The
+ * appropriate block of routines is called depending on the transport protocol
+ * in use. When the transfer has finished, these routines call
+ * umass_cam_cb again to complete the CAM command.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <dev/usb/usb_port.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_subr.h>
+
+#include "usbdevs.h"
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_da.h>
+
+#include <cam/cam_periph.h>
+
+#ifdef USB_DEBUG
+#define DIF(m, x)				\
+  do {						\
+    if (umass_debug & (m)) { x }		\
+  } while (0)
+
+#define	DPRINTF(sc, m, fmt, ...)			\
+  do {							\
+    if (umass_debug & (m)) {				\
+        printf("%s:%s: " fmt,				\
+	       (sc) ? (const char *)(sc)->sc_name :	\
+	       (const char *)"umassX",			\
+		__FUNCTION__ ,## __VA_ARGS__);		\
+    }							\
+  } while(0)
+
+#define UDMASS_GEN	0x00010000	/* general */
+#define UDMASS_SCSI	0x00020000	/* scsi */
+#define UDMASS_UFI	0x00040000	/* ufi command set */
+#define UDMASS_ATAPI	0x00080000	/* 8070i command set */
+#define UDMASS_CMD	(UDMASS_SCSI|UDMASS_UFI|UDMASS_ATAPI)
+#define UDMASS_USB	0x00100000	/* USB general */
+#define UDMASS_BBB	0x00200000	/* Bulk-Only transfers */
+#define UDMASS_CBI	0x00400000	/* CBI transfers */
+#define UDMASS_WIRE	(UDMASS_BBB|UDMASS_CBI)
+#define UDMASS_ALL	0xffff0000	/* all of the above */
+static int umass_debug = 0;
+SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass");
+SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW,
+	   &umass_debug, 0, "umass debug level");
+#else
+#define DIF(...)	/* nop */
+#define	DPRINTF(...)	/* nop */
+#endif
+
+#define UMASS_BULK_SIZE (1 << 17) /* bytes, must not be less than (1<<16) */
+#define UMASS_CBI_DIAGNOSTIC_CMDLEN 12 /* bytes */
+#define UMASS_MAX_CMDLEN MAX(12, CAM_MAX_CDBLEN) /* bytes */
+
+/* USB transfer definitions */
+
+#define UMASS_T_BBB_RESET1      0 /* Bulk-Only */
+#define UMASS_T_BBB_RESET2      1
+#define UMASS_T_BBB_RESET3      2
+#define UMASS_T_BBB_COMMAND     3
+#define UMASS_T_BBB_DATA_READ   4
+#define UMASS_T_BBB_DATA_RD_CS  5
+#define UMASS_T_BBB_DATA_WRITE  6
+#define UMASS_T_BBB_DATA_WR_CS  7
+#define UMASS_T_BBB_STATUS      8
+#define UMASS_T_BBB_MAX         9
+
+#define UMASS_T_CBI_RESET1      0 /* CBI */
+#define UMASS_T_CBI_RESET2      1
+#define UMASS_T_CBI_RESET3      2
+#define UMASS_T_CBI_COMMAND     3
+#define UMASS_T_CBI_DATA_READ   4
+#define UMASS_T_CBI_DATA_RD_CS  5
+#define UMASS_T_CBI_DATA_WRITE  6
+#define UMASS_T_CBI_DATA_WR_CS  7
+#define UMASS_T_CBI_STATUS      8
+#define UMASS_T_CBI_RESET4      9
+#define UMASS_T_CBI_MAX        10
+
+#define UMASS_T_MAX MAX(UMASS_T_CBI_MAX, UMASS_T_BBB_MAX)
+
+/* Generic definitions */
+
+/* Direction for transfer */
+#define DIR_NONE	0
+#define DIR_IN		1
+#define DIR_OUT		2
+
+/* device name */
+#define DEVNAME		"umass"
+#define DEVNAME_SIM	"umass-sim"
+
+/* Approximate maximum transfer speeds (assumes 33% overhead). */
+#define UMASS_FULL_TRANSFER_SPEED	1000
+#define UMASS_HIGH_TRANSFER_SPEED	40000
+#define UMASS_FLOPPY_TRANSFER_SPEED	20
+
+#define UMASS_TIMEOUT			5000 /* ms */
+
+/* CAM specific definitions */
+
+#define UMASS_SCSIID_MAX	1	/* maximum number of drives expected */
+#define UMASS_SCSIID_HOST	UMASS_SCSIID_MAX
+
+/* Bulk-Only features */
+
+#define UR_BBB_RESET		0xff		/* Bulk-Only reset */
+#define UR_BBB_GET_MAX_LUN	0xfe		/* Get maximum lun */
+
+/* Command Block Wrapper */
+typedef struct {
+	uDWord		dCBWSignature;
+#	define CBWSIGNATURE	0x43425355
+	uDWord		dCBWTag;
+	uDWord		dCBWDataTransferLength;
+	uByte		bCBWFlags;
+#	define CBWFLAGS_OUT	0x00
+#	define CBWFLAGS_IN	0x80
+	uByte		bCBWLUN;
+	uByte		bCDBLength;
+#	define CBWCDBLENGTH	16
+	uByte		CBWCDB[CBWCDBLENGTH];
+} UPACKED umass_bbb_cbw_t;
+#define	UMASS_BBB_CBW_SIZE	31
+
+/* Command Status Wrapper */
+typedef struct {
+	uDWord		dCSWSignature;
+#	define CSWSIGNATURE	0x53425355
+#	define CSWSIGNATURE_IMAGINATION_DBX1	0x43425355
+#	define CSWSIGNATURE_OLYMPUS_C1	0x55425355
+	uDWord		dCSWTag;
+	uDWord		dCSWDataResidue;
+	uByte		bCSWStatus;
+#	define CSWSTATUS_GOOD	0x0
+#	define CSWSTATUS_FAILED	0x1
+#	define CSWSTATUS_PHASE	0x2
+} UPACKED umass_bbb_csw_t;
+#define	UMASS_BBB_CSW_SIZE	13
+
+/* CBI features */
+
+#define UR_CBI_ADSC	0x00
+
+typedef union {
+	struct {
+		u_int8_t	type;
+#		define IDB_TYPE_CCI		0x00
+		u_int8_t	value;
+#		define IDB_VALUE_PASS		0x00
+#		define IDB_VALUE_FAIL		0x01
+#		define IDB_VALUE_PHASE		0x02
+#		define IDB_VALUE_PERSISTENT	0x03
+#		define IDB_VALUE_STATUS_MASK	0x03
+	} UPACKED common;
+
+	struct {
+		u_int8_t	asc;
+		u_int8_t	ascq;
+	} UPACKED ufi;
+} UPACKED umass_cbi_sbl_t;
+
+struct umass_softc;		/* see below */
+
+typedef void (umass_callback_t)	(struct umass_softc *sc, union ccb *ccb,
+				 u_int32_t residue, u_int8_t status);
+#define STATUS_CMD_OK		0	/* everything ok */
+#define STATUS_CMD_UNKNOWN	1	/* will have to fetch sense */
+#define STATUS_CMD_FAILED	2	/* transfer was ok, command failed */
+#define STATUS_WIRE_FAILED	3	/* couldn't even get command across */
+
+typedef u_int8_t (umass_transform_t) (struct umass_softc *sc, u_int8_t *cmd_ptr,
+				      u_int8_t cmd_len);
+
+struct umass_devdescr {
+	u_int32_t	vid;
+#	define VID_WILDCARD	0xffffffff
+#	define VID_EOT		0xfffffffe
+	u_int32_t	pid;
+#	define PID_WILDCARD	0xffffffff
+#	define PID_EOT		0xfffffffe
+	u_int32_t	rid;
+#	define RID_WILDCARD	0xffffffff
+#	define RID_EOT		0xfffffffe
+
+	/* wire and command protocol */
+	u_int16_t	proto;
+#	define UMASS_PROTO_BBB		0x0001	/* USB wire protocol */
+#	define UMASS_PROTO_CBI		0x0002
+#	define UMASS_PROTO_CBI_I	0x0004
+#	define UMASS_PROTO_WIRE		0x00ff	/* USB wire protocol mask */
+#	define UMASS_PROTO_SCSI		0x0100	/* command protocol */
+#	define UMASS_PROTO_ATAPI	0x0200
+#	define UMASS_PROTO_UFI		0x0400
+#	define UMASS_PROTO_RBC		0x0800
+#	define UMASS_PROTO_COMMAND	0xff00	/* command protocol mask */
+
+	/* Device specific quirks */
+	u_int16_t	quirks;
+#	define NO_QUIRKS		0x0000
+	/* The drive does not support Test Unit Ready. Convert to Start Unit
+	 */
+#	define NO_TEST_UNIT_READY	0x0001
+	/* The drive does not reset the Unit Attention state after REQUEST
+	 * SENSE has been sent. The INQUIRY command does not reset the UA
+	 * either, and so CAM runs in circles trying to retrieve the initial
+	 * INQUIRY data.
+	 */
+#	define RS_NO_CLEAR_UA		0x0002
+	/* The drive does not support START STOP.  */
+#	define NO_START_STOP		0x0004
+	/* Don't ask for full inquiry data (255b).  */
+#	define FORCE_SHORT_INQUIRY	0x0008
+	/* Needs to be initialised the Shuttle way */
+#	define SHUTTLE_INIT		0x0010
+	/* Drive needs to be switched to alternate iface 1 */
+#	define ALT_IFACE_1		0x0020
+	/* Drive does not do 1Mb/s, but just floppy speeds (20kb/s) */
+#	define FLOPPY_SPEED		0x0040
+	/* The device can't count and gets the residue of transfers wrong */
+#	define IGNORE_RESIDUE		0x0080
+	/* No GetMaxLun call */
+#	define NO_GETMAXLUN		0x0100
+	/* The device uses a weird CSWSIGNATURE. */
+#	define WRONG_CSWSIG		0x0200
+	/* Device cannot handle INQUIRY so fake a generic response */
+#	define NO_INQUIRY		0x0400
+	/* Device cannot handle INQUIRY EVPD, return CHECK CONDITION */
+#	define NO_INQUIRY_EVPD		0x0800
+	/* Pad all RBC requests to 12 bytes. */
+#	define RBC_PAD_TO_12		0x1000
+};
+
+static const struct umass_devdescr umass_devdescr[] = {
+	{ USB_VENDOR_ASAHIOPTICAL, PID_WILDCARD, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+	  RS_NO_CLEAR_UA
+	},
+	{ USB_VENDOR_ADDON, USB_PRODUCT_ADDON_ATTACHE, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+	  RS_NO_CLEAR_UA
+	},
+	{ USB_VENDOR_ADDON, USB_PRODUCT_ADDON_A256MB, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_ADDON, USB_PRODUCT_ADDON_DISKPRO512, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_GENESYS,  USB_PRODUCT_GENESYS_GL641USB2IDE, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_GENESYS,  USB_PRODUCT_GENESYS_GL641USB2IDE_2, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_GENESYS,  USB_PRODUCT_GENESYS_GL641USB, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_GENESYS,  USB_PRODUCT_GENESYS_GL641USB_2, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  WRONG_CSWSIG
+	},
+	{ USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_USB, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_HP, USB_PRODUCT_HP_CDW8200, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+	  NO_TEST_UNIT_READY | NO_START_STOP
+	},
+	{ USB_VENDOR_IMAGINATION, USB_PRODUCT_IMAGINATION_DBX1, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  WRONG_CSWSIG
+	},
+	{ USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
+	  NO_TEST_UNIT_READY | NO_START_STOP | ALT_IFACE_1
+	},
+	{ USB_VENDOR_IODATA, USB_PRODUCT_IODATA_IU_CD2, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_IODATA, USB_PRODUCT_IODATA_DVR_UEH8, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100, RID_WILDCARD,
+	  /* XXX This is not correct as there are Zip drives that use ATAPI.
+	   */
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_TEST_UNIT_READY
+	},
+	{ USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443SU2, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443U2, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_MELCO,  USB_PRODUCT_MELCO_DUBPXXG, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+	  NO_TEST_UNIT_READY | NO_START_STOP
+	},
+	{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_E398, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY | NO_INQUIRY_EVPD | NO_GETMAXLUN
+	},
+	{ USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE | NO_GETMAXLUN | RS_NO_CLEAR_UA
+	},
+	{ USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY2, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND3260, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY
+	},
+	{ USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  WRONG_CSWSIG
+	},
+	{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_UCF100, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
+	  NO_INQUIRY | NO_GETMAXLUN
+	},
+	{ USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB20AN, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB35AN, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_PLEXTOR, USB_PRODUCT_PLEXTOR_40_12_40U, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_TEST_UNIT_READY
+	},
+	{ USB_VENDOR_PNY, USB_PRODUCT_PNY_ATTACHE2, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE | NO_START_STOP
+	},
+	{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ2_256, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_128, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_256, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+	  NO_TEST_UNIT_READY | NO_START_STOP | SHUTTLE_INIT
+	},
+	{ USB_VENDOR_SIGMATEL, USB_PRODUCT_SIGMATEL_I_BEAD100, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  SHUTTLE_INIT
+	},
+	{ USB_VENDOR_SIIG, USB_PRODUCT_SIIG_WINTERREADER, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, 0x0500,
+	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+	  RBC_PAD_TO_12
+	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, 0x0600,
+	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+	  RBC_PAD_TO_12
+	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, RID_WILDCARD,
+	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_HANDYCAM, RID_WILDCARD,
+	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC, RID_WILDCARD,
+	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_TREK, USB_PRODUCT_TREK_THUMBDRIVE_8MB, RID_WILDCARD,
+          UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_C3310, RID_WILDCARD,
+	  UMASS_PROTO_UFI | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_MDIV, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_WESTERN,  USB_PRODUCT_WESTERN_EXTHDD, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_YANO,  USB_PRODUCT_YANO_U640MO, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
+	  FORCE_SHORT_INQUIRY
+	},
+	{ VID_EOT, PID_EOT, RID_EOT, 0, 0 }
+};
+
+struct umass_softc {
+
+	struct usbd_memory_wait	sc_mem_wait;
+	struct scsi_sense	cam_scsi_sense;
+	struct scsi_test_unit_ready cam_scsi_test_unit_ready;
+	struct mtx		sc_mtx;
+	struct {
+	    u_int8_t * data_ptr;
+	    union ccb * ccb;
+	    umass_callback_t * callback;
+
+	    u_int32_t data_len; /* bytes */
+	    u_int32_t data_rem; /* bytes */
+	    u_int32_t data_timeout; /* ms */
+	    u_int32_t actlen; /* bytes */
+
+	    u_int8_t cmd_data[UMASS_MAX_CMDLEN];
+	    u_int8_t cmd_len; /* bytes */
+	    u_int8_t dir;
+	    u_int8_t lun;
+	} sc_transfer;
+
+	/* Bulk specific variables for transfers in progress */
+	umass_bbb_cbw_t		cbw;	/* command block wrapper */
+	umass_bbb_csw_t		csw;	/* command status wrapper*/
+
+	/* CBI specific variables for transfers in progress */
+	umass_cbi_sbl_t		sbl;	/* status block */
+
+	device_t		sc_dev;
+	struct usbd_device *	sc_udev;
+	struct cam_sim *	sc_sim;	/* SCSI Interface Module */
+	struct usbd_xfer *	sc_xfer[UMASS_T_MAX];
+
+	/* The command transform function is used to convert the SCSI commands
+	 * into their derivatives, like UFI, ATAPI, and friends.
+	 */
+	umass_transform_t *	sc_transform;
+
+	u_int32_t		sc_unit;
+
+	u_int16_t		sc_proto;	/* wire and cmd protocol */
+	u_int16_t		sc_quirks;	/* they got it almost right */
+
+	u_int8_t		sc_name[16];
+	u_int8_t		sc_iface_no;	/* interface number */
+	u_int8_t		sc_maxlun;	/* maximum LUN number, inclusive */
+	u_int8_t		sc_last_xfer_index;
+	u_int8_t		sc_reset_count;
+	u_int8_t		sc_status_try;
+};
+
+struct umass_probe_proto {
+    u_int16_t quirks;
+    u_int16_t proto;
+
+    int32_t error;
+};
+
+/* prototypes */
+
+static device_probe_t umass_probe;
+static device_attach_t umass_attach;
+static device_detach_t umass_detach;
+
+static void
+umass_init_shuttle(struct umass_softc *sc);
+
+static void
+umass_reset(struct umass_softc *sc);
+
+static void
+umass_tr_error(struct usbd_xfer *xfer);
+
+static void
+umass_t_bbb_reset1_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_bbb_reset2_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_bbb_reset3_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_bbb_data_clear_stall_callback(struct usbd_xfer *xfer,
+				      u_int8_t next_xfer,
+				      u_int8_t stall_xfer);
+static void
+umass_t_bbb_command_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_bbb_data_read_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_bbb_data_rd_cs_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_bbb_data_write_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_bbb_data_wr_cs_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_bbb_status_callback(struct usbd_xfer *xfer);
+
+static void
+umass_command_start(struct umass_softc *sc, u_int8_t dir, 
+		    void *data_ptr, u_int32_t data_len, 
+		    u_int32_t data_timeout, umass_callback_t *callback, 
+		    union ccb *ccb);
+static u_int8_t
+umass_bbb_get_max_lun(struct umass_softc *sc);
+
+static void
+umass_cbi_start_status(struct umass_softc *sc);
+
+static void
+umass_t_cbi_reset1_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_cbi_reset2_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_cbi_reset3_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_cbi_reset4_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_cbi_data_clear_stall_callback(struct usbd_xfer *xfer,
+				      u_int8_t next_xfer,
+				      u_int8_t stall_xfer);
+static void
+umass_t_cbi_command_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_cbi_data_read_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_cbi_data_rd_cs_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_cbi_data_write_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_cbi_data_wr_cs_callback(struct usbd_xfer *xfer);
+
+static void
+umass_t_cbi_status_callback(struct usbd_xfer *xfer);
+
+static int
+umass_cam_attach_sim(struct umass_softc *sc);
+
+static void
+umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb);
+
+static void
+umass_cam_rescan(struct umass_softc *sc);
+
+static void
+umass_cam_attach(struct umass_softc *sc);
+
+static void
+umass_cam_detach_sim(struct umass_softc *sc);
+
+static void
+umass_cam_action(struct cam_sim *sim, union ccb *ccb);
+
+static void
+umass_cam_poll(struct cam_sim *sim);
+
+static void
+umass_cam_cb(struct umass_softc *sc, union ccb *ccb, u_int32_t residue, 
+	     u_int8_t status);
+static void
+umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, u_int32_t residue, 
+		   u_int8_t status);
+static void
+umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, u_int32_t residue, 
+		   u_int8_t status);
+static u_int8_t
+umass_scsi_transform(struct umass_softc *sc, u_int8_t *cmd_ptr, 
+		     u_int8_t cmd_len);
+static u_int8_t
+umass_rbc_transform(struct umass_softc *sc, u_int8_t *cmd_ptr, u_int8_t cmd_len);
+
+static u_int8_t
+umass_ufi_transform(struct umass_softc *sc, u_int8_t *cmd_ptr, 
+		    u_int8_t cmd_len);
+static u_int8_t
+umass_atapi_transform(struct umass_softc *sc, u_int8_t *cmd_ptr, 
+		      u_int8_t cmd_len);
+static u_int8_t
+umass_no_transform(struct umass_softc *sc, u_int8_t *cmd, 
+		   u_int8_t cmdlen);
+#ifdef USB_DEBUG
+static void
+umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw);
+
+static void
+umass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw);
+
+static void
+umass_cbi_dump_cmd(struct umass_softc *sc, void *cmd, u_int8_t cmdlen);
+
+static void
+umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, u_int32_t buflen,
+		  u_int32_t printlen);
+#endif
+
+struct usbd_config umass_bbb_config[UMASS_T_BBB_MAX] = {
+
+    [UMASS_T_BBB_RESET1] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_bbb_reset1_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_BBB_RESET2] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_bbb_reset2_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_BBB_RESET3] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_bbb_reset3_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_BBB_COMMAND] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_OUT,
+      .bufsize   = sizeof(umass_bbb_cbw_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_bbb_command_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_BBB_DATA_READ] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .bufsize   = UMASS_BULK_SIZE,
+      .flags     = (USBD_USE_DMA|USBD_SHORT_XFER_OK),
+      .callback  = &umass_t_bbb_data_read_callback,
+      .timeout   = 0, /* overwritten later */
+    },
+
+    [UMASS_T_BBB_DATA_RD_CS] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_bbb_data_rd_cs_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_BBB_DATA_WRITE] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_OUT,
+      .bufsize   = UMASS_BULK_SIZE,
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_bbb_data_write_callback,
+      .timeout   = 0, /* overwritten later */
+    },
+
+    [UMASS_T_BBB_DATA_WR_CS] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_bbb_data_wr_cs_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_BBB_STATUS] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .bufsize   = sizeof(umass_bbb_csw_t),
+      .flags     = (USBD_USE_DMA|USBD_SHORT_XFER_OK),
+      .callback  = &umass_t_bbb_status_callback,
+      .timeout   = 5000, /* ms */
+    },
+};
+
+struct usbd_config umass_cbi_config[UMASS_T_CBI_MAX] = {
+
+    [UMASS_T_CBI_RESET1] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = (sizeof(usb_device_request_t) + 
+		    UMASS_CBI_DIAGNOSTIC_CMDLEN),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_cbi_reset1_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_CBI_RESET2] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_cbi_reset2_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_CBI_RESET3] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_cbi_reset3_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_CBI_COMMAND] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = (sizeof(usb_device_request_t) + 
+		    UMASS_MAX_CMDLEN),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_cbi_command_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_CBI_DATA_READ] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .bufsize   = UMASS_BULK_SIZE,
+      .flags     = (USBD_USE_DMA|USBD_SHORT_XFER_OK),
+      .callback  = &umass_t_cbi_data_read_callback,
+      .timeout   = 0, /* overwritten later */
+    },
+
+    [UMASS_T_CBI_DATA_RD_CS] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_cbi_data_rd_cs_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_CBI_DATA_WRITE] = {
+      .type      = UE_BULK,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_OUT,
+      .bufsize   = UMASS_BULK_SIZE,
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_cbi_data_write_callback,
+      .timeout   = 0, /* overwritten later */
+    },
+
+    [UMASS_T_CBI_DATA_WR_CS] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_cbi_data_wr_cs_callback,
+      .timeout   = 5000, /* 5 seconds */
+    },
+
+    [UMASS_T_CBI_STATUS] = {
+      .type      = UE_INTERRUPT,
+      .endpoint  = -1, /* any */
+      .direction = UE_DIR_IN,
+      .flags     = (USBD_USE_DMA|USBD_SHORT_XFER_OK),
+      .bufsize   = sizeof(umass_cbi_sbl_t),
+      .callback  = &umass_t_cbi_status_callback,
+      .timeout   = 5000, /* ms */
+    },
+
+    [UMASS_T_CBI_RESET4] = {
+      .type      = UE_CONTROL,
+      .endpoint  = 0x00, /* Control pipe */
+      .direction = -1,
+      .bufsize   = sizeof(usb_device_request_t),
+      .flags     = USBD_USE_DMA,
+      .callback  = &umass_t_cbi_reset4_callback,
+      .timeout   = 5000, /* ms */
+    },
+};
+
+/* If device cannot return valid inquiry data, fake it */
+static const u_int8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = {
+	0, /*removable*/ 0x80, SCSI_REV_2, SCSI_REV_2,
+	/*additional_length*/ 31, 0, 0, 0
+};
+
+#define UFI_COMMAND_LENGTH	12	/* UFI commands are always 12 bytes */
+#define ATAPI_COMMAND_LENGTH	12	/* ATAPI commands are always 12 bytes */
+
+static devclass_t umass_devclass;
+
+static device_method_t umass_methods[] = {
+  /* Device interface */
+  DEVMETHOD(device_probe, umass_probe), 
+  DEVMETHOD(device_attach, umass_attach),
+  DEVMETHOD(device_detach, umass_detach),
+  { 0, 0 }
+};
+
+static driver_t umass_driver = {
+  .name    = "umass",
+  .methods = umass_methods,
+  .size    = sizeof(struct umass_softc),
+};
+
+DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, usbd_driver_load, 0);
+
+MODULE_DEPEND(umass, usb, 1,1,1);
+MODULE_DEPEND(umass, cam, 1,1,1);
+
+/*
+ * USB device probe/attach/detach
+ */
+
+/*
+ * Match the device we are seeing with the 
+ * devices supported.
+ */
+static struct umass_probe_proto
+umass_probe_proto(device_t dev, struct usb_attach_arg *uaa)
+{
+	const struct umass_devdescr *udd = umass_devdescr;
+	usb_interface_descriptor_t *id;
+	struct umass_probe_proto ret;
+

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list