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