summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Binkert <nate@cvs.openbsd.org>2003-05-17 06:07:58 +0000
committerNathan Binkert <nate@cvs.openbsd.org>2003-05-17 06:07:58 +0000
commitdf7d9b90217d237dbfa834d916f3dd30fd17acf9 (patch)
treebad00563dfc21d9a28ce8ed0d3b424ebd4b5a335
parent3df1cd04c783ecc40cffe562619053e8c7012be2 (diff)
sync with NetBSD and add various local hacks to make things work correctly
with our scsi layer
-rw-r--r--sys/dev/usb/FILES9
-rw-r--r--sys/dev/usb/TODO2
-rw-r--r--sys/dev/usb/files.usb6
-rw-r--r--sys/dev/usb/umass.c2595
-rw-r--r--sys/dev/usb/umass_quirks.c484
-rw-r--r--sys/dev/usb/umass_quirks.h62
-rw-r--r--sys/dev/usb/umass_scsi.c464
-rw-r--r--sys/dev/usb/umass_scsi.h42
-rw-r--r--sys/dev/usb/umassvar.h272
-rw-r--r--sys/dev/usb/usb.h6
-rw-r--r--sys/dev/usb/usb_port.h33
-rw-r--r--sys/dev/usb/usscanner.c18
12 files changed, 1760 insertions, 2233 deletions
diff --git a/sys/dev/usb/FILES b/sys/dev/usb/FILES
index a7138531869..4b3398b0ad6 100644
--- a/sys/dev/usb/FILES
+++ b/sys/dev/usb/FILES
@@ -39,7 +39,14 @@ ukbd.c USB keyboard driver
ukbdmap.c wscons key mapping for ukbd
ukbdvar.h API for ukbd.c
ulpt.c USB printer class driver
-umass.c USB mass storage driver (bulk only for now)
+umass.c USB mass storage wire protocol driver
+umass_isdata.c In-System Design ATA over bulk-only driver
+umass_isdata.h and definitions for it
+umass_quirks.c Table of strange umass devices
+umass_quirks.h and definitions for it
+umass_scsi.c umass command protocol driver
+umass_scsi.h and definitions for it
+umassvar.h definitions for umass.c
umidi.c USB MIDI driver
umidi_quirks.c Strange MIDI devices
umidi_quirks.h and definitions for it
diff --git a/sys/dev/usb/TODO b/sys/dev/usb/TODO
index 28088a69fb3..2bc3497628a 100644
--- a/sys/dev/usb/TODO
+++ b/sys/dev/usb/TODO
@@ -85,6 +85,8 @@ Get rid of hcpriv.
Keyspan serial driver
+Clean up umass driver
+
Documentation:
--------------
diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb
index e95b5efd221..c3bbcfa5697 100644
--- a/sys/dev/usb/files.usb
+++ b/sys/dev/usb/files.usb
@@ -1,4 +1,4 @@
-# $OpenBSD: files.usb,v 1.31 2002/11/30 19:29:29 nate Exp $
+# $OpenBSD: files.usb,v 1.32 2003/05/17 06:07:57 nate Exp $
# $NetBSD: files.usb,v 1.16 2000/02/14 20:29:54 augustss Exp $
#
# Config file and device description for machine-independent USB code.
@@ -89,9 +89,11 @@ file dev/usb/ulpt.c ulpt needs-flag
# Mass storage
-device umass: scsi, atapi
+device umass: scsi, atapi, ata
attach umass at uhub
file dev/usb/umass.c umass
+file dev/usb/umass_quirks.c umass
+file dev/usb/umass_scsi.c umass & (scsibus | atapiscsi)
# Misc
diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c
index ae7dc941aa6..c01a43d1d89 100644
--- a/sys/dev/usb/umass.c
+++ b/sys/dev/usb/umass.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: umass.c,v 1.23 2003/05/07 04:33:33 deraadt Exp $ */
-/* $NetBSD: umass.c,v 1.49 2001/01/21 18:56:38 augustss Exp $ */
+/* $OpenBSD: umass.c,v 1.24 2003/05/17 06:07:57 nate Exp $ */
+/* $NetBSD: umass.c,v 1.96 2003/04/26 12:46:59 dsainty Exp $ */
/*-
* Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>,
* Nick Hibma <n_hibma@freebsd.org>
@@ -30,7 +30,7 @@
*/
/*
- * Universal Serial Bus Mass Storage Class Bulk-Only Transport
+ * Universal Serial Bus Mass Storage Class specs:
* http://www.usb.org/developers/data/devclass/usbmassover_11.pdf
* http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf
* http://www.usb.org/developers/data/devclass/usbmass-cbi10.pdf
@@ -39,7 +39,7 @@
/*
* Ported to NetBSD by Lennart Augustsson <augustss@netbsd.org>.
- * Parts of the code written my Jason R. Thorpe <thorpej@shagadelic.org>.
+ * Parts of the code written by Jason R. Thorpe <thorpej@shagadelic.org>.
*/
/*
@@ -51,13 +51,14 @@
*
* Over these wire protocols it handles the following command protocols
* - SCSI
- * - UFI (floppy command set)
- * - 8070 (ATA/ATAPI)
+ * - 8070 (ATA/ATAPI for rewritable removable media)
+ * - UFI (USB Floppy Interface)
*
- * UFI and 8070i are transformed versions of the SCSI command set. The
- * 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.
+ * 8070i is a transformed version of the SCSI command set. UFI is a transformed
+ * version of the 8070i command set. The sc->transform method is used to
+ * convert the commands into the appropriate format (if at all necessary).
+ * For example, ATAPI 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):
@@ -93,15 +94,15 @@
* umass_cam_cb again to complete the CAM command.
*/
-/* XXX Should we split the driver into a number of files? umass.c,
- * umass_scsi.c, umass_8070.c, umass_ufi.c, umass_bbb.c, umass_cbi.c or
- * something similar?
- */
-
-#if !defined(__OpenBSD__)
+#if defined(__NetBSD__)
#include "atapibus.h"
+#include "scsibus.h"
+#elif defined(__OpenBSD__)
+#include "atapiscsi.h"
#endif
+#include "wd.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -109,7 +110,6 @@
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/buf.h>
#include <sys/device.h>
-#include <sys/ioctl.h>
#include <sys/malloc.h>
#undef KASSERT
#define KASSERT(cond, msg)
@@ -124,396 +124,14 @@
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
-#if defined(__FreeBSD__)
-#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>
-
-#ifdef UMASS_DO_CAM_RESCAN
-#include <sys/devicestat.h>
-#include <cam/cam_periph.h>
-#endif
+#include <dev/usb/umassvar.h>
+#include <dev/usb/umass_quirks.h>
+#include <dev/usb/umass_scsi.h>
-#elif defined(__NetBSD__)
-#include <sys/scsiio.h>
-#include <dev/scsipi/scsi_all.h>
-#include <dev/scsipi/scsipi_all.h>
-#include <dev/scsipi/scsiconf.h>
-
-#include <dev/scsipi/atapiconf.h>
-
-#include <dev/scsipi/scsipi_disk.h>
-#include <dev/scsipi/scsi_disk.h>
-#include <dev/scsipi/scsi_changer.h>
-
-#include <dev/ata/atavar.h> /* XXX */
-
-#define SCSI_LINK_TARGET(sc) ((sc)->scsipi_scsi.target)
-#define SCSI_LINK_LUN(sc) ((sc)->scsipi_scsi.lun)
-#elif defined(__OpenBSD__)
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_disk.h>
-#include <machine/bus.h>
-
-#define SCSI_LINK_TARGET(sc) ((sc)->target)
-#define SCSI_LINK_LUN(sc) ((sc)->lun)
-#define scsipi_generic scsi_generic
-
-#endif
-
-#define SHORT_INQUIRY_LENGTH 36 /* XXX */
#ifdef UMASS_DEBUG
-#define DIF(m, x) if (umassdebug & (m)) do { x ; } while (0)
-#define DPRINTF(m, x) if (umassdebug & (m)) logprintf x
-#define UDMASS_UPPER 0x00008000 /* upper layer */
-#define UDMASS_GEN 0x00010000 /* general */
-#define UDMASS_SCSI 0x00020000 /* scsi */
-#define UDMASS_UFI 0x00040000 /* ufi command set */
-#define UDMASS_8070 0x00080000 /* 8070i command set */
-#define UDMASS_USB 0x00100000 /* USB general */
-#define UDMASS_BBB 0x00200000 /* Bulk-Only transfers */
-#define UDMASS_CBI 0x00400000 /* CBI transfers */
-#define UDMASS_ALL 0xffff0000 /* all of the above */
-
-#define UDMASS_XFER 0x40000000 /* all transfers */
-#define UDMASS_CMD 0x80000000
-
int umassdebug = 0;
-#else
-#define DIF(m, x) /* nop */
-#define DPRINTF(m, x) /* nop */
-#endif
-
-
-/* Generic definitions */
-
-#define UFI_COMMAND_LENGTH 12
-#define ATAPI_COMMAND_LENGTH 12
-
-/* Direction for umass_*_transfer */
-#define DIR_NONE 0
-#define DIR_IN 1
-#define DIR_OUT 2
-
-/* The transfer speed determines the timeout value */
-#define UMASS_DEFAULT_TRANSFER_SPEED 150 /* in kb/s, conservative est. */
-#define UMASS_FLOPPY_TRANSFER_SPEED 20
-#define UMASS_ZIP100_TRANSFER_SPEED 650
-
-#define UMASS_SPINUP_TIME 10000 /* ms */
-
-#ifdef __FreeBSD__
-/* device name */
-#define DEVNAME "umass"
-#define DEVNAME_SIM "umass-"
-
-#define UMASS_MAX_TRANSFER_SIZE 65536
-
-/* CAM specific definitions */
-
-/* The bus id, whatever that is */
-#define UMASS_SCSI_BUS 0
-
-/* All USB drives are 'connected' to one SIM (SCSI controller). umass3
- * ends up being target 3 on that SIM. When a request for target 3
- * comes in we fetch the softc with devclass_get_softc(target_id).
- *
- * The SIM is the highest target number. This makes sure that umass0 corresponds
- * to target 0 on the USB SCSI bus.
- */
-#ifndef UMASS_DEBUG
-#define UMASS_SCSIID_MAX 32 /* maximum number of drives expected */
-#else
-/* while debugging avoid unnecessary clutter in the output at umass_cam_rescan
- * (XPT_PATH_INQ)
- */
-#define UMASS_SCSIID_MAX 3 /* maximum number of drives expected */
-#endif
-#define UMASS_SCSIID_HOST UMASS_SCSIID_MAX
-#endif
-
-#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
-
-
-/* Bulk-Only features */
-
-#define UR_BBB_RESET 0xff /* Bulk-Only reset */
-#define UR_BBB_GET_MAX_LUN 0xfe
-
-/* 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];
-} umass_bbb_cbw_t;
-#define UMASS_BBB_CBW_SIZE 31
-
-/* Command Status Wrapper */
-typedef struct {
- uDWord dCSWSignature;
-# define CSWSIGNATURE 0x53425355
- uDWord dCSWTag;
- uDWord dCSWDataResidue;
- uByte bCSWStatus;
-# define CSWSTATUS_GOOD 0x0
-# define CSWSTATUS_FAILED 0x1
-# define CSWSTATUS_PHASE 0x2
-} umass_bbb_csw_t;
-#define UMASS_BBB_CSW_SIZE 13
-
-/* CBI features */
-
-#define UR_CBI_ADSC 0x00
-
-typedef unsigned char umass_cbi_cbl_t[16]; /* Command block */
-
-typedef union {
- struct {
- unsigned char type;
- #define IDB_TYPE_CCI 0x00
- unsigned char 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
- } common;
-
- struct {
- unsigned char asc;
- unsigned char ascq;
- } ufi;
-} umass_cbi_sbl_t;
-
-
-
-struct umass_softc; /* see below */
-
-typedef void (*transfer_cb_f)(struct umass_softc *sc, void *priv,
- int residue, int 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 void (*wire_reset_f)(struct umass_softc *sc, int status);
-typedef void (*wire_transfer_f)(struct umass_softc *sc, int lun,
- void *cmd, int cmdlen, void *data, int datalen,
- int dir, transfer_cb_f cb, void *priv);
-typedef void (*wire_state_f)(usbd_xfer_handle xfer,
- usbd_private_handle priv, usbd_status err);
-
-#if defined(__FreeBSD__)
-typedef int (*command_transform_f)(struct umass_softc *sc,
- unsigned char *cmd, int cmdlen,
- unsigned char **rcmd, int *rcmdlen);
-#endif
-
-
-/* the per device structure */
-struct umass_softc {
- USBBASEDEVICE sc_dev; /* base device */
- usbd_device_handle sc_udev; /* device */
-
- unsigned char drive;
-# define DRIVE_GENERIC 0 /* use defaults for this one */
-# define ZIP_100 1 /* to be used for quirks */
-# define ZIP_250 2
-# define SHUTTLE_EUSB 3
-# define INSYSTEM_USBCABLE 4
- unsigned char quirks;
- /* The drive does not support Test Unit Ready. Convert to
- * Start Unit.
- * Y-E Data
- * ZIP 100
- */
-# define NO_TEST_UNIT_READY 0x01
- /* 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.
- * Y-E Data
- */
-# define RS_NO_CLEAR_UA 0x02 /* no REQUEST SENSE on INQUIRY*/
- /* The drive does not support START_STOP.
- * Shuttle E-USB
- */
-# define NO_START_STOP 0x04
- /* Don't ask for full inquiry data (255 bytes).
- * Yano ATAPI-USB
- */
-# define FORCE_SHORT_INQUIRY 0x08
-
- unsigned int proto;
-# define PROTO_UNKNOWN 0x0000 /* unknown protocol */
-# define PROTO_BBB 0x0001 /* USB wire protocol */
-# define PROTO_CBI 0x0002
-# define PROTO_CBI_I 0x0004
-# define PROTO_WIRE 0x00ff /* USB wire protocol mask */
-# define PROTO_SCSI 0x0100 /* command protocol */
-# define PROTO_ATAPI 0x0200
-# define PROTO_UFI 0x0400
-# define PROTO_RBC 0x0800
-# define PROTO_COMMAND 0xff00 /* command protocol mask */
-
- u_char subclass; /* interface subclass */
- u_char protocol; /* interface protocol */
-
- usbd_interface_handle iface; /* Mass Storage interface */
- int ifaceno; /* MS iface number */
-
- u_int8_t bulkin; /* bulk-in Endpoint Address */
- u_int8_t bulkout; /* bulk-out Endpoint Address */
- u_int8_t intrin; /* intr-in Endp. (CBI) */
- usbd_pipe_handle bulkin_pipe;
- usbd_pipe_handle bulkout_pipe;
- usbd_pipe_handle intrin_pipe;
-
- /* Reset the device in a wire protocol specific way */
- wire_reset_f reset;
-
- /* The start of a wire transfer. It prepares the whole transfer (cmd,
- * data, and status stage) and initiates it. It is up to the state
- * machine (below) to handle the various stages and errors in these
- */
- wire_transfer_f transfer;
-
- /* The state machine, handling the various states during a transfer */
- wire_state_f state;
-
-#if defined(__FreeBSD__)
- /* The command transform function is used to conver the SCSI commands
- * into their derivatives, like UFI, ATAPI, and friends.
- */
- command_transform_f transform; /* command transform */
-#endif
-
- /* 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_cbl_t cbl; /* command block */
- umass_cbi_sbl_t sbl; /* status block */
-
- /* generic variables for transfers in progress */
- /* ctrl transfer requests */
- usb_device_request_t request;
-
- /* xfer handles
- * Most of our operations are initiated from interrupt context, so
- * we need to avoid using the one that is in use. We want to avoid
- * allocating them in the interrupt context as well.
- */
- /* indices into array below */
-# define XFER_BBB_CBW 0 /* Bulk-Only */
-# define XFER_BBB_DATA 1
-# define XFER_BBB_DCLEAR 2
-# define XFER_BBB_CSW1 3
-# define XFER_BBB_CSW2 4
-# define XFER_BBB_SCLEAR 5
-# define XFER_BBB_RESET1 6
-# define XFER_BBB_RESET2 7
-# define XFER_BBB_RESET3 8
-
-# define XFER_CBI_CB 0 /* CBI */
-# define XFER_CBI_DATA 1
-# define XFER_CBI_STATUS 2
-# define XFER_CBI_DCLEAR 3
-# define XFER_CBI_SCLEAR 4
-# define XFER_CBI_RESET1 5
-# define XFER_CBI_RESET2 6
-# define XFER_CBI_RESET3 7
-
-# define XFER_NR 9 /* maximum number */
-
- usbd_xfer_handle transfer_xfer[XFER_NR]; /* for ctrl xfers */
-
- void *data_buffer;
-
- int transfer_dir; /* data direction */
- void *transfer_data; /* data buffer */
- int transfer_datalen; /* (maximum) length */
- int transfer_actlen; /* actual length */
- transfer_cb_f transfer_cb; /* callback */
- void *transfer_priv; /* for callback */
- int transfer_status;
-
- int transfer_state;
-# define TSTATE_IDLE 0
-# define TSTATE_BBB_COMMAND 1 /* CBW transfer */
-# define TSTATE_BBB_DATA 2 /* Data transfer */
-# define TSTATE_BBB_DCLEAR 3 /* clear endpt stall */
-# define TSTATE_BBB_STATUS1 4 /* clear endpt stall */
-# define TSTATE_BBB_SCLEAR 5 /* clear endpt stall */
-# define TSTATE_BBB_STATUS2 6 /* CSW transfer */
-# define TSTATE_BBB_RESET1 7 /* reset command */
-# define TSTATE_BBB_RESET2 8 /* in clear stall */
-# define TSTATE_BBB_RESET3 9 /* out clear stall */
-# define TSTATE_CBI_COMMAND 10 /* command transfer */
-# define TSTATE_CBI_DATA 11 /* data transfer */
-# define TSTATE_CBI_STATUS 12 /* status transfer */
-# define TSTATE_CBI_DCLEAR 13 /* clear ep stall */
-# define TSTATE_CBI_SCLEAR 14 /* clear ep stall */
-# define TSTATE_CBI_RESET1 15 /* reset command */
-# define TSTATE_CBI_RESET2 16 /* in clear stall */
-# define TSTATE_CBI_RESET3 17 /* out clear stall */
-# define TSTATE_STATES 18 /* # of states above */
-
-
- int transfer_speed; /* in kb/s */
- int timeout; /* in msecs */
-
- u_int8_t maxlun; /* max lun supported */
-
-#ifdef UMASS_DEBUG
- struct timeval tv;
-#endif
-
-#if defined(__FreeBSD__)
- /* SCSI/CAM specific variables */
- struct scsi_sense cam_scsi_sense;
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
- union {
- struct scsipi_link sc_link;
-#if defined(__NetBSD__)
- struct {
- struct ata_atapi_attach sc_aa;
- struct ata_drive_datas sc_aa_drive;
- } aa;
-#endif
- } u;
-#if defined(__NetBSD__)
- struct atapi_adapter sc_atapi_adapter;
-#define sc_adapter sc_atapi_adapter._generic
-#else
- struct scsi_adapter sc_atapi_adapter;
-#define sc_adapter sc_atapi_adapter
-#endif
- int sc_xfer_flags;
- usbd_status sc_sync_status;
- struct scsipi_sense sc_sense_cmd;
-
- device_ptr_t sc_child; /* child device, for detach */
- char sc_dying;
-
-#endif
-};
-#ifdef UMASS_DEBUG
char *states[TSTATE_STATES+1] = {
/* should be kept in sync with the list at transfer_state */
"Idle",
@@ -538,17 +156,9 @@ char *states[TSTATE_STATES+1] = {
};
#endif
-struct cam_sim *umass_sim; /* SCSI Interface Module */
-struct cam_path *umass_path; /* and its path */
-
-
/* USB device probe/attach/detach functions */
USB_DECLARE_DRIVER(umass);
Static void umass_disco(struct umass_softc *sc);
-Static int umass_match_proto(struct umass_softc *sc,
- usbd_interface_handle iface,
- usbd_device_handle dev);
-Static void umass_init_shuttle(struct umass_softc *sc);
/* generic transfer functions */
Static usbd_status umass_setup_transfer(struct umass_softc *sc,
@@ -556,113 +166,42 @@ Static usbd_status umass_setup_transfer(struct umass_softc *sc,
void *buffer, int buflen, int flags,
usbd_xfer_handle xfer);
Static usbd_status umass_setup_ctrl_transfer(struct umass_softc *sc,
- usbd_device_handle dev,
usb_device_request_t *req,
void *buffer, int buflen, int flags,
usbd_xfer_handle xfer);
-Static void umass_clear_endpoint_stall(struct umass_softc *sc,
- u_int8_t endpt, usbd_pipe_handle pipe,
- int state, usbd_xfer_handle xfer);
+Static void umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
+ usbd_xfer_handle xfer);
#if 0
-Static void umass_reset(struct umass_softc *sc,
- transfer_cb_f cb, void *priv);
+Static void umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv);
#endif
/* Bulk-Only related functions */
-Static void umass_bbb_reset(struct umass_softc *sc, int status);
-Static void umass_bbb_transfer(struct umass_softc *sc, int lun,
- void *cmd, int cmdlen,
- void *data, int datalen, int dir,
- transfer_cb_f cb, void *priv);
-Static void umass_bbb_state(usbd_xfer_handle xfer,
- usbd_private_handle priv,
- usbd_status err);
-usbd_status umass_bbb_get_max_lun(struct umass_softc *sc,
- u_int8_t *maxlun);
+Static void umass_bbb_transfer(struct umass_softc *, int, void *, int, void *,
+ int, int, u_int, umass_callback, void *);
+Static void umass_bbb_reset(struct umass_softc *, int);
+Static void umass_bbb_state(usbd_xfer_handle, usbd_private_handle, usbd_status);
+usbd_status umass_bbb_get_max_lun(struct umass_softc *, u_int8_t *);
/* CBI related functions */
-Static int umass_cbi_adsc(struct umass_softc *sc, char *buffer,int buflen,
- usbd_xfer_handle xfer);
-Static void umass_cbi_reset(struct umass_softc *sc, int status);
-Static void umass_cbi_transfer(struct umass_softc *sc, int lun,
- void *cmd, int cmdlen,
- void *data, int datalen, int dir,
- transfer_cb_f cb, void *priv);
-Static void umass_cbi_state(usbd_xfer_handle xfer,
- usbd_private_handle priv, usbd_status err);
-
-#if defined(__FreeBSD__)
-/* CAM related functions */
-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, void *priv,
- int residue, int status);
-Static void umass_cam_sense_cb(struct umass_softc *sc, void *priv,
- int residue, int status);
-
-#ifdef UMASS_DO_CAM_RESCAN
-Static void umass_cam_rescan(struct umass_softc *sc);
-#endif
-
-Static int umass_cam_attach_sim(void);
-Static int umass_cam_attach(struct umass_softc *sc);
-Static int umass_cam_detach_sim(void);
-Static int umass_cam_detach(struct umass_softc *sc);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-
-#define UMASS_SCSIID_HOST 0x00
-#define UMASS_SCSIID_DEVICE 0x01
-
-#define UMASS_ATAPI_DRIVE 0
+Static void umass_cbi_transfer(struct umass_softc *, int, void *, int, void *,
+ int, int, u_int, umass_callback, void *);
+Static void umass_cbi_reset(struct umass_softc *, int);
+Static void umass_cbi_state(usbd_xfer_handle, usbd_private_handle, usbd_status);
-#define UMASS_MAX_TRANSFER_SIZE MAXBSIZE
+Static int umass_cbi_adsc(struct umass_softc *, char *, int, usbd_xfer_handle);
-struct scsipi_device umass_dev =
-{
- NULL, /* Use default error handler */
- NULL, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
+const struct umass_wire_methods umass_bbb_methods = {
+ umass_bbb_transfer,
+ umass_bbb_reset,
+ umass_bbb_state
};
-Static int umass_scsipi_cmd(struct scsipi_xfer *xs);
-Static void umass_scsipi_minphys(struct buf *bp);
-Static int umass_scsipi_ioctl(struct scsipi_link *, u_long,
- caddr_t, int, struct proc *);
-Static void umass_scsipi_cb(struct umass_softc *sc, void *priv,
- int residue, int status);
-Static void umass_scsipi_sense_cb(struct umass_softc *sc, void *priv,
- int residue, int status);
-
-Static int scsipiprint(void *aux, const char *pnp);
-Static int umass_ufi_transform(struct umass_softc *sc,
- struct scsipi_generic *cmd, int cmdlen,
- struct scsipi_generic *rcmd, int *rcmdlen);
-
-#if NATAPIBUS > 0
-Static void umass_atapi_probedev(struct atapibus_softc *, int);
-#endif
-#endif
-
-#if defined(__FreeBSD__)
-/* SCSI specific functions */
-Static int umass_scsi_transform(struct umass_softc *sc,
- unsigned char *cmd, int cmdlen,
- unsigned char **rcmd, int *rcmdlen);
-
-/* UFI specific functions */
-Static int umass_ufi_transform(struct umass_softc *sc,
- unsigned char *cmd, int cmdlen,
- unsigned char **rcmd, int *rcmdlen);
-
-/* 8070 specific functions */
-Static int umass_8070_transform(struct umass_softc *sc,
- unsigned char *cmd, int cmdlen,
- unsigned char **rcmd, int *rcmdlen);
-#endif
+const struct umass_wire_methods umass_cbi_methods = {
+ umass_cbi_transfer,
+ umass_cbi_reset,
+ umass_cbi_state
+};
#ifdef UMASS_DEBUG
/* General debugging functions */
@@ -675,298 +214,180 @@ Static void umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer,
#endif
-void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe); /* XXXXX */
-
/*
* USB device probe/attach/detach
*/
-/*
- * Match the device we are seeing with the devices supported. Fill in the
- * proto and drive fields in the softc accordingly.
- * This function is called from both probe and attach.
- */
-
-Static int
-umass_match_proto(sc, iface, dev)
- struct umass_softc *sc;
- usbd_interface_handle iface;
- usbd_device_handle dev;
+USB_MATCH(umass)
{
- usb_device_descriptor_t *dd;
+ USB_MATCH_START(umass, uaa);
+ const struct umass_quirk *quirk;
usb_interface_descriptor_t *id;
- u_int vendor, product;
-
- /*
- * Fill in sc->drive and sc->proto and return a match
- * value if both are determined and 0 otherwise.
- */
-
- sc->drive = DRIVE_GENERIC;
- sc->proto = PROTO_UNKNOWN;
- sc->transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED;
-
- sc->sc_udev = dev;
- dd = usbd_get_device_descriptor(dev);
- vendor = UGETW(dd->idVendor);
- product = UGETW(dd->idProduct);
-
- if (vendor == USB_VENDOR_SHUTTLE &&
- product == USB_PRODUCT_SHUTTLE_EUSB) {
- sc->drive = SHUTTLE_EUSB;
-#if CBI_I
- sc->proto = PROTO_ATAPI | PROTO_CBI_I;
-#else
- sc->proto = PROTO_ATAPI | PROTO_CBI;
-#endif
- sc->subclass = UISUBCLASS_SFF8020I;
- sc->protocol = UIPROTO_MASS_CBI;
- sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
- return (UMATCH_VENDOR_PRODUCT);
- }
-
- if (vendor == USB_VENDOR_TRUMPION &&
- product == USB_PRODUCT_TRUMPION_XXX1100) {
- sc->proto = PROTO_ATAPI | PROTO_CBI;
- return (UMATCH_VENDOR_PRODUCT);
- }
-
- if (vendor == USB_VENDOR_YANO &&
- product == USB_PRODUCT_YANO_U640MO) {
- sc->proto = PROTO_ATAPI | PROTO_CBI_I;
- sc->quirks |= FORCE_SHORT_INQUIRY;
- return (UMATCH_VENDOR_PRODUCT);
- }
-
- if (vendor == USB_VENDOR_SONY &&
- product == USB_PRODUCT_SONY_MSC) {
- printf ("XXX Sony MSC\n");
- sc->quirks |= FORCE_SHORT_INQUIRY;
- }
-
- if (vendor == USB_VENDOR_YEDATA &&
- product == USB_PRODUCT_YEDATA_FLASHBUSTERU) {
-
- /* Revisions < 1.28 do not handle the interrupt endpoint
- * very well.
- */
- if (UGETW(dd->bcdDevice) < 0x128)
- sc->proto = PROTO_UFI | PROTO_CBI;
- else
-#if CBI_I
- sc->proto = PROTO_UFI | PROTO_CBI_I;
-#else
- sc->proto = PROTO_UFI | PROTO_CBI;
-#endif
- /*
- * Revisions < 1.28 do not have the TEST UNIT READY command
- * Revisions == 1.28 have a broken TEST UNIT READY
- */
- if (UGETW(dd->bcdDevice) <= 0x128)
- sc->quirks |= NO_TEST_UNIT_READY;
-
- sc->subclass = UISUBCLASS_UFI;
- sc->protocol = UIPROTO_MASS_CBI;
- sc->quirks |= RS_NO_CLEAR_UA;
- sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
- return (UMATCH_VENDOR_PRODUCT_REV);
- }
+ if (uaa->iface == NULL)
+ return (UMATCH_NONE);
- if (vendor == USB_VENDOR_INSYSTEM &&
- product == USB_PRODUCT_INSYSTEM_USBCABLE) {
- sc->drive = INSYSTEM_USBCABLE;
- sc->proto = PROTO_ATAPI | PROTO_CBI;
- sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
- return (UMATCH_VENDOR_PRODUCT);
- }
+ quirk = umass_lookup(uaa->vendor, uaa->product);
+ if (quirk != NULL)
+ return (quirk->uq_match);
- id = usbd_get_interface_descriptor(iface);
+ id = usbd_get_interface_descriptor(uaa->iface);
if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
return (UMATCH_NONE);
- if (vendor == USB_VENDOR_SONY && id->bInterfaceSubClass == 0xff) {
- /*
- * Sony DSC devices set the sub class to 0xff
- * instead of 1 (RBC). Fix that here.
- */
- id->bInterfaceSubClass = UISUBCLASS_RBC;
- /* They also should be able to do higher speed. */
- sc->transfer_speed = 500;
- }
-
- if (vendor == USB_VENDOR_FUJIPHOTO &&
- product == USB_PRODUCT_FUJIPHOTO_MASS0100)
- sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP;
-
- sc->subclass = id->bInterfaceSubClass;
- sc->protocol = id->bInterfaceProtocol;
-
- switch (sc->subclass) {
- case UISUBCLASS_SCSI:
- sc->proto |= PROTO_SCSI;
- break;
- case UISUBCLASS_UFI:
- sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED;
- sc->proto |= PROTO_UFI;
- break;
+ switch (id->bInterfaceSubClass) {
+ case UISUBCLASS_RBC:
case UISUBCLASS_SFF8020I:
- case UISUBCLASS_SFF8070I:
case UISUBCLASS_QIC157:
- sc->proto |= PROTO_ATAPI;
- break;
- case UISUBCLASS_RBC:
- sc->proto |= PROTO_RBC;
+ case UISUBCLASS_UFI:
+ case UISUBCLASS_SFF8070I:
+ case UISUBCLASS_SCSI:
break;
default:
- /* Assume that unsupported devices are ATAPI */
- DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n",
- USBDEVNAME(sc->sc_dev), id->bInterfaceSubClass));
-
- sc->proto |= PROTO_ATAPI;
- break;
+ return (UMATCH_IFACECLASS);
}
- switch (sc->protocol) {
- case UIPROTO_MASS_CBI:
- sc->proto |= PROTO_CBI;
- break;
+ switch (id->bInterfaceProtocol) {
case UIPROTO_MASS_CBI_I:
-#if CBI_I
- sc->proto |= PROTO_CBI_I;
-#else
- sc->proto |= PROTO_CBI;
-#endif
- break;
+ case UIPROTO_MASS_CBI:
+ case UIPROTO_MASS_BBB_OLD:
case UIPROTO_MASS_BBB:
- sc->proto |= PROTO_BBB;
- break;
- case UIPROTO_MASS_BBB_P:
- sc->drive = ZIP_100;
- sc->proto |= PROTO_BBB;
- sc->transfer_speed = UMASS_ZIP100_TRANSFER_SPEED;
- sc->quirks |= NO_TEST_UNIT_READY;
break;
default:
- DPRINTF(UDMASS_GEN, ("%s: Unsupported wire protocol %d\n",
- USBDEVNAME(sc->sc_dev), id->bInterfaceProtocol));
- return (UMATCH_NONE);
+ return (UMATCH_IFACECLASS_IFACESUBCLASS);
}
- return (UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO);
-}
-
-USB_MATCH(umass)
-{
- USB_MATCH_START(umass, uaa);
-#if defined(__FreeBSD__)
- struct umass_softc *sc = device_get_softc(self);
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
- struct umass_softc scs, *sc = &scs;
- memset(sc, 0, sizeof *sc);
- strlcpy(sc->sc_dev.dv_xname, "umass", sizeof sc->sc_dev.dv_xname);
-#endif
-
- if (uaa->iface == NULL)
- return(UMATCH_NONE);
-
- return (umass_match_proto(sc, uaa->iface, uaa->device));
+ return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
}
-void umass_delayed_attach(struct umass_softc *sc);
-
USB_ATTACH(umass)
{
USB_ATTACH_START(umass, sc, uaa);
+ const struct umass_quirk *quirk;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
- const char *sSubclass, *sProto;
+ const char *sWire, *sCommand;
char devinfo[1024];
- int i, bno;
- int err;
-
- /*
- * the softc struct is bzero-ed in device_set_driver. We can safely
- * call umass_detach without specifically initialising the struct.
- */
+ usbd_status err;
+ int i, bno, error;
usbd_devinfo(uaa->device, 0, devinfo, sizeof devinfo);
USB_ATTACH_SETUP;
- sc->iface = uaa->iface;
- sc->ifaceno = uaa->ifaceno;
+ sc->sc_udev = uaa->device;
+ sc->sc_iface = uaa->iface;
+ sc->sc_ifaceno = uaa->ifaceno;
+
+ quirk = umass_lookup(uaa->vendor, uaa->product);
+ if (quirk != NULL) {
+ sc->sc_wire = quirk->uq_wire;
+ sc->sc_cmd = quirk->uq_cmd;
+ sc->sc_quirks = quirk->uq_flags;
+ sc->sc_busquirks = quirk->uq_busquirks;
- /* initialise the proto and drive values in the umass_softc (again) */
- if (umass_match_proto(sc, sc->iface, uaa->device) == 0) {
- printf("%s: match failed\n", USBDEVNAME(sc->sc_dev));
+ if (quirk->uq_fixup != NULL)
+ (*quirk->uq_fixup)(sc);
+ } else {
+ sc->sc_wire = UMASS_WPROTO_UNSPEC;
+ sc->sc_cmd = UMASS_CPROTO_UNSPEC;
+ sc->sc_quirks = 0;
+ sc->sc_busquirks = 0;
+ }
+
+ id = usbd_get_interface_descriptor(sc->sc_iface);
+ if (id == NULL)
USB_ATTACH_ERROR_RETURN;
+
+ if (sc->sc_wire == UMASS_WPROTO_UNSPEC) {
+ switch (id->bInterfaceProtocol) {
+ case UIPROTO_MASS_CBI:
+ sc->sc_wire = UMASS_WPROTO_CBI;
+ break;
+ case UIPROTO_MASS_CBI_I:
+ sc->sc_wire = UMASS_WPROTO_CBI_I;
+ break;
+ case UIPROTO_MASS_BBB:
+ case UIPROTO_MASS_BBB_OLD:
+ sc->sc_wire = UMASS_WPROTO_BBB;
+ break;
+ default:
+ DPRINTF(UDMASS_GEN,
+ ("%s: Unsupported wire protocol %u\n",
+ USBDEVNAME(sc->sc_dev),
+ id->bInterfaceProtocol));
+ USB_ATTACH_ERROR_RETURN;
+ }
}
- /*
- * The timeout is based on the maximum expected transfer size
- * divided by the expected transfer speed.
- * We multiply by 4 to make sure a busy system doesn't make things
- * fail.
- */
- sc->timeout = 4 * UMASS_MAX_TRANSFER_SIZE / sc->transfer_speed;
- sc->timeout += UMASS_SPINUP_TIME; /* allow for spinning up */
+ /* XXX - Now unsupported CBI with CCI */
+ if (sc->sc_wire == UMASS_WPROTO_CBI_I)
+ sc->sc_wire = UMASS_WPROTO_CBI;
+
+ if (sc->sc_cmd == UMASS_CPROTO_UNSPEC) {
+ switch (id->bInterfaceSubClass) {
+ case UISUBCLASS_SCSI:
+ sc->sc_cmd = UMASS_CPROTO_SCSI;
+ break;
+ case UISUBCLASS_UFI:
+ sc->sc_cmd = UMASS_CPROTO_UFI;
+ break;
+ case UISUBCLASS_SFF8020I:
+ case UISUBCLASS_SFF8070I:
+ case UISUBCLASS_QIC157:
+ sc->sc_cmd = UMASS_CPROTO_ATAPI;
+ break;
+ case UISUBCLASS_RBC:
+ sc->sc_cmd = UMASS_CPROTO_RBC;
+ break;
+ default:
+ DPRINTF(UDMASS_GEN,
+ ("%s: Unsupported command protocol %u\n",
+ USBDEVNAME(sc->sc_dev),
+ id->bInterfaceSubClass));
+ USB_ATTACH_ERROR_RETURN;
+ }
+ }
- id = usbd_get_interface_descriptor(sc->iface);
printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
- switch (sc->subclass) {
- case UISUBCLASS_RBC:
- sSubclass = "RBC";
- break;
- case UISUBCLASS_SCSI:
- sSubclass = "SCSI";
- break;
- case UISUBCLASS_UFI:
- sSubclass = "UFI";
+ switch (sc->sc_wire) {
+ case UMASS_WPROTO_CBI:
+ sWire = "CBI";
break;
- case UISUBCLASS_SFF8020I:
- sSubclass = "SFF8020i";
+ case UMASS_WPROTO_CBI_I:
+ sWire = "CBI with CCI";
break;
- case UISUBCLASS_SFF8070I:
- sSubclass = "SFF8070i";
- break;
- case UISUBCLASS_QIC157:
- sSubclass = "QIC157";
+ case UMASS_WPROTO_BBB:
+ sWire = "Bulk-Only";
break;
default:
- sSubclass = "unknown";
+ sWire = "unknown";
break;
}
- switch (sc->protocol) {
- case UIPROTO_MASS_CBI:
- sProto = "CBI";
+
+ switch (sc->sc_cmd) {
+ case UMASS_CPROTO_RBC:
+ sCommand = "RBC";
break;
- case UIPROTO_MASS_CBI_I:
- sProto = "CBI-I";
+ case UMASS_CPROTO_SCSI:
+ sCommand = "SCSI";
break;
- case UIPROTO_MASS_BBB:
- sProto = "BBB";
+ case UMASS_CPROTO_UFI:
+ sCommand = "UFI";
break;
- case UIPROTO_MASS_BBB_P:
- sProto = "BBB-P";
+ case UMASS_CPROTO_ATAPI:
+ sCommand = "ATAPI";
+ break;
+ case UMASS_CPROTO_ISD_ATA:
+ sCommand = "ISD-ATA";
break;
default:
- sProto = "unknown";
+ sCommand = "unknown";
break;
}
- printf("%s: using %s over %s\n", USBDEVNAME(sc->sc_dev), sSubclass,
- sProto);
- if (sc->drive == INSYSTEM_USBCABLE) {
- err = usbd_set_interface(0, 1);
- if (err) {
- DPRINTF(UDMASS_USB, ("%s: could not switch to "
- "Alt Interface %d\n",
- USBDEVNAME(sc->sc_dev), 1));
- umass_disco(sc);
- USB_ATTACH_ERROR_RETURN;
- }
- }
+ printf("%s: using %s over %s\n", USBDEVNAME(sc->sc_dev), sCommand,
+ sWire);
/*
* In addition to the Control endpoint the following endpoints
@@ -980,22 +401,22 @@ USB_ATTACH(umass)
* from the device descriptors of the current interface.
*/
for (i = 0 ; i < id->bNumEndpoints ; i++) {
- ed = usbd_interface2endpoint_descriptor(sc->iface, i);
- if (!ed) {
+ ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
+ if (ed == NULL) {
printf("%s: could not read endpoint descriptor\n",
USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
&& (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
- sc->bulkin = ed->bEndpointAddress;
+ sc->sc_epaddr[UMASS_BULKIN] = ed->bEndpointAddress;
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
&& (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
- sc->bulkout = ed->bEndpointAddress;
- } else if (sc->proto & PROTO_CBI_I
+ sc->sc_epaddr[UMASS_BULKOUT] = ed->bEndpointAddress;
+ } else if (sc->sc_wire == UMASS_WPROTO_CBI_I
&& UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
&& (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
- sc->intrin = ed->bEndpointAddress;
+ sc->sc_epaddr[UMASS_INTRIN] = ed->bEndpointAddress;
#ifdef UMASS_DEBUG
if (UGETW(ed->wMaxPacketSize) > 2) {
DPRINTF(UDMASS_CBI, ("%s: intr size is %d\n",
@@ -1007,19 +428,21 @@ USB_ATTACH(umass)
}
/* check whether we found all the endpoints we need */
- if (!sc->bulkin || !sc->bulkout
- || (sc->proto & PROTO_CBI_I && !sc->intrin) ) {
- DPRINTF(UDMASS_USB, ("%s: endpoint not found %d/%d/%d\n",
- USBDEVNAME(sc->sc_dev),
- sc->bulkin, sc->bulkout, sc->intrin));
- umass_disco(sc);
+ if (!sc->sc_epaddr[UMASS_BULKIN] || !sc->sc_epaddr[UMASS_BULKOUT] ||
+ (sc->sc_wire == UMASS_WPROTO_CBI_I &&
+ !sc->sc_epaddr[UMASS_INTRIN])) {
+ DPRINTF(UDMASS_USB, ("%s: endpoint not found %u/%u/%u\n",
+ USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKIN],
+ sc->sc_epaddr[UMASS_BULKOUT],
+ sc->sc_epaddr[UMASS_INTRIN]));
USB_ATTACH_ERROR_RETURN;
}
/*
* Get the maximum LUN supported by the device.
*/
- if ((sc->proto & PROTO_WIRE) == PROTO_BBB) {
+ if (sc->sc_wire == UMASS_WPROTO_BBB &&
+ !(sc->sc_quirks & UMASS_QUIRK_NO_MAX_LUN)) {
err = umass_bbb_get_max_lun(sc, &sc->maxlun);
if (err) {
printf("%s: unable to get Max Lun: %s\n",
@@ -1031,19 +454,20 @@ USB_ATTACH(umass)
}
/* Open the bulk-in and -out pipe */
- err = usbd_open_pipe(sc->iface, sc->bulkout,
- USBD_EXCLUSIVE_USE, &sc->bulkout_pipe);
+ err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKOUT],
+ USBD_EXCLUSIVE_USE,
+ &sc->sc_pipe[UMASS_BULKOUT]);
if (err) {
- DPRINTF(UDMASS_USB, ("%s: cannot open %d-out pipe (bulk)\n",
- USBDEVNAME(sc->sc_dev), sc->bulkout));
+ DPRINTF(UDMASS_USB, ("%s: cannot open %u-out pipe (bulk)\n",
+ USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKOUT]));
umass_disco(sc);
USB_ATTACH_ERROR_RETURN;
}
- err = usbd_open_pipe(sc->iface, sc->bulkin,
- USBD_EXCLUSIVE_USE, &sc->bulkin_pipe);
+ err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKIN],
+ USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_BULKIN]);
if (err) {
- DPRINTF(UDMASS_USB, ("%s: could not open %d-in pipe (bulk)\n",
- USBDEVNAME(sc->sc_dev), sc->bulkin));
+ DPRINTF(UDMASS_USB, ("%s: could not open %u-in pipe (bulk)\n",
+ USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKIN]));
umass_disco(sc);
USB_ATTACH_ERROR_RETURN;
}
@@ -1059,12 +483,13 @@ USB_ATTACH(umass)
* code for handling the data on that endpoint simpler. No data
* arriving concurrently.
*/
- if (sc->proto & PROTO_CBI_I) {
- err = usbd_open_pipe(sc->iface, sc->intrin,
- USBD_EXCLUSIVE_USE, &sc->intrin_pipe);
+ if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
+ err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_INTRIN],
+ USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_INTRIN]);
if (err) {
- DPRINTF(UDMASS_USB, ("%s: couldn't open %d-in (intr)\n",
- USBDEVNAME(sc->sc_dev), sc->intrin));
+ DPRINTF(UDMASS_USB, ("%s: couldn't open %u-in (intr)\n",
+ USBDEVNAME(sc->sc_dev),
+ sc->sc_epaddr[UMASS_INTRIN]));
umass_disco(sc);
USB_ATTACH_ERROR_RETURN;
}
@@ -1076,7 +501,7 @@ USB_ATTACH(umass)
/* request a sufficient number of xfer handles */
for (i = 0; i < XFER_NR; i++) {
sc->transfer_xfer[i] = usbd_alloc_xfer(uaa->device);
- if (sc->transfer_xfer[i] == 0) {
+ if (sc->transfer_xfer[i] == NULL) {
DPRINTF(UDMASS_USB, ("%s: Out of memory\n",
USBDEVNAME(sc->sc_dev)));
umass_disco(sc);
@@ -1084,14 +509,14 @@ USB_ATTACH(umass)
}
}
/* Allocate buffer for data transfer (it's huge). */
- switch (sc->proto & PROTO_WIRE) {
- case PROTO_BBB:
+ switch (sc->sc_wire) {
+ case UMASS_WPROTO_BBB:
bno = XFER_BBB_DATA;
goto dalloc;
- case PROTO_CBI:
+ case UMASS_WPROTO_CBI:
bno = XFER_CBI_DATA;
goto dalloc;
- case PROTO_CBI_I:
+ case UMASS_WPROTO_CBI_I:
bno = XFER_CBI_DATA;
dalloc:
sc->data_buffer = usbd_alloc_buffer(sc->transfer_xfer[bno],
@@ -1106,144 +531,108 @@ USB_ATTACH(umass)
}
/* Initialise the wire protocol specific methods */
- if (sc->proto & PROTO_BBB) {
- sc->reset = umass_bbb_reset;
- sc->transfer = umass_bbb_transfer;
- sc->state = umass_bbb_state;
- } else if ((sc->proto & PROTO_CBI) || (sc->proto & PROTO_CBI_I)) {
- sc->reset = umass_cbi_reset;
- sc->transfer = umass_cbi_transfer;
- sc->state = umass_cbi_state;
-#ifdef UMASS_DEBUG
- } else {
- panic("%s:%d: Unknown proto 0x%02x",
- __FILE__, __LINE__, sc->proto);
-#endif
+ switch (sc->sc_wire) {
+ case UMASS_WPROTO_BBB:
+ sc->sc_methods = &umass_bbb_methods;
+ break;
+ case UMASS_WPROTO_CBI:
+ case UMASS_WPROTO_CBI_I:
+ sc->sc_methods = &umass_cbi_methods;
+ break;
+ default:
+ umass_disco(sc);
+ USB_ATTACH_ERROR_RETURN;
}
- if (sc->drive == SHUTTLE_EUSB)
- umass_init_shuttle(sc);
+ if (quirk != NULL && quirk->uq_init != NULL) {
+ err = (*quirk->uq_init)(sc);
+ if (err) {
+ umass_disco(sc);
+ USB_ATTACH_ERROR_RETURN;
+ }
+ }
- /*
- * Fill in the adapter.
- */
- sc->sc_adapter.scsipi_cmd = umass_scsipi_cmd;
- sc->sc_adapter.scsipi_minphys = umass_scsipi_minphys;
+ error = 0;
+ switch (sc->sc_cmd) {
+ case UMASS_CPROTO_RBC:
+ case UMASS_CPROTO_SCSI:
+#if defined(__OpenBSD__) || NSCSIBUS > 0
+ error = umass_scsi_attach(sc);
+#else
+ printf("%s: scsibus not configured\n", USBDEVNAME(sc->sc_dev));
+#endif
+ break;
- /*
- * fill in the prototype scsipi_link.
- */
- switch (sc->proto & PROTO_COMMAND) {
- case PROTO_SCSI:
- case PROTO_UFI:
- case PROTO_ATAPI:
- case PROTO_RBC:
- if ((sc->proto & PROTO_COMMAND) != PROTO_SCSI)
- sc->u.sc_link.flags |= SDEV_ATAPI;
- else
- sc->u.sc_link.flags &= ~SDEV_ATAPI;
-
- sc->u.sc_link.adapter_buswidth = 2;
- sc->u.sc_link.adapter_target = UMASS_SCSIID_HOST;
- sc->u.sc_link.luns = sc->maxlun + 1;
-
- sc->u.sc_link.adapter_softc = sc;
- sc->u.sc_link.adapter = &sc->sc_adapter;
- sc->u.sc_link.device = &umass_dev;
- sc->u.sc_link.openings = 1;
-
- if(sc->quirks & NO_TEST_UNIT_READY)
- sc->u.sc_link.quirks |= ADEV_NOTUR;
+ case UMASS_CPROTO_UFI:
+ case UMASS_CPROTO_ATAPI:
+#if (NATAPIBUS > 0) || (NATAPISCSI > 0)
+ error = umass_atapi_attach(sc);
+#else
+ printf("%s: "UMASS_ATAPISTR" not configured\n",
+ USBDEVNAME(sc->sc_dev));
+#endif
break;
+ case UMASS_CPROTO_ISD_ATA:
+#if defined (__NetBSD__) && NWD > 0
+ error = umass_isdata_attach(sc);
+#else
+ printf("%s: isdata not configured\n", USBDEVNAME(sc->sc_dev));
+#endif
+ break;
default:
- printf("%s: proto=0x%x not supported yet\n",
- USBDEVNAME(sc->sc_dev), sc->proto);
+ printf("%s: command protocol=0x%x not supported\n",
+ USBDEVNAME(sc->sc_dev), sc->sc_cmd);
umass_disco(sc);
USB_ATTACH_ERROR_RETURN;
}
-
- if (cold) {
- startuphook_establish((void (*)(void *))umass_delayed_attach,
- sc);
- } else {
- /* hot plug, do it now */
- umass_delayed_attach(sc);
- }
-
- DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", USBDEVNAME(sc->sc_dev)));
-
- USB_ATTACH_SUCCESS_RETURN;
-}
-
-void
-umass_delayed_attach(struct umass_softc *sc)
-{
- sc->sc_child = config_found(&sc->sc_dev, &sc->u, scsipiprint);
- if (sc->sc_child == NULL) {
+ if (error) {
+ printf("%s: bus attach failed\n", USBDEVNAME(sc->sc_dev));
umass_disco(sc);
- /* Not an error, just not a complete success. */
- USB_ATTACH_SUCCESS_RETURN;
+ USB_ATTACH_ERROR_RETURN;
}
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
USBDEV(sc->sc_dev));
-}
-Static int
-scsipiprint(aux, pnp)
- void *aux;
- const char *pnp;
-{
-#if !defined(__OpenBSD__)
- extern int atapi_print(void *aux, const char *pnp);
- struct scsipi_link *l = aux;
-
- if (l->type == BUS_SCSI)
- return (scsiprint(aux, pnp));
- else
- return (atapi_print(aux, pnp));
-#else
- return (scsiprint(aux, pnp));
-#endif
+ DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", USBDEVNAME(sc->sc_dev)));
+
+ USB_ATTACH_SUCCESS_RETURN;
}
USB_DETACH(umass)
{
USB_DETACH_START(umass, sc);
- int rv = 0;
+ struct umassbus_softc *scbus = sc->bus;
+ int rv = 0, i, s;
DPRINTF(UDMASS_USB, ("%s: detached\n", USBDEVNAME(sc->sc_dev)));
/* Abort the pipes to wake up any waiting processes. */
- if (sc->bulkout_pipe != NULL)
- usbd_abort_pipe(sc->bulkout_pipe);
- if (sc->bulkin_pipe != NULL)
- usbd_abort_pipe(sc->bulkin_pipe);
- if (sc->intrin_pipe != NULL)
- usbd_abort_pipe(sc->intrin_pipe);
+ for (i = 0 ; i < UMASS_NEP ; i++) {
+ if (sc->sc_pipe[i] != NULL)
+ usbd_abort_pipe(sc->sc_pipe[i]);
+ }
-#if 0
/* Do we really need reference counting? Perhaps in ioctl() */
s = splusb();
if (--sc->sc_refcnt >= 0) {
+#ifdef DIAGNOSTIC
+ printf("%s: waiting for refcnt\n", USBDEVNAME(sc->sc_dev));
+#endif
/* Wait for processes to go away. */
usb_detach_wait(USBDEV(sc->sc_dev));
}
splx(s);
-#endif
-#if defined(__FreeBSD__)
- if ((sc->proto & PROTO_SCSI) ||
- (sc->proto & PROTO_ATAPI) ||
- (sc->proto & PROTO_UFI))
- /* detach the device from the SCSI host controller (SIM) */
- rv = umass_cam_detach(sc);
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
- if (sc->sc_child != NULL)
- rv = config_detach(sc->sc_child, flags);
-#endif
+ if (scbus != NULL) {
+ if (scbus->sc_child != NULL)
+ rv = config_detach(scbus->sc_child, flags);
+ free(scbus, M_DEVBUF);
+ sc->bus = NULL;
+ }
+
if (rv != 0)
return (rv);
@@ -1252,16 +641,14 @@ USB_DETACH(umass)
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
USBDEV(sc->sc_dev));
- return (0);
+ return (rv);
}
-#if defined(__NetBSD__) || defined(__OpenBSD__)
int
-umass_activate(self, act)
- struct device *self;
- enum devact act;
+umass_activate(struct device *dev, enum devact act)
{
- struct umass_softc *sc = (struct umass_softc *) self;
+ struct umass_softc *sc = (struct umass_softc *)dev;
+ struct umassbus_softc *scbus = sc->bus;
int rv = 0;
DPRINTF(UDMASS_USB, ("%s: umass_activate: %d\n",
@@ -1273,22 +660,19 @@ umass_activate(self, act)
break;
case DVACT_DEACTIVATE:
- if (sc->sc_child == NULL)
+ sc->sc_dying = 1;
+ if (scbus == NULL || scbus->sc_child == NULL)
break;
- rv = config_deactivate(sc->sc_child);
+ rv = config_deactivate(scbus->sc_child);
DPRINTF(UDMASS_USB, ("%s: umass_activate: child "
"returned %d\n", USBDEVNAME(sc->sc_dev), rv));
- if (rv == 0)
- sc->sc_dying = 1;
break;
}
return (rv);
}
-#endif
Static void
-umass_disco(sc)
- struct umass_softc *sc;
+umass_disco(struct umass_softc *sc)
{
int i;
@@ -1302,27 +686,12 @@ umass_disco(sc)
}
/* Remove all the pipes. */
- if (sc->bulkout_pipe != NULL)
- usbd_close_pipe(sc->bulkout_pipe);
- if (sc->bulkin_pipe != NULL)
- usbd_close_pipe(sc->bulkin_pipe);
- if (sc->intrin_pipe != NULL)
- usbd_close_pipe(sc->intrin_pipe);
-}
-
-Static void
-umass_init_shuttle(struct umass_softc *sc)
-{
- usb_device_request_t req;
- u_char status[2];
-
- /* The Linux driver does this */
- req.bmRequestType = UT_READ_VENDOR_DEVICE;
- req.bRequest = 1;
- USETW(req.wValue, 0);
- USETW(req.wIndex, sc->ifaceno);
- USETW(req.wLength, sizeof status);
- (void)usbd_do_request(sc->sc_udev, &req, &status);
+ for (i = 0 ; i < UMASS_NEP ; i++) {
+ if (sc->sc_pipe[i] != NULL) {
+ usbd_close_pipe(sc->sc_pipe[i]);
+ sc->sc_pipe[i] = NULL;
+ }
+ }
}
/*
@@ -1342,7 +711,7 @@ umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe,
/* Initialiase a USB transfer and then schedule it */
usbd_setup_xfer(xfer, pipe, (void *)sc, buffer, buflen,
- flags | sc->sc_xfer_flags, sc->timeout, sc->state);
+ flags | sc->sc_xfer_flags, sc->timeout, sc->sc_methods->wire_state);
err = usbd_transfer(xfer);
DPRINTF(UDMASS_XFER,("%s: start xfer buffer=%p buflen=%d flags=0x%x "
@@ -1359,10 +728,8 @@ umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe,
Static usbd_status
-umass_setup_ctrl_transfer(struct umass_softc *sc, usbd_device_handle dev,
- usb_device_request_t *req,
- void *buffer, int buflen, int flags,
- usbd_xfer_handle xfer)
+umass_setup_ctrl_transfer(struct umass_softc *sc, usb_device_request_t *req,
+ void *buffer, int buflen, int flags, usbd_xfer_handle xfer)
{
usbd_status err;
@@ -1371,8 +738,8 @@ umass_setup_ctrl_transfer(struct umass_softc *sc, usbd_device_handle dev,
/* Initialiase a USB control transfer and then schedule it */
- usbd_setup_default_xfer(xfer, dev, (void *) sc,
- sc->timeout, req, buffer, buflen, flags, sc->state);
+ usbd_setup_default_xfer(xfer, sc->sc_udev, (void *) sc, sc->timeout,
+ req, buffer, buflen, flags, sc->sc_methods->wire_state);
err = usbd_transfer(xfer);
if (err && err != USBD_IN_PROGRESS) {
@@ -1387,30 +754,23 @@ umass_setup_ctrl_transfer(struct umass_softc *sc, usbd_device_handle dev,
}
Static void
-umass_clear_endpoint_stall(struct umass_softc *sc,
- u_int8_t endpt, usbd_pipe_handle pipe,
- int state, usbd_xfer_handle xfer)
+umass_clear_endpoint_stall(struct umass_softc *sc, int endpt,
+ usbd_xfer_handle xfer)
{
- usbd_device_handle dev;
-
if (sc->sc_dying)
return;
DPRINTF(UDMASS_BBB, ("%s: Clear endpoint 0x%02x stall\n",
- USBDEVNAME(sc->sc_dev), endpt));
-
- usbd_interface2device_handle(sc->iface, &dev);
+ USBDEVNAME(sc->sc_dev), sc->sc_epaddr[endpt]));
- sc->transfer_state = state;
+ usbd_clear_endpoint_toggle(sc->sc_pipe[endpt]);
- usbd_clear_endpoint_toggle(pipe);
-
- sc->request.bmRequestType = UT_WRITE_ENDPOINT;
- sc->request.bRequest = UR_CLEAR_FEATURE;
- USETW(sc->request.wValue, UF_ENDPOINT_HALT);
- USETW(sc->request.wIndex, endpt);
- USETW(sc->request.wLength, 0);
- umass_setup_ctrl_transfer(sc, dev, &sc->request, NULL, 0, 0, xfer);
+ sc->sc_req.bmRequestType = UT_WRITE_ENDPOINT;
+ sc->sc_req.bRequest = UR_CLEAR_FEATURE;
+ USETW(sc->sc_req.wValue, UF_ENDPOINT_HALT);
+ USETW(sc->sc_req.wIndex, sc->sc_epaddr[endpt]);
+ USETW(sc->sc_req.wLength, 0);
+ umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, xfer);
}
#if 0
@@ -1432,10 +792,9 @@ umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv)
Static void
umass_bbb_reset(struct umass_softc *sc, int status)
{
- usbd_device_handle dev;
-
- KASSERT(sc->proto & PROTO_BBB,
- ("sc->proto == 0x%02x wrong for umass_bbb_reset\n", sc->proto));
+ KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
+ ("sc->sc_wire == 0x%02x wrong for umass_bbb_reset\n",
+ sc->sc_wire));
if (sc->sc_dying)
return;
@@ -1462,31 +821,32 @@ umass_bbb_reset(struct umass_softc *sc, int status)
sc->transfer_state = TSTATE_BBB_RESET1;
sc->transfer_status = status;
- usbd_interface2device_handle(sc->iface, &dev);
-
/* reset is a class specific interface write */
- sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE;
- sc->request.bRequest = UR_BBB_RESET;
- USETW(sc->request.wValue, 0);
- USETW(sc->request.wIndex, sc->ifaceno);
- USETW(sc->request.wLength, 0);
- umass_setup_ctrl_transfer(sc, dev, &sc->request, NULL, 0, 0,
+ sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+ sc->sc_req.bRequest = UR_BBB_RESET;
+ USETW(sc->sc_req.wValue, 0);
+ USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
+ USETW(sc->sc_req.wLength, 0);
+ umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0,
sc->transfer_xfer[XFER_BBB_RESET1]);
}
Static void
umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
- void *data, int datalen, int dir,
- transfer_cb_f cb, void *priv)
+ void *data, int datalen, int dir, u_int timeout,
+ umass_callback cb, void *priv)
{
static int dCBWtag = 42; /* unique for CBW of transfer */
DPRINTF(UDMASS_BBB,("%s: umass_bbb_transfer cmd=0x%02x\n",
USBDEVNAME(sc->sc_dev), *(u_char *)cmd));
- KASSERT(sc->proto & PROTO_BBB,
- ("sc->proto == 0x%02x wrong for umass_bbb_transfer\n",
- sc->proto));
+ KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
+ ("sc->sc_wire == 0x%02x wrong for umass_bbb_transfer\n",
+ sc->sc_wire));
+
+ /* Be a little generous. */
+ sc->timeout = timeout + USBD_DEFAULT_TIMEOUT;
/*
* Do a Bulk-Only transfer with cmdlen bytes from cmd, possibly
@@ -1558,7 +918,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
sc->cbw.bCBWFlags = (dir == DIR_IN? CBWFLAGS_IN:CBWFLAGS_OUT);
sc->cbw.bCBWLUN = lun;
sc->cbw.bCDBLength = cmdlen;
- bcopy(cmd, sc->cbw.CBWCDB, cmdlen);
+ memcpy(sc->cbw.CBWCDB, cmd, cmdlen);
DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw));
@@ -1575,7 +935,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
sc->transfer_state = TSTATE_BBB_COMMAND;
/* Send the CBW from host to device via bulk-out endpoint. */
- if (umass_setup_transfer(sc, sc->bulkout_pipe,
+ if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
&sc->cbw, UMASS_BBB_CBW_SIZE, 0,
sc->transfer_xfer[XFER_BBB_CBW])) {
umass_bbb_reset(sc, STATUS_WIRE_FAILED);
@@ -1590,8 +950,9 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
struct umass_softc *sc = (struct umass_softc *) priv;
usbd_xfer_handle next_xfer;
- KASSERT(sc->proto & PROTO_BBB,
- ("sc->proto == 0x%02x wrong for umass_bbb_state\n",sc->proto));
+ KASSERT(sc->sc_wire & UMASS_WPROTO_BBB,
+ ("sc->sc_wire == 0x%02x wrong for umass_bbb_state\n",
+ sc->sc_wire));
if (sc->sc_dying)
return;
@@ -1630,7 +991,7 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
/* Data transport phase, setup transfer */
sc->transfer_state = TSTATE_BBB_DATA;
if (sc->transfer_dir == DIR_IN) {
- if (umass_setup_transfer(sc, sc->bulkin_pipe,
+ if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN],
sc->data_buffer, sc->transfer_datalen,
USBD_SHORT_XFER_OK | USBD_NO_COPY,
sc->transfer_xfer[XFER_BBB_DATA]))
@@ -1640,7 +1001,7 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
} else if (sc->transfer_dir == DIR_OUT) {
memcpy(sc->data_buffer, sc->transfer_data,
sc->transfer_datalen);
- if (umass_setup_transfer(sc, sc->bulkout_pipe,
+ if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
sc->data_buffer, sc->transfer_datalen,
USBD_NO_COPY,/* fixed length transfer */
sc->transfer_xfer[XFER_BBB_DATA]))
@@ -1662,18 +1023,16 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
&sc->transfer_actlen, NULL);
if (err) {
- DPRINTF(UDMASS_BBB, ("%s: Data-%s %db failed, "
+ DPRINTF(UDMASS_BBB, ("%s: Data-%s %d failed, "
"%s\n", USBDEVNAME(sc->sc_dev),
(sc->transfer_dir == DIR_IN?"in":"out"),
sc->transfer_datalen,usbd_errstr(err)));
if (err == USBD_STALLED) {
+ sc->transfer_state = TSTATE_BBB_DCLEAR;
umass_clear_endpoint_stall(sc,
(sc->transfer_dir == DIR_IN?
- sc->bulkin:sc->bulkout),
- (sc->transfer_dir == DIR_IN?
- sc->bulkin_pipe:sc->bulkout_pipe),
- TSTATE_BBB_DCLEAR,
+ UMASS_BULKIN:UMASS_BULKOUT),
sc->transfer_xfer[XFER_BBB_DCLEAR]);
return;
} else {
@@ -1729,9 +1088,8 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
}
/* Read the Command Status Wrapper via bulk-in endpoint. */
- if (umass_setup_transfer(sc, sc->bulkin_pipe,
- &sc->csw, UMASS_BBB_CSW_SIZE, 0,
- next_xfer)) {
+ if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN],
+ &sc->csw, UMASS_BBB_CSW_SIZE, 0, next_xfer)) {
umass_bbb_reset(sc, STATUS_WIRE_FAILED);
return;
}
@@ -1750,10 +1108,9 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
* retry it, otherwise fail.
*/
if (sc->transfer_state == TSTATE_BBB_STATUS1) {
- umass_clear_endpoint_stall(sc,
- sc->bulkin, sc->bulkin_pipe,
- TSTATE_BBB_SCLEAR,
- sc->transfer_xfer[XFER_BBB_SCLEAR]);
+ sc->transfer_state = TSTATE_BBB_SCLEAR;
+ umass_clear_endpoint_stall(sc, UMASS_BULKIN,
+ sc->transfer_xfer[XFER_BBB_SCLEAR]);
return;
} else {
umass_bbb_reset(sc, STATUS_WIRE_FAILED);
@@ -1763,6 +1120,15 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw));
+ /* Translate weird command-status signatures. */
+ if ((sc->sc_quirks & UMASS_QUIRK_WRONG_CSWSIG) &&
+ UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1)
+ USETDW(sc->csw.dCSWSignature, CSWSIGNATURE);
+
+ /* Translate invalid command-status tags */
+ if (sc->sc_quirks & UMASS_QUIRK_WRONG_CSWTAG)
+ USETDW(sc->csw.dCSWTag, UGETDW(sc->cbw.dCBWTag));
+
/* Check CSW and handle any error */
if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) {
/* Invalid CSW: Wrong signature or wrong tag might
@@ -1807,9 +1173,8 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
panic("%s: transferred %d bytes instead of %d bytes",
USBDEVNAME(sc->sc_dev),
sc->transfer_actlen, sc->transfer_datalen);
- }
#if 0
- else if (sc->transfer_datalen - sc->transfer_actlen
+ } else if (sc->transfer_datalen - sc->transfer_actlen
!= UGETDW(sc->csw.dCSWDataResidue)) {
DPRINTF(UDMASS_BBB, ("%s: actlen=%d != residue=%d\n",
USBDEVNAME(sc->sc_dev),
@@ -1818,10 +1183,8 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
umass_bbb_reset(sc, STATUS_WIRE_FAILED);
return;
-
- }
#endif
- else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) {
+ } else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) {
DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n",
USBDEVNAME(sc->sc_dev),
UGETDW(sc->csw.dCSWDataResidue)));
@@ -1849,8 +1212,8 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
printf("%s: BBB reset failed, %s\n",
USBDEVNAME(sc->sc_dev), usbd_errstr(err));
- umass_clear_endpoint_stall(sc,
- sc->bulkin, sc->bulkin_pipe, TSTATE_BBB_RESET2,
+ sc->transfer_state = TSTATE_BBB_RESET2;
+ umass_clear_endpoint_stall(sc, UMASS_BULKIN,
sc->transfer_xfer[XFER_BBB_RESET2]);
return;
@@ -1860,8 +1223,8 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
USBDEVNAME(sc->sc_dev), usbd_errstr(err));
/* no error recovery, otherwise we end up in a loop */
- umass_clear_endpoint_stall(sc,
- sc->bulkout, sc->bulkout_pipe, TSTATE_BBB_RESET3,
+ sc->transfer_state = TSTATE_BBB_RESET3;
+ umass_clear_endpoint_stall(sc, UMASS_BULKOUT,
sc->transfer_xfer[XFER_BBB_RESET3]);
return;
@@ -1895,19 +1258,16 @@ Static int
umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen,
usbd_xfer_handle xfer)
{
- usbd_device_handle dev;
-
- KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
- ("sc->proto == 0x%02x wrong for umass_cbi_adsc\n",sc->proto));
-
- usbd_interface2device_handle(sc->iface, &dev);
-
- sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE;
- sc->request.bRequest = UR_CBI_ADSC;
- USETW(sc->request.wValue, 0);
- USETW(sc->request.wIndex, sc->ifaceno);
- USETW(sc->request.wLength, buflen);
- return umass_setup_ctrl_transfer(sc, dev, &sc->request, buffer,
+ KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
+ ("sc->sc_wire == 0x%02x wrong for umass_cbi_adsc\n",
+ sc->sc_wire));
+
+ sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+ sc->sc_req.bRequest = UR_CBI_ADSC;
+ USETW(sc->sc_req.wValue, 0);
+ USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
+ USETW(sc->sc_req.wLength, buflen);
+ return umass_setup_ctrl_transfer(sc, &sc->sc_req, buffer,
buflen, 0, xfer);
}
@@ -1918,8 +1278,9 @@ umass_cbi_reset(struct umass_softc *sc, int status)
int i;
# define SEND_DIAGNOSTIC_CMDLEN 12
- KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
- ("sc->proto == 0x%02x wrong for umass_cbi_reset\n",sc->proto));
+ KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
+ ("sc->sc_wire == 0x%02x wrong for umass_cbi_reset\n",
+ sc->sc_wire));
if (sc->sc_dying)
return;
@@ -1965,19 +1326,22 @@ umass_cbi_reset(struct umass_softc *sc, int status)
Static void
umass_cbi_transfer(struct umass_softc *sc, int lun,
- void *cmd, int cmdlen, void *data, int datalen, int dir,
- transfer_cb_f cb, void *priv)
+ void *cmd, int cmdlen, void *data, int datalen, int dir,
+ u_int timeout, umass_callback cb, void *priv)
{
DPRINTF(UDMASS_CBI,("%s: umass_cbi_transfer cmd=0x%02x, len=%d\n",
USBDEVNAME(sc->sc_dev), *(u_char *)cmd, datalen));
- KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
- ("sc->proto == 0x%02x wrong for umass_cbi_transfer\n",
- sc->proto));
+ KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
+ ("sc->sc_wire == 0x%02x wrong for umass_cbi_transfer\n",
+ sc->sc_wire));
if (sc->sc_dying)
return;
+ /* Be a little generous. */
+ sc->timeout = timeout + USBD_DEFAULT_TIMEOUT;
+
/*
* Do a CBI transfer with cmdlen bytes from cmd, possibly
* a data phase of datalen bytes from/to the device and finally a
@@ -2025,8 +1389,9 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
{
struct umass_softc *sc = (struct umass_softc *) priv;
- KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I),
- ("sc->proto == 0x%02x wrong for umass_cbi_state\n", sc->proto));
+ KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I),
+ ("sc->sc_wire == 0x%02x wrong for umass_cbi_state\n",
+ sc->sc_wire));
if (sc->sc_dying)
return;
@@ -2049,10 +1414,10 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
/* Status transport by control pipe (section 2.3.2.1).
* The command contained in the command block failed.
*
- * The control pipe has already been unstalled by the
- * USB stack.
- * Section 2.4.3.1.1 states that the bulk in endpoints
- * should not stalled at this point.
+ * The control pipe has already been unstalled by the
+ * USB stack.
+ * Section 2.4.3.1.1 states that the bulk in endpoints
+ * should not stalled at this point.
*/
sc->transfer_state = TSTATE_IDLE;
@@ -2071,7 +1436,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
sc->transfer_state = TSTATE_CBI_DATA;
if (sc->transfer_dir == DIR_IN) {
- if (umass_setup_transfer(sc, sc->bulkin_pipe,
+ if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN],
sc->transfer_data, sc->transfer_datalen,
USBD_SHORT_XFER_OK | USBD_NO_COPY,
sc->transfer_xfer[XFER_CBI_DATA]))
@@ -2080,17 +1445,17 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
} else if (sc->transfer_dir == DIR_OUT) {
memcpy(sc->data_buffer, sc->transfer_data,
sc->transfer_datalen);
- if (umass_setup_transfer(sc, sc->bulkout_pipe,
+ if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT],
sc->transfer_data, sc->transfer_datalen,
USBD_NO_COPY,/* fixed length transfer */
sc->transfer_xfer[XFER_CBI_DATA]))
umass_cbi_reset(sc, STATUS_WIRE_FAILED);
- } else if (sc->proto & PROTO_CBI_I) {
+ } else if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
USBDEVNAME(sc->sc_dev)));
sc->transfer_state = TSTATE_CBI_STATUS;
- if (umass_setup_transfer(sc, sc->intrin_pipe,
+ if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN],
&sc->sbl, sizeof(sc->sbl),
0, /* fixed length transfer */
sc->transfer_xfer[XFER_CBI_STATUS])){
@@ -2116,15 +1481,14 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
USBDEVNAME(sc->sc_dev), sc->transfer_actlen));
if (err) {
- DPRINTF(UDMASS_CBI, ("%s: Data-%s %db failed, "
+ DPRINTF(UDMASS_CBI, ("%s: Data-%s %d failed, "
"%s\n", USBDEVNAME(sc->sc_dev),
(sc->transfer_dir == DIR_IN?"in":"out"),
sc->transfer_datalen,usbd_errstr(err)));
if (err == USBD_STALLED) {
- umass_clear_endpoint_stall(sc,
- sc->bulkin, sc->bulkin_pipe,
- TSTATE_CBI_DCLEAR,
+ sc->transfer_state = TSTATE_CBI_DCLEAR;
+ umass_clear_endpoint_stall(sc, UMASS_BULKIN,
sc->transfer_xfer[XFER_CBI_DCLEAR]);
} else {
umass_cbi_reset(sc, STATUS_WIRE_FAILED);
@@ -2140,10 +1504,10 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
umass_dump_buffer(sc, sc->transfer_data,
sc->transfer_actlen, 48));
- if (sc->proto & PROTO_CBI_I) {
+ if (sc->sc_wire == UMASS_WPROTO_CBI_I) {
sc->transfer_state = TSTATE_CBI_STATUS;
memset(&sc->sbl, 0, sizeof(sc->sbl));
- if (umass_setup_transfer(sc, sc->intrin_pipe,
+ if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN],
&sc->sbl, sizeof(sc->sbl),
0, /* fixed length transfer */
sc->transfer_xfer[XFER_CBI_STATUS])){
@@ -2168,9 +1532,8 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
*/
if (err == USBD_STALLED) {
- umass_clear_endpoint_stall(sc,
- sc->intrin, sc->intrin_pipe,
- TSTATE_CBI_SCLEAR,
+ sc->transfer_state = TSTATE_CBI_SCLEAR;
+ umass_clear_endpoint_stall(sc, UMASS_INTRIN,
sc->transfer_xfer[XFER_CBI_SCLEAR]);
} else {
umass_cbi_reset(sc, STATUS_WIRE_FAILED);
@@ -2180,7 +1543,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
/* Dissect the information in the buffer */
- if (sc->proto & PROTO_UFI) {
+ if (sc->sc_cmd == UMASS_CPROTO_UFI) {
int status;
/* Section 3.4.3.1.3 specifies that the UFI command
@@ -2256,8 +1619,8 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
printf("%s: CBI reset failed, %s\n",
USBDEVNAME(sc->sc_dev), usbd_errstr(err));
- umass_clear_endpoint_stall(sc,
- sc->bulkin, sc->bulkin_pipe, TSTATE_CBI_RESET2,
+ sc->transfer_state = TSTATE_CBI_RESET2;
+ umass_clear_endpoint_stall(sc, UMASS_BULKIN,
sc->transfer_xfer[XFER_CBI_RESET2]);
return;
@@ -2267,8 +1630,8 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
USBDEVNAME(sc->sc_dev), usbd_errstr(err));
/* no error recovery, otherwise we end up in a loop */
- umass_clear_endpoint_stall(sc,
- sc->bulkout, sc->bulkout_pipe, TSTATE_CBI_RESET3,
+ sc->transfer_state = TSTATE_CBI_RESET3;
+ umass_clear_endpoint_stall(sc, UMASS_BULKOUT,
sc->transfer_xfer[XFER_CBI_RESET3]);
return;
@@ -2298,26 +1661,21 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
usbd_status
umass_bbb_get_max_lun(struct umass_softc *sc, u_int8_t *maxlun)
{
- usbd_device_handle dev;
usb_device_request_t req;
usbd_status err;
- usb_interface_descriptor_t *id;
*maxlun = 0; /* Default to 0. */
DPRINTF(UDMASS_BBB, ("%s: Get Max Lun\n", USBDEVNAME(sc->sc_dev)));
- usbd_interface2device_handle(sc->iface, &dev);
- id = usbd_get_interface_descriptor(sc->iface);
-
/* The Get Max Lun command is a class-specific request. */
req.bmRequestType = UT_READ_CLASS_INTERFACE;
req.bRequest = UR_BBB_GET_MAX_LUN;
USETW(req.wValue, 0);
- USETW(req.wIndex, id->bInterfaceNumber);
+ USETW(req.wIndex, sc->sc_ifaceno);
USETW(req.wLength, 1);
- err = usbd_do_request(dev, &req, maxlun);
+ err = usbd_do_request(sc->sc_udev, &req, maxlun);
switch (err) {
case USBD_NORMAL_COMPLETION:
DPRINTF(UDMASS_BBB, ("%s: Max Lun %d\n",
@@ -2354,706 +1712,6 @@ umass_bbb_get_max_lun(struct umass_softc *sc, u_int8_t *maxlun)
-#if defined(__FreeBSD__)
-/*
- * CAM specific functions (used by SCSI, UFI, 8070)
- */
-
-Static int
-umass_cam_attach_sim()
-{
- struct cam_devq *devq; /* Per device Queue */
-
- /* A HBA is attached to the CAM layer.
- *
- * The CAM layer will then after a while start probing for
- * devices on the bus. The number of devices is limitted to one.
- */
-
- /* SCSI transparent command set */
-
- devq = cam_simq_alloc(1 /*maximum openings*/);
- if (devq == NULL)
- return(ENOMEM);
-
- umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll, DEVNAME,
- NULL /*priv*/, 0 /*unit number*/,
- 1 /*maximum device openings*/,
- 0 /*maximum tagged device openings*/,
- devq);
- if (umass_sim == NULL) {
- cam_simq_free(devq);
- return(ENOMEM);
- }
-
- if(xpt_bus_register(umass_sim, 0) != CAM_SUCCESS)
- return(ENOMEM);
-
- if (xpt_create_path(&umass_path, NULL, cam_sim_path(umass_sim),
- UMASS_SCSIID_HOST, 0)
- != CAM_REQ_CMP)
- return(ENOMEM);
-
- return(0);
-}
-
-#ifdef UMASS_DO_CAM_RESCAN
-/* this function is only used from umass_cam_rescan, so mention
- * prototype down here.
- */
-Static void umass_cam_rescan_callback(struct cam_periph *periph,union ccb *ccb);
-
-Static void
-umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
-{
-#ifdef UMASS_DEBUG
- struct umass_softc *sc = devclass_get_softc(umass_devclass,
- ccb->ccb_h.target_id);
-
- if (ccb->ccb_h.status != CAM_REQ_CMP) {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: Rescan failed, 0x%04x\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccb->ccb_h.status));
- } else {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: Rescan succeeded, freeing resources.\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
- }
-#endif
-
- xpt_free_path(ccb->ccb_h.path);
- free(ccb, M_USBDEV);
-}
-
-Static void
-umass_cam_rescan(struct umass_softc *sc)
-{
- struct cam_path *path;
- union ccb *ccb = malloc(sizeof(union ccb), M_USBDEV, M_WAITOK);
-
- memset(ccb, 0, sizeof(union ccb));
-
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: scanning bus for new device %d\n",
- USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim),
- device_get_unit(sc->sc_dev), 0,
- device_get_unit(sc->sc_dev)));
-
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(umass_sim),
- device_get_unit(sc->sc_dev), 0)
- != CAM_REQ_CMP)
- return;
-
- xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = umass_cam_rescan_callback;
- ccb->crcn.flags = CAM_FLAG_NONE;
- xpt_action(ccb);
-
- /* The scan is in progress now. */
-}
-#endif
-
-Static int
-umass_cam_attach(struct umass_softc *sc)
-{
- /* SIM already attached at module load. The device is a target on the
- * one SIM we registered: target device_get_unit(self).
- */
-
- /* The artificial limit UMASS_SCSIID_MAX is there because CAM expects
- * a limit to the number of targets that are present on a SIM.
- */
- if (device_get_unit(sc->sc_dev) > UMASS_SCSIID_MAX) {
- printf("%s: Increase UMASS_SCSIID_MAX (currently %d) in %s "
- "and try again.\n", USBDEVNAME(sc->sc_dev),
- UMASS_SCSIID_MAX, __FILE__);
- return(1);
- }
-
-#ifdef UMASS_DO_CAM_RESCAN
- if (!cold) {
- /* Notify CAM of the new device. Any failure is benign, as the
- * user can still do it by hand (camcontrol rescan <busno>).
- * Only do this if we are not booting, because CAM does a scan
- * after booting has completed, when interrupts have been
- * enabled.
- */
- umass_cam_rescan(sc);
- }
-#endif
-
- return(0); /* always succesful */
-}
-
-/* umass_cam_detach
- * detach from the CAM layer
- */
-
-Static int
-umass_cam_detach_sim()
-{
- if (umass_sim)
- return(EBUSY); /* XXX CAM can't handle disappearing SIMs yet */
-
- if (umass_path) {
- /* XXX do we need to send an asynchroneous event for the SIM?
- xpt_async(AC_LOST_DEVICE, umass_path, NULL);
- */
- xpt_free_path(umass_path);
- umass_path = NULL;
- }
-
- if (umass_sim) {
- if (xpt_bus_deregister(cam_sim_path(umass_sim)))
- cam_sim_free(umass_sim, /*free_devq*/TRUE);
- else
- return(EBUSY);
-
- umass_sim = NULL;
- }
-
- return(0);
-}
-
-Static int
-umass_cam_detach(struct umass_softc *sc)
-{
- struct cam_path *path;
-
- /* detach of sim not done until module unload */
- DPRINTF(UDMASS_SCSI, ("%s: losing CAM device entry\n",
- USBDEVNAME(sc->sc_dev)));
-
- if (xpt_create_path(&path, NULL, cam_sim_path(umass_sim),
- device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD)
- != CAM_REQ_CMP)
- return(ENOMEM);
- xpt_async(AC_LOST_DEVICE, path, NULL);
- xpt_free_path(path);
-
- return(0);
-}
-
-
-
-/* umass_cam_action
- * CAM requests for action come through here
- */
-
-Static void
-umass_cam_action(struct cam_sim *sim, union ccb *ccb)
-{
- struct umass_softc *sc = devclass_get_softc(umass_devclass,
- ccb->ccb_h.target_id);
-
- /* The softc is still there, but marked as going away. umass_cam_detach
- * has not yet notified CAM of the lost device however.
- */
- if (sc && sc->sc_dying) {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
- "Invalid target (gone)\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccb->ccb_h.func_code));
- ccb->ccb_h.status = CAM_TID_INVALID;
- xpt_done(ccb);
- return;
- }
-
- /* Verify, depending on the operation to perform, that we either got a
- * valid sc, because an existing target was referenced, or otherwise
- * the SIM is addressed.
- *
- * This avoids bombing out at a printf and does give the CAM layer some
- * sensible feedback on errors.
- */
- switch (ccb->ccb_h.func_code) {
- case XPT_SCSI_IO:
- case XPT_RESET_DEV:
- case XPT_GET_TRAN_SETTINGS:
- case XPT_SET_TRAN_SETTINGS:
- case XPT_CALC_GEOMETRY:
- /* the opcodes requiring a target. These should never occur. */
- if (sc == NULL) {
- printf("%s:%d:%d:%d:func_code 0x%04x: "
- "Invalid target\n",
- DEVNAME_SIM, UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccb->ccb_h.func_code);
-
- ccb->ccb_h.status = CAM_TID_INVALID;
- xpt_done(ccb);
- return;
- }
- break;
- case XPT_PATH_INQ:
- case XPT_NOOP:
- /* The opcodes sometimes aimed at a target (sc is valid),
- * sometimes aimed at the SIM (sc is invalid and target is
- * CAM_TARGET_WILDCARD)
- */
- if (sc == NULL && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
- "Invalid target\n",
- DEVNAME_SIM, UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccb->ccb_h.func_code));
-
- ccb->ccb_h.status = CAM_TID_INVALID;
- xpt_done(ccb);
- return;
- }
- break;
- default:
- /* XXX Hm, we should check the input parameters */
- }
-
- /* Perform the requested action */
- switch (ccb->ccb_h.func_code) {
- case XPT_SCSI_IO:
- {
- struct ccb_scsiio *csio = &ccb->csio; /* deref union */
- int dir;
- unsigned char *cmd;
- int cmdlen;
-
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: "
- "cmd: 0x%02x, flags: 0x%02x, "
- "%db cmd/%db data/%db sense\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- csio->cdb_io.cdb_bytes[0],
- ccb->ccb_h.flags & CAM_DIR_MASK,
- csio->cdb_len, csio->dxfer_len,
- csio->sense_len));
-
- /* clear the end of the buffer to make sure we don't send out
- * garbage.
- */
- DIF(UDMASS_SCSI, if ((ccb->ccb_h.flags & CAM_DIR_MASK)
- == CAM_DIR_OUT)
- umass_dump_buffer(sc, csio->data_ptr,
- csio->dxfer_len, 48));
-
- if (sc->transfer_state != TSTATE_IDLE) {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: "
- "I/O requested while busy (state %d, %s)\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- sc->transfer_state,states[sc->transfer_state]));
- ccb->ccb_h.status = CAM_SCSI_BUSY;
- xpt_done(ccb);
- return;
- }
-
- switch(ccb->ccb_h.flags&CAM_DIR_MASK) {
- case CAM_DIR_IN:
- dir = DIR_IN;
- break;
- case CAM_DIR_OUT:
- dir = DIR_OUT;
- break;
- default:
- dir = DIR_NONE;
- }
-
- ccb->ccb_h.status = CAM_REQ_INPROG | CAM_SIM_QUEUED;
- if (sc->transform(sc, csio->cdb_io.cdb_bytes, csio->cdb_len,
- &cmd, &cmdlen)) {
- sc->transfer(sc, ccb->ccb_h.target_lun, cmd, cmdlen,
- csio->data_ptr,
- csio->dxfer_len, dir,
- umass_cam_cb, (void *) ccb);
- } else {
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
- }
-
- break;
- }
- case XPT_PATH_INQ:
- {
- struct ccb_pathinq *cpi = &ccb->cpi;
-
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_PATH_INQ:.\n",
- (sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
- UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
-
- /* host specific information */
- cpi->version_num = 1;
- cpi->hba_inquiry = 0;
- cpi->target_sprt = 0;
- cpi->hba_misc = 0;
- cpi->hba_eng_cnt = 0;
- cpi->max_target = UMASS_SCSIID_MAX; /* one target */
- cpi->max_lun = 0; /* no LUN's supported */
- cpi->initiator_id = UMASS_SCSIID_HOST;
- strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
- strncpy(cpi->hba_vid, "USB SCSI", HBA_IDLEN);
- strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
- cpi->unit_number = cam_sim_unit(sim);
- cpi->bus_id = UMASS_SCSI_BUS;
- if (sc) {
- cpi->base_transfer_speed = sc->transfer_speed;
- cpi->max_lun = sc->maxlun;
- }
-
- cpi->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
- case XPT_RESET_DEV:
- {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_RESET_DEV:.\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
-
- ccb->ccb_h.status = CAM_REQ_INPROG;
- umass_reset(sc, umass_cam_cb, (void *) ccb);
- break;
- }
- case XPT_GET_TRAN_SETTINGS:
- {
- struct ccb_trans_settings *cts = &ccb->cts;
-
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_GET_TRAN_SETTINGS:.\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
-
- cts->valid = 0;
- cts->flags = 0; /* no disconnection, tagging */
-
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
- case XPT_SET_TRAN_SETTINGS:
- {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SET_TRAN_SETTINGS:.\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
-
- ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- xpt_done(ccb);
- break;
- }
- case XPT_CALC_GEOMETRY:
- {
- struct ccb_calc_geometry *ccg = &ccb->ccg;
-
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_CALC_GEOMETRY: "
- "Volume size = %d\n",
- USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccg->volume_size));
-
- /* XXX We should probably ask the drive for the details
- * instead of cluching them up ourselves
- */
- if (sc->drive == ZIP_100) {
- ccg->heads = 64;
- ccg->secs_per_track = 32;
- ccg->cylinders = ccg->volume_size / ccg->heads
- / ccg->secs_per_track;
- ccb->ccb_h.status = CAM_REQ_CMP;
- break;
- } else if (sc->proto & PROTO_UFI) {
- ccg->heads = 2;
- if (ccg->volume_size == 2880)
- ccg->secs_per_track = 18;
- else
- ccg->secs_per_track = 9;
- ccg->cylinders = 80;
- break;
- } else {
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- }
-
- xpt_done(ccb);
- break;
- }
- case XPT_NOOP:
- {
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_NOOP:.\n",
- (sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
- UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
-
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
- default:
- DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
- "Not implemented\n",
- (sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
- UMASS_SCSI_BUS,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccb->ccb_h.func_code));
-
- ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- xpt_done(ccb);
- break;
- }
-}
-
-/* umass_cam_poll
- * all requests are handled through umass_cam_action, requests
- * are never pending. So, nothing to do here.
- */
-Static void
-umass_cam_poll(struct cam_sim *sim)
-{
-#ifdef UMASS_DEBUG
- struct umass_softc *sc = (struct umass_softc *) sim->softc;
-
- DPRINTF(UDMASS_SCSI, ("%s: CAM poll\n",
- USBDEVNAME(sc->sc_dev)));
-#endif
-
- /* nop */
-}
-
-
-/* umass_cam_cb
- * finalise a completed CAM command
- */
-
-Static void
-umass_cam_cb(struct umass_softc *sc, void *priv, int residue, int status)
-{
- union ccb *ccb = (union ccb *) priv;
- struct ccb_scsiio *csio = &ccb->csio; /* deref union */
-
- csio->resid = residue;
-
- switch (status) {
- case STATUS_CMD_OK:
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
-
- case STATUS_CMD_UNKNOWN:
- case STATUS_CMD_FAILED:
- switch (ccb->ccb_h.func_code) {
- case XPT_SCSI_IO:
- {
- unsigned char *cmd;
- int cmdlen;
-
- /* fetch sense data */
- DPRINTF(UDMASS_SCSI,("%s: Fetching %db sense data\n",
- USBDEVNAME(sc->sc_dev),
- sc->cam_scsi_sense.length));
-
- sc->cam_scsi_sense.length = csio->sense_len;
-
- if (sc->transform(sc, (char *) &sc->cam_scsi_sense,
- sizeof(sc->cam_scsi_sense),
- &cmd, &cmdlen)) {
- sc->transfer(sc, ccb->ccb_h.target_lun,
- cmd, cmdlen,
- &csio->sense_data,
- csio->sense_len, DIR_IN,
- umass_cam_sense_cb, (void *) ccb);
- } else {
-#ifdef UMASS_DEBUG
- panic("transform(REQUEST_SENSE) failed");
-#else
- csio->resid = sc->transfer_datalen;
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- xpt_done(ccb);
-#endif
- }
- break;
- }
- case XPT_RESET_DEV: /* Reset failed */
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- xpt_done(ccb);
- break;
- default:
- panic("umass_cam_cb called for func_code %d",
- ccb->ccb_h.func_code);
- }
- break;
-
- case STATUS_WIRE_FAILED:
- /* the wire protocol failed and will have recovered
- * (hopefully). We return an error to CAM and let CAM retry
- * the command if necessary.
- */
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- xpt_done(ccb);
- break;
-
- default:
- panic("%s: Unknown status %d in umass_cam_cb",
- USBDEVNAME(sc->sc_dev), status);
- }
-}
-
-/* Finalise a completed autosense operation
- */
-Static void
-umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status)
-{
- union ccb *ccb = (union ccb *) priv;
- struct ccb_scsiio *csio = &ccb->csio; /* deref union */
-
- switch (status) {
- case STATUS_CMD_OK:
- case STATUS_CMD_UNKNOWN:
- /* Getting sense data succeeded. The length of the sense data
- * is not returned in any way. The sense data itself contains
- * the length of the sense data that is valid.
- */
- if (sc->quirks & RS_NO_CLEAR_UA
- && csio->cdb_io.cdb_bytes[0] == INQUIRY
- && (csio->sense_data.flags & SSD_KEY)
- == SSD_KEY_UNIT_ATTENTION) {
- /* Ignore unit attention errors in the case where
- * the Unit Attention state is not cleared on
- * REQUEST SENSE. They will appear again at the next
- * command.
- */
- ccb->ccb_h.status = CAM_REQ_CMP;
- } else if ((csio->sense_data.flags & SSD_KEY)
- == SSD_KEY_NO_SENSE) {
- /* No problem after all (in the case of CBI without
- * CCI)
- */
- ccb->ccb_h.status = CAM_REQ_CMP;
- } else {
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
- csio->scsi_status = SCSI_STATUS_CHECK_COND;
- }
- xpt_done(ccb);
- break;
-
- default:
- DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n",
- USBDEVNAME(sc->sc_dev), status));
- ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
- xpt_done(ccb);
- }
-}
-
-
-Static int
-umass_driver_load(module_t mod, int what, void *arg)
-{
- int err;
-
- switch (what) {
- case MOD_UNLOAD:
- err = umass_cam_detach_sim();
- if (err)
- return(err);
- return(usbd_driver_load(mod, what, arg));
- case MOD_LOAD:
- /* We don't attach to CAM at this point, because it will try
- * and malloc memory for it. This is not possible when the
- * boot loader loads umass as a module before the kernel
- * has been bootstrapped.
- */
- default:
- return(usbd_driver_load(mod, what, arg));
- }
-}
-
-
-
-/* (even the comment is missing) */
-
-DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, umass_driver_load, 0);
-
-
-/*
- * SCSI specific functions
- */
-
-Static int
-umass_scsi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
- unsigned char **rcmd, int *rcmdlen)
-{
- *rcmd = cmd; /* trivial copy */
- *rcmdlen = cmdlen;
-
- switch (cmd[0]) {
- case TEST_UNIT_READY:
- if (sc->quirks & NO_TEST_UNIT_READY) {
- DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY "
- "to START_UNIT\n", USBDEVNAME(sc->sc_dev)));
- cmd[0] = START_STOP_UNIT;
- cmd[4] = SSS_START;
- }
- break;
- }
-
- return 1; /* success */
-}
-
-/*
- * UFI specific functions
- */
-
-Static int
-umass_ufi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
- unsigned char **rcmd, int *rcmdlen)
-{
- *rcmd = cmd;
- /* A UFI command is always 12 bytes in length */
- /* XXX cmd[(cmdlen+1)..12] contains garbage */
- *rcmdlen = 12;
-
- switch (cmd[0]) {
- case TEST_UNIT_READY:
- if (sc->quirks & NO_TEST_UNIT_READY) {
- DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY "
- "to START_UNIT\n", USBDEVNAME(sc->sc_dev)));
- cmd[0] = START_STOP_UNIT;
- cmd[4] = SSS_START;
- }
- return 1;
- case INQUIRY:
- case START_STOP_UNIT:
- case MODE_SENSE:
- case PREVENT_ALLOW:
- case READ_10:
- case READ_12:
- case READ_CAPACITY:
- case REQUEST_SENSE:
- case REZERO_UNIT:
- case POSITION_TO_ELEMENT: /* SEEK_10 */
- case SEND_DIAGNOSTIC:
- case WRITE_10:
- case WRITE_12:
- /* FORMAT_UNIT */
- /* MODE_SELECT */
- /* READ_FORMAT_CAPACITY */
- /* VERIFY */
- /* WRITE_AND_VERIFY */
- return 1; /* success */
- default:
- return 0; /* success */
- }
-}
-
-/*
- * 8070 specific functions
- */
-Static int
-umass_8070_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
- unsigned char **rcmd, int *rcmdlen)
-{
- return 0; /* failure */
-}
-
-#endif /* __FreeBSD__ */
-
#ifdef UMASS_DEBUG
Static void
@@ -3065,11 +1723,13 @@ umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw)
int tag = UGETDW(cbw->dCBWTag);
int flags = cbw->bCBWFlags;
- DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmd = %db "
- "(0x%02x%02x%02x%02x%02x%02x%s), "
+ DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmdlen=%d "
+ "(0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%s), "
"data = %d bytes, dir = %s\n",
USBDEVNAME(sc->sc_dev), tag, clen,
- c[0], c[1], c[2], c[3], c[4], c[5], (clen > 6? "...":""),
+ c[0], c[1], c[2], c[3], c[4], c[5],
+ c[6], c[7], c[8], c[9],
+ (clen > 10? "...":""),
dlen, (flags == CBWFLAGS_IN? "in":
(flags == CBWFLAGS_OUT? "out":"<invalid>"))));
}
@@ -3119,482 +1779,3 @@ umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, int buflen,
USBDEVNAME(sc->sc_dev), s1, s2, s3));
}
#endif
-
-
-
-
-
-
-
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static int
-umass_scsipi_cmd(xs)
- struct scsipi_xfer *xs;
-{
- struct scsipi_link *sc_link = xs->sc_link;
- struct umass_softc *sc = sc_link->adapter_softc;
- struct scsipi_generic *cmd, trcmd;
- int cmdlen;
- int dir;
-#ifdef UMASS_DEBUG
- microtime(&sc->tv);
-#endif
-
- memset(&trcmd, 0, sizeof(trcmd));
-
-#if defined(__NetBSD__)
- DIF(UDMASS_UPPER, sc_link->flags |= DEBUGLEVEL);
-#endif
-#if defined(__OpenBSD__)
- DIF(UDMASS_UPPER, sc_link->flags |= SCSIDEBUG_LEVEL);
-#endif
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
- DPRINTF(UDMASS_CMD, ("%s: umass_scsi_cmd: %d:%d xs=%p cmd=0x%02x "
- "(quirks=0x%x, poll=%d)\n", USBDEVNAME(sc->sc_dev),
- SCSI_LINK_TARGET(sc_link), SCSI_LINK_LUN(sc_link),
- xs, xs->cmd->opcode, sc_link->quirks,
- xs->xs_control & XS_CTL_POLL));
-#endif
-
-#if defined(USB_DEBUG) && defined(SCSIDEBUG)
- if (umassdebug & UDMASS_SCSI)
- show_scsipi_xs(xs);
- else if (umassdebug & ~UDMASS_CMD)
- show_scsipi_cmd(xs);
-#endif
-
- if (sc->sc_dying) {
- xs->error = XS_DRIVER_STUFFUP;
- goto done;
- }
-
-#ifdef UMASS_DEBUG
-#if defined(__NetBSD__)
- if ((sc_link->type == BUS_ATAPI ?
- sc_link->scsipi_atapi.drive : SCSI_LINK_TARGET(sc_link))
- != UMASS_SCSIID_DEVICE) {
- DPRINTF(UDMASS_SCSI, ("%s: wrong SCSI ID %d\n",
- USBDEVNAME(sc->sc_dev),
- SCSI_LINK_TARGET(sc_link)));
- xs->error = XS_DRIVER_STUFFUP;
- goto done;
- }
-#endif
-#if defined(__OpenBSD__)
- if (sc_link->target != UMASS_SCSIID_DEVICE) {
- DPRINTF(UDMASS_SCSI, ("%s: wrong SCSI ID %d\n",
- USBDEVNAME(sc->sc_dev),
- sc_link->target));
- xs->error = XS_DRIVER_STUFFUP;
- goto done;
- }
-#endif
-#endif
-
- cmd = xs->cmd;
-
- if (xs->cmd->opcode == MODE_SENSE &&
- (sc_link->quirks & SDEV_NOMODESENSE)) {
- /*printf("%s: MODE_SENSE\n", USBDEVNAME(sc->sc_dev));*/
- xs->error = XS_TIMEOUT;
- goto done;
- }
-
- if (xs->cmd->opcode == START_STOP &&
- (sc->quirks & NO_START_STOP)) {
- /*printf("%s: START_STOP\n", USBDEVNAME(sc->sc_dev));*/
- xs->error = XS_NOERROR;
- goto done;
- }
-
- if (xs->cmd->opcode == INQUIRY &&
- (sc->quirks & FORCE_SHORT_INQUIRY)) {
- memcpy(&trcmd, cmd, sizeof trcmd);
- trcmd.bytes[4] = SHORT_INQUIRY_LENGTH;
- cmd = &trcmd;
- }
-
- dir = DIR_NONE;
- if (xs->datalen) {
- switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
- case XS_CTL_DATA_IN:
- dir = DIR_IN;
- break;
- case XS_CTL_DATA_OUT:
- dir = DIR_OUT;
- break;
- }
- }
-
- if (xs->datalen > UMASS_MAX_TRANSFER_SIZE) {
- printf("umass_cmd: large datalen, %d\n", xs->datalen);
- xs->error = XS_DRIVER_STUFFUP;
- goto done;
- }
-
- cmdlen = xs->cmdlen;
- if (sc->proto & PROTO_UFI) {
- if (!umass_ufi_transform(sc, cmd, cmdlen, &trcmd, &cmdlen)) {
- xs->error = XS_DRIVER_STUFFUP;
- goto done;
- }
- cmd= &trcmd;
- }
-
- if (sc->proto & PROTO_ATAPI) {
- bcopy(cmd, &trcmd, cmdlen);
- cmd = &trcmd;
- cmdlen = ATAPI_COMMAND_LENGTH;
- }
-
- if (xs->xs_control & XS_CTL_POLL) {
- /* Use sync transfer. XXX Broken! */
- DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: sync dir=%d\n", dir));
- sc->sc_xfer_flags = USBD_SYNCHRONOUS;
- sc->sc_sync_status = USBD_INVAL;
- sc->transfer(sc, SCSI_LINK_LUN(sc_link), cmd, cmdlen,
- xs->data, xs->datalen, dir, 0, xs);
- sc->sc_xfer_flags = 0;
- DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done err=%d\n",
- sc->sc_sync_status));
- switch (sc->sc_sync_status) {
- case USBD_NORMAL_COMPLETION:
- xs->error = XS_NOERROR;
- break;
- case USBD_TIMEOUT:
- xs->error = XS_TIMEOUT;
- break;
- default:
- xs->error = XS_DRIVER_STUFFUP;
- break;
- }
- goto done;
- } else {
- DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: async dir=%d, cmdlen=%d"
- " datalen=%d\n",
- dir, cmdlen, xs->datalen));
- sc->transfer(sc, SCSI_LINK_LUN(sc_link), cmd, cmdlen,
- xs->data, xs->datalen, dir, umass_scsipi_cb, xs);
- return (SUCCESSFULLY_QUEUED);
- }
-
- /* Return if command finishes early. */
- done:
-#if defined(__NetBSD__)
- xs->xs_status |= XS_STS_DONE;
-#endif
-#if defined(__OpenBSD__)
- xs->flags |= ITSDONE;
-#endif
-
- scsipi_done(xs);
- if (xs->xs_control & XS_CTL_POLL)
- return (COMPLETE);
- else
- return (SUCCESSFULLY_QUEUED);
-}
-
-Static void
-umass_scsipi_minphys(bp)
- struct buf *bp;
-{
- if (bp->b_bcount > UMASS_MAX_TRANSFER_SIZE)
- bp->b_bcount = UMASS_MAX_TRANSFER_SIZE;
- minphys(bp);
-}
-
-int
-umass_scsipi_ioctl(link, cmd, arg, flag, p)
- struct scsipi_link *link;
- u_long cmd;
- caddr_t arg;
- int flag;
- struct proc *p;
-{
- /*struct umass_softc *sc = link->adapter_softc;*/
-
- switch (cmd) {
-#if 0
- case SCBUSIORESET:
- ccb->ccb_h.status = CAM_REQ_INPROG;
- umass_reset(sc, umass_cam_cb, (void *) ccb);
- return (0);
-#endif
- default:
- return (ENOTTY);
- }
-}
-
-Static void
-umass_scsipi_cb(struct umass_softc *sc, void *priv, int residue, int status)
-{
- struct scsipi_xfer *xs = priv;
- struct scsipi_link *sc_link = xs->sc_link;
- int cmdlen;
- int s;
-#ifdef UMASS_DEBUG
- struct timeval tv;
- u_int delta;
- microtime(&tv);
- delta = (tv.tv_sec - sc->tv.tv_sec) * 1000000 + tv.tv_usec - sc->tv.tv_usec;
-#endif
-
- DPRINTF(UDMASS_CMD,("umass_scsipi_cb: at %lu.%06lu, delta=%u: xs=%p residue=%d"
- " status=%d\n", tv.tv_sec, tv.tv_usec, delta, xs, residue, status));
- xs->resid = residue;
-
- switch (status) {
- case STATUS_CMD_OK:
- xs->error = XS_NOERROR;
- break;
-
- case STATUS_CMD_UNKNOWN:
- case STATUS_CMD_FAILED:
- /* fetch sense data */
- memset(&sc->sc_sense_cmd, 0, sizeof(sc->sc_sense_cmd));
- sc->sc_sense_cmd.opcode = REQUEST_SENSE;
- sc->sc_sense_cmd.byte2 = SCSI_LINK_LUN(sc_link) <<
- SCSI_CMD_LUN_SHIFT;
- sc->sc_sense_cmd.length = sizeof(xs->sense);
-
- cmdlen = sizeof(sc->sc_sense_cmd);
- if (sc->proto & PROTO_UFI)
- cmdlen = UFI_COMMAND_LENGTH;
- else if (sc->proto & PROTO_ATAPI)
- cmdlen = ATAPI_COMMAND_LENGTH;
-
- sc->transfer(sc, SCSI_LINK_LUN(sc_link),
- &sc->sc_sense_cmd, cmdlen,
- &xs->sense, sizeof(xs->sense), DIR_IN,
- umass_scsipi_sense_cb, xs);
- return;
-
- case STATUS_WIRE_FAILED:
- xs->error = XS_RESET;
- break;
-
- default:
- panic("%s: Unknown status %d in umass_scsipi_cb",
- USBDEVNAME(sc->sc_dev), status);
- }
-
-#if defined(__NetBSD__)
- xs->xs_status |= XS_STS_DONE;
-#endif
-#if defined(__OpenBSD__)
- xs->flags |= ITSDONE;
-#endif
-
- DPRINTF(UDMASS_CMD,("umass_scsipi_cb: at %lu.%06lu: return xs->error="
- "%d, xs->xs_status=0x%x xs->resid=%d\n",
- tv.tv_sec, tv.tv_usec,
- xs->error, xs->xs_status, xs->resid));
-
- s = splbio();
- scsipi_done(xs);
- splx(s);
-}
-
-/*
- * Finalise a completed autosense operation
- */
-Static void
-umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, int residue,
- int status)
-{
- struct scsipi_xfer *xs = priv;
- int s;
- int bytes_received;
-
- DPRINTF(UDMASS_CMD,("umass_scsipi_sense_cb: xs=%p residue=%d "
- "status=%d\n", xs, residue, status));
-
- switch (status) {
- case STATUS_CMD_OK:
- case STATUS_CMD_UNKNOWN:
- /* getting sense data succeeded */
- if ((xs->cmd->opcode == INQUIRY)
- && (xs->resid < xs->datalen)) {
- /* Some drivers return SENSE errors even after INQUIRY
- * The upper layer doesn't like that.
- */
- xs->error = XS_NOERROR;
- break;
- }
-
- bytes_received = sizeof(xs->sense) - residue;
-
- if (bytes_received < 8 ||
- (bytes_received < xs->sense.extra_len + 8))
- xs->error = XS_SHORTSENSE;
- else
- xs->error = XS_SENSE;
-
-#if defined(__OpenBSD__)
- /* Note that this test may need to be revised
- with QIC-157a/SCSI tape drives that return
- ILI, EOM in the high bits of flags.
- */
- if ((xs->sense.error_code & SSD_ERRCODE) == 0x70 &&
- (xs->sense.flags == 0))
- xs->error = XS_NOERROR;
-#endif
-
- break;
- default:
- DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n",
- USBDEVNAME(sc->sc_dev), status));
- xs->error = XS_DRIVER_STUFFUP;
- break;
- }
-
-#if defined(__NetBSD__)
- xs->xs_status |= XS_STS_DONE;
-#endif
-#if defined(__OpenBSD__)
- xs->flags |= ITSDONE;
-#endif
-
- DPRINTF(UDMASS_CMD,("umass_scsipi_sense_cb: return xs->error=%d, "
- "xs->xs_status=0x%x xs->resid=%d\n", xs->error, xs->xs_status,
- xs->resid));
-
- s = splbio();
- scsipi_done(xs);
- splx(s);
-}
-
-/*
- * UFI specific functions
- */
-
-Static int
-umass_ufi_transform(struct umass_softc *sc, struct scsipi_generic *cmd,
- int cmdlen, struct scsipi_generic *rcmd, int *rcmdlen)
-{
- *rcmdlen = UFI_COMMAND_LENGTH;
- memset(rcmd, 0, sizeof *rcmd);
-
- /* Handle any quirks */
- if (cmd->opcode == TEST_UNIT_READY
- && (sc->quirks & NO_TEST_UNIT_READY)) {
- /*
- * Some devices do not support this command.
- * Start Stop Unit should give the same results
- */
- DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY "
- "to START_UNIT\n", USBDEVNAME(sc->sc_dev)));
- rcmd->opcode = START_STOP;
- rcmd->bytes[3] = SSS_START;
- return 1;
- }
-
- switch (cmd->opcode) {
- /* Commands of which the format has been verified. They should work. */
- case TEST_UNIT_READY:
- case REZERO_UNIT:
- case REQUEST_SENSE:
- case INQUIRY:
- case START_STOP:
- /*case SEND_DIAGNOSTIC: ??*/
- case PREVENT_ALLOW:
- case READ_CAPACITY:
- case READ_BIG:
- case WRITE_BIG:
- case POSITION_TO_ELEMENT: /* SEEK_10 */
- case MODE_SELECT_BIG:
- case MODE_SENSE_BIG:
- default:
- /* Copy the command into the (zeroed out) destination buffer */
- memcpy(rcmd, cmd, cmdlen);
- return (1); /* success */
-
- /*
- * Other UFI commands: FORMAT_UNIT, MODE_SELECT, READ_FORMAT_CAPACITY,
- * VERIFY, WRITE_AND_VERIFY.
- * These should be checked whether they somehow can be made to fit.
- */
-
- /* These commands are known _not_ to work. They should be converted. */
- case READ_COMMAND:
- case WRITE_COMMAND:
- case MODE_SENSE:
- case MODE_SELECT:
- printf("%s: Unsupported UFI command 0x%02x",
- USBDEVNAME(sc->sc_dev), cmd->opcode);
- if (cmdlen == 6)
- printf(", 6 byte command should have been converted");
- printf("\n");
- return (0); /* failure */
- }
-}
-
-
-#if NATAPIBUS > 0
-Static void
-umass_atapi_probedev(atapi, target)
- struct atapibus_softc *atapi;
- int target;
-{
- struct scsipi_link *sc_link;
- struct scsipibus_attach_args sa;
- struct ata_drive_datas *drvp = &atapi->sc_drvs[target];
- char vendor[33], product[65], revision[17];
- struct scsipi_inquiry_data inqbuf;
-
- DPRINTF(UDMASS_SCSI,("umass_atapi_probedev: atapi=%p target=%d\n",
- atapi, target));
-
- if (atapi->sc_link[target])
- return;
-
- sc_link = malloc(sizeof(*sc_link), M_DEVBUF, M_NOWAIT);
- if (sc_link == NULL) {
- printf("%s: can't allocate link for drive %d\n",
- atapi->sc_dev.dv_xname, target);
- return;
- }
- *sc_link = *atapi->adapter_link;
-
- DIF(UDMASS_UPPER, sc_link->flags |= DEBUGLEVEL);
-
- /* Fill generic parts of the link. */
- sc_link->active = 0;
- sc_link->scsipi_atapi.drive = target;
- sc_link->device = &umass_dev;
- TAILQ_INIT(&sc_link->pending_xfers);
-
- DPRINTF(UDMASS_SCSI, ("umass_atapi_probedev: doing inquiry\n"));
- /* Now go ask the device all about itself. */
- memset(&inqbuf, 0, sizeof(inqbuf));
- if (scsipi_inquire(sc_link, &inqbuf, XS_CTL_DISCOVERY) != 0)
- goto bad;
-
- scsipi_strvis(vendor, 33, inqbuf.vendor, 8);
- scsipi_strvis(product, 65, inqbuf.product, 16);
- scsipi_strvis(revision, 17, inqbuf.revision, 4);
-
- sa.sa_sc_link = sc_link;
- sa.sa_inqbuf.type = inqbuf.device;
- sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ?
- T_REMOV : T_FIXED;
- if (sa.sa_inqbuf.removable)
- sc_link->flags |= SDEV_REMOVABLE;
- /* XXX how? sc_link->scsipi_atapi.cap |= ACAP_LEN;*/
- sa.sa_inqbuf.vendor = vendor;
- sa.sa_inqbuf.product = product;
- sa.sa_inqbuf.revision = revision;
- sa.sa_inqptr = NULL;
-
- drvp->drv_softc = atapi_probedev(atapi, target, sc_link, &sa);
- /* atapi_probedev() frees the scsipi_link when there is no device. */
- return;
-
-bad:
- free(sc_link, M_DEVBUF);
- return;
-}
-#endif
-#endif
diff --git a/sys/dev/usb/umass_quirks.c b/sys/dev/usb/umass_quirks.c
new file mode 100644
index 00000000000..95f07084eda
--- /dev/null
+++ b/sys/dev/usb/umass_quirks.c
@@ -0,0 +1,484 @@
+/* $OpenBSD: umass_quirks.c,v 1.3 2003/05/17 06:07:57 nate Exp $ */
+/* $NetBSD: umass_quirks.c,v 1.39 2003/05/08 15:19:47 augustss Exp $ */
+
+/*
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by MAEKAWA Masahide (gehenna@NetBSD.org).
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+
+#if defined(__NetBSD__)
+#include <dev/scsipi/scsipi_all.h> /* for scsiconf.h below */
+#include <dev/scsipi/scsiconf.h> /* for quirks defines */
+#elif defined(__OpenBSD__)
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#endif
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdevs.h>
+
+#include <dev/usb/umassvar.h>
+#include <dev/usb/umass_quirks.h>
+
+Static usbd_status umass_init_insystem(struct umass_softc *);
+Static usbd_status umass_init_shuttle(struct umass_softc *);
+
+Static void umass_fixup_sony(struct umass_softc *);
+Static void umass_fixup_yedata(struct umass_softc *);
+
+Static const struct umass_quirk umass_quirks[] = {
+ { { USB_VENDOR_ATI, USB_PRODUCT_ATI2_205 },
+ UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA,
+ 0,
+ 0,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_DMI, USB_PRODUCT_DMI_SA2_0 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_EASYDISK, USB_PRODUCT_EASYDISK_EASYDISK },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_NO_START_STOP,
+ PQUIRK_NOTUR | PQUIRK_NOSENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_FORCE_SHORT_INQUIRY | UMASS_QUIRK_NO_START_STOP,
+ PQUIRK_NOMODESENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_HP, USB_PRODUCT_HP_CDWRITERPLUS },
+ UMASS_WPROTO_CBI, UMASS_CPROTO_ATAPI,
+ 0,
+ PQUIRK_NOSENSE | PQUIRK_NOMODESENSE,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ADAPTERV2 },
+ UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA,
+ 0,
+ 0,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ATAPI },
+ UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA,
+ 0,
+ 0,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_DRIVEV2_5 },
+ UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA,
+ 0,
+ 0,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_IDEUSB2 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE },
+ UMASS_WPROTO_CBI, UMASS_CPROTO_ATAPI,
+ UMASS_QUIRK_NO_START_STOP,
+ PQUIRK_NOTUR,
+ UMATCH_VENDOR_PRODUCT,
+ umass_init_insystem, NULL
+ },
+
+ { { USB_VENDOR_IODATA2, USB_PRODUCT_IODATA2_USB2SC },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ 0,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOTUR,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP250 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOTUR,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_DUBPXXG },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_FORCE_SHORT_INQUIRY | UMASS_QUIRK_NO_START_STOP,
+ PQUIRK_NOMODESENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM },
+ UMASS_WPROTO_CBI, UMASS_CPROTO_ATAPI,
+ 0,
+ PQUIRK_NOTUR,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_S304 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_NO_MAX_LUN | UMASS_QUIRK_NO_START_STOP,
+ 0,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_X },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_NO_MAX_LUN | UMASS_QUIRK_NO_START_STOP,
+ 0,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_NO_MAX_LUN,
+ PQUIRK_NOMODESENSE | PQUIRK_NODOORLOCK | PQUIRK_NOBIGMODESENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY2 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_NO_MAX_LUN,
+ PQUIRK_NOMODESENSE | PQUIRK_NODOORLOCK | PQUIRK_NOBIGMODESENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND3050 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE | PQUIRK_FORCELUNS,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND5010 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE | PQUIRK_FORCELUNS,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_WRONG_CSWSIG,
+ 0,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C700 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_ONLYBIG | SDEV_NOSYNCCACHE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MD1II },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_NO_MAX_LUN | UMASS_QUIRK_NO_START_STOP,
+ PQUIRK_NOMODESENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MD2 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_OTI, USB_PRODUCT_OTI_SOLID },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE | PQUIRK_NOBIGMODESENSE,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_PEN, USB_PRODUCT_PEN_MOBILEDRIVE },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE | PQUIRK_NODOORLOCK | PQUIRK_FORCELUNS,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_PEN, USB_PRODUCT_PEN_USBDISK },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_NO_MAX_LUN | UMASS_QUIRK_NO_START_STOP,
+ 0,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_PEN, USB_PRODUCT_PEN_USBREADER },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_PILOTECH, USB_PRODUCT_PILOTECH_CRW600 },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE | PQUIRK_FORCELUNS,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_PQI, USB_PRODUCT_PQI_TRAVELFLASH },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE | PQUIRK_NODOORLOCK,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UFI,
+ UMASS_QUIRK_WRONG_CSWTAG,
+ 0,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB },
+ UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI,
+ UMASS_QUIRK_NO_START_STOP,
+ PQUIRK_NOTUR,
+ UMATCH_VENDOR_PRODUCT,
+ umass_init_shuttle, NULL
+ },
+
+ { { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_ZIOMMC },
+ UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI,
+ UMASS_QUIRK_NO_START_STOP,
+ PQUIRK_NOTUR,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_SIIG, USB_PRODUCT_SIIG_MULTICARDREADER },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ UMASS_QUIRK_NO_START_STOP,
+ 0,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL,NULL
+ },
+
+ { { USB_VENDOR_SONY, USB_PRODUCT_SONY_DRIVEV2 },
+ UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA,
+ 0,
+ 0,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ 0,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, umass_fixup_sony
+ },
+
+ { { USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC },
+ UMASS_WPROTO_CBI, UMASS_CPROTO_UFI,
+ UMASS_QUIRK_FORCE_SHORT_INQUIRY | UMASS_QUIRK_RS_NO_CLEAR_UA,
+ PQUIRK_NOMODESENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_TEAC, USB_PRODUCT_TEAC_FD05PUB },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC,
+ 0,
+ PQUIRK_NOMODESENSE,
+ UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_XXX1100 },
+ UMASS_WPROTO_CBI, UMASS_CPROTO_ATAPI,
+ 0,
+ 0,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO },
+ UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI,
+ UMASS_QUIRK_FORCE_SHORT_INQUIRY,
+ 0,
+ UMATCH_VENDOR_PRODUCT,
+ NULL, NULL
+ },
+
+ { { USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU },
+ UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UFI,
+ UMASS_QUIRK_RS_NO_CLEAR_UA,
+ PQUIRK_NOMODESENSE,
+ UMATCH_VENDOR_PRODUCT_REV,
+ NULL, umass_fixup_yedata
+ },
+
+};
+
+const struct umass_quirk *
+umass_lookup(u_int16_t vendor, u_int16_t product)
+{
+ return ((const struct umass_quirk *)
+ usb_lookup(umass_quirks, vendor, product));
+}
+
+Static usbd_status
+umass_init_insystem(struct umass_softc *sc)
+{
+ usbd_status err;
+
+ err = usbd_set_interface(sc->sc_iface, 1);
+ if (err) {
+ DPRINTF(UDMASS_USB,
+ ("%s: could not switch to Alt Interface 1\n",
+ USBDEVNAME(sc->sc_dev)));
+ return (err);
+ }
+
+ return (USBD_NORMAL_COMPLETION);
+}
+
+Static usbd_status
+umass_init_shuttle(struct umass_softc *sc)
+{
+ usb_device_request_t req;
+ u_int8_t status[2];
+
+ /* The Linux driver does this */
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = 1;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, sc->sc_ifaceno);
+ USETW(req.wLength, sizeof(status));
+
+ return (usbd_do_request(sc->sc_udev, &req, &status));
+}
+
+Static void
+umass_fixup_sony(struct umass_softc *sc)
+{
+ usb_interface_descriptor_t *id;
+
+ id = usbd_get_interface_descriptor(sc->sc_iface);
+ if (id->bInterfaceSubClass == 0xff) {
+ sc->sc_cmd = UMASS_CPROTO_RBC;
+ }
+}
+
+Static void
+umass_fixup_yedata(struct umass_softc *sc)
+{
+ usb_device_descriptor_t *dd;
+
+ dd = usbd_get_device_descriptor(sc->sc_udev);
+
+ /*
+ * Revisions < 1.28 do not handle the interrupt endpoint very well.
+ */
+ if (UGETW(dd->bcdDevice) < 0x128)
+ sc->sc_wire = UMASS_WPROTO_CBI;
+ else
+ sc->sc_wire = UMASS_WPROTO_CBI_I;
+
+ /*
+ * Revisions < 1.28 do not have the TEST UNIT READY command
+ * Revisions == 1.28 have a broken TEST UNIT READY
+ */
+ if (UGETW(dd->bcdDevice) <= 0x128)
+ sc->sc_busquirks |= PQUIRK_NOTUR;
+}
diff --git a/sys/dev/usb/umass_quirks.h b/sys/dev/usb/umass_quirks.h
new file mode 100644
index 00000000000..f8fb586b3c3
--- /dev/null
+++ b/sys/dev/usb/umass_quirks.h
@@ -0,0 +1,62 @@
+/* $OpenBSD: umass_quirks.h,v 1.3 2003/05/17 06:07:57 nate Exp $ */
+/* $NetBSD: umass_quirks.h,v 1.3 2001/12/29 13:46:23 augustss Exp $ */
+
+/*
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by MAEKAWA Masahide (gehenna@NetBSD.org).
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+
+#ifndef _DEV_USB_UMASS_QUIRKS_H_
+#define _DEV_USB_UMASS_QUIRKS_H_
+
+typedef usbd_status (*umass_init_quirk)(struct umass_softc *);
+typedef void (*umass_fixup_quirk)(struct umass_softc *);
+
+struct umass_quirk {
+ struct usb_devno uq_dev;
+
+ u_int8_t uq_wire;
+ u_int8_t uq_cmd;
+ u_int32_t uq_flags;
+ u_int32_t uq_busquirks;
+ int uq_match;
+
+ umass_init_quirk uq_init;
+ umass_fixup_quirk uq_fixup;
+};
+
+const struct umass_quirk *umass_lookup(u_int16_t, u_int16_t);
+
+#endif /* _DEV_USB_UMASS_QUIRKS_H_ */
diff --git a/sys/dev/usb/umass_scsi.c b/sys/dev/usb/umass_scsi.c
new file mode 100644
index 00000000000..0c7f4b91f5c
--- /dev/null
+++ b/sys/dev/usb/umass_scsi.c
@@ -0,0 +1,464 @@
+/* $OpenBSD: umass_scsi.c,v 1.3 2003/05/17 06:07:57 nate Exp $ */
+/* $NetBSD: umass_scsipi.c,v 1.9 2003/02/16 23:14:08 augustss Exp $ */
+/*
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include "atapiscsi.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/malloc.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdevs.h>
+
+#include <dev/usb/umassvar.h>
+#include <dev/usb/umass_scsi.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_disk.h>
+#include <machine/bus.h>
+
+struct umass_scsi_softc {
+ struct umassbus_softc base;
+ struct scsi_link sc_link;
+ struct scsi_adapter sc_adapter;
+
+ usbd_status sc_sync_status;
+ struct scsi_sense sc_sense_cmd;
+};
+
+
+#define SHORT_INQUIRY_LENGTH 36 /* XXX */
+
+#define UMASS_SCSIID_HOST 0x00
+#define UMASS_SCSIID_DEVICE 0x01
+
+#define UMASS_ATAPI_DRIVE 0
+
+int umass_scsi_cmd(struct scsi_xfer *);
+void umass_scsi_minphys(struct buf *);
+
+void umass_scsi_cb(struct umass_softc *sc, void *priv, int residue,
+ int status);
+void umass_scsi_sense_cb(struct umass_softc *sc, void *priv, int residue,
+ int status);
+struct umass_scsi_softc *umass_scsi_setup(struct umass_softc *);
+
+struct scsi_device umass_scsi_dev = { NULL, NULL, NULL, NULL, };
+
+#if NATAPISCSI > 0
+struct scsi_device umass_atapiscsi_dev = { NULL, NULL, NULL, NULL, };
+#endif
+
+int
+umass_scsi_attach(struct umass_softc *sc)
+{
+ struct umass_scsi_softc *scbus;
+
+ scbus = umass_scsi_setup(sc);
+ scbus->sc_link.adapter_target = UMASS_SCSIID_HOST;
+ scbus->sc_link.luns = sc->maxlun + 1;
+ scbus->sc_link.flags &= ~SDEV_ATAPI;
+ scbus->sc_link.device = &umass_scsi_dev;
+
+ DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: SCSI\n"
+ "sc = 0x%x, scbus = 0x%x\n",
+ USBDEVNAME(sc->sc_dev), sc, scbus));
+
+ sc->sc_refcnt++;
+ scbus->base.sc_child =
+ config_found((struct device *)sc, &scbus->sc_link, scsiprint);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+
+ return (0);
+}
+
+#if NATAPISCSI > 0
+int
+umass_atapi_attach(struct umass_softc *sc)
+{
+ struct umass_scsi_softc *scbus;
+
+ scbus = umass_scsi_setup(sc);
+ scbus->sc_link.adapter_target = UMASS_SCSIID_HOST;
+ scbus->sc_link.luns = 1;
+ scbus->sc_link.flags |= SDEV_ATAPI;
+ scbus->sc_link.quirks |= SDEV_NOLUNS;
+ scbus->sc_link.device = &umass_atapiscsi_dev;
+
+ DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: ATAPI\n"
+ "sc = 0x%x, scbus = 0x%x\n",
+ USBDEVNAME(sc->sc_dev), sc, scbus));
+
+ sc->sc_refcnt++;
+ scbus->base.sc_child =
+ config_found((struct device *)sc, &scbus->sc_link, scsiprint);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+
+ return (0);
+}
+#endif
+
+struct umass_scsi_softc *
+umass_scsi_setup(struct umass_softc *sc)
+{
+ struct umass_scsi_softc *scbus;
+
+ scbus = malloc(sizeof(struct umass_scsi_softc), M_DEVBUF, M_WAITOK);
+ memset(&scbus->sc_link, 0, sizeof(struct scsi_link));
+ memset(&scbus->sc_adapter, 0, sizeof(struct scsi_adapter));
+
+ sc->bus = (struct umassbus_softc *)scbus;
+
+ /* Fill in the adapter. */
+ scbus->sc_adapter.scsi_cmd = umass_scsi_cmd;
+ scbus->sc_adapter.scsi_minphys = umass_scsi_minphys;
+
+ /* Fill in the link. */
+ scbus->sc_link.adapter_buswidth = 2;
+ scbus->sc_link.openings = 1;
+ scbus->sc_link.adapter = &scbus->sc_adapter;
+ scbus->sc_link.adapter_softc = sc;
+ scbus->sc_link.openings = 1;
+ scbus->sc_link.quirks |= PQUIRK_ONLYBIG | PQUIRK_NOMODESENSE |
+ sc->sc_busquirks;
+
+ return (scbus);
+}
+
+int
+umass_scsi_cmd(struct scsi_xfer *xs)
+{
+ struct scsi_link *sc_link = xs->sc_link;
+ struct umass_softc *sc = sc_link->adapter_softc;
+ struct umass_scsi_softc *scbus = (struct umass_scsi_softc *)sc->bus;
+
+ struct scsi_generic *cmd, trcmd;
+ int cmdlen, dir, s;
+
+#ifdef UMASS_DEBUG
+ microtime(&sc->tv);
+#endif
+
+ memset(&trcmd, 0, sizeof(trcmd));
+
+ DIF(UDMASS_UPPER, sc_link->flags |= SCSIDEBUG_LEVEL);
+
+ DPRINTF(UDMASS_CMD, ("%s: umass_scsi_cmd: at %lu.%06lu: %d:%d "
+ "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n",
+ USBDEVNAME(sc->sc_dev), sc->tv.tv_sec, sc->tv.tv_usec,
+ sc_link->target, sc_link->lun, xs, xs->cmd->opcode,
+ xs->datalen, sc_link->quirks, xs->flags & SCSI_POLL));
+
+#if defined(USB_DEBUG) && defined(SCSIDEBUG)
+ if (umassdebug & UDMASS_SCSI)
+ show_scsi_xs(xs);
+ else if (umassdebug & ~UDMASS_CMD)
+ show_scsi_cmd(xs);
+#endif
+
+ if (sc->sc_dying) {
+ xs->error = XS_DRIVER_STUFFUP;
+ goto done;
+ }
+
+#if defined(UMASS_DEBUG)
+ if (sc_link->target != UMASS_SCSIID_DEVICE) {
+ DPRINTF(UDMASS_SCSI, ("%s: wrong SCSI ID %d\n",
+ USBDEVNAME(sc->sc_dev), sc_link->target));
+ xs->error = XS_DRIVER_STUFFUP;
+ goto done;
+ }
+#endif
+
+ cmd = xs->cmd;
+ cmdlen = xs->cmdlen;
+
+ if (cmd->opcode == MODE_SENSE &&
+ (sc_link->quirks & SDEV_NOMODESENSE)) {
+ xs->error = XS_TIMEOUT;
+ goto done;
+ }
+
+ if (cmd->opcode == START_STOP &&
+ (sc->sc_quirks & UMASS_QUIRK_NO_START_STOP)) {
+ xs->error = XS_NOERROR;
+ goto done;
+ }
+
+ if (cmd->opcode == INQUIRY &&
+ (sc->sc_quirks & UMASS_QUIRK_FORCE_SHORT_INQUIRY)) {
+ /*
+ * Some drives wedge when asked for full inquiry
+ * information.
+ */
+ memcpy(&trcmd, cmd, sizeof(trcmd));
+ trcmd.bytes[4] = SHORT_INQUIRY_LENGTH;
+ cmd = &trcmd;
+ xs->datalen = SHORT_INQUIRY_LENGTH;
+ }
+
+ dir = DIR_NONE;
+ if (xs->datalen) {
+ switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
+ case SCSI_DATA_IN:
+ dir = DIR_IN;
+ break;
+ case SCSI_DATA_OUT:
+ dir = DIR_OUT;
+ break;
+ }
+ }
+
+ if (xs->datalen > UMASS_MAX_TRANSFER_SIZE) {
+ printf("umass_cmd: large datalen, %d\n", xs->datalen);
+ xs->error = XS_DRIVER_STUFFUP;
+ goto done;
+ }
+
+ if (xs->flags & SCSI_POLL) {
+ /* Use sync transfer. XXX Broken! */
+ DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: sync dir=%d\n", dir));
+ sc->sc_xfer_flags = USBD_SYNCHRONOUS;
+ scbus->sc_sync_status = USBD_INVAL;
+ sc->sc_methods->wire_xfer(sc, sc_link->lun, cmd, cmdlen,
+ xs->data, xs->datalen, dir,
+ xs->timeout, 0, xs);
+ sc->sc_xfer_flags = 0;
+ DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done err=%d\n",
+ scbus->sc_sync_status));
+ switch (scbus->sc_sync_status) {
+ case USBD_NORMAL_COMPLETION:
+ xs->error = XS_NOERROR;
+ break;
+ case USBD_TIMEOUT:
+ xs->error = XS_TIMEOUT;
+ break;
+ default:
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+ }
+ goto done;
+ } else {
+ DPRINTF(UDMASS_SCSI,
+ ("umass_scsi_cmd: async dir=%d, cmdlen=%d"
+ " datalen=%d\n",
+ dir, cmdlen, xs->datalen));
+ sc->sc_methods->wire_xfer(sc, sc_link->lun, cmd, cmdlen,
+ xs->data, xs->datalen, dir,
+ xs->timeout, umass_scsi_cb, xs);
+ return (SUCCESSFULLY_QUEUED);
+ }
+
+ /* Return if command finishes early. */
+ done:
+ xs->flags |= ITSDONE;
+
+ s = splbio();
+ scsi_done(xs);
+ splx(s);
+ if (xs->flags & SCSI_POLL)
+ return (COMPLETE);
+ else
+ return (SUCCESSFULLY_QUEUED);
+}
+
+void
+umass_scsi_minphys(struct buf *bp)
+{
+ if (bp->b_bcount > UMASS_MAX_TRANSFER_SIZE)
+ bp->b_bcount = UMASS_MAX_TRANSFER_SIZE;
+
+ minphys(bp);
+}
+
+void
+umass_scsi_cb(struct umass_softc *sc, void *priv, int residue, int status)
+{
+ struct umass_scsi_softc *scbus = (struct umass_scsi_softc *)sc->bus;
+ struct scsi_xfer *xs = priv;
+ struct scsi_link *link = xs->sc_link;
+ int cmdlen;
+ int s;
+#ifdef UMASS_DEBUG
+ struct timeval tv;
+ u_int delta;
+ microtime(&tv);
+ delta = (tv.tv_sec - sc->tv.tv_sec) * 1000000 +
+ tv.tv_usec - sc->tv.tv_usec;
+#endif
+
+ DPRINTF(UDMASS_CMD,
+ ("umass_scsi_cb: at %lu.%06lu, delta=%u: xs=%p residue=%d"
+ " status=%d\n", tv.tv_sec, tv.tv_usec, delta, xs, residue,
+ status));
+
+ xs->resid = residue;
+
+ switch (status) {
+ case STATUS_CMD_OK:
+ xs->error = XS_NOERROR;
+ break;
+
+ case STATUS_CMD_UNKNOWN:
+ DPRINTF(UDMASS_CMD, ("umass_scsi_cb: status cmd unknown\n"));
+ /* we can't issue REQUEST SENSE */
+ if (xs->sc_link->quirks & PQUIRK_NOSENSE) {
+ /*
+ * If no residue and no other USB error,
+ * command succeeded.
+ */
+ if (residue == 0) {
+ xs->error = XS_NOERROR;
+ break;
+ }
+
+ /*
+ * Some devices return a short INQUIRY
+ * response, omitting response data from the
+ * "vendor specific data" on...
+ */
+ if (xs->cmd->opcode == INQUIRY &&
+ residue < xs->datalen) {
+ xs->error = XS_NOERROR;
+ break;
+ }
+
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+ }
+ /* FALLTHROUGH */
+ case STATUS_CMD_FAILED:
+ printf("umass_scsi_cb: status cmd failed\n");
+ /* fetch sense data */
+ memset(&scbus->sc_sense_cmd, 0, sizeof(scbus->sc_sense_cmd));
+ scbus->sc_sense_cmd.opcode = REQUEST_SENSE;
+ scbus->sc_sense_cmd.byte2 = link->lun << SCSI_CMD_LUN_SHIFT;
+ scbus->sc_sense_cmd.length = sizeof(xs->sense);
+
+ cmdlen = sizeof(scbus->sc_sense_cmd);
+ if (sc->sc_cmd == UMASS_CPROTO_UFI) /* XXX */
+ cmdlen = UFI_COMMAND_LENGTH;
+ sc->sc_methods->wire_xfer(sc, link->lun,
+ &scbus->sc_sense_cmd, cmdlen,
+ &xs->sense, sizeof(xs->sense),
+ DIR_IN, xs->timeout,
+ umass_scsi_sense_cb, xs);
+ return;
+
+ case STATUS_WIRE_FAILED:
+ xs->error = XS_RESET;
+ break;
+
+ default:
+ panic("%s: Unknown status %d in umass_scsi_cb",
+ USBDEVNAME(sc->sc_dev), status);
+ }
+
+ xs->flags |= ITSDONE;
+
+ DPRINTF(UDMASS_CMD,("umass_scsi_cb: at %lu.%06lu: return error=%d, "
+ "status=0x%x resid=%d\n",
+ tv.tv_sec, tv.tv_usec,
+ xs->error, xs->status, xs->resid));
+
+ s = splbio();
+ scsi_done(xs);
+ splx(s);
+}
+
+/*
+ * Finalise a completed autosense operation
+ */
+void
+umass_scsi_sense_cb(struct umass_softc *sc, void *priv, int residue,
+ int status)
+{
+ struct scsi_xfer *xs = priv;
+ int s;
+
+ DPRINTF(UDMASS_CMD,("umass_scsi_sense_cb: xs=%p residue=%d "
+ "status=%d\n", xs, residue, status));
+
+ switch (status) {
+ case STATUS_CMD_OK:
+ case STATUS_CMD_UNKNOWN:
+ /* getting sense data succeeded */
+ if (xs->cmd->opcode == INQUIRY && (xs->resid < xs->datalen ||
+ (sc->sc_quirks & UMASS_QUIRK_RS_NO_CLEAR_UA /* XXX */))) {
+ /*
+ * Some drivers return SENSE errors even after INQUIRY.
+ * The upper layer doesn't like that.
+ */
+ xs->error = XS_NOERROR;
+ break;
+ }
+ /* XXX look at residue */
+ if (residue == 0 || residue == 14)/* XXX */
+ xs->error = XS_SENSE;
+ else
+ xs->error = XS_SHORTSENSE;
+ break;
+ default:
+ DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n",
+ USBDEVNAME(sc->sc_dev), status));
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+ }
+
+ xs->flags |= ITSDONE;
+
+ DPRINTF(UDMASS_CMD,("umass_scsi_sense_cb: return xs->error=%d, "
+ "xs->flags=0x%x xs->resid=%d\n", xs->error, xs->status,
+ xs->resid));
+
+ s = splbio();
+ scsi_done(xs);
+ splx(s);
+}
+
diff --git a/sys/dev/usb/umass_scsi.h b/sys/dev/usb/umass_scsi.h
new file mode 100644
index 00000000000..73961b59454
--- /dev/null
+++ b/sys/dev/usb/umass_scsi.h
@@ -0,0 +1,42 @@
+/* $OpenBSD: umass_scsi.h,v 1.3 2003/05/17 06:07:57 nate Exp $ */
+/* $NetBSD: umass_scsipi.h,v 1.1 2001/12/24 13:25:53 augustss Exp $ */
+
+/*
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+int umass_scsi_attach(struct umass_softc *sc);
+int umass_atapi_attach(struct umass_softc *sc);
diff --git a/sys/dev/usb/umassvar.h b/sys/dev/usb/umassvar.h
new file mode 100644
index 00000000000..e7636bfc4f3
--- /dev/null
+++ b/sys/dev/usb/umassvar.h
@@ -0,0 +1,272 @@
+/* $OpenBSD: umassvar.h,v 1.3 2003/05/17 06:07:57 nate Exp $ */
+/* $NetBSD: umassvar.h,v 1.19 2003/02/22 05:18:50 tsutsui Exp $ */
+/*-
+ * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>,
+ * Nick Hibma <n_hibma@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.13 2000/03/26 01:39:12 n_hibma Exp $
+ */
+
+#ifdef UMASS_DEBUG
+#define DIF(m, x) if (umassdebug & (m)) do { x ; } while (0)
+#define DPRINTF(m, x) if (umassdebug & (m)) logprintf x
+#define UDMASS_UPPER 0x00008000 /* upper layer */
+#define UDMASS_GEN 0x00010000 /* general */
+#define UDMASS_SCSI 0x00020000 /* scsi */
+#define UDMASS_UFI 0x00040000 /* ufi command set */
+#define UDMASS_8070 0x00080000 /* 8070i command set */
+#define UDMASS_USB 0x00100000 /* USB general */
+#define UDMASS_BBB 0x00200000 /* Bulk-Only transfers */
+#define UDMASS_CBI 0x00400000 /* CBI transfers */
+#define UDMASS_ALL 0xffff0000 /* all of the above */
+
+#define UDMASS_XFER 0x40000000 /* all transfers */
+#define UDMASS_CMD 0x80000000
+
+extern int umassdebug;
+#else
+#define DIF(m, x) /* nop */
+#define DPRINTF(m, x) /* nop */
+#endif
+
+/* Generic definitions */
+
+#define UFI_COMMAND_LENGTH 12
+
+/* Direction for umass_*_transfer */
+#define DIR_NONE 0
+#define DIR_IN 1
+#define DIR_OUT 2
+
+/* Endpoints for umass */
+#define UMASS_BULKIN 0
+#define UMASS_BULKOUT 1
+#define UMASS_INTRIN 2
+#define UMASS_NEP 3
+
+/* Bulk-Only features */
+
+#define UR_BBB_RESET 0xff /* Bulk-Only reset */
+#define UR_BBB_GET_MAX_LUN 0xfe
+
+/* 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];
+} umass_bbb_cbw_t;
+#define UMASS_BBB_CBW_SIZE 31
+
+/* Command Status Wrapper */
+typedef struct {
+ uDWord dCSWSignature;
+#define CSWSIGNATURE 0x53425355
+#define CSWSIGNATURE_OLYMPUS_C1 0x55425355
+ uDWord dCSWTag;
+ uDWord dCSWDataResidue;
+ uByte bCSWStatus;
+#define CSWSTATUS_GOOD 0x0
+#define CSWSTATUS_FAILED 0x1
+#define CSWSTATUS_PHASE 0x2
+} umass_bbb_csw_t;
+#define UMASS_BBB_CSW_SIZE 13
+
+/* CBI features */
+
+#define UR_CBI_ADSC 0x00
+
+typedef unsigned char umass_cbi_cbl_t[16]; /* Command block */
+
+typedef union {
+ struct {
+ uByte type;
+#define IDB_TYPE_CCI 0x00
+ uByte 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
+ } common;
+
+ struct {
+ uByte asc;
+ uByte ascq;
+ } ufi;
+} umass_cbi_sbl_t;
+
+struct umass_softc; /* see below */
+
+typedef void (*umass_callback)(struct umass_softc *, void *, int, int);
+#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 void (*umass_wire_xfer)(struct umass_softc *, int, void *, int, void *,
+ int, int, u_int, umass_callback, void *);
+typedef void (*umass_wire_reset)(struct umass_softc *, int);
+typedef void (*umass_wire_state)(usbd_xfer_handle, usbd_private_handle,
+ usbd_status);
+
+struct umass_wire_methods {
+ umass_wire_xfer wire_xfer;
+ umass_wire_reset wire_reset;
+ umass_wire_state wire_state;
+};
+
+struct umassbus_softc {
+ device_ptr_t sc_child; /* child device, for detach */
+};
+
+/* the per device structure */
+struct umass_softc {
+ USBBASEDEVICE sc_dev; /* base device */
+ usbd_device_handle sc_udev; /* device */
+ usbd_interface_handle sc_iface; /* interface */
+ int sc_ifaceno; /* interface number */
+
+ u_int8_t sc_epaddr[UMASS_NEP];
+ usbd_pipe_handle sc_pipe[UMASS_NEP];
+ usb_device_request_t sc_req;
+
+ const struct umass_wire_methods *sc_methods;
+
+ u_int8_t sc_wire; /* wire protocol */
+#define UMASS_WPROTO_UNSPEC 0
+#define UMASS_WPROTO_BBB 1
+#define UMASS_WPROTO_CBI 2
+#define UMASS_WPROTO_CBI_I 3
+
+ u_int8_t sc_cmd; /* command protocol */
+#define UMASS_CPROTO_UNSPEC 0
+#define UMASS_CPROTO_SCSI 1
+#define UMASS_CPROTO_ATAPI 2
+#define UMASS_CPROTO_UFI 3
+#define UMASS_CPROTO_RBC 4
+#define UMASS_CPROTO_ISD_ATA 5
+
+ u_int32_t sc_quirks;
+#define UMASS_QUIRK_RS_NO_CLEAR_UA 0x00000002
+#define UMASS_QUIRK_NO_START_STOP 0x00000004
+#define UMASS_QUIRK_FORCE_SHORT_INQUIRY 0x00000008
+#define UMASS_QUIRK_WRONG_CSWSIG 0x00000010
+#define UMASS_QUIRK_NO_MAX_LUN 0x00000020
+#define UMASS_QUIRK_WRONG_CSWTAG 0x00000040
+
+ u_int32_t sc_busquirks;
+
+ /* 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_cbl_t cbl; /* command block */
+ umass_cbi_sbl_t sbl; /* status block */
+
+ /* xfer handles
+ * Most of our operations are initiated from interrupt context, so
+ * we need to avoid using the one that is in use. We want to avoid
+ * allocating them in the interrupt context as well.
+ */
+ /* indices into array below */
+#define XFER_BBB_CBW 0 /* Bulk-Only */
+#define XFER_BBB_DATA 1
+#define XFER_BBB_DCLEAR 2
+#define XFER_BBB_CSW1 3
+#define XFER_BBB_CSW2 4
+#define XFER_BBB_SCLEAR 5
+#define XFER_BBB_RESET1 6
+#define XFER_BBB_RESET2 7
+#define XFER_BBB_RESET3 8
+
+#define XFER_CBI_CB 0 /* CBI */
+#define XFER_CBI_DATA 1
+#define XFER_CBI_STATUS 2
+#define XFER_CBI_DCLEAR 3
+#define XFER_CBI_SCLEAR 4
+#define XFER_CBI_RESET1 5
+#define XFER_CBI_RESET2 6
+#define XFER_CBI_RESET3 7
+
+#define XFER_NR 9 /* maximum number */
+
+ usbd_xfer_handle transfer_xfer[XFER_NR]; /* for ctrl xfers */
+
+ void *data_buffer;
+
+ int transfer_dir; /* data direction */
+ void *transfer_data; /* data buffer */
+ int transfer_datalen; /* (maximum) length */
+ int transfer_actlen; /* actual length */
+ umass_callback transfer_cb; /* callback */
+ void *transfer_priv; /* for callback */
+ int transfer_status;
+
+ int transfer_state;
+#define TSTATE_IDLE 0
+#define TSTATE_BBB_COMMAND 1 /* CBW transfer */
+#define TSTATE_BBB_DATA 2 /* Data transfer */
+#define TSTATE_BBB_DCLEAR 3 /* clear endpt stall */
+#define TSTATE_BBB_STATUS1 4 /* clear endpt stall */
+#define TSTATE_BBB_SCLEAR 5 /* clear endpt stall */
+#define TSTATE_BBB_STATUS2 6 /* CSW transfer */
+#define TSTATE_BBB_RESET1 7 /* reset command */
+#define TSTATE_BBB_RESET2 8 /* in clear stall */
+#define TSTATE_BBB_RESET3 9 /* out clear stall */
+#define TSTATE_CBI_COMMAND 10 /* command transfer */
+#define TSTATE_CBI_DATA 11 /* data transfer */
+#define TSTATE_CBI_STATUS 12 /* status transfer */
+#define TSTATE_CBI_DCLEAR 13 /* clear ep stall */
+#define TSTATE_CBI_SCLEAR 14 /* clear ep stall */
+#define TSTATE_CBI_RESET1 15 /* reset command */
+#define TSTATE_CBI_RESET2 16 /* in clear stall */
+#define TSTATE_CBI_RESET3 17 /* out clear stall */
+#define TSTATE_STATES 18 /* # of states above */
+
+
+ int timeout; /* in msecs */
+
+ u_int8_t maxlun; /* max lun supported */
+
+#ifdef UMASS_DEBUG
+ struct timeval tv;
+#endif
+
+ int sc_xfer_flags;
+ char sc_dying;
+ int sc_refcnt;
+
+ struct umassbus_softc *bus; /* bus dependent data */
+};
+
+#define UMASS_MAX_TRANSFER_SIZE MAXBSIZE
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index 38764f82edb..79786cc37a1 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb.h,v 1.20 2002/07/25 02:18:11 nate Exp $ */
+/* $OpenBSD: usb.h,v 1.21 2003/05/17 06:07:57 nate Exp $ */
/* $NetBSD: usb.h,v 1.52 2001/07/23 15:17:50 nathanw Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb.h,v 1.14 1999/11/17 22:33:46 n_hibma Exp $ */
@@ -392,8 +392,8 @@ typedef struct {
#define UISUBCLASS_SCSI 6
#define UIPROTO_MASS_CBI_I 0
#define UIPROTO_MASS_CBI 1
-#define UIPROTO_MASS_BBB 2
-#define UIPROTO_MASS_BBB_P 80 /* 'P' for the Iomega Zip drive */
+#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */
+#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */
#define UICLASS_HUB 0x09
#define UISUBCLASS_HUB 0
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
index 4b4d3004cc0..2bdd1ef61e4 100644
--- a/sys/dev/usb/usb_port.h
+++ b/sys/dev/usb/usb_port.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_port.h,v 1.40 2002/07/25 02:18:11 nate Exp $ */
+/* $OpenBSD: usb_port.h,v 1.41 2003/05/17 06:07:57 nate Exp $ */
/* $NetBSD: usb_port.h,v 1.44 2001/05/14 20:35:29 bouyer Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_port.h,v 1.21 1999/11/17 22:33:47 n_hibma Exp $ */
@@ -216,26 +216,21 @@ __CONCAT(dname,_detach)(self, flags) \
#define Static
+#define UMASS_ATAPISTR "atapiscsi"
+
+/* periph_quirks */
+#define PQUIRK_FORCELUNS SDEV_FORCELUNS /* prehistoric device groks
+ LUNs */
+#define PQUIRK_NOMODESENSE SDEV_NOMODESENSE/* device doesn't do MODE SENSE
+ properly */
+#define PQUIRK_NOTUR ADEV_NOTUR /* no TEST UNIT READY */
+#define PQUIRK_NODOORLOCK ADEV_NODOORLOCK /* can't lock door */
+#define PQUIRK_NOSENSE ADEV_NOSENSE /* can't REQUEST SENSE */
+#define PQUIRK_ONLYBIG SDEV_ONLYBIG
+#define PQUIRK_NOBIGMODESENSE 0
+
#define UCOMBUSCF_PORTNO -1
#define UCOMBUSCF_PORTNO_DEFAULT -1
-
-#define SCSI_MODE_SENSE MODE_SENSE
-#define XS_STS_DONE ITSDONE
-#define XS_CTL_POLL SCSI_POLL
-#define XS_CTL_DATA_IN SCSI_DATA_IN
-#define XS_CTL_DATA_OUT SCSI_DATA_OUT
-#define scsipi_adapter scsi_adapter
-#define scsipi_cmd scsi_cmd
-#define scsipi_device scsi_device
-#define scsipi_done scsi_done
-#define scsipi_link scsi_link
-#define scsipi_minphys scsi_minphys
-#define scsipi_sense scsi_sense
-#define scsipi_xfer scsi_xfer
-#define show_scsipi_xs show_scsi_xs
-#define show_scsipi_cmd show_scsi_cmd
-#define xs_control flags
-#define xs_status status
#define UHIDBUSCF_REPORTID -1
#define UHIDBUSCF_REPORTID_DEFAULT -1
diff --git a/sys/dev/usb/usscanner.c b/sys/dev/usb/usscanner.c
index 7479f6c72b6..3ab9f622ebb 100644
--- a/sys/dev/usb/usscanner.c
+++ b/sys/dev/usb/usscanner.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usscanner.c,v 1.7 2003/05/07 04:33:33 deraadt Exp $ */
+/* $OpenBSD: usscanner.c,v 1.8 2003/05/17 06:07:57 nate Exp $ */
/* $NetBSD: usscanner.c,v 1.6 2001/01/23 14:04:14 augustss Exp $ */
/*
@@ -89,6 +89,22 @@ int usscannerdebug = 0;
#define DPRINTFN(n,x)
#endif
+#define XS_CTL_DATA_IN SCSI_DATA_IN
+#define XS_CTL_DATA_OUT SCSI_DATA_OUT
+#define scsipi_adapter scsi_adapter
+#define scsipi_cmd scsi_cmd
+#define scsipi_device scsi_device
+#define scsipi_done scsi_done
+#define scsipi_link scsi_link
+#define scsipi_minphys scsi_minphys
+#define scsipi_sense scsi_sense
+#define scsipi_xfer scsi_xfer
+#define show_scsipi_xs show_scsi_xs
+#define show_scsipi_cmd show_scsi_cmd
+#define xs_control flags
+#define xs_status status
+#define XS_STS_DONE ITSDONE
+#define XS_CTL_POLL SCSI_POLL
#define USSCANNER_CONFIG_NO 1
#define USSCANNER_IFACE_IDX 0