Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
58a5ae6a
Commit
58a5ae6a
authored
May 11, 2002
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
USB storage
sync up with both the -dj and cvs version of the usb-storage code.
parent
ea3aba35
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
825 additions
and
559 deletions
+825
-559
drivers/usb/storage/datafab.c
drivers/usb/storage/datafab.c
+28
-2
drivers/usb/storage/debug.c
drivers/usb/storage/debug.c
+8
-3
drivers/usb/storage/freecom.c
drivers/usb/storage/freecom.c
+1
-1
drivers/usb/storage/isd200.c
drivers/usb/storage/isd200.c
+171
-187
drivers/usb/storage/jumpshot.c
drivers/usb/storage/jumpshot.c
+31
-4
drivers/usb/storage/protocol.c
drivers/usb/storage/protocol.c
+37
-23
drivers/usb/storage/scsiglue.c
drivers/usb/storage/scsiglue.c
+57
-76
drivers/usb/storage/sddr09.c
drivers/usb/storage/sddr09.c
+13
-20
drivers/usb/storage/shuttle_usbat.c
drivers/usb/storage/shuttle_usbat.c
+16
-7
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+366
-215
drivers/usb/storage/transport.h
drivers/usb/storage/transport.h
+3
-2
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_devs.h
+68
-11
drivers/usb/storage/usb.c
drivers/usb/storage/usb.c
+15
-6
drivers/usb/storage/usb.h
drivers/usb/storage/usb.h
+11
-2
No files found.
drivers/usb/storage/datafab.c
View file @
58a5ae6a
/* Driver for Datafab USB Compact Flash reader
/* Driver for Datafab USB Compact Flash reader
*
* $Id: datafab.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
*
*
* datafab driver v0.1:
* datafab driver v0.1:
*
*
...
@@ -6,11 +8,18 @@
...
@@ -6,11 +8,18 @@
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org)
* (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org)
* many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
*
* Many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
* which I used as a template for this driver.
* which I used as a template for this driver.
*
* Some bugfixes and scatter-gather code by Gregory P. Smith
* Some bugfixes and scatter-gather code by Gregory P. Smith
* (greg-usb@electricrain.com)
* (greg-usb@electricrain.com)
*
*
* Fix for media change by Joerg Schneider (js@joergschneider.com)
*
* Other contributors:
* (c) 2002 Alan Stern <stern@rowland.org>
*
* This program is free software; you can redistribute it and/or modify it
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* Free Software Foundation; either version 2, or (at your option) any
...
@@ -102,7 +111,7 @@ static int datafab_raw_bulk(int direction,
...
@@ -102,7 +111,7 @@ static int datafab_raw_bulk(int direction,
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"datafab_raw_bulk: EPIPE. clearing endpoint halt for"
US_DEBUGP
(
"datafab_raw_bulk: EPIPE. clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes
\n
"
,
pipe
,
act_len
);
" pipe 0x%x, stalled at %d bytes
\n
"
,
pipe
,
act_len
);
usb_
clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_
stor_clear_halt
(
us
,
pipe
);
}
}
if
(
result
)
{
if
(
result
)
{
...
@@ -801,6 +810,23 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
...
@@ -801,6 +810,23 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
return
USB_STOR_TRANSPORT_GOOD
;
return
USB_STOR_TRANSPORT_GOOD
;
}
}
if
(
srb
->
cmnd
[
0
]
==
START_STOP
)
{
/* this is used by sd.c'check_scsidisk_media_change to detect
media change */
US_DEBUGP
(
"datafab_transport: START_STOP.
\n
"
);
/* the first datafab_id_device after a media change returns
an error (determined experimentally) */
rc
=
datafab_id_device
(
us
,
info
);
if
(
rc
==
USB_STOR_TRANSPORT_GOOD
)
{
info
->
sense_key
=
NO_SENSE
;
srb
->
result
=
SUCCESS
;
}
else
{
info
->
sense_key
=
UNIT_ATTENTION
;
srb
->
result
=
CHECK_CONDITION
;
}
return
rc
;
}
US_DEBUGP
(
"datafab_transport: Gah! Unknown command: %d (0x%x)
\n
"
,
srb
->
cmnd
[
0
],
srb
->
cmnd
[
0
]);
US_DEBUGP
(
"datafab_transport: Gah! Unknown command: %d (0x%x)
\n
"
,
srb
->
cmnd
[
0
],
srb
->
cmnd
[
0
]);
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_ERROR
;
}
}
drivers/usb/storage/debug.c
View file @
58a5ae6a
/* Driver for USB Mass Storage compliant devices
/* Driver for USB Mass Storage compliant devices
* Debugging Functions Source Code File
* Debugging Functions Source Code File
*
*
* $Id: debug.c,v 1.
5 2001/06/27 23:20:45
mdharm Exp $
* $Id: debug.c,v 1.
9 2002/04/22 03:39:43
mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Developed with the assistance of:
* (c) 2002 Alan Stern <stern@rowland.org>
*
*
* Initial work by:
* Initial work by:
* (c) 1999 Michael Gee (michael@linuxspecific.com)
* (c) 1999 Michael Gee (michael@linuxspecific.com)
...
@@ -302,9 +305,11 @@ void usb_stor_show_sense(
...
@@ -302,9 +305,11 @@ void usb_stor_show_sense(
case
0x1902
:
what
=
"defect list error in primary list"
;
break
;
case
0x1902
:
what
=
"defect list error in primary list"
;
break
;
case
0x1903
:
what
=
"defect list error in grown list"
;
break
;
case
0x1903
:
what
=
"defect list error in grown list"
;
break
;
case
0x1C00
:
what
=
"defect list not found"
;
break
;
case
0x1C00
:
what
=
"defect list not found"
;
break
;
case
0x2000
:
what
=
"invalid command operation code"
;
break
;
case
0x2400
:
what
=
"invalid field in CDB"
;
break
;
case
0x2400
:
what
=
"invalid field in CDB"
;
break
;
case
0x2703
:
what
=
"associated write protect"
;
break
;
case
0x2703
:
what
=
"associated write protect"
;
break
;
case
0x2800
:
what
=
"not ready to ready transition"
;
break
;
case
0x2800
:
what
=
"not ready to ready transition"
;
break
;
case
0x2900
:
what
=
"device reset occurred"
;
break
;
case
0x2903
:
what
=
"bus device reset function occurred"
;
break
;
case
0x2903
:
what
=
"bus device reset function occurred"
;
break
;
case
0x2904
:
what
=
"device internal reset"
;
break
;
case
0x2904
:
what
=
"device internal reset"
;
break
;
case
0x2B00
:
what
=
"copy can't execute / host can't disconnect"
;
break
;
case
0x2B00
:
what
=
"copy can't execute / host can't disconnect"
;
break
;
...
@@ -327,7 +332,7 @@ void usb_stor_show_sense(
...
@@ -327,7 +332,7 @@ void usb_stor_show_sense(
case
0x3502
:
what
=
"enclosure services unavailable"
;
break
;
case
0x3502
:
what
=
"enclosure services unavailable"
;
break
;
case
0x3503
:
what
=
"enclosure services transfer failure"
;
break
;
case
0x3503
:
what
=
"enclosure services transfer failure"
;
break
;
case
0x3504
:
what
=
"enclosure services transfer refused"
;
break
;
case
0x3504
:
what
=
"enclosure services transfer refused"
;
break
;
case
0x3A00
:
what
=
"medi
um
not present"
;
break
;
case
0x3A00
:
what
=
"medi
a
not present"
;
break
;
case
0x3B0F
:
what
=
"end of medium reached"
;
break
;
case
0x3B0F
:
what
=
"end of medium reached"
;
break
;
case
0x3F02
:
what
=
"changed operating definition"
;
break
;
case
0x3F02
:
what
=
"changed operating definition"
;
break
;
case
0x4100
:
what
=
"data path failure (should use 40 NN)"
;
break
;
case
0x4100
:
what
=
"data path failure (should use 40 NN)"
;
break
;
...
...
drivers/usb/storage/freecom.c
View file @
58a5ae6a
/* Driver for Freecom USB/IDE adaptor
/* Driver for Freecom USB/IDE adaptor
*
*
* $Id: freecom.c,v 1.2
1 2001/12/29 03:47:3
3 mdharm Exp $
* $Id: freecom.c,v 1.2
2 2002/04/22 03:39:4
3 mdharm Exp $
*
*
* Freecom v0.1:
* Freecom v0.1:
*
*
...
...
drivers/usb/storage/isd200.c
View file @
58a5ae6a
/* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC
/* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC
*
*
*
First release
*
$Id: isd200.c,v 1.16 2002/04/22 03:39:43 mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance:
* (c) 2000 In-System Design, Inc. (support@in-system.com)
* (C) 2001-2002 Bjrn Stenberg (bjorn@haxx.se)
*
* Developed with the assistance of:
* (C) 2002 Alan Stern <stern@rowland.org>
*
* Initial work:
* (C) 2000 In-System Design, Inc. (support@in-system.com)
*
*
* The ISD200 ASIC does not natively support ATA devices. The chip
* The ISD200 ASIC does not natively support ATA devices. The chip
* does implement an interface, the ATA Command Block (ATACB) which provides
* does implement an interface, the ATA Command Block (ATACB) which provides
...
@@ -27,6 +33,10 @@
...
@@ -27,6 +33,10 @@
*
*
* 2001-02-24: Removed lots of duplicate code and simplified the structure.
* 2001-02-24: Removed lots of duplicate code and simplified the structure.
* (bjorn@haxx.se)
* (bjorn@haxx.se)
* 2002-01-16: Fixed endianness bug so it works on the ppc arch.
* (Luc Saillard <luc@saillard.org>)
* 2002-01-17: All bitfields removed.
* (bjorn@haxx.se)
*/
*/
...
@@ -45,15 +55,6 @@
...
@@ -45,15 +55,6 @@
#include <linux/hdreg.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/ide.h>
/*
* Inquiry defines. Used to interpret data returned from target as result
* of inquiry command.
*
* DeviceType field
*/
#define DIRECT_ACCESS_DEVICE 0x00
/* disks */
/* Timeout defines (in Seconds) */
/* Timeout defines (in Seconds) */
#define ISD200_ENUM_BSY_TIMEOUT 35
#define ISD200_ENUM_BSY_TIMEOUT 35
...
@@ -88,6 +89,19 @@
...
@@ -88,6 +89,19 @@
#define ACTION_SELECT_6 0x40
#define ACTION_SELECT_6 0x40
#define ACTION_SELECT_7 0x80
#define ACTION_SELECT_7 0x80
/* Register Select bits */
#define REG_ALTERNATE_STATUS 0x01
#define REG_DEVICE_CONTROL 0x01
#define REG_ERROR 0x02
#define REG_FEATURES 0x02
#define REG_SECTOR_COUNT 0x04
#define REG_SECTOR_NUMBER 0x08
#define REG_CYLINDER_LOW 0x10
#define REG_CYLINDER_HIGH 0x20
#define REG_DEVICE_HEAD 0x40
#define REG_STATUS 0x80
#define REG_COMMAND 0x80
/* ATA error definitions not in <linux/hdreg.h> */
/* ATA error definitions not in <linux/hdreg.h> */
#define ATA_ERROR_MEDIA_CHANGE 0x20
#define ATA_ERROR_MEDIA_CHANGE 0x20
...
@@ -152,20 +166,8 @@ union ata_cdb {
...
@@ -152,20 +166,8 @@ union ata_cdb {
struct
{
struct
{
unsigned
char
SignatureByte0
;
unsigned
char
SignatureByte0
;
unsigned
char
SignatureByte1
;
unsigned
char
SignatureByte1
;
unsigned
char
ReadRegisterAccessBit
:
1
;
unsigned
char
ActionSelect
;
unsigned
char
NoDeviceSelectionBit
:
1
;
unsigned
char
RegisterSelect
;
unsigned
char
NoBSYPollBit
:
1
;
unsigned
char
IgnorePhaseErrorBit
:
1
;
unsigned
char
IgnoreDeviceErrorBit
:
1
;
unsigned
char
Reserved0Bit
:
3
;
unsigned
char
SelectAlternateStatus
:
1
;
unsigned
char
SelectError
:
1
;
unsigned
char
SelectSectorCount
:
1
;
unsigned
char
SelectSectorNumber
:
1
;
unsigned
char
SelectCylinderLow
:
1
;
unsigned
char
SelectCylinderHigh
:
1
;
unsigned
char
SelectDeviceHead
:
1
;
unsigned
char
SelectStatus
:
1
;
unsigned
char
TransferBlockSize
;
unsigned
char
TransferBlockSize
;
unsigned
char
AlternateStatusByte
;
unsigned
char
AlternateStatusByte
;
unsigned
char
ErrorByte
;
unsigned
char
ErrorByte
;
...
@@ -181,20 +183,8 @@ union ata_cdb {
...
@@ -181,20 +183,8 @@ union ata_cdb {
struct
{
struct
{
unsigned
char
SignatureByte0
;
unsigned
char
SignatureByte0
;
unsigned
char
SignatureByte1
;
unsigned
char
SignatureByte1
;
unsigned
char
ReadRegisterAccessBit
:
1
;
unsigned
char
ActionSelect
;
unsigned
char
NoDeviceSelectionBit
:
1
;
unsigned
char
RegisterSelect
;
unsigned
char
NoBSYPollBit
:
1
;
unsigned
char
IgnorePhaseErrorBit
:
1
;
unsigned
char
IgnoreDeviceErrorBit
:
1
;
unsigned
char
Reserved0Bit
:
3
;
unsigned
char
SelectDeviceControl
:
1
;
unsigned
char
SelectFeatures
:
1
;
unsigned
char
SelectSectorCount
:
1
;
unsigned
char
SelectSectorNumber
:
1
;
unsigned
char
SelectCylinderLow
:
1
;
unsigned
char
SelectCylinderHigh
:
1
;
unsigned
char
SelectDeviceHead
:
1
;
unsigned
char
SelectCommand
:
1
;
unsigned
char
TransferBlockSize
;
unsigned
char
TransferBlockSize
;
unsigned
char
DeviceControlByte
;
unsigned
char
DeviceControlByte
;
unsigned
char
FeaturesByte
;
unsigned
char
FeaturesByte
;
...
@@ -218,27 +208,20 @@ union ata_cdb {
...
@@ -218,27 +208,20 @@ union ata_cdb {
* includes fields through ProductRevisionLevel.
* includes fields through ProductRevisionLevel.
*/
*/
/*
* DeviceType field
*/
#define DIRECT_ACCESS_DEVICE 0x00
/* disks */
#define DEVICE_REMOVABLE 0x80
struct
inquiry_data
{
struct
inquiry_data
{
unsigned
char
DeviceType
:
5
;
unsigned
char
DeviceType
;
unsigned
char
DeviceTypeQualifier
:
3
;
unsigned
char
DeviceTypeModifier
;
unsigned
char
DeviceTypeModifier
:
7
;
unsigned
char
RemovableMedia
:
1
;
unsigned
char
Versions
;
unsigned
char
Versions
;
unsigned
char
ResponseDataFormat
:
4
;
unsigned
char
Format
;
unsigned
char
HiSupport
:
1
;
unsigned
char
NormACA
:
1
;
unsigned
char
ReservedBit
:
1
;
unsigned
char
AERC
:
1
;
unsigned
char
AdditionalLength
;
unsigned
char
AdditionalLength
;
unsigned
char
Reserved
[
2
];
unsigned
char
Reserved
[
2
];
unsigned
char
SoftReset
:
1
;
unsigned
char
Capability
;
unsigned
char
CommandQueue
:
1
;
unsigned
char
Reserved2
:
1
;
unsigned
char
LinkedCommands
:
1
;
unsigned
char
Synchronous
:
1
;
unsigned
char
Wide16Bit
:
1
;
unsigned
char
Wide32Bit
:
1
;
unsigned
char
RelativeAddressing
:
1
;
unsigned
char
VendorId
[
8
];
unsigned
char
VendorId
[
8
];
unsigned
char
ProductId
[
16
];
unsigned
char
ProductId
[
16
];
unsigned
char
ProductRevisionLevel
[
4
];
unsigned
char
ProductRevisionLevel
[
4
];
...
@@ -257,25 +240,30 @@ struct inquiry_data {
...
@@ -257,25 +240,30 @@ struct inquiry_data {
* ISD200 CONFIG data struct
* ISD200 CONFIG data struct
*/
*/
#define ATACFG_TIMING 0x0f
#define ATACFG_ATAPI_RESET 0x10
#define ATACFG_MASTER 0x20
#define ATACFG_BLOCKSIZE 0xa0
#define ATACFGE_LAST_LUN 0x07
#define ATACFGE_DESC_OVERRIDE 0x08
#define ATACFGE_STATE_SUSPEND 0x10
#define ATACFGE_SKIP_BOOT 0x20
#define ATACFGE_CONF_DESC2 0x40
#define ATACFGE_INIT_STATUS 0x80
#define CFG_CAPABILITY_SRST 0x01
struct
isd200_config
{
struct
isd200_config
{
unsigned
char
EventNotification
;
unsigned
char
EventNotification
;
unsigned
char
ExternalClock
;
unsigned
char
ExternalClock
;
unsigned
char
ATAInitTimeout
;
unsigned
char
ATAInitTimeout
;
unsigned
char
ATATiming
:
4
;
unsigned
char
ATAConfig
;
unsigned
char
ATAPIReset
:
1
;
unsigned
char
MasterSlaveSelection
:
1
;
unsigned
char
ATAPICommandBlockSize
:
2
;
unsigned
char
ATAMajorCommand
;
unsigned
char
ATAMajorCommand
;
unsigned
char
ATAMinorCommand
;
unsigned
char
ATAMinorCommand
;
unsigned
char
LastLUNIdentifier
:
3
;
unsigned
char
ATAExtraConfig
;
unsigned
char
DescriptOverride
:
1
;
unsigned
char
Capability
;
unsigned
char
ATA3StateSuspend
:
1
;
}
__attribute__
((
packed
));
unsigned
char
SkipDeviceBoot
:
1
;
unsigned
char
ConfigDescriptor2
:
1
;
unsigned
char
InitStatus
:
1
;
unsigned
char
SRSTEnable
:
1
;
unsigned
char
Reserved0
:
7
;
};
/*
/*
...
@@ -321,15 +309,16 @@ struct read_block_limits {
...
@@ -321,15 +309,16 @@ struct read_block_limits {
* Sense Data Format
* Sense Data Format
*/
*/
#define SENSE_ERRCODE 0x7f
#define SENSE_ERRCODE_VALID 0x80
#define SENSE_FLAG_SENSE_KEY 0x0f
#define SENSE_FLAG_BAD_LENGTH 0x20
#define SENSE_FLAG_END_OF_MEDIA 0x40
#define SENSE_FLAG_FILE_MARK 0x80
struct
sense_data
{
struct
sense_data
{
unsigned
char
ErrorCode
:
7
;
unsigned
char
ErrorCode
;
unsigned
char
Valid
:
1
;
unsigned
char
SegmentNumber
;
unsigned
char
SegmentNumber
;
unsigned
char
Flags
;
unsigned
char
SenseKey
:
4
;
unsigned
char
Reserved
:
1
;
unsigned
char
IncorrectLength
:
1
;
unsigned
char
EndOfMedia
:
1
;
unsigned
char
FileMark
:
1
;
unsigned
char
Information
[
4
];
unsigned
char
Information
[
4
];
unsigned
char
AdditionalSenseLength
;
unsigned
char
AdditionalSenseLength
;
unsigned
char
CommandSpecificInformation
[
4
];
unsigned
char
CommandSpecificInformation
[
4
];
...
@@ -349,7 +338,6 @@ struct sense_data {
...
@@ -349,7 +338,6 @@ struct sense_data {
* Helper routines
* Helper routines
***********************************************************************/
***********************************************************************/
/**************************************************************************
/**************************************************************************
* isd200_build_sense
* isd200_build_sense
*
*
...
@@ -366,38 +354,33 @@ void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb)
...
@@ -366,38 +354,33 @@ void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb)
unsigned
char
error
=
info
->
ATARegs
[
IDE_ERROR_OFFSET
];
unsigned
char
error
=
info
->
ATARegs
[
IDE_ERROR_OFFSET
];
if
(
error
&
ATA_ERROR_MEDIA_CHANGE
)
{
if
(
error
&
ATA_ERROR_MEDIA_CHANGE
)
{
buf
->
ErrorCode
=
0x70
;
buf
->
ErrorCode
=
0x70
|
SENSE_ERRCODE_VALID
;
buf
->
Valid
=
1
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
SenseKey
=
UNIT_ATTENTION
;
buf
->
Flags
=
UNIT_ATTENTION
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
else
if
(
error
&
MCR_ERR
)
{
}
else
if
(
error
&
MCR_ERR
)
{
buf
->
ErrorCode
=
0x70
;
buf
->
ErrorCode
=
0x70
|
SENSE_ERRCODE_VALID
;
buf
->
Valid
=
1
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
SenseKey
=
UNIT_ATTENTION
;
buf
->
Flags
=
UNIT_ATTENTION
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
else
if
(
error
&
TRK0_ERR
)
{
}
else
if
(
error
&
TRK0_ERR
)
{
buf
->
ErrorCode
=
0x70
;
buf
->
ErrorCode
=
0x70
|
SENSE_ERRCODE_VALID
;
buf
->
Valid
=
1
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
SenseKey
=
NOT_READY
;
buf
->
Flags
=
NOT_READY
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
else
if
(
error
&
ECC_ERR
)
{
}
else
if
(
error
&
ECC_ERR
)
{
buf
->
ErrorCode
=
0x70
;
buf
->
ErrorCode
=
0x70
|
SENSE_ERRCODE_VALID
;
buf
->
Valid
=
1
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
SenseKey
=
DATA_PROTECT
;
buf
->
Flags
=
DATA_PROTECT
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
else
{
}
else
{
buf
->
ErrorCode
=
0
;
buf
->
ErrorCode
=
0
;
buf
->
Valid
=
0
;
buf
->
AdditionalSenseLength
=
0
;
buf
->
AdditionalSenseLength
=
0
;
buf
->
SenseKey
=
0
;
buf
->
Flags
=
0
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
}
...
@@ -442,7 +425,7 @@ static int isd200_transfer_partial( struct us_data *us,
...
@@ -442,7 +425,7 @@ static int isd200_transfer_partial( struct us_data *us,
/* if we stall, we need to clear it before we go on */
/* if we stall, we need to clear it before we go on */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_stor_clear_halt
(
us
,
pipe
);
}
}
/* did we send all the data? */
/* did we send all the data? */
...
@@ -524,7 +507,7 @@ static void isd200_transfer( struct us_data *us, Scsi_Cmnd *srb )
...
@@ -524,7 +507,7 @@ static void isd200_transfer( struct us_data *us, Scsi_Cmnd *srb )
}
else
}
else
result
=
isd200_transfer_partial
(
us
,
result
=
isd200_transfer_partial
(
us
,
srb
->
sc_data_direction
,
srb
->
sc_data_direction
,
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
,
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
,
transfer_amount
-
total_transferred
);
transfer_amount
-
total_transferred
);
/* if we get an error, end the loop here */
/* if we get an error, end the loop here */
...
@@ -593,7 +576,7 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
...
@@ -593,7 +576,7 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
US_DEBUGP
(
"Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d
\n
"
,
US_DEBUGP
(
"Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d
\n
"
,
le32_to_cpu
(
bcb
.
Signature
),
bcb
.
Tag
,
le32_to_cpu
(
bcb
.
Signature
),
bcb
.
Tag
,
(
bcb
.
Lun
>>
4
),
(
bcb
.
Lun
&
0xFF
),
(
bcb
.
Lun
>>
4
),
(
bcb
.
Lun
&
0xFF
),
bcb
.
DataTransferLength
,
bcb
.
Flags
,
bcb
.
Length
);
le32_to_cpu
(
bcb
.
DataTransferLength
)
,
bcb
.
Flags
,
bcb
.
Length
);
result
=
usb_stor_bulk_msg
(
us
,
&
bcb
,
pipe
,
US_BULK_CB_WRAP_LEN
,
result
=
usb_stor_bulk_msg
(
us
,
&
bcb
,
pipe
,
US_BULK_CB_WRAP_LEN
,
&
partial
);
&
partial
);
US_DEBUGP
(
"Bulk command transfer result=%d
\n
"
,
result
);
US_DEBUGP
(
"Bulk command transfer result=%d
\n
"
,
result
);
...
@@ -603,7 +586,7 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
...
@@ -603,7 +586,7 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
else
if
(
result
==
-
EPIPE
)
{
else
if
(
result
==
-
EPIPE
)
{
/* if we stall, we need to clear it before we go on */
/* if we stall, we need to clear it before we go on */
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_stor_clear_halt
(
us
,
pipe
);
}
else
if
(
result
)
}
else
if
(
result
)
return
ISD200_TRANSPORT_ERROR
;
return
ISD200_TRANSPORT_ERROR
;
...
@@ -633,7 +616,7 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
...
@@ -633,7 +616,7 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
/* did the attempt to read the CSW fail? */
/* did the attempt to read the CSW fail? */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_stor_clear_halt
(
us
,
pipe
);
/* get the status again */
/* get the status again */
US_DEBUGP
(
"Attempting to get CSW (2nd try)...
\n
"
);
US_DEBUGP
(
"Attempting to get CSW (2nd try)...
\n
"
);
...
@@ -647,7 +630,7 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
...
@@ -647,7 +630,7 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
/* if it fails again, we need a reset and return an error*/
/* if it fails again, we need a reset and return an error*/
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"clearing halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing halt for pipe 0x%x
\n
"
,
pipe
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_stor_clear_halt
(
us
,
pipe
);
return
ISD200_TRANSPORT_ERROR
;
return
ISD200_TRANSPORT_ERROR
;
}
}
}
}
...
@@ -716,10 +699,9 @@ static int isd200_action( struct us_data *us, int action,
...
@@ -716,10 +699,9 @@ static int isd200_action( struct us_data *us, int action,
case
ACTION_READ_STATUS
:
case
ACTION_READ_STATUS
:
US_DEBUGP
(
" isd200_action(READ_STATUS)
\n
"
);
US_DEBUGP
(
" isd200_action(READ_STATUS)
\n
"
);
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_0
|
ACTION_SELECT_2
;
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_0
|
ACTION_SELECT_2
;
ata
.
read
.
SelectStatus
=
1
;
ata
.
generic
.
RegisterSelect
=
ata
.
read
.
SelectError
=
1
;
REG_CYLINDER_LOW
|
REG_CYLINDER_HIGH
|
ata
.
read
.
SelectCylinderHigh
=
1
;
REG_STATUS
|
REG_ERROR
;
ata
.
read
.
SelectCylinderLow
=
1
;
srb
.
sc_data_direction
=
SCSI_DATA_READ
;
srb
.
sc_data_direction
=
SCSI_DATA_READ
;
srb
.
request_buffer
=
pointer
;
srb
.
request_buffer
=
pointer
;
srb
.
request_bufflen
=
value
;
srb
.
request_bufflen
=
value
;
...
@@ -730,7 +712,7 @@ static int isd200_action( struct us_data *us, int action,
...
@@ -730,7 +712,7 @@ static int isd200_action( struct us_data *us, int action,
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_2
|
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_2
|
ACTION_SELECT_3
|
ACTION_SELECT_4
|
ACTION_SELECT_3
|
ACTION_SELECT_4
|
ACTION_SELECT_5
;
ACTION_SELECT_5
;
ata
.
write
.
SelectDeviceHead
=
1
;
ata
.
generic
.
RegisterSelect
=
REG_DEVICE_HEAD
;
ata
.
write
.
DeviceHeadByte
=
value
;
ata
.
write
.
DeviceHeadByte
=
value
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
break
;
break
;
...
@@ -739,7 +721,7 @@ static int isd200_action( struct us_data *us, int action,
...
@@ -739,7 +721,7 @@ static int isd200_action( struct us_data *us, int action,
US_DEBUGP
(
" isd200_action(RESET)
\n
"
);
US_DEBUGP
(
" isd200_action(RESET)
\n
"
);
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_2
|
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_2
|
ACTION_SELECT_3
|
ACTION_SELECT_4
;
ACTION_SELECT_3
|
ACTION_SELECT_4
;
ata
.
write
.
SelectDeviceControl
=
1
;
ata
.
generic
.
RegisterSelect
=
REG_DEVICE_CONTROL
;
ata
.
write
.
DeviceControlByte
=
ATA_DC_RESET_CONTROLLER
;
ata
.
write
.
DeviceControlByte
=
ATA_DC_RESET_CONTROLLER
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
break
;
break
;
...
@@ -748,7 +730,7 @@ static int isd200_action( struct us_data *us, int action,
...
@@ -748,7 +730,7 @@ static int isd200_action( struct us_data *us, int action,
US_DEBUGP
(
" isd200_action(REENABLE)
\n
"
);
US_DEBUGP
(
" isd200_action(REENABLE)
\n
"
);
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_2
|
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_2
|
ACTION_SELECT_3
|
ACTION_SELECT_4
;
ACTION_SELECT_3
|
ACTION_SELECT_4
;
ata
.
write
.
SelectDeviceControl
=
1
;
ata
.
generic
.
RegisterSelect
=
REG_DEVICE_CONTROL
;
ata
.
write
.
DeviceControlByte
=
ATA_DC_REENABLE_CONTROLLER
;
ata
.
write
.
DeviceControlByte
=
ATA_DC_REENABLE_CONTROLLER
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
break
;
break
;
...
@@ -756,16 +738,15 @@ static int isd200_action( struct us_data *us, int action,
...
@@ -756,16 +738,15 @@ static int isd200_action( struct us_data *us, int action,
case
ACTION_SOFT_RESET
:
case
ACTION_SOFT_RESET
:
US_DEBUGP
(
" isd200_action(SOFT_RESET)
\n
"
);
US_DEBUGP
(
" isd200_action(SOFT_RESET)
\n
"
);
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_5
;
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_5
;
ata
.
write
.
SelectDeviceHead
=
1
;
ata
.
generic
.
RegisterSelect
=
REG_DEVICE_HEAD
|
REG_COMMAND
;
ata
.
write
.
DeviceHeadByte
=
info
->
DeviceHead
;
ata
.
write
.
DeviceHeadByte
=
info
->
DeviceHead
;
ata
.
write
.
SelectCommand
=
1
;
ata
.
write
.
CommandByte
=
WIN_SRST
;
ata
.
write
.
CommandByte
=
WIN_SRST
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
break
;
break
;
case
ACTION_IDENTIFY
:
case
ACTION_IDENTIFY
:
US_DEBUGP
(
" isd200_action(IDENTIFY)
\n
"
);
US_DEBUGP
(
" isd200_action(IDENTIFY)
\n
"
);
ata
.
write
.
SelectCommand
=
1
;
ata
.
generic
.
RegisterSelect
=
REG_COMMAND
;
ata
.
write
.
CommandByte
=
WIN_IDENTIFY
;
ata
.
write
.
CommandByte
=
WIN_IDENTIFY
;
srb
.
sc_data_direction
=
SCSI_DATA_READ
;
srb
.
sc_data_direction
=
SCSI_DATA_READ
;
srb
.
request_buffer
=
(
void
*
)
&
info
->
drive
;
srb
.
request_buffer
=
(
void
*
)
&
info
->
drive
;
...
@@ -886,6 +867,43 @@ void isd200_invoke_transport( struct us_data *us,
...
@@ -886,6 +867,43 @@ void isd200_invoke_transport( struct us_data *us,
srb
->
result
=
CHECK_CONDITION
;
srb
->
result
=
CHECK_CONDITION
;
}
}
#ifdef CONFIG_USB_STORAGE_DEBUG
static
void
isd200_log_config
(
struct
isd200_info
*
info
)
{
US_DEBUGP
(
" Event Notification: 0x%x
\n
"
,
info
->
ConfigData
.
EventNotification
);
US_DEBUGP
(
" External Clock: 0x%x
\n
"
,
info
->
ConfigData
.
ExternalClock
);
US_DEBUGP
(
" ATA Init Timeout: 0x%x
\n
"
,
info
->
ConfigData
.
ATAInitTimeout
);
US_DEBUGP
(
" ATAPI Command Block Size: 0x%x
\n
"
,
(
info
->
ConfigData
.
ATAConfig
&
ATACFG_BLOCKSIZE
)
>>
6
);
US_DEBUGP
(
" Master/Slave Selection: 0x%x
\n
"
,
info
->
ConfigData
.
ATAConfig
&
ATACFG_MASTER
);
US_DEBUGP
(
" ATAPI Reset: 0x%x
\n
"
,
info
->
ConfigData
.
ATAConfig
&
ATACFG_ATAPI_RESET
);
US_DEBUGP
(
" ATA Timing: 0x%x
\n
"
,
info
->
ConfigData
.
ATAConfig
&
ATACFG_TIMING
);
US_DEBUGP
(
" ATA Major Command: 0x%x
\n
"
,
info
->
ConfigData
.
ATAMajorCommand
);
US_DEBUGP
(
" ATA Minor Command: 0x%x
\n
"
,
info
->
ConfigData
.
ATAMinorCommand
);
US_DEBUGP
(
" Init Status: 0x%x
\n
"
,
info
->
ConfigData
.
ATAExtraConfig
&
ATACFGE_INIT_STATUS
);
US_DEBUGP
(
" Config Descriptor 2: 0x%x
\n
"
,
info
->
ConfigData
.
ATAExtraConfig
&
ATACFGE_CONF_DESC2
);
US_DEBUGP
(
" Skip Device Boot: 0x%x
\n
"
,
info
->
ConfigData
.
ATAExtraConfig
&
ATACFGE_SKIP_BOOT
);
US_DEBUGP
(
" ATA 3 State Supsend: 0x%x
\n
"
,
info
->
ConfigData
.
ATAExtraConfig
&
ATACFGE_STATE_SUSPEND
);
US_DEBUGP
(
" Descriptor Override: 0x%x
\n
"
,
info
->
ConfigData
.
ATAExtraConfig
&
ATACFGE_DESC_OVERRIDE
);
US_DEBUGP
(
" Last LUN Identifier: 0x%x
\n
"
,
info
->
ConfigData
.
ATAExtraConfig
&
ATACFGE_LAST_LUN
);
US_DEBUGP
(
" SRST Enable: 0x%x
\n
"
,
info
->
ConfigData
.
ATAExtraConfig
&
CFG_CAPABILITY_SRST
);
}
#endif
/**************************************************************************
/**************************************************************************
* isd200_write_config
* isd200_write_config
...
@@ -901,26 +919,11 @@ int isd200_write_config( struct us_data *us )
...
@@ -901,26 +919,11 @@ int isd200_write_config( struct us_data *us )
int
retStatus
=
ISD200_GOOD
;
int
retStatus
=
ISD200_GOOD
;
int
result
;
int
result
;
#ifdef CONFIG_USB_STORAGE_DEBUG
US_DEBUGP
(
"Entering isd200_write_config
\n
"
);
US_DEBUGP
(
"Entering isd200_write_config
\n
"
);
US_DEBUGP
(
" Writing the following ISD200 Config Data:
\n
"
);
US_DEBUGP
(
" Writing the following ISD200 Config Data:
\n
"
);
US_DEBUGP
(
" Event Notification: 0x%x
\n
"
,
info
->
ConfigData
.
EventNotification
);
isd200_log_config
(
info
);
US_DEBUGP
(
" External Clock: 0x%x
\n
"
,
info
->
ConfigData
.
ExternalClock
);
#endif
US_DEBUGP
(
" ATA Init Timeout: 0x%x
\n
"
,
info
->
ConfigData
.
ATAInitTimeout
);
US_DEBUGP
(
" ATAPI Command Block Size: 0x%x
\n
"
,
info
->
ConfigData
.
ATAPICommandBlockSize
);
US_DEBUGP
(
" Master/Slave Selection: 0x%x
\n
"
,
info
->
ConfigData
.
MasterSlaveSelection
);
US_DEBUGP
(
" ATAPI Reset: 0x%x
\n
"
,
info
->
ConfigData
.
ATAPIReset
);
US_DEBUGP
(
" ATA Timing: 0x%x
\n
"
,
info
->
ConfigData
.
ATATiming
);
US_DEBUGP
(
" ATA Major Command: 0x%x
\n
"
,
info
->
ConfigData
.
ATAMajorCommand
);
US_DEBUGP
(
" ATA Minor Command: 0x%x
\n
"
,
info
->
ConfigData
.
ATAMinorCommand
);
US_DEBUGP
(
" Init Status: 0x%x
\n
"
,
info
->
ConfigData
.
InitStatus
);
US_DEBUGP
(
" Config Descriptor 2: 0x%x
\n
"
,
info
->
ConfigData
.
ConfigDescriptor2
);
US_DEBUGP
(
" Skip Device Boot: 0x%x
\n
"
,
info
->
ConfigData
.
SkipDeviceBoot
);
US_DEBUGP
(
" ATA 3 State Supsend: 0x%x
\n
"
,
info
->
ConfigData
.
ATA3StateSuspend
);
US_DEBUGP
(
" Descriptor Override: 0x%x
\n
"
,
info
->
ConfigData
.
DescriptOverride
);
US_DEBUGP
(
" Last LUN Identifier: 0x%x
\n
"
,
info
->
ConfigData
.
LastLUNIdentifier
);
US_DEBUGP
(
" SRST Enable: 0x%x
\n
"
,
info
->
ConfigData
.
SRSTEnable
);
/* let's send the command via the control pipe */
/* let's send the command via the control pipe */
result
=
usb_stor_control_msg
(
result
=
usb_stor_control_msg
(
...
@@ -941,8 +944,8 @@ int isd200_write_config( struct us_data *us )
...
@@ -941,8 +944,8 @@ int isd200_write_config( struct us_data *us )
/* STALL must be cleared when they are detected */
/* STALL must be cleared when they are detected */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
result
=
usb_stor_clear_halt
(
us
->
pusb_dev
,
result
=
usb_stor_clear_halt
(
us
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
));
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
));
US_DEBUGP
(
"-- usb_stor_clear_halt() returns %d
\n
"
,
result
);
US_DEBUGP
(
"-- usb_stor_clear_halt() returns %d
\n
"
,
result
);
}
}
...
@@ -986,30 +989,17 @@ int isd200_read_config( struct us_data *us )
...
@@ -986,30 +989,17 @@ int isd200_read_config( struct us_data *us )
if
(
result
>=
0
)
{
if
(
result
>=
0
)
{
US_DEBUGP
(
" Retrieved the following ISD200 Config Data:
\n
"
);
US_DEBUGP
(
" Retrieved the following ISD200 Config Data:
\n
"
);
US_DEBUGP
(
" Event Notification: 0x%x
\n
"
,
info
->
ConfigData
.
EventNotification
);
#ifdef CONFIG_USB_STORAGE_DEBUG
US_DEBUGP
(
" External Clock: 0x%x
\n
"
,
info
->
ConfigData
.
ExternalClock
);
isd200_log_config
(
info
);
US_DEBUGP
(
" ATA Init Timeout: 0x%x
\n
"
,
info
->
ConfigData
.
ATAInitTimeout
);
#endif
US_DEBUGP
(
" ATAPI Command Block Size: 0x%x
\n
"
,
info
->
ConfigData
.
ATAPICommandBlockSize
);
US_DEBUGP
(
" Master/Slave Selection: 0x%x
\n
"
,
info
->
ConfigData
.
MasterSlaveSelection
);
US_DEBUGP
(
" ATAPI Reset: 0x%x
\n
"
,
info
->
ConfigData
.
ATAPIReset
);
US_DEBUGP
(
" ATA Timing: 0x%x
\n
"
,
info
->
ConfigData
.
ATATiming
);
US_DEBUGP
(
" ATA Major Command: 0x%x
\n
"
,
info
->
ConfigData
.
ATAMajorCommand
);
US_DEBUGP
(
" ATA Minor Command: 0x%x
\n
"
,
info
->
ConfigData
.
ATAMinorCommand
);
US_DEBUGP
(
" Init Status: 0x%x
\n
"
,
info
->
ConfigData
.
InitStatus
);
US_DEBUGP
(
" Config Descriptor 2: 0x%x
\n
"
,
info
->
ConfigData
.
ConfigDescriptor2
);
US_DEBUGP
(
" Skip Device Boot: 0x%x
\n
"
,
info
->
ConfigData
.
SkipDeviceBoot
);
US_DEBUGP
(
" ATA 3 State Supsend: 0x%x
\n
"
,
info
->
ConfigData
.
ATA3StateSuspend
);
US_DEBUGP
(
" Descriptor Override: 0x%x
\n
"
,
info
->
ConfigData
.
DescriptOverride
);
US_DEBUGP
(
" Last LUN Identifier: 0x%x
\n
"
,
info
->
ConfigData
.
LastLUNIdentifier
);
US_DEBUGP
(
" SRST Enable: 0x%x
\n
"
,
info
->
ConfigData
.
SRSTEnable
);
}
else
{
}
else
{
US_DEBUGP
(
" Request to get ISD200 Config Data failed!
\n
"
);
US_DEBUGP
(
" Request to get ISD200 Config Data failed!
\n
"
);
/* STALL must be cleared when they are detected */
/* STALL must be cleared when they are detected */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
result
=
usb_stor_clear_halt
(
us
->
pusb_dev
,
result
=
usb_stor_clear_halt
(
us
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
));
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
));
US_DEBUGP
(
"-- usb_stor_clear_halt() returns %d
\n
"
,
result
);
US_DEBUGP
(
"-- usb_stor_clear_halt() returns %d
\n
"
,
result
);
}
}
...
@@ -1175,11 +1165,12 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
...
@@ -1175,11 +1165,12 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
break
;
break
;
}
}
}
else
{
}
else
{
US_DEBUGP
(
" Not ATA, not ATAPI. Weird.
\n
"
);
US_DEBUGP
(
" Not ATA, not ATAPI. Weird.
\n
"
);
break
;
}
}
/* check for timeout on this request */
/* check for timeout on this request */
if
(
jiffies
>=
endTime
)
{
if
(
time_after_eq
(
jiffies
,
endTime
)
)
{
if
(
!
detect
)
if
(
!
detect
)
US_DEBUGP
(
" BSY check timeout, just continue with next operation...
\n
"
);
US_DEBUGP
(
" BSY check timeout, just continue with next operation...
\n
"
);
else
else
...
@@ -1223,9 +1214,10 @@ int isd200_manual_enum(struct us_data *us)
...
@@ -1223,9 +1214,10 @@ int isd200_manual_enum(struct us_data *us)
}
}
isslave
=
(
info
->
DeviceHead
&
ATA_ADDRESS_DEVHEAD_SLAVE
)
?
1
:
0
;
isslave
=
(
info
->
DeviceHead
&
ATA_ADDRESS_DEVHEAD_SLAVE
)
?
1
:
0
;
if
(
info
->
ConfigData
.
MasterSlaveSelection
!=
isslave
)
{
if
(
!
(
info
->
ConfigData
.
ATAConfig
&
ATACFG_MASTER
)
)
{
US_DEBUGP
(
" Setting Master/Slave selection to %d
\n
"
,
isslave
);
US_DEBUGP
(
" Setting Master/Slave selection to %d
\n
"
,
isslave
);
info
->
ConfigData
.
MasterSlaveSelection
=
isslave
;
info
->
ConfigData
.
ATAConfig
&=
0x3f
;
info
->
ConfigData
.
ATAConfig
|=
(
isslave
<<
6
);
retStatus
=
isd200_write_config
(
us
);
retStatus
=
isd200_write_config
(
us
);
}
}
}
}
...
@@ -1272,6 +1264,8 @@ int isd200_get_inquiry_data( struct us_data *us )
...
@@ -1272,6 +1264,8 @@ int isd200_get_inquiry_data( struct us_data *us )
}
else
{
}
else
{
/* ATA Command Identify successful */
/* ATA Command Identify successful */
int
i
;
int
i
;
__u16
*
src
,
*
dest
;
ide_fix_driveid
(
&
info
->
drive
);
US_DEBUGP
(
" Identify Data Structure:
\n
"
);
US_DEBUGP
(
" Identify Data Structure:
\n
"
);
US_DEBUGP
(
" config = 0x%x
\n
"
,
info
->
drive
.
config
);
US_DEBUGP
(
" config = 0x%x
\n
"
,
info
->
drive
.
config
);
...
@@ -1317,31 +1311,25 @@ int isd200_get_inquiry_data( struct us_data *us )
...
@@ -1317,31 +1311,25 @@ int isd200_get_inquiry_data( struct us_data *us )
if
(
info
->
drive
.
command_set_1
&
COMMANDSET_MEDIA_STATUS
)
{
if
(
info
->
drive
.
command_set_1
&
COMMANDSET_MEDIA_STATUS
)
{
/* set the removable bit */
/* set the removable bit */
info
->
InquiryData
.
RemovableMedia
=
1
;
info
->
InquiryData
.
DeviceTypeModifier
=
DEVICE_REMOVABLE
;
info
->
DeviceFlags
|=
DF_REMOVABLE_MEDIA
;
info
->
DeviceFlags
|=
DF_REMOVABLE_MEDIA
;
}
}
/* Fill in vendor identification fields */
/* Fill in vendor identification fields */
for
(
i
=
0
;
i
<
20
;
i
+=
2
)
{
src
=
(
__u16
*
)
info
->
drive
.
model
;
info
->
InquiryData
.
VendorId
[
i
]
=
dest
=
(
__u16
*
)
info
->
InquiryData
.
VendorId
;
info
->
drive
.
model
[
i
+
1
];
for
(
i
=
0
;
i
<
4
;
i
++
)
info
->
InquiryData
.
VendorId
[
i
+
1
]
=
dest
[
i
]
=
be16_to_cpu
(
src
[
i
]);
info
->
drive
.
model
[
i
];
}
/* Initialize unused portion of product id */
src
=
(
__u16
*
)(
info
->
drive
.
model
+
8
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
dest
=
(
__u16
*
)
info
->
InquiryData
.
ProductId
;
info
->
InquiryData
.
ProductId
[
12
+
i
]
=
' '
;
for
(
i
=
0
;
i
<
8
;
i
++
)
}
dest
[
i
]
=
be16_to_cpu
(
src
[
i
]);
/* Move firmware revision from IDENTIFY data to */
src
=
(
__u16
*
)
info
->
drive
.
fw_rev
;
/* product revision in INQUIRY data */
dest
=
(
__u16
*
)
info
->
InquiryData
.
ProductRevisionLevel
;
for
(
i
=
0
;
i
<
4
;
i
+=
2
)
{
for
(
i
=
0
;
i
<
2
;
i
++
)
info
->
InquiryData
.
ProductRevisionLevel
[
i
]
=
dest
[
i
]
=
be16_to_cpu
(
src
[
i
]);
info
->
drive
.
fw_rev
[
i
+
1
];
info
->
InquiryData
.
ProductRevisionLevel
[
i
+
1
]
=
info
->
drive
.
fw_rev
[
i
];
}
/* determine if it supports Media Status Notification */
/* determine if it supports Media Status Notification */
if
(
info
->
drive
.
command_set_2
&
COMMANDSET_MEDIA_STATUS
)
{
if
(
info
->
drive
.
command_set_2
&
COMMANDSET_MEDIA_STATUS
)
{
...
@@ -1483,7 +1471,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
...
@@ -1483,7 +1471,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
write
.
SelectCommand
=
1
;
ataCdb
->
generic
.
RegisterSelect
=
REG_COMMAND
;
ataCdb
->
write
.
CommandByte
=
ATA_COMMAND_GET_MEDIA_STATUS
;
ataCdb
->
write
.
CommandByte
=
ATA_COMMAND_GET_MEDIA_STATUS
;
srb
->
request_bufflen
=
0
;
srb
->
request_bufflen
=
0
;
}
else
{
}
else
{
...
@@ -1504,7 +1492,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
...
@@ -1504,7 +1492,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
write
.
SelectCommand
=
1
;
ataCdb
->
generic
.
RegisterSelect
=
REG_COMMAND
;
ataCdb
->
write
.
CommandByte
=
ATA_COMMAND_GET_MEDIA_STATUS
;
ataCdb
->
write
.
CommandByte
=
ATA_COMMAND_GET_MEDIA_STATUS
;
srb
->
request_bufflen
=
0
;
srb
->
request_bufflen
=
0
;
}
else
{
}
else
{
...
@@ -1561,17 +1549,15 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
...
@@ -1561,17 +1549,15 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
write
.
SelectSectorCount
=
1
;
ataCdb
->
generic
.
RegisterSelect
=
REG_SECTOR_COUNT
|
REG_SECTOR_NUMBER
|
REG_CYLINDER_LOW
|
REG_CYLINDER_HIGH
|
REG_DEVICE_HEAD
|
REG_COMMAND
;
ataCdb
->
write
.
SectorCountByte
=
(
unsigned
char
)
blockCount
;
ataCdb
->
write
.
SectorCountByte
=
(
unsigned
char
)
blockCount
;
ataCdb
->
write
.
SelectSectorNumber
=
1
;
ataCdb
->
write
.
SectorNumberByte
=
sectnum
;
ataCdb
->
write
.
SectorNumberByte
=
sectnum
;
ataCdb
->
write
.
SelectCylinderHigh
=
1
;
ataCdb
->
write
.
CylinderHighByte
=
(
unsigned
char
)(
cylinder
>>
8
);
ataCdb
->
write
.
CylinderHighByte
=
(
unsigned
char
)(
cylinder
>>
8
);
ataCdb
->
write
.
SelectCylinderLow
=
1
;
ataCdb
->
write
.
CylinderLowByte
=
(
unsigned
char
)
cylinder
;
ataCdb
->
write
.
CylinderLowByte
=
(
unsigned
char
)
cylinder
;
ataCdb
->
write
.
SelectDeviceHead
=
1
;
ataCdb
->
write
.
DeviceHeadByte
=
(
head
|
ATA_ADDRESS_DEVHEAD_STD
);
ataCdb
->
write
.
DeviceHeadByte
=
(
head
|
ATA_ADDRESS_DEVHEAD_STD
);
ataCdb
->
write
.
SelectCommand
=
1
;
ataCdb
->
write
.
CommandByte
=
WIN_READ
;
ataCdb
->
write
.
CommandByte
=
WIN_READ
;
break
;
break
;
...
@@ -1594,17 +1580,15 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
...
@@ -1594,17 +1580,15 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
write
.
SelectSectorCount
=
1
;
ataCdb
->
generic
.
RegisterSelect
=
REG_SECTOR_COUNT
|
REG_SECTOR_NUMBER
|
REG_CYLINDER_LOW
|
REG_CYLINDER_HIGH
|
REG_DEVICE_HEAD
|
REG_COMMAND
;
ataCdb
->
write
.
SectorCountByte
=
(
unsigned
char
)
blockCount
;
ataCdb
->
write
.
SectorCountByte
=
(
unsigned
char
)
blockCount
;
ataCdb
->
write
.
SelectSectorNumber
=
1
;
ataCdb
->
write
.
SectorNumberByte
=
sectnum
;
ataCdb
->
write
.
SectorNumberByte
=
sectnum
;
ataCdb
->
write
.
SelectCylinderHigh
=
1
;
ataCdb
->
write
.
CylinderHighByte
=
(
unsigned
char
)(
cylinder
>>
8
);
ataCdb
->
write
.
CylinderHighByte
=
(
unsigned
char
)(
cylinder
>>
8
);
ataCdb
->
write
.
SelectCylinderLow
=
1
;
ataCdb
->
write
.
CylinderLowByte
=
(
unsigned
char
)
cylinder
;
ataCdb
->
write
.
CylinderLowByte
=
(
unsigned
char
)
cylinder
;
ataCdb
->
write
.
SelectDeviceHead
=
1
;
ataCdb
->
write
.
DeviceHeadByte
=
(
head
|
ATA_ADDRESS_DEVHEAD_STD
);
ataCdb
->
write
.
DeviceHeadByte
=
(
head
|
ATA_ADDRESS_DEVHEAD_STD
);
ataCdb
->
write
.
SelectCommand
=
1
;
ataCdb
->
write
.
CommandByte
=
WIN_WRITE
;
ataCdb
->
write
.
CommandByte
=
WIN_WRITE
;
break
;
break
;
...
@@ -1617,7 +1601,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
...
@@ -1617,7 +1601,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
write
.
SelectCommand
=
1
;
ataCdb
->
generic
.
RegisterSelect
=
REG_COMMAND
;
ataCdb
->
write
.
CommandByte
=
(
srb
->
cmnd
[
4
]
&
0x1
)
?
ataCdb
->
write
.
CommandByte
=
(
srb
->
cmnd
[
4
]
&
0x1
)
?
WIN_DOORLOCK
:
WIN_DOORUNLOCK
;
WIN_DOORLOCK
:
WIN_DOORUNLOCK
;
srb
->
request_bufflen
=
0
;
srb
->
request_bufflen
=
0
;
...
@@ -1640,14 +1624,14 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
...
@@ -1640,14 +1624,14 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
TransferBlockSize
=
0
;
ataCdb
->
generic
.
TransferBlockSize
=
0
;
ataCdb
->
write
.
SelectCommand
=
1
;
ataCdb
->
generic
.
RegisterSelect
=
REG_COMMAND
;
ataCdb
->
write
.
CommandByte
=
ATA_COMMAND_MEDIA_EJECT
;
ataCdb
->
write
.
CommandByte
=
ATA_COMMAND_MEDIA_EJECT
;
}
else
if
((
srb
->
cmnd
[
4
]
&
0x3
)
==
0x1
)
{
}
else
if
((
srb
->
cmnd
[
4
]
&
0x3
)
==
0x1
)
{
US_DEBUGP
(
" Get Media Status
\n
"
);
US_DEBUGP
(
" Get Media Status
\n
"
);
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
ataCdb
->
write
.
SelectCommand
=
1
;
ataCdb
->
generic
.
RegisterSelect
=
REG_COMMAND
;
ataCdb
->
write
.
CommandByte
=
ATA_COMMAND_GET_MEDIA_STATUS
;
ataCdb
->
write
.
CommandByte
=
ATA_COMMAND_GET_MEDIA_STATUS
;
srb
->
request_bufflen
=
0
;
srb
->
request_bufflen
=
0
;
}
else
{
}
else
{
...
...
drivers/usb/storage/jumpshot.c
View file @
58a5ae6a
/* Driver for Lexar "Jumpshot" Compact Flash reader
/* Driver for Lexar "Jumpshot" Compact Flash reader
*
* $Id: jumpshot.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
*
*
* jumpshot driver v0.1:
* jumpshot driver v0.1:
*
*
...
@@ -6,11 +8,19 @@
...
@@ -6,11 +8,19 @@
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org)
* (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org)
* many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
*
* Many thanks to Robert Baruch for the SanDisk SmartMedia reader driver
* which I used as a template for this driver.
* which I used as a template for this driver.
*
* Some bugfixes and scatter-gather code by Gregory P. Smith
* Some bugfixes and scatter-gather code by Gregory P. Smith
* (greg-usb@electricrain.com)
* (greg-usb@electricrain.com)
*
*
* Fix for media change by Joerg Schneider (js@joergschneider.com)
*
* Developed with the assistance of:
*
* (C) 2002 Alan Stern <stern@rowland.org>
*
* This program is free software; you can redistribute it and/or modify it
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* Free Software Foundation; either version 2, or (at your option) any
...
@@ -128,8 +138,8 @@ static int jumpshot_send_control(struct us_data *us,
...
@@ -128,8 +138,8 @@ static int jumpshot_send_control(struct us_data *us,
/* a stall is a fatal condition from the device */
/* a stall is a fatal condition from the device */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"jumpshot_send_control: -- Stall on control pipe. Clearing
\n
"
);
US_DEBUGP
(
"jumpshot_send_control: -- Stall on control pipe. Clearing
\n
"
);
result
=
usb_
clear_halt
(
us
->
pusb_dev
,
pipe
);
result
=
usb_
stor_clear_halt
(
us
,
pipe
);
US_DEBUGP
(
"jumpshot_send_control: -- usb_clear_halt() returns %d
\n
"
,
result
);
US_DEBUGP
(
"jumpshot_send_control: -- usb_
stor_
clear_halt() returns %d
\n
"
,
result
);
return
USB_STOR_TRANSPORT_FAILED
;
return
USB_STOR_TRANSPORT_FAILED
;
}
}
...
@@ -161,7 +171,7 @@ static int jumpshot_raw_bulk(int direction,
...
@@ -161,7 +171,7 @@ static int jumpshot_raw_bulk(int direction,
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"jumpshot_raw_bulk: EPIPE. clearing endpoint halt for"
US_DEBUGP
(
"jumpshot_raw_bulk: EPIPE. clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes
\n
"
,
pipe
,
act_len
);
" pipe 0x%x, stalled at %d bytes
\n
"
,
pipe
,
act_len
);
usb_
clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_
stor_clear_halt
(
us
,
pipe
);
}
}
if
(
result
)
{
if
(
result
)
{
...
@@ -798,6 +808,23 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
...
@@ -798,6 +808,23 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
//
//
return
USB_STOR_TRANSPORT_GOOD
;
return
USB_STOR_TRANSPORT_GOOD
;
}
}
if
(
srb
->
cmnd
[
0
]
==
START_STOP
)
{
/* this is used by sd.c'check_scsidisk_media_change to detect
media change */
US_DEBUGP
(
"jumpshot_transport: START_STOP.
\n
"
);
/* the first jumpshot_id_device after a media change returns
an error (determined experimentally) */
rc
=
jumpshot_id_device
(
us
,
info
);
if
(
rc
==
USB_STOR_TRANSPORT_GOOD
)
{
info
->
sense_key
=
NO_SENSE
;
srb
->
result
=
SUCCESS
;
}
else
{
info
->
sense_key
=
UNIT_ATTENTION
;
srb
->
result
=
CHECK_CONDITION
;
}
return
rc
;
}
US_DEBUGP
(
"jumpshot_transport: Gah! Unknown command: %d (0x%x)
\n
"
,
srb
->
cmnd
[
0
],
srb
->
cmnd
[
0
]);
US_DEBUGP
(
"jumpshot_transport: Gah! Unknown command: %d (0x%x)
\n
"
,
srb
->
cmnd
[
0
],
srb
->
cmnd
[
0
]);
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_ERROR
;
...
...
drivers/usb/storage/protocol.c
View file @
58a5ae6a
/* Driver for USB Mass Storage compliant devices
/* Driver for USB Mass Storage compliant devices
*
*
* $Id: protocol.c,v 1.1
1 2002/01/13 06:40:25
mdharm Exp $
* $Id: protocol.c,v 1.1
4 2002/04/22 03:39:43
mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 1999
, 2000
Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999
-2002
Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
*
* Developed with the assistance of:
* Developed with the assistance of:
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
* (c) 2002 Alan Stern (stern@rowland.org)
*
*
* Initial work by:
* Initial work by:
* (c) 1999 Michael Gee (michael@linuxspecific.com)
* (c) 1999 Michael Gee (michael@linuxspecific.com)
...
@@ -67,10 +68,16 @@ void fix_inquiry_data(Scsi_Cmnd *srb)
...
@@ -67,10 +68,16 @@ void fix_inquiry_data(Scsi_Cmnd *srb)
US_DEBUGP
(
"Fixing INQUIRY data to show SCSI rev 2
\n
"
);
US_DEBUGP
(
"Fixing INQUIRY data to show SCSI rev 2
\n
"
);
/* find the location of the data */
/* find the location of the data */
if
(
srb
->
use_sg
)
if
(
srb
->
use_sg
)
{
BUG
();
/* this piece of code only works if the first page is big enough to
* hold more than 3 bytes -- which is _very_ likely
*/
struct
scatterlist
*
sg
;
data_ptr
=
(
unsigned
char
*
)
srb
->
request_buffer
;
sg
=
(
struct
scatterlist
*
)
srb
->
request_buffer
;
data_ptr
=
(
unsigned
char
*
)
page_address
(
sg
[
0
].
page
)
+
sg
[
0
].
offset
;
}
else
data_ptr
=
(
unsigned
char
*
)
srb
->
request_buffer
;
/* Change the SCSI revision number */
/* Change the SCSI revision number */
data_ptr
[
2
]
=
(
data_ptr
[
2
]
&
~
7
)
|
2
;
data_ptr
[
2
]
=
(
data_ptr
[
2
]
&
~
7
)
|
2
;
...
@@ -94,9 +101,11 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -94,9 +101,11 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
/* send the command to the transport layer */
usb_stor_invoke_transport
(
srb
,
us
);
usb_stor_invoke_transport
(
srb
,
us
);
if
(
srb
->
result
==
GOOD
<<
1
)
{
/* fix the INQUIRY data if necessary */
/* fix the INQUIRY data if necessary */
fix_inquiry_data
(
srb
);
fix_inquiry_data
(
srb
);
}
}
}
void
usb_stor_ATAPI_command
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
)
void
usb_stor_ATAPI_command
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
)
...
@@ -165,13 +174,15 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -165,13 +174,15 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
/* send the command to the transport layer */
usb_stor_invoke_transport
(
srb
,
us
);
usb_stor_invoke_transport
(
srb
,
us
);
if
(
srb
->
result
==
GOOD
<<
1
)
{
/* Fix the MODE_SENSE data if we translated the command */
/* Fix the MODE_SENSE data if we translated the command */
if
((
old_cmnd
==
MODE_SENSE
)
&&
(
status_byte
(
srb
->
result
)
==
GOOD
)
)
if
(
old_cmnd
==
MODE_SENSE
)
usb_stor_scsiSense10to6
(
srb
);
usb_stor_scsiSense10to6
(
srb
);
/* fix the INQUIRY data if necessary */
/* fix the INQUIRY data if necessary */
fix_inquiry_data
(
srb
);
fix_inquiry_data
(
srb
);
}
}
}
...
@@ -260,13 +271,15 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -260,13 +271,15 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
/* send the command to the transport layer */
usb_stor_invoke_transport
(
srb
,
us
);
usb_stor_invoke_transport
(
srb
,
us
);
if
(
srb
->
result
==
GOOD
<<
1
)
{
/* Fix the MODE_SENSE data if we translated the command */
/* Fix the MODE_SENSE data if we translated the command */
if
((
old_cmnd
==
MODE_SENSE
)
&&
(
status_byte
(
srb
->
result
)
==
GOOD
)
)
if
(
old_cmnd
==
MODE_SENSE
)
usb_stor_scsiSense10to6
(
srb
);
usb_stor_scsiSense10to6
(
srb
);
/* Fix the data for an INQUIRY, if necessary */
/* Fix the data for an INQUIRY, if necessary */
fix_inquiry_data
(
srb
);
fix_inquiry_data
(
srb
);
}
}
}
void
usb_stor_transparent_scsi_command
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
)
void
usb_stor_transparent_scsi_command
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
)
...
@@ -327,13 +340,14 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -327,13 +340,14 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
/* send the command to the transport layer */
usb_stor_invoke_transport
(
srb
,
us
);
usb_stor_invoke_transport
(
srb
,
us
);
if
(
srb
->
result
==
GOOD
<<
1
)
{
/* Fix the MODE_SENSE data if we translated the command */
/* Fix the MODE_SENSE data if we translated the command */
if
((
us
->
flags
&
US_FL_MODE_XLATE
)
&&
(
old_cmnd
==
MODE_SENSE
)
if
((
us
->
flags
&
US_FL_MODE_XLATE
)
&&
(
old_cmnd
==
MODE_SENSE
))
&&
(
status_byte
(
srb
->
result
)
==
GOOD
))
usb_stor_scsiSense10to6
(
srb
);
usb_stor_scsiSense10to6
(
srb
);
/* fix the INQUIRY data if necessary */
/* fix the INQUIRY data if necessary */
fix_inquiry_data
(
srb
);
fix_inquiry_data
(
srb
);
}
}
}
drivers/usb/storage/scsiglue.c
View file @
58a5ae6a
/* Driver for USB Mass Storage compliant devices
/* Driver for USB Mass Storage compliant devices
* SCSI layer glue code
* SCSI layer glue code
*
*
* $Id: scsiglue.c,v 1.2
4 2001/11/11 03:33:58
mdharm Exp $
* $Id: scsiglue.c,v 1.2
6 2002/04/22 03:39:43
mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
...
@@ -177,22 +177,8 @@ static int command_abort( Scsi_Cmnd *srb )
...
@@ -177,22 +177,8 @@ static int command_abort( Scsi_Cmnd *srb )
US_DEBUGP
(
"command_abort() called
\n
"
);
US_DEBUGP
(
"command_abort() called
\n
"
);
/* if we're stuck waiting for an IRQ, simulate it */
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_RUNNING
)
{
if
(
atomic_read
(
us
->
ip_wanted
))
{
usb_stor_abort_transport
(
us
);
US_DEBUGP
(
"-- simulating missing IRQ
\n
"
);
up
(
&
(
us
->
ip_waitq
));
}
/* if the device has been removed, this worked */
if
(
!
us
->
pusb_dev
)
{
US_DEBUGP
(
"-- device removed already
\n
"
);
return
SUCCESS
;
}
/* if we have an urb pending, let's wake the control thread up */
if
(
us
->
current_urb
->
status
==
-
EINPROGRESS
)
{
/* cancel the URB -- this will automatically wake the thread */
usb_unlink_urb
(
us
->
current_urb
);
/* wait for us to be done */
/* wait for us to be done */
wait_for_completion
(
&
(
us
->
notify
));
wait_for_completion
(
&
(
us
->
notify
));
...
@@ -208,47 +194,57 @@ static int command_abort( Scsi_Cmnd *srb )
...
@@ -208,47 +194,57 @@ static int command_abort( Scsi_Cmnd *srb )
static
int
device_reset
(
Scsi_Cmnd
*
srb
)
static
int
device_reset
(
Scsi_Cmnd
*
srb
)
{
{
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
host
->
hostdata
[
0
];
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
host
->
hostdata
[
0
];
int
result
;
US_DEBUGP
(
"device_reset() called
\n
"
);
US_DEBUGP
(
"device_reset() called
\n
"
);
return
us
->
transport_reset
(
us
);
/* if the device was removed, then we're already reset */
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_DETACHED
)
return
SUCCESS
;
/* lock the device pointers */
down
(
&
(
us
->
dev_semaphore
));
us
->
srb
=
srb
;
atomic_set
(
&
us
->
sm_state
,
US_STATE_RESETTING
);
result
=
us
->
transport_reset
(
us
);
atomic_set
(
&
us
->
sm_state
,
US_STATE_IDLE
);
/* unlock the device pointers */
up
(
&
(
us
->
dev_semaphore
));
return
result
;
}
}
/* This resets the device port, and simulates the device
/* This resets the device port, and simulates the device
* disconnect/reconnect for all drivers which have claimed
other
* disconnect/reconnect for all drivers which have claimed
* interfaces. */
* interfaces
, including ourself
. */
static
int
bus_reset
(
Scsi_Cmnd
*
srb
)
static
int
bus_reset
(
Scsi_Cmnd
*
srb
)
{
{
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
host
->
hostdata
[
0
];
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
host
->
hostdata
[
0
];
int
i
;
int
i
;
int
result
;
int
result
;
struct
usb_device
*
pusb_dev_save
=
us
->
pusb_dev
;
/* we use the usb_reset_device() function to handle this for us */
/* we use the usb_reset_device() function to handle this for us */
US_DEBUGP
(
"bus_reset() called
\n
"
);
US_DEBUGP
(
"bus_reset() called
\n
"
);
/* if the device has been removed, this worked */
/* if the device has been removed, this worked */
if
(
!
us
->
pusb_dev
)
{
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_DETACHED
)
{
US_DEBUGP
(
"-- device removed already
\n
"
);
US_DEBUGP
(
"-- device removed already
\n
"
);
return
SUCCESS
;
return
SUCCESS
;
}
}
/* release the IRQ, if we have one */
down
(
&
(
us
->
irq_urb_sem
));
if
(
us
->
irq_urb
)
{
US_DEBUGP
(
"-- releasing irq URB
\n
"
);
result
=
usb_unlink_urb
(
us
->
irq_urb
);
US_DEBUGP
(
"-- usb_unlink_urb() returned %d
\n
"
,
result
);
}
up
(
&
(
us
->
irq_urb_sem
));
/* attempt to reset the port */
/* attempt to reset the port */
if
(
usb_reset_device
(
us
->
pusb_dev
)
<
0
)
result
=
usb_reset_device
(
pusb_dev_save
);
US_DEBUGP
(
"usb_reset_device returns %d
\n
"
,
result
);
if
(
result
<
0
)
return
FAILED
;
return
FAILED
;
/* FIXME: This needs to lock out driver probing while it's working
/* FIXME: This needs to lock out driver probing while it's working
* or we can have race conditions */
* or we can have race conditions */
for
(
i
=
0
;
i
<
us
->
pusb_dev
->
actconfig
->
bNumInterfaces
;
i
++
)
{
/* Is that still true? I don't see how... AS */
for
(
i
=
0
;
i
<
pusb_dev_save
->
actconfig
->
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
intf
=
struct
usb_interface
*
intf
=
&
us
->
pusb_dev
->
actconfig
->
interface
[
i
];
&
pusb_dev_save
->
actconfig
->
interface
[
i
];
const
struct
usb_device_id
*
id
;
const
struct
usb_device_id
*
id
;
/* if this is an unclaimed interface, skip it */
/* if this is an unclaimed interface, skip it */
...
@@ -256,33 +252,17 @@ static int bus_reset( Scsi_Cmnd *srb )
...
@@ -256,33 +252,17 @@ static int bus_reset( Scsi_Cmnd *srb )
continue
;
continue
;
}
}
US_DEBUGP
(
"Examinging driver %s..."
,
intf
->
driver
->
name
);
US_DEBUGP
(
"Examining driver %s..."
,
intf
->
driver
->
name
);
/* skip interfaces which we've claimed */
if
(
intf
->
driver
==
&
usb_storage_driver
)
{
US_DEBUGPX
(
"skipping ourselves.
\n
"
);
continue
;
}
/* simulate a disconnect and reconnect for all interfaces */
/* simulate a disconnect and reconnect for all interfaces */
US_DEBUGPX
(
"simulating disconnect/reconnect.
\n
"
);
US_DEBUGPX
(
"simulating disconnect/reconnect.
\n
"
);
down
(
&
intf
->
driver
->
serialize
);
down
(
&
intf
->
driver
->
serialize
);
intf
->
driver
->
disconnect
(
us
->
pusb_dev
,
intf
->
private_data
);
intf
->
driver
->
disconnect
(
pusb_dev_save
,
intf
->
private_data
);
id
=
usb_match_id
(
us
->
pusb_dev
,
intf
,
intf
->
driver
->
id_table
);
id
=
usb_match_id
(
pusb_dev_save
,
intf
,
intf
->
driver
->
id_table
);
intf
->
driver
->
probe
(
us
->
pusb_dev
,
i
,
id
);
intf
->
driver
->
probe
(
pusb_dev_save
,
i
,
id
);
up
(
&
intf
->
driver
->
serialize
);
up
(
&
intf
->
driver
->
serialize
);
}
}
/* re-allocate the IRQ URB and submit it to restore connectivity
* for CBI devices
*/
if
(
us
->
protocol
==
US_PR_CBI
)
{
down
(
&
(
us
->
irq_urb_sem
));
us
->
irq_urb
->
dev
=
us
->
pusb_dev
;
result
=
usb_submit_urb
(
us
->
irq_urb
,
GFP_NOIO
);
US_DEBUGP
(
"usb_submit_urb() returns %d
\n
"
,
result
);
up
(
&
(
us
->
irq_urb_sem
));
}
US_DEBUGP
(
"bus_reset() complete
\n
"
);
US_DEBUGP
(
"bus_reset() complete
\n
"
);
return
SUCCESS
;
return
SUCCESS
;
}
}
...
@@ -346,7 +326,8 @@ static int proc_info (char *buffer, char **start, off_t offset, int length,
...
@@ -346,7 +326,8 @@ static int proc_info (char *buffer, char **start, off_t offset, int length,
/* show the GUID of the device */
/* show the GUID of the device */
SPRINTF
(
" GUID: "
GUID_FORMAT
"
\n
"
,
GUID_ARGS
(
us
->
guid
));
SPRINTF
(
" GUID: "
GUID_FORMAT
"
\n
"
,
GUID_ARGS
(
us
->
guid
));
SPRINTF
(
" Attached: %s
\n
"
,
us
->
pusb_dev
?
"Yes"
:
"No"
);
SPRINTF
(
" Attached: %s
\n
"
,
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_DETACHED
)
?
"Yes"
:
"No"
);
/*
/*
* Calculate start of next buffer, and return value.
* Calculate start of next buffer, and return value.
...
@@ -565,11 +546,11 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
...
@@ -565,11 +546,11 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
/* copy one byte */
/* copy one byte */
{
{
char
*
src
=
page_address
(
sg
[
sb
].
page
)
+
sg
[
sb
].
offset
+
si
;
char
*
src
=
page_address
(
sg
[
sb
].
page
)
+
sg
[
sb
].
offset
+
si
;
char
*
dst
=
page_address
(
sg
[
db
].
page
)
+
sg
[
db
].
offset
+
di
;
char
*
dst
=
page_address
(
sg
[
db
].
page
)
+
sg
[
db
].
offset
+
di
;
*
dst
=
*
src
;
*
dst
=
*
src
;
}
}
/* get next destination */
/* get next destination */
if
(
sg
[
db
].
length
-
1
==
di
)
if
(
sg
[
db
].
length
-
1
==
di
)
...
@@ -607,7 +588,7 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
...
@@ -607,7 +588,7 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
break
;
break
;
}
}
*
(
char
*
)(
page_address
(
sg
[
db
].
page
)
+
sg
[
db
].
offset
)
=
0
;
*
(
char
*
)(
page_address
(
sg
[
db
].
page
)
+
sg
[
db
].
offset
)
=
0
;
/* get next destination */
/* get next destination */
if
(
sg
[
db
].
length
-
1
==
di
)
if
(
sg
[
db
].
length
-
1
==
di
)
...
@@ -758,11 +739,11 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
...
@@ -758,11 +739,11 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
/* copy one byte */
/* copy one byte */
{
{
char
*
src
=
page_address
(
sg
[
sb
].
page
)
+
sg
[
sb
].
offset
+
si
;
char
*
src
=
page_address
(
sg
[
sb
].
page
)
+
sg
[
sb
].
offset
+
si
;
char
*
dst
=
page_address
(
sg
[
db
].
page
)
+
sg
[
db
].
offset
+
di
;
char
*
dst
=
page_address
(
sg
[
db
].
page
)
+
sg
[
db
].
offset
+
di
;
*
dst
=
*
src
;
*
dst
=
*
src
;
}
}
/* get next destination */
/* get next destination */
if
(
di
==
0
)
if
(
di
==
0
)
...
@@ -799,11 +780,12 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
...
@@ -799,11 +780,12 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
break
;
break
;
}
}
{
{
char
*
dst
=
page_address
(
sg
[
db
].
page
)
+
sg
[
db
].
offset
+
di
;
char
*
dst
=
page_address
(
sg
[
db
].
page
)
+
sg
[
db
].
offset
+
di
;
*
dst
=
tempBuffer
[
element
-
USB_STOR_SCSI_SENSE_HDRSZ
];
}
*
dst
=
tempBuffer
[
element
-
USB_STOR_SCSI_SENSE_HDRSZ
];
}
/* get next destination */
/* get next destination */
if
(
di
==
0
)
if
(
di
==
0
)
...
@@ -853,19 +835,18 @@ void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* t
...
@@ -853,19 +835,18 @@ void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* t
if
(
element
<
USB_STOR_SCSI_SENSE_HDRSZ
)
if
(
element
<
USB_STOR_SCSI_SENSE_HDRSZ
)
{
{
/* fill in the pointers for both header types */
/* fill in the pointers for both header types */
the6
->
array
[
element
]
=
the6
->
array
[
element
]
=
page_address
(
sg
[
i
].
page
)
+
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
+
j
;
sg
[
i
].
offset
+
j
;
the10
->
array
[
element
]
=
page_address
(
sg
[
i
].
page
)
+
the10
->
array
[
element
]
=
sg
[
i
].
offset
+
j
;
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
+
j
;
}
}
else
if
(
element
<
USB_STOR_SCSI_SENSE_10_HDRSZ
)
else
if
(
element
<
USB_STOR_SCSI_SENSE_10_HDRSZ
)
{
{
/* only the longer headers still cares now */
/* only the longer headers still cares now */
the10
->
array
[
element
]
=
the10
->
array
[
element
]
=
page_address
(
sg
[
i
].
page
)
+
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
+
j
;
sg
[
i
].
offset
+
j
;
}
}
/* increase element counter */
/* increase element counter */
element
++
;
element
++
;
...
...
drivers/usb/storage/sddr09.c
View file @
58a5ae6a
/* Driver for SanDisk SDDR-09 SmartMedia reader
/* Driver for SanDisk SDDR-09 SmartMedia reader
*
*
* $Id: sddr09.c,v 1.24 2002/04/22 03:39:43 mdharm Exp $
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
* (c) 2002 Andries Brouwer (aeb@cwi.nl)
* (c) 2002 Andries Brouwer (aeb@cwi.nl)
* Developed with the assistance of:
* (c) 2002 Alan Stern <stern@rowland.org>
*
*
* The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip.
* The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip.
* This chip is a programmable USB controller. In the SDDR-09, it has
* This chip is a programmable USB controller. In the SDDR-09, it has
...
@@ -262,8 +265,8 @@ sddr09_send_control(struct us_data *us,
...
@@ -262,8 +265,8 @@ sddr09_send_control(struct us_data *us,
/* a stall is a fatal condition from the device */
/* a stall is a fatal condition from the device */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
result
=
usb_
clear_halt
(
us
->
pusb_dev
,
pipe
);
result
=
usb_
stor_clear_halt
(
us
,
pipe
);
US_DEBUGP
(
"-- usb_clear_halt() returns %d
\n
"
,
result
);
US_DEBUGP
(
"-- usb_
stor_
clear_halt() returns %d
\n
"
,
result
);
return
USB_STOR_TRANSPORT_FAILED
;
return
USB_STOR_TRANSPORT_FAILED
;
}
}
...
@@ -317,13 +320,13 @@ sddr09_raw_bulk(struct us_data *us, int direction,
...
@@ -317,13 +320,13 @@ sddr09_raw_bulk(struct us_data *us, int direction,
result
=
usb_stor_bulk_msg
(
us
,
data
,
pipe
,
len
,
&
act_len
);
result
=
usb_stor_bulk_msg
(
us
,
data
,
pipe
,
len
,
&
act_len
);
/* if we stall, we need to clear it before we go on */
/* if we stall, we need to clear it before we go on */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"EPIPE: clearing endpoint halt for"
US_DEBUGP
(
"EPIPE: clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes
\n
"
,
" pipe 0x%x, stalled at %d bytes
\n
"
,
pipe
,
act_len
);
pipe
,
act_len
);
usb_clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_stor_clear_halt
(
us
,
pipe
);
}
}
if
(
result
)
{
if
(
result
)
{
/* -ENOENT -- we canceled this transfer */
/* -ENOENT -- we canceled this transfer */
...
@@ -1386,15 +1389,6 @@ sddr09_read_map(struct us_data *us) {
...
@@ -1386,15 +1389,6 @@ sddr09_read_map(struct us_data *us) {
// Each block is 64 bytes of control data, so block i is located in
// Each block is 64 bytes of control data, so block i is located in
// scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
// scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
#if 0
/* No translation */
for (i=0; i<numblocks; i++) {
lba = i;
info->pba_to_lba[i] = lba;
info->lba_to_pba[lba] = i;
}
printk("sddr09: no translation today\n");
#else
for
(
i
=
0
;
i
<
numblocks
;
i
++
)
{
for
(
i
=
0
;
i
<
numblocks
;
i
++
)
{
ptr
=
page_address
(
sg
[
i
>>
11
].
page
)
+
ptr
=
page_address
(
sg
[
i
>>
11
].
page
)
+
sg
[
i
>>
11
].
offset
+
((
i
&
0x7ff
)
<<
6
);
sg
[
i
>>
11
].
offset
+
((
i
&
0x7ff
)
<<
6
);
...
@@ -1482,7 +1476,6 @@ sddr09_read_map(struct us_data *us) {
...
@@ -1482,7 +1476,6 @@ sddr09_read_map(struct us_data *us) {
info
->
pba_to_lba
[
i
]
=
lba
;
info
->
pba_to_lba
[
i
]
=
lba
;
info
->
lba_to_pba
[
lba
]
=
i
;
info
->
lba_to_pba
[
lba
]
=
i
;
}
}
#endif
/*
/*
* Approximate capacity. This is not entirely correct yet,
* Approximate capacity. This is not entirely correct yet,
...
@@ -1508,7 +1501,7 @@ sddr09_read_map(struct us_data *us) {
...
@@ -1508,7 +1501,7 @@ sddr09_read_map(struct us_data *us) {
US_DEBUGP
(
"Found %d LBA's
\n
"
,
lbact
);
US_DEBUGP
(
"Found %d LBA's
\n
"
,
lbact
);
for
(
i
=
0
;
i
<
alloc_blocks
;
i
++
)
for
(
i
=
0
;
i
<
alloc_blocks
;
i
++
)
kfree
(
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
);
kfree
(
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
);
kfree
(
sg
);
kfree
(
sg
);
return
0
;
return
0
;
}
}
...
...
drivers/usb/storage/shuttle_usbat.c
View file @
58a5ae6a
/* Driver for SCM Microsystems USB-ATAPI cable
/* Driver for SCM Microsystems USB-ATAPI cable
*
*
* $Id: shuttle_usbat.c,v 1.1
5 2001/12/08 23:32:48
mdharm Exp $
* $Id: shuttle_usbat.c,v 1.1
7 2002/04/22 03:39:43
mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
*
*
* Developed with the assistance of:
* (c) 2002 Alan Stern <stern@rowland.org>
*
* Many originally ATAPI devices were slightly modified to meet the USB
* Many originally ATAPI devices were slightly modified to meet the USB
* market by using some kind of translation from ATAPI to USB on the host,
* market by using some kind of translation from ATAPI to USB on the host,
* and the peripheral would translate from USB back to ATAPI.
* and the peripheral would translate from USB back to ATAPI.
...
@@ -107,8 +110,8 @@ static int usbat_send_control(struct us_data *us,
...
@@ -107,8 +110,8 @@ static int usbat_send_control(struct us_data *us,
/* a stall is a fatal condition from the device */
/* a stall is a fatal condition from the device */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
result
=
usb_
clear_halt
(
us
->
pusb_dev
,
pipe
);
result
=
usb_
stor_clear_halt
(
us
,
pipe
);
US_DEBUGP
(
"-- usb_clear_halt() returns %d
\n
"
,
result
);
US_DEBUGP
(
"-- usb_
stor_
clear_halt() returns %d
\n
"
,
result
);
return
USB_STOR_TRANSPORT_FAILED
;
return
USB_STOR_TRANSPORT_FAILED
;
}
}
...
@@ -140,7 +143,7 @@ static int usbat_raw_bulk(struct us_data *us,
...
@@ -140,7 +143,7 @@ static int usbat_raw_bulk(struct us_data *us,
US_DEBUGP
(
"EPIPE: clearing endpoint halt for"
US_DEBUGP
(
"EPIPE: clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes
\n
"
,
" pipe 0x%x, stalled at %d bytes
\n
"
,
pipe
,
act_len
);
pipe
,
act_len
);
usb_
clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_
stor_clear_halt
(
us
,
pipe
);
}
}
if
(
result
)
{
if
(
result
)
{
...
@@ -214,7 +217,7 @@ static int usbat_bulk_transport(struct us_data *us,
...
@@ -214,7 +217,7 @@ static int usbat_bulk_transport(struct us_data *us,
sg
=
(
struct
scatterlist
*
)
data
;
sg
=
(
struct
scatterlist
*
)
data
;
for
(
i
=
0
;
i
<
use_sg
&&
transferred
<
len
;
i
++
)
{
for
(
i
=
0
;
i
<
use_sg
&&
transferred
<
len
;
i
++
)
{
result
=
usbat_raw_bulk
(
us
,
direction
,
result
=
usbat_raw_bulk
(
us
,
direction
,
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
,
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
,
len
-
transferred
>
sg
[
i
].
length
?
len
-
transferred
>
sg
[
i
].
length
?
sg
[
i
].
length
:
len
-
transferred
);
sg
[
i
].
length
:
len
-
transferred
);
if
(
result
!=
US_BULK_TRANSFER_GOOD
)
if
(
result
!=
US_BULK_TRANSFER_GOOD
)
...
@@ -515,7 +518,7 @@ int usbat_rw_block_test(struct us_data *us,
...
@@ -515,7 +518,7 @@ int usbat_rw_block_test(struct us_data *us,
*/
*/
if
(
direction
==
SCSI_DATA_READ
&&
i
==
0
)
if
(
direction
==
SCSI_DATA_READ
&&
i
==
0
)
usb_
clear_halt
(
us
->
pusb_dev
,
usb_
stor_clear_halt
(
us
,
usb_sndbulkpipe
(
us
->
pusb_dev
,
usb_sndbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
));
us
->
ep_out
));
/*
/*
...
@@ -675,9 +678,15 @@ int usbat_handle_read10(struct us_data *us,
...
@@ -675,9 +678,15 @@ int usbat_handle_read10(struct us_data *us,
len
=
short_pack
(
data
[
7
+
9
],
data
[
7
+
8
]);
len
=
short_pack
(
data
[
7
+
9
],
data
[
7
+
8
]);
len
<<=
16
;
len
<<=
16
;
len
|=
data
[
7
+
7
];
len
|=
data
[
7
+
7
];
US_DEBUGP
(
"handle_read10: GPCMD_READ_CD: len %d
\n
"
,
len
);
srb
->
transfersize
=
srb
->
request_bufflen
/
len
;
srb
->
transfersize
=
srb
->
request_bufflen
/
len
;
}
}
if
(
!
srb
->
transfersize
)
{
srb
->
transfersize
=
2048
;
/* A guess */
US_DEBUGP
(
"handle_read10: transfersize 0, forcing %d
\n
"
,
srb
->
transfersize
);
}
len
=
(
65535
/
srb
->
transfersize
)
*
srb
->
transfersize
;
len
=
(
65535
/
srb
->
transfersize
)
*
srb
->
transfersize
;
US_DEBUGP
(
"Max read is %d bytes
\n
"
,
len
);
US_DEBUGP
(
"Max read is %d bytes
\n
"
,
len
);
...
@@ -734,7 +743,7 @@ int usbat_handle_read10(struct us_data *us,
...
@@ -734,7 +743,7 @@ int usbat_handle_read10(struct us_data *us,
if
(
len
-
amount
>=
if
(
len
-
amount
>=
sg
[
sg_segment
].
length
-
sg_offset
)
{
sg
[
sg_segment
].
length
-
sg_offset
)
{
memcpy
(
page_address
(
sg
[
sg_segment
].
page
)
+
memcpy
(
page_address
(
sg
[
sg_segment
].
page
)
+
sg
[
sg_s
eg
ment
].
offset
+
sg_offset
,
sg
[
sg_s
ge
ment
].
offset
+
sg_offset
,
buffer
+
amount
,
buffer
+
amount
,
sg
[
sg_segment
].
length
-
sg_offset
);
sg
[
sg_segment
].
length
-
sg_offset
);
amount
+=
amount
+=
...
...
drivers/usb/storage/transport.c
View file @
58a5ae6a
/* Driver for USB Mass Storage compliant devices
/* Driver for USB Mass Storage compliant devices
*
*
* $Id: transport.c,v 1.4
2 2001/12/08 23:32:48
mdharm Exp $
* $Id: transport.c,v 1.4
7 2002/04/22 03:39:43
mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 1999
, 2000
Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999
-2002
Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
*
* Developed with the assistance of:
* Developed with the assistance of:
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
* (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov)
* (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov)
* (c) 2002 Alan Stern <stern@rowland.org>
*
*
* Initial work by:
* Initial work by:
* (c) 1999 Michael Gee (michael@linuxspecific.com)
* (c) 1999 Michael Gee (michael@linuxspecific.com)
...
@@ -329,37 +330,21 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb)
...
@@ -329,37 +330,21 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb)
for
(
i
=
0
;
i
<
srb
->
use_sg
;
i
++
)
for
(
i
=
0
;
i
<
srb
->
use_sg
;
i
++
)
total
+=
sg
[
i
].
length
;
total
+=
sg
[
i
].
length
;
len
=
total
;
len
=
total
;
/* Double-check to see if the advertised buffer
* length less than the actual buffer length --
* in other words, we should tend towards the
* conservative side for data transfers.
*/
if
(
len
>
srb
->
request_bufflen
)
len
=
srb
->
request_bufflen
;
}
}
else
else
/* Just return the length of the buffer */
/* Just return the length of the buffer */
len
=
srb
->
request_bufflen
;
len
=
srb
->
request_bufflen
;
}
}
return
len
;
return
len
;
}
/* This is a version of usb_clear_halt() that doesn't read the status from
* the device -- this is because some devices crash their internal firmware
* when the status is requested after a halt
*/
int
usb_stor_clear_halt
(
struct
usb_device
*
dev
,
int
pipe
)
{
int
result
;
int
endp
=
usb_pipeendpoint
(
pipe
)
|
(
usb_pipein
(
pipe
)
<<
7
);
result
=
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_CLEAR_FEATURE
,
USB_RECIP_ENDPOINT
,
0
,
endp
,
NULL
,
0
,
HZ
*
3
);
/* this is a failure case */
if
(
result
<
0
)
return
result
;
/* reset the toggles and endpoint flags */
usb_endpoint_running
(
dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
));
usb_settoggle
(
dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
),
0
);
return
0
;
}
}
/***********************************************************************
/***********************************************************************
...
@@ -376,109 +361,142 @@ static void usb_stor_blocking_completion(struct urb *urb)
...
@@ -376,109 +361,142 @@ static void usb_stor_blocking_completion(struct urb *urb)
complete
(
urb_done_ptr
);
complete
(
urb_done_ptr
);
}
}
/* This is our function to emulate usb_control_msg() but give us enough
/* This is the common part of the URB message submission code
* access to make aborts/resets work
* This function expects the current_urb_sem to be held upon entry.
*/
static
int
usb_stor_msg_common
(
struct
us_data
*
us
)
{
struct
completion
urb_done
;
int
status
;
/* set up data structures for the wakeup system */
init_completion
(
&
urb_done
);
/* fill the common fields in the URB */
us
->
current_urb
->
context
=
&
urb_done
;
us
->
current_urb
->
actual_length
=
0
;
us
->
current_urb
->
error_count
=
0
;
us
->
current_urb
->
transfer_flags
=
USB_ASYNC_UNLINK
;
/* submit the URB */
status
=
usb_submit_urb
(
us
->
current_urb
,
GFP_NOIO
);
if
(
status
)
{
/* something went wrong */
return
status
;
}
/* has the current command been aborted? */
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_ABORTING
)
{
/* avoid a race with usb_stor_abort_transport():
* if the abort took place before we submitted
* the URB, we must cancel it ourselves */
if
(
us
->
current_urb
->
status
==
-
EINPROGRESS
)
usb_unlink_urb
(
us
->
current_urb
);
}
/* wait for the completion of the URB */
up
(
&
(
us
->
current_urb_sem
));
wait_for_completion
(
&
urb_done
);
down
(
&
(
us
->
current_urb_sem
));
/* return the URB status */
return
us
->
current_urb
->
status
;
}
/* This is our function to emulate usb_control_msg() with enough control
* to make aborts/resets/timeouts work
*/
*/
int
usb_stor_control_msg
(
struct
us_data
*
us
,
unsigned
int
pipe
,
int
usb_stor_control_msg
(
struct
us_data
*
us
,
unsigned
int
pipe
,
u8
request
,
u8
requesttype
,
u16
value
,
u16
index
,
u8
request
,
u8
requesttype
,
u16
value
,
u16
index
,
void
*
data
,
u16
size
)
void
*
data
,
u16
size
)
{
{
struct
completion
urb_done
;
int
status
;
int
status
;
struct
usb_ctrlrequest
*
dr
;
struct
usb_ctrlrequest
*
dr
;
/* allocate the device request structure */
dr
=
kmalloc
(
sizeof
(
struct
usb_ctrlrequest
),
GFP_NOIO
);
dr
=
kmalloc
(
sizeof
(
struct
usb_ctrlrequest
),
GFP_NOIO
);
if
(
!
dr
)
if
(
!
dr
)
return
-
ENOMEM
;
return
-
ENOMEM
;
/* fill in the structure */
/* fill in the
devrequest
structure */
dr
->
bRequestType
=
requesttype
;
dr
->
bRequestType
=
requesttype
;
dr
->
bRequest
=
request
;
dr
->
bRequest
=
request
;
dr
->
wValue
=
cpu_to_le16
(
value
);
dr
->
wValue
=
cpu_to_le16
(
value
);
dr
->
wIndex
=
cpu_to_le16
(
index
);
dr
->
wIndex
=
cpu_to_le16
(
index
);
dr
->
wLength
=
cpu_to_le16
(
size
);
dr
->
wLength
=
cpu_to_le16
(
size
);
/* set up data structures for the wakeup system */
init_completion
(
&
urb_done
);
/* lock the URB */
/* lock the URB */
down
(
&
(
us
->
current_urb_sem
));
down
(
&
(
us
->
current_urb_sem
));
/* fill the URB */
/* fill the URB */
FILL_CONTROL_URB
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
FILL_CONTROL_URB
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
(
unsigned
char
*
)
dr
,
data
,
size
,
(
unsigned
char
*
)
&
dr
,
data
,
size
,
usb_stor_blocking_completion
,
&
urb_done
);
usb_stor_blocking_completion
,
NULL
);
us
->
current_urb
->
actual_length
=
0
;
us
->
current_urb
->
error_count
=
0
;
us
->
current_urb
->
transfer_flags
=
USB_ASYNC_UNLINK
;
/* submit the URB */
/* submit the URB */
status
=
usb_submit_urb
(
us
->
current_urb
,
GFP_NOIO
);
status
=
usb_stor_msg_common
(
us
);
if
(
status
)
{
/* something went wrong */
up
(
&
(
us
->
current_urb_sem
));
kfree
(
dr
);
return
status
;
}
/* wait for the completion of the URB */
up
(
&
(
us
->
current_urb_sem
));
wait_for_completion
(
&
urb_done
);
down
(
&
(
us
->
current_urb_sem
));
/* return the actual length of the data transferred if no error*/
/* return the actual length of the data transferred if no error*/
status
=
us
->
current_urb
->
status
;
if
(
status
>=
0
)
if
(
status
>=
0
)
status
=
us
->
current_urb
->
actual_length
;
status
=
us
->
current_urb
->
actual_length
;
/* release the lock and return status */
/* release the lock and return status */
up
(
&
(
us
->
current_urb_sem
));
up
(
&
(
us
->
current_urb_sem
));
kfree
(
dr
);
return
status
;
return
status
;
}
}
/* This is our function to emulate usb_bulk_msg()
but give us enough
/* This is our function to emulate usb_bulk_msg()
with enough control
*
access to make aborts/rese
ts work
*
to make aborts/resets/timeou
ts work
*/
*/
int
usb_stor_bulk_msg
(
struct
us_data
*
us
,
void
*
data
,
int
pipe
,
int
usb_stor_bulk_msg
(
struct
us_data
*
us
,
void
*
data
,
int
pipe
,
unsigned
int
len
,
unsigned
int
*
act_len
)
unsigned
int
len
,
unsigned
int
*
act_len
)
{
{
struct
completion
urb_done
;
int
status
;
int
status
;
/* set up data structures for the wakeup system */
init_completion
(
&
urb_done
);
/* lock the URB */
/* lock the URB */
down
(
&
(
us
->
current_urb_sem
));
down
(
&
(
us
->
current_urb_sem
));
/* fill the URB */
/* fill the URB */
FILL_BULK_URB
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
data
,
len
,
FILL_BULK_URB
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
data
,
len
,
usb_stor_blocking_completion
,
&
urb_done
);
usb_stor_blocking_completion
,
NULL
);
us
->
current_urb
->
actual_length
=
0
;
us
->
current_urb
->
error_count
=
0
;
us
->
current_urb
->
transfer_flags
=
USB_ASYNC_UNLINK
;
/* submit the URB */
/* submit the URB */
status
=
usb_submit_urb
(
us
->
current_urb
,
GFP_NOIO
);
status
=
usb_stor_msg_common
(
us
);
if
(
status
)
{
/* something went wrong */
up
(
&
(
us
->
current_urb_sem
));
return
status
;
}
/* wait for the completion of the URB */
up
(
&
(
us
->
current_urb_sem
));
wait_for_completion
(
&
urb_done
);
down
(
&
(
us
->
current_urb_sem
));
/* return the actual length of the data transferred */
/* return the actual length of the data transferred */
*
act_len
=
us
->
current_urb
->
actual_length
;
*
act_len
=
us
->
current_urb
->
actual_length
;
/* release the lock and return status */
/* release the lock and return status */
up
(
&
(
us
->
current_urb_sem
));
up
(
&
(
us
->
current_urb_sem
));
return
us
->
current_urb
->
status
;
return
status
;
}
/* This is a version of usb_clear_halt() that doesn't read the status from
* the device -- this is because some devices crash their internal firmware
* when the status is requested after a halt
*/
int
usb_stor_clear_halt
(
struct
us_data
*
us
,
int
pipe
)
{
int
result
;
int
endp
=
usb_pipeendpoint
(
pipe
)
|
(
usb_pipein
(
pipe
)
<<
7
);
result
=
usb_stor_control_msg
(
us
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
USB_REQ_CLEAR_FEATURE
,
USB_RECIP_ENDPOINT
,
0
,
endp
,
NULL
,
0
);
/* note: no 3*HZ timeout */
US_DEBUGP
(
"usb_stor_clear_halt: result=%d
\n
"
,
result
);
/* this is a failure case */
if
(
result
<
0
)
return
result
;
/* reset the toggles and endpoint flags */
usb_endpoint_running
(
us
->
pusb_dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
));
usb_settoggle
(
us
->
pusb_dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
),
0
);
return
0
;
}
}
/*
/*
...
@@ -513,7 +531,13 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
...
@@ -513,7 +531,13 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
/* if we stall, we need to clear it before we go on */
/* if we stall, we need to clear it before we go on */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_stor_clear_halt
(
us
,
pipe
);
}
/* did we abort this command? */
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_ABORTING
)
{
US_DEBUGP
(
"usb_stor_transfer_partial(): transfer aborted
\n
"
);
return
US_BULK_TRANSFER_ABORTED
;
}
}
/* did we send all the data? */
/* did we send all the data? */
...
@@ -522,21 +546,14 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
...
@@ -522,21 +546,14 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
return
US_BULK_TRANSFER_GOOD
;
return
US_BULK_TRANSFER_GOOD
;
}
}
/* uh oh... we have an error code, so something went wrong. */
/* NAK - that means we've retried a few times already */
if
(
result
)
{
if
(
result
==
-
ETIMEDOUT
)
{
/* NAK - that means we've retried a few times already */
US_DEBUGP
(
"usb_stor_transfer_partial(): device NAKed
\n
"
);
if
(
result
==
-
ETIMEDOUT
)
{
return
US_BULK_TRANSFER_FAILED
;
US_DEBUGP
(
"usb_stor_transfer_partial(): device NAKed
\n
"
);
}
return
US_BULK_TRANSFER_FAILED
;
}
/* -ENOENT -- we canceled this transfer */
if
(
result
==
-
ENOENT
)
{
US_DEBUGP
(
"usb_stor_transfer_partial(): transfer aborted
\n
"
);
return
US_BULK_TRANSFER_ABORTED
;
}
/* the catch-all case */
/* the catch-all error case */
if
(
result
)
{
US_DEBUGP
(
"usb_stor_transfer_partial(): unknown error
\n
"
);
US_DEBUGP
(
"usb_stor_transfer_partial(): unknown error
\n
"
);
return
US_BULK_TRANSFER_FAILED
;
return
US_BULK_TRANSFER_FAILED
;
}
}
...
@@ -550,7 +567,7 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
...
@@ -550,7 +567,7 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
* Transfer an entire SCSI command's worth of data payload over the bulk
* Transfer an entire SCSI command's worth of data payload over the bulk
* pipe.
* pipe.
*
*
* Note that this uses usb_stor_transfer_partial to achieve it
'
s goals -- this
* Note that this uses usb_stor_transfer_partial to achieve its goals -- this
* function simply determines if we're going to use scatter-gather or not,
* function simply determines if we're going to use scatter-gather or not,
* and acts appropriately. For now, it also re-interprets the error codes.
* and acts appropriately. For now, it also re-interprets the error codes.
*/
*/
...
@@ -631,6 +648,14 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -631,6 +648,14 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
return
;
return
;
}
}
/* if there is a transport error, reset and don't auto-sense */
if
(
result
==
USB_STOR_TRANSPORT_ERROR
)
{
US_DEBUGP
(
"-- transport indicates error, resetting
\n
"
);
us
->
transport_reset
(
us
);
srb
->
result
=
DID_ERROR
<<
16
;
return
;
}
/* Determine if we need to auto-sense
/* Determine if we need to auto-sense
*
*
* I normally don't use a flag like this, but it's almost impossible
* I normally don't use a flag like this, but it's almost impossible
...
@@ -660,7 +685,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -660,7 +685,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
}
}
/*
/*
* If we have a
n error
, we're going to do a REQUEST_SENSE
* If we have a
failure
, we're going to do a REQUEST_SENSE
* automatically. Note that we differentiate between a command
* automatically. Note that we differentiate between a command
* "failure" and an "error" in the transport mechanism.
* "failure" and an "error" in the transport mechanism.
*/
*/
...
@@ -668,13 +693,6 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -668,13 +693,6 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP
(
"-- transport indicates command failure
\n
"
);
US_DEBUGP
(
"-- transport indicates command failure
\n
"
);
need_auto_sense
=
1
;
need_auto_sense
=
1
;
}
}
if
(
result
==
USB_STOR_TRANSPORT_ERROR
)
{
us
->
transport_reset
(
us
);
US_DEBUGP
(
"-- transport indicates transport failure
\n
"
);
need_auto_sense
=
0
;
srb
->
result
=
DID_ERROR
<<
16
;
return
;
}
/*
/*
* Also, if we have a short transfer on a command that can't have
* Also, if we have a short transfer on a command that can't have
...
@@ -730,6 +748,19 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -730,6 +748,19 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
/* issue the auto-sense command */
/* issue the auto-sense command */
temp_result
=
us
->
transport
(
us
->
srb
,
us
);
temp_result
=
us
->
transport
(
us
->
srb
,
us
);
/* let's clean up right away */
srb
->
request_buffer
=
old_request_buffer
;
srb
->
request_bufflen
=
old_request_bufflen
;
srb
->
use_sg
=
old_sg
;
srb
->
sc_data_direction
=
old_sc_data_direction
;
memcpy
(
srb
->
cmnd
,
old_cmnd
,
MAX_COMMAND_SIZE
);
if
(
temp_result
==
USB_STOR_TRANSPORT_ABORTED
)
{
US_DEBUGP
(
"-- auto-sense aborted
\n
"
);
srb
->
result
=
DID_ABORT
<<
16
;
return
;
}
if
(
temp_result
!=
USB_STOR_TRANSPORT_GOOD
)
{
if
(
temp_result
!=
USB_STOR_TRANSPORT_GOOD
)
{
US_DEBUGP
(
"-- auto-sense failure
\n
"
);
US_DEBUGP
(
"-- auto-sense failure
\n
"
);
...
@@ -760,13 +791,6 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -760,13 +791,6 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
/* set the result so the higher layers expect this data */
/* set the result so the higher layers expect this data */
srb
->
result
=
CHECK_CONDITION
<<
1
;
srb
->
result
=
CHECK_CONDITION
<<
1
;
/* we're done here, let's clean up */
srb
->
request_buffer
=
old_request_buffer
;
srb
->
request_bufflen
=
old_request_bufflen
;
srb
->
use_sg
=
old_sg
;
srb
->
sc_data_direction
=
old_sc_data_direction
;
memcpy
(
srb
->
cmnd
,
old_cmnd
,
MAX_COMMAND_SIZE
);
/* If things are really okay, then let's show that */
/* If things are really okay, then let's show that */
if
((
srb
->
sense_buffer
[
2
]
&
0xf
)
==
0x0
)
if
((
srb
->
sense_buffer
[
2
]
&
0xf
)
==
0x0
)
srb
->
result
=
GOOD
<<
1
;
srb
->
result
=
GOOD
<<
1
;
...
@@ -789,6 +813,39 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -789,6 +813,39 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
srb
->
sense_buffer
[
0
]
=
0x0
;
srb
->
sense_buffer
[
0
]
=
0x0
;
}
}
/* Abort the currently running scsi command or device reset.
*/
void
usb_stor_abort_transport
(
struct
us_data
*
us
)
{
int
state
=
atomic_read
(
&
us
->
sm_state
);
US_DEBUGP
(
"usb_stor_abort_transport called
\n
"
);
/* If the current state is wrong or if there's
* no srb, then there's nothing to do */
if
(
!
(
state
==
US_STATE_RUNNING
||
state
==
US_STATE_RESETTING
)
||
!
us
->
srb
)
{
US_DEBUGP
(
"-- invalid current state
\n
"
);
return
;
}
atomic_set
(
&
us
->
sm_state
,
US_STATE_ABORTING
);
/* If the state machine is blocked waiting for an URB or an IRQ,
* let's wake it up */
/* if we have an URB pending, cancel it */
if
(
us
->
current_urb
->
status
==
-
EINPROGRESS
)
{
US_DEBUGP
(
"-- cancelling URB
\n
"
);
usb_unlink_urb
(
us
->
current_urb
);
}
/* if we are waiting for an IRQ, simulate it */
else
if
(
test_bit
(
IP_WANTED
,
&
us
->
bitflags
))
{
US_DEBUGP
(
"-- simulating missing IRQ
\n
"
);
usb_stor_CBI_irq
(
us
->
irq_urb
);
}
}
/*
/*
* Control/Bulk/Interrupt transport
* Control/Bulk/Interrupt transport
*/
*/
...
@@ -804,15 +861,40 @@ void usb_stor_CBI_irq(struct urb *urb)
...
@@ -804,15 +861,40 @@ void usb_stor_CBI_irq(struct urb *urb)
US_DEBUGP
(
"-- Interrupt Status (0x%x, 0x%x)
\n
"
,
US_DEBUGP
(
"-- Interrupt Status (0x%x, 0x%x)
\n
"
,
us
->
irqbuf
[
0
],
us
->
irqbuf
[
1
]);
us
->
irqbuf
[
0
],
us
->
irqbuf
[
1
]);
/* reject improper IRQs */
/* has the current command been aborted? */
if
(
urb
->
actual_length
!=
2
)
{
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_ABORTING
)
{
US_DEBUGP
(
"-- IRQ too short
\n
"
);
/* was this a wanted interrupt? */
if
(
!
test_and_clear_bit
(
IP_WANTED
,
&
us
->
bitflags
))
{
US_DEBUGP
(
"ERROR: Unwanted interrupt received!
\n
"
);
return
;
}
US_DEBUGP
(
"-- command aborted
\n
"
);
/* wake up the command thread */
up
(
&
us
->
ip_waitq
);
return
;
return
;
}
}
/* is the device removed? */
/* is the device removed? */
if
(
urb
->
status
==
-
ENOENT
)
{
if
(
urb
->
status
==
-
ENOENT
)
{
US_DEBUGP
(
"-- device has been removed
\n
"
);
US_DEBUGP
(
"-- device has been removed
\n
"
);
/* was this a wanted interrupt? */
if
(
!
test_and_clear_bit
(
IP_WANTED
,
&
us
->
bitflags
))
return
;
/* indicate a transport error -- this is the best we can do */
us
->
irqdata
[
0
]
=
us
->
irqdata
[
1
]
=
0xFF
;
/* wake up the command thread */
up
(
&
us
->
ip_waitq
);
return
;
}
/* reject improper IRQs */
if
(
urb
->
actual_length
!=
2
)
{
US_DEBUGP
(
"-- IRQ too short
\n
"
);
return
;
return
;
}
}
...
@@ -823,21 +905,16 @@ void usb_stor_CBI_irq(struct urb *urb)
...
@@ -823,21 +905,16 @@ void usb_stor_CBI_irq(struct urb *urb)
}
}
/* was this a wanted interrupt? */
/* was this a wanted interrupt? */
if
(
!
atomic_read
(
us
->
ip_wanted
))
{
if
(
!
test_and_clear_bit
(
IP_WANTED
,
&
us
->
bitflags
))
{
US_DEBUGP
(
"ERROR: Unwanted interrupt received!
\n
"
);
US_DEBUGP
(
"ERROR: Unwanted interrupt received!
\n
"
);
return
;
return
;
}
}
/* adjust the flag */
atomic_set
(
us
->
ip_wanted
,
0
);
/* copy the valid data */
/* copy the valid data */
us
->
irqdata
[
0
]
=
us
->
irqbuf
[
0
];
us
->
irqdata
[
0
]
=
us
->
irqbuf
[
0
];
us
->
irqdata
[
1
]
=
us
->
irqbuf
[
1
];
us
->
irqdata
[
1
]
=
us
->
irqbuf
[
1
];
/* wake up the command thread */
/* wake up the command thread */
US_DEBUGP
(
"-- Current value of ip_waitq is: %d
\n
"
,
atomic_read
(
&
us
->
ip_waitq
.
count
));
up
(
&
(
us
->
ip_waitq
));
up
(
&
(
us
->
ip_waitq
));
}
}
...
@@ -845,13 +922,13 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -845,13 +922,13 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
{
{
int
result
;
int
result
;
/* Set up for status notification */
atomic_set
(
us
->
ip_wanted
,
1
);
/* re-initialize the mutex so that we avoid any races with
/* re-initialize the mutex so that we avoid any races with
* early/late IRQs from previous commands */
* early/late IRQs from previous commands */
init_MUTEX_LOCKED
(
&
(
us
->
ip_waitq
));
init_MUTEX_LOCKED
(
&
(
us
->
ip_waitq
));
/* Set up for status notification */
set_bit
(
IP_WANTED
,
&
us
->
bitflags
);
/* COMMAND STAGE */
/* COMMAND STAGE */
/* let's send the command via the control pipe */
/* let's send the command via the control pipe */
result
=
usb_stor_control_msg
(
us
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
result
=
usb_stor_control_msg
(
us
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
...
@@ -863,22 +940,26 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -863,22 +940,26 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP
(
"Call to usb_stor_control_msg() returned %d
\n
"
,
result
);
US_DEBUGP
(
"Call to usb_stor_control_msg() returned %d
\n
"
,
result
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
/* Reset flag for status notification */
/* Reset flag for status notification */
atomic_set
(
us
->
ip_wanted
,
0
);
clear_bit
(
IP_WANTED
,
&
us
->
bitflags
);
}
/* if the command was aborted, indicate that */
if
(
result
==
-
ENOENT
)
return
USB_STOR_TRANSPORT_ABORTED
;
/* STALL must be cleared when it is detected */
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
result
=
usb_stor_clear_halt
(
us
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
));
/* if the command was aborted, indicate that */
/* if the command was aborted, indicate that */
if
(
result
==
-
ENOENT
)
if
(
result
==
-
ENOENT
)
return
USB_STOR_TRANSPORT_ABORTED
;
return
USB_STOR_TRANSPORT_ABORTED
;
return
USB_STOR_TRANSPORT_FAILED
;
}
/* STALL must be cleared when they are detected */
if
(
result
<
0
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
result
=
usb_stor_clear_halt
(
us
->
pusb_dev
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
));
US_DEBUGP
(
"-- usb_stor_clear_halt() returns %d
\n
"
,
result
);
return
USB_STOR_TRANSPORT_FAILED
;
}
/* Uh oh... serious problem here */
/* Uh oh... serious problem here */
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_ERROR
;
}
}
...
@@ -887,24 +968,28 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -887,24 +968,28 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* transfer the data payload for this command, if one exists*/
/* transfer the data payload for this command, if one exists*/
if
(
usb_stor_transfer_length
(
srb
))
{
if
(
usb_stor_transfer_length
(
srb
))
{
usb_stor_transfer
(
srb
,
us
);
usb_stor_transfer
(
srb
,
us
);
US_DEBUGP
(
"CBI data stage result is 0x%x
\n
"
,
srb
->
result
);
result
=
srb
->
result
;
US_DEBUGP
(
"CBI data stage result is 0x%x
\n
"
,
result
);
/* if it was aborted, we need to indicate that */
/* report any errors */
if
(
srb
->
result
==
USB_STOR_TRANSPORT_ABORTED
)
{
if
(
result
==
US_BULK_TRANSFER_ABORTED
)
{
clear_bit
(
IP_WANTED
,
&
us
->
bitflags
);
return
USB_STOR_TRANSPORT_ABORTED
;
return
USB_STOR_TRANSPORT_ABORTED
;
}
}
if
(
result
==
US_BULK_TRANSFER_FAILED
)
{
clear_bit
(
IP_WANTED
,
&
us
->
bitflags
);
return
USB_STOR_TRANSPORT_FAILED
;
}
}
}
/* STATUS STAGE */
/* STATUS STAGE */
/* go to sleep until we get this interrupt */
/* go to sleep until we get this interrupt */
US_DEBUGP
(
"Current value of ip_waitq is: %d
\n
"
,
atomic_read
(
&
us
->
ip_waitq
.
count
));
down
(
&
(
us
->
ip_waitq
));
down
(
&
(
us
->
ip_waitq
));
/* if we were woken up by an abort instead of the actual interrupt */
/* has the current command been aborted? */
if
(
atomic_read
(
us
->
ip_wanted
))
{
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_ABORTING
)
{
US_DEBUGP
(
"Did not get interrupt on CBI
\n
"
);
US_DEBUGP
(
"CBI interrupt aborted
\n
"
);
atomic_set
(
us
->
ip_wanted
,
0
);
return
USB_STOR_TRANSPORT_ABORTED
;
return
USB_STOR_TRANSPORT_ABORTED
;
}
}
...
@@ -922,11 +1007,12 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -922,11 +1007,12 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
if
(
srb
->
cmnd
[
0
]
==
REQUEST_SENSE
||
if
(
srb
->
cmnd
[
0
]
==
REQUEST_SENSE
||
srb
->
cmnd
[
0
]
==
INQUIRY
)
srb
->
cmnd
[
0
]
==
INQUIRY
)
return
USB_STOR_TRANSPORT_GOOD
;
return
USB_STOR_TRANSPORT_GOOD
;
else
else
{
if
(
((
unsigned
char
*
)
us
->
irq_urb
->
transfer_buffer
)
[
0
])
if
(
us
->
irqdata
[
0
])
return
USB_STOR_TRANSPORT_FAILED
;
return
USB_STOR_TRANSPORT_FAILED
;
else
else
return
USB_STOR_TRANSPORT_GOOD
;
return
USB_STOR_TRANSPORT_GOOD
;
}
}
}
/* If not UFI, we interpret the data as a result code
/* If not UFI, we interpret the data as a result code
...
@@ -976,10 +1062,12 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -976,10 +1062,12 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* a stall is a fatal condition from the device */
/* a stall is a fatal condition from the device */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
US_DEBUGP
(
"-- Stall on control pipe. Clearing
\n
"
);
result
=
usb_stor_clear_halt
(
us
->
pusb_dev
,
result
=
usb_stor_clear_halt
(
us
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
));
0
));
US_DEBUGP
(
"-- usb_stor_clear_halt() returns %d
\n
"
,
result
);
/* if the command was aborted, indicate that */
if
(
result
==
-
ENOENT
)
return
USB_STOR_TRANSPORT_ABORTED
;
return
USB_STOR_TRANSPORT_FAILED
;
return
USB_STOR_TRANSPORT_FAILED
;
}
}
...
@@ -991,11 +1079,16 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -991,11 +1079,16 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* transfer the data payload for this command, if one exists*/
/* transfer the data payload for this command, if one exists*/
if
(
usb_stor_transfer_length
(
srb
))
{
if
(
usb_stor_transfer_length
(
srb
))
{
usb_stor_transfer
(
srb
,
us
);
usb_stor_transfer
(
srb
,
us
);
US_DEBUGP
(
"CB data stage result is 0x%x
\n
"
,
srb
->
result
);
result
=
srb
->
result
;
US_DEBUGP
(
"CB data stage result is 0x%x
\n
"
,
result
);
/*
if it was aborted, we need to indicate that
*/
/*
report any errors
*/
if
(
srb
->
result
==
USB_STOR_TRANSPORT_ABORTED
)
if
(
result
==
US_BULK_TRANSFER_ABORTED
)
{
return
USB_STOR_TRANSPORT_ABORTED
;
return
USB_STOR_TRANSPORT_ABORTED
;
}
if
(
result
==
US_BULK_TRANSFER_FAILED
)
{
return
USB_STOR_TRANSPORT_FAILED
;
}
}
}
/* STATUS STAGE */
/* STATUS STAGE */
...
@@ -1016,7 +1109,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
...
@@ -1016,7 +1109,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
int
result
;
int
result
;
int
pipe
;
int
pipe
;
/* issue the command */
/* issue the command -- use usb_control_msg() because
* the state machine is not yet alive */
pipe
=
usb_rcvctrlpipe
(
us
->
pusb_dev
,
0
);
pipe
=
usb_rcvctrlpipe
(
us
->
pusb_dev
,
0
);
result
=
usb_control_msg
(
us
->
pusb_dev
,
pipe
,
result
=
usb_control_msg
(
us
->
pusb_dev
,
pipe
,
US_BULK_GET_MAX_LUN
,
US_BULK_GET_MAX_LUN
,
...
@@ -1034,15 +1128,16 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
...
@@ -1034,15 +1128,16 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
/* if we get a STALL, clear the stall */
/* if we get a STALL, clear the stall */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
pipe
);
/* Use usb_clear_halt() because the state machine
* is not yet alive */
usb_clear_halt
(
us
->
pusb_dev
,
pipe
);
}
}
/* return the default -- no LUNs */
/* return the default -- no LUNs */
return
0
;
return
0
;
}
}
int
usb_stor_Bulk_reset
(
struct
us_data
*
us
);
int
usb_stor_Bulk_transport
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
)
int
usb_stor_Bulk_transport
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
)
{
{
struct
bulk_cb_wrap
bcb
;
struct
bulk_cb_wrap
bcb
;
...
@@ -1051,10 +1146,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1051,10 +1146,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
int
pipe
;
int
pipe
;
int
partial
;
int
partial
;
/* if the device was removed, then we're already reset */
if
(
!
us
->
pusb_dev
)
return
SUCCESS
;
/* set up the command wrapper */
/* set up the command wrapper */
bcb
.
Signature
=
cpu_to_le32
(
US_BULK_CB_SIGN
);
bcb
.
Signature
=
cpu_to_le32
(
US_BULK_CB_SIGN
);
bcb
.
DataTransferLength
=
cpu_to_le32
(
usb_stor_transfer_length
(
srb
));
bcb
.
DataTransferLength
=
cpu_to_le32
(
usb_stor_transfer_length
(
srb
));
...
@@ -1088,7 +1179,12 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1088,7 +1179,12 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* if we stall, we need to clear it before we go on */
/* if we stall, we need to clear it before we go on */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
pipe
);
result
=
usb_stor_clear_halt
(
us
,
pipe
);
/* if the command was aborted, indicate that */
if
(
result
==
-
ENOENT
)
return
USB_STOR_TRANSPORT_ABORTED
;
result
=
-
EPIPE
;
}
else
if
(
result
)
{
}
else
if
(
result
)
{
/* unknown error -- we've got a problem */
/* unknown error -- we've got a problem */
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_ERROR
;
...
@@ -1099,11 +1195,11 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1099,11 +1195,11 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* send/receive data payload, if there is any */
/* send/receive data payload, if there is any */
if
(
bcb
.
DataTransferLength
)
{
if
(
bcb
.
DataTransferLength
)
{
usb_stor_transfer
(
srb
,
us
);
usb_stor_transfer
(
srb
,
us
);
US_DEBUGP
(
"Bulk data transfer result 0x%x
\n
"
,
result
=
srb
->
result
;
srb
->
result
);
US_DEBUGP
(
"Bulk data transfer result 0x%x
\n
"
,
result
);
/* if it was aborted, we need to indicate that */
/* if it was aborted, we need to indicate that */
if
(
srb
->
result
==
USB_STOR_TRANSPORT
_ABORTED
)
if
(
result
==
US_BULK_TRANSFER
_ABORTED
)
return
USB_STOR_TRANSPORT_ABORTED
;
return
USB_STOR_TRANSPORT_ABORTED
;
}
}
}
}
...
@@ -1127,8 +1223,12 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1127,8 +1223,12 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* did the attempt to read the CSW fail? */
/* did the attempt to read the CSW fail? */
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
pipe
);
result
=
usb_stor_clear_halt
(
us
,
pipe
);
/* if the command was aborted, indicate that */
if
(
result
==
-
ENOENT
)
return
USB_STOR_TRANSPORT_ABORTED
;
/* get the status again */
/* get the status again */
US_DEBUGP
(
"Attempting to get CSW (2nd try)...
\n
"
);
US_DEBUGP
(
"Attempting to get CSW (2nd try)...
\n
"
);
result
=
usb_stor_bulk_msg
(
us
,
&
bcs
,
pipe
,
result
=
usb_stor_bulk_msg
(
us
,
&
bcs
,
pipe
,
...
@@ -1141,7 +1241,11 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1141,7 +1241,11 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* if it fails again, we need a reset and return an error*/
/* if it fails again, we need a reset and return an error*/
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"clearing halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing halt for pipe 0x%x
\n
"
,
pipe
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
pipe
);
result
=
usb_stor_clear_halt
(
us
,
pipe
);
/* if the command was aborted, indicate that */
if
(
result
==
-
ENOENT
)
return
USB_STOR_TRANSPORT_ABORTED
;
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_ERROR
;
}
}
}
}
...
@@ -1188,46 +1292,117 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1188,46 +1292,117 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
* Reset routines
* Reset routines
***********************************************************************/
***********************************************************************/
/* This issues a CB[I] Reset to the device in question
struct
us_timeout
{
struct
us_data
*
us
;
spinlock_t
timer_lock
;
};
/* The timeout event handler
*/
*/
int
usb_stor_CB_reset
(
struct
us_data
*
us
)
static
void
usb_stor_timeout_handler
(
unsigned
long
to__
)
{
struct
us_timeout
*
to
=
(
struct
us_timeout
*
)
to__
;
struct
us_data
*
us
=
to
->
us
;
US_DEBUGP
(
"Timeout occurred
\n
"
);
/* abort the current request */
usb_stor_abort_transport
(
us
);
/* let the reset routine know we have finished */
spin_unlock
(
&
to
->
timer_lock
);
}
/* This is the common part of the device reset code.
*
* It's handy that every transport mechanism uses the control endpoint for
* resets.
*
* Basically, we send a reset with a 20-second timeout, so we don't get
* jammed attempting to do the reset.
*/
void
usb_stor_reset_common
(
struct
us_data
*
us
,
u8
request
,
u8
requesttype
,
u16
value
,
u16
index
,
void
*
data
,
u16
size
)
{
{
unsigned
char
cmd
[
12
];
int
result
;
int
result
;
struct
us_timeout
timeout_data
=
{
us
,
SPIN_LOCK_UNLOCKED
};
struct
timer_list
timeout_list
;
US_DEBUGP
(
"CB_reset() called
\n
"
);
/* prepare the timeout handler */
spin_lock
(
&
timeout_data
.
timer_lock
);
init_timer
(
&
timeout_list
);
/*
if the device was removed, then we're already reset */
/*
A 20-second timeout may seem rather long, but a LaCie
if
(
!
us
->
pusb_dev
)
* StudioDrive USB2 device takes 16+ seconds to get going
return
SUCCESS
;
* following a powerup or USB attach event. */
memset
(
cmd
,
0xFF
,
sizeof
(
cmd
));
timeout_list
.
expires
=
jiffies
+
20
*
HZ
;
cmd
[
0
]
=
SEND_DIAGNOSTIC
;
timeout_list
.
data
=
(
unsigned
long
)
&
timeout_data
;
cmd
[
1
]
=
4
;
timeout_list
.
function
=
usb_stor_timeout_handler
;
result
=
usb_control_msg
(
us
->
pusb_dev
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
add_timer
(
&
timeout_list
);
US_CBI_ADSC
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
0
,
us
->
ifnum
,
cmd
,
sizeof
(
cmd
),
HZ
*
5
);
if
(
result
<
0
)
{
result
=
usb_stor_control_msg
(
us
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
US_DEBUGP
(
"CB[I] soft reset failed %d
\n
"
,
result
);
request
,
requesttype
,
value
,
index
,
data
,
size
);
return
FAILED
;
if
(
result
<
0
)
}
goto
Done
;
/* long wait for reset */
/* long wait for reset */
set_current_state
(
TASK_UNINTERRUPTIBLE
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
*
6
);
schedule_timeout
(
HZ
*
6
);
set_current_state
(
TASK_RUNNING
);
set_current_state
(
TASK_RUNNING
);
US_DEBUGP
(
"CB_reset: clearing endpoint halt
\n
"
);
US_DEBUGP
(
"Soft reset: clearing bulk-in endpoint halt
\n
"
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
result
=
usb_stor_clear_halt
(
us
,
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_in
));
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_in
));
usb_stor_clear_halt
(
us
->
pusb_dev
,
if
(
result
<
0
)
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
));
goto
Done
;
US_DEBUGP
(
"Soft reset: clearing bulk-out endpoint halt
\n
"
);
result
=
usb_stor_clear_halt
(
us
,
usb_sndbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
));
Done:
/* prevent the timer from coming back to haunt us */
if
(
!
del_timer
(
&
timeout_list
))
{
/* the handler has already started; wait for it to finish */
spin_lock
(
&
timeout_data
.
timer_lock
);
/* change the abort into a timeout */
if
(
result
==
-
ENOENT
)
result
=
-
ETIMEDOUT
;
}
US_DEBUGP
(
"CB_reset done
\n
"
);
/* return a result code based on the result of the control message */
/* return a result code based on the result of the control message */
return
SUCCESS
;
if
(
result
>=
0
)
US_DEBUGP
(
"Soft reset done
\n
"
);
else
US_DEBUGP
(
"Soft reset failed: %d
\n
"
,
result
);
if
(
result
==
-
ETIMEDOUT
)
us
->
srb
->
result
=
DID_TIME_OUT
<<
16
;
else
if
(
result
==
-
ENOENT
)
us
->
srb
->
result
=
DID_ABORT
<<
16
;
else
if
(
result
<
0
)
us
->
srb
->
result
=
DID_ERROR
<<
16
;
else
us
->
srb
->
result
=
GOOD
<<
1
;
}
/* This issues a CB[I] Reset to the device in question
*/
int
usb_stor_CB_reset
(
struct
us_data
*
us
)
{
unsigned
char
cmd
[
12
];
US_DEBUGP
(
"CB_reset() called
\n
"
);
memset
(
cmd
,
0xFF
,
sizeof
(
cmd
));
cmd
[
0
]
=
SEND_DIAGNOSTIC
;
cmd
[
1
]
=
4
;
usb_stor_reset_common
(
us
,
US_CBI_ADSC
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
0
,
us
->
ifnum
,
cmd
,
sizeof
(
cmd
));
return
(
us
->
srb
->
result
==
GOOD
<<
1
?
SUCCESS
:
FAILED
);
}
}
/* This issues a Bulk-only Reset to the device in question, including
/* This issues a Bulk-only Reset to the device in question, including
...
@@ -1235,34 +1410,10 @@ int usb_stor_CB_reset(struct us_data *us)
...
@@ -1235,34 +1410,10 @@ int usb_stor_CB_reset(struct us_data *us)
*/
*/
int
usb_stor_Bulk_reset
(
struct
us_data
*
us
)
int
usb_stor_Bulk_reset
(
struct
us_data
*
us
)
{
{
int
result
;
US_DEBUGP
(
"Bulk reset requested
\n
"
);
US_DEBUGP
(
"Bulk reset requested
\n
"
);
/* if the device was removed, then we're already reset */
usb_stor_reset_common
(
us
,
US_BULK_RESET_REQUEST
,
if
(
!
us
->
pusb_dev
)
return
SUCCESS
;
result
=
usb_control_msg
(
us
->
pusb_dev
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
US_BULK_RESET_REQUEST
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
0
,
us
->
ifnum
,
NULL
,
0
,
HZ
*
5
);
0
,
us
->
ifnum
,
NULL
,
0
);
return
(
us
->
srb
->
result
==
GOOD
<<
1
?
SUCCESS
:
FAILED
);
if
(
result
<
0
)
{
US_DEBUGP
(
"Bulk soft reset failed %d
\n
"
,
result
);
return
FAILED
;
}
/* long wait for reset */
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
*
6
);
set_current_state
(
TASK_RUNNING
);
usb_stor_clear_halt
(
us
->
pusb_dev
,
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_in
));
usb_stor_clear_halt
(
us
->
pusb_dev
,
usb_sndbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
));
US_DEBUGP
(
"Bulk soft reset completed
\n
"
);
return
SUCCESS
;
}
}
drivers/usb/storage/transport.h
View file @
58a5ae6a
/* Driver for USB Mass Storage compliant devices
/* Driver for USB Mass Storage compliant devices
* Transport Functions Header File
* Transport Functions Header File
*
*
* $Id: transport.h,v 1.1
5 2001/03/17 20:06:23 jrmayfield
Exp $
* $Id: transport.h,v 1.1
8 2002/04/21 02:57:59 mdharm
Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
...
@@ -146,11 +146,12 @@ extern int usb_stor_Bulk_reset(struct us_data*);
...
@@ -146,11 +146,12 @@ extern int usb_stor_Bulk_reset(struct us_data*);
extern
unsigned
int
usb_stor_transfer_length
(
Scsi_Cmnd
*
);
extern
unsigned
int
usb_stor_transfer_length
(
Scsi_Cmnd
*
);
extern
void
usb_stor_invoke_transport
(
Scsi_Cmnd
*
,
struct
us_data
*
);
extern
void
usb_stor_invoke_transport
(
Scsi_Cmnd
*
,
struct
us_data
*
);
extern
void
usb_stor_abort_transport
(
struct
us_data
*
);
extern
int
usb_stor_transfer_partial
(
struct
us_data
*
,
char
*
,
int
);
extern
int
usb_stor_transfer_partial
(
struct
us_data
*
,
char
*
,
int
);
extern
int
usb_stor_bulk_msg
(
struct
us_data
*
,
void
*
,
int
,
unsigned
int
,
extern
int
usb_stor_bulk_msg
(
struct
us_data
*
,
void
*
,
int
,
unsigned
int
,
unsigned
int
*
);
unsigned
int
*
);
extern
int
usb_stor_control_msg
(
struct
us_data
*
,
unsigned
int
,
u8
,
u8
,
extern
int
usb_stor_control_msg
(
struct
us_data
*
,
unsigned
int
,
u8
,
u8
,
u16
,
u16
,
void
*
,
u16
);
u16
,
u16
,
void
*
,
u16
);
extern
int
usb_stor_clear_halt
(
struct
us_data
*
,
int
);
extern
void
usb_stor_transfer
(
Scsi_Cmnd
*
,
struct
us_data
*
);
extern
void
usb_stor_transfer
(
Scsi_Cmnd
*
,
struct
us_data
*
);
extern
int
usb_stor_clear_halt
(
struct
usb_device
*
,
int
);
#endif
#endif
drivers/usb/storage/unusual_devs.h
View file @
58a5ae6a
/* Driver for USB Mass Storage compliant devices
/* Driver for USB Mass Storage compliant devices
* Ununsual Devices File
* Ununsual Devices File
*
*
* $Id: unusual_devs.h,v 1.
25 2002/01/13 06:39:17
mdharm Exp $
* $Id: unusual_devs.h,v 1.
32 2002/02/25 02:41:24
mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 2000
-2002
Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
*
* Initial work by:
* Initial work by:
* (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc.
* (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc.
...
@@ -110,6 +110,13 @@ UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200,
...
@@ -110,6 +110,13 @@ UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200,
"LS-120 Camera"
,
"LS-120 Camera"
,
US_SC_UFI
,
US_PR_CBI
,
NULL
,
0
),
US_SC_UFI
,
US_PR_CBI
,
NULL
,
0
),
/* Reported by Peter Wchtler <pwaechtler@loewe-komp.de> */
UNUSUAL_DEV
(
0x04ce
,
0x0002
,
0x0074
,
0x0074
,
"ScanLogic"
,
"SL11R-IDE 0049SQFP-1.2 A002"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Most of the following entries were developed with the help of
/* Most of the following entries were developed with the help of
* Shuttle/SCM directly.
* Shuttle/SCM directly.
*/
*/
...
@@ -198,7 +205,7 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
...
@@ -198,7 +205,7 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100,
/* This entry is needed because the device reports Sub=ff */
/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV
(
0x054c
,
0x0010
,
0x0106
,
0x0422
,
UNUSUAL_DEV
(
0x054c
,
0x0010
,
0x0106
,
0x0422
,
"Sony"
,
"Sony"
,
"DSC-S30/S70/S75/505V/F505"
,
"DSC-S30/S70/S75/505V/F505
/F707
"
,
US_SC_SCSI
,
US_PR_CB
,
NULL
,
US_SC_SCSI
,
US_PR_CB
,
NULL
,
US_FL_SINGLE_LUN
|
US_FL_START_STOP
|
US_FL_MODE_XLATE
),
US_FL_SINGLE_LUN
|
US_FL_START_STOP
|
US_FL_MODE_XLATE
),
...
@@ -289,9 +296,36 @@ UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
...
@@ -289,9 +296,36 @@ UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
"Lexar"
,
"Lexar"
,
"Jumpshot USB CF Reader"
,
"Jumpshot USB CF Reader"
,
US_SC_SCSI
,
US_PR_JUMPSHOT
,
NULL
,
US_SC_SCSI
,
US_PR_JUMPSHOT
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
),
US_FL_MODE_XLATE
),
#endif
#endif
/* Reported by Carlos Villegas <cav@uniscope.co.jp>
* This device needs an INQUIRY of exactly 36-bytes to function.
* That is the only reason this entry is needed.
*/
UNUSUAL_DEV
(
0x05e3
,
0x0700
,
0x0000
,
0xffff
,
"SIIG"
,
"CompactFlash Card Reader"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Reported by Peter Marks <peter.marks@turner.com>
* Like the SIIG unit above, this unit needs an INQUIRY to ask for exactly
* 36 bytes of data. No more, no less. That is the only reason this entry
* is needed.
*/
UNUSUAL_DEV
(
0x05e3
,
0x0702
,
0x0000
,
0xffff
,
"EagleTec"
,
"External Hard Disk"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_FIX_INQUIRY
),
UNUSUAL_DEV
(
0x05e3
,
0x0700
,
0x0000
,
0x9999
,
"Unknown"
,
"GL641USB based CF Card reader"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_FIX_INQUIRY
|
US_FL_MODE_XLATE
),
UNUSUAL_DEV
(
0x0644
,
0x0000
,
0x0100
,
0x0100
,
UNUSUAL_DEV
(
0x0644
,
0x0000
,
0x0100
,
0x0100
,
"TEAC"
,
"TEAC"
,
"Floppy Drive"
,
"Floppy Drive"
,
...
@@ -305,6 +339,14 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
...
@@ -305,6 +339,14 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
US_FL_SINGLE_LUN
|
US_FL_START_STOP
),
US_FL_SINGLE_LUN
|
US_FL_START_STOP
),
#endif
#endif
/* Submitted by kedar@centillium
* Needed for START_STOP flag, but that is unconfirmed */
UNUSUAL_DEV
(
0x0686
,
0x4006
,
0x0001
,
0x0001
,
"Minolta"
,
"Dimage S304"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_START_STOP
),
/* Submitted by f.brugmans@hccnet.nl
/* Submitted by f.brugmans@hccnet.nl
* Needed for START_STOP flag */
* Needed for START_STOP flag */
UNUSUAL_DEV
(
0x0686
,
0x4007
,
0x0001
,
0x0001
,
UNUSUAL_DEV
(
0x0686
,
0x4007
,
0x0001
,
0x0001
,
...
@@ -381,7 +423,7 @@ UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015,
...
@@ -381,7 +423,7 @@ UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015,
"Datafab"
,
"Datafab"
,
"MDCFE-B USB CF Reader"
,
"MDCFE-B USB CF Reader"
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
),
US_FL_MODE_XLATE
),
/*
/*
* The following Datafab-based devices may or may not work
* The following Datafab-based devices may or may not work
...
@@ -398,38 +440,38 @@ UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
...
@@ -398,38 +440,38 @@ UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
"SIIG/Datafab"
,
"SIIG/Datafab"
,
"SIIG/Datafab Memory Stick+CF Reader/Writer"
,
"SIIG/Datafab Memory Stick+CF Reader/Writer"
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
),
US_FL_MODE_XLATE
),
UNUSUAL_DEV
(
0x07c4
,
0xa003
,
0x0000
,
0xffff
,
UNUSUAL_DEV
(
0x07c4
,
0xa003
,
0x0000
,
0xffff
,
"Datafab/Unknown"
,
"Datafab/Unknown"
,
"Datafab-based Reader"
,
"Datafab-based Reader"
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
),
US_FL_MODE_XLATE
),
UNUSUAL_DEV
(
0x07c4
,
0xa004
,
0x0000
,
0xffff
,
UNUSUAL_DEV
(
0x07c4
,
0xa004
,
0x0000
,
0xffff
,
"Datafab/Unknown"
,
"Datafab/Unknown"
,
"Datafab-based Reader"
,
"Datafab-based Reader"
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
),
US_FL_MODE_XLATE
),
UNUSUAL_DEV
(
0x07c4
,
0xa005
,
0x0000
,
0xffff
,
UNUSUAL_DEV
(
0x07c4
,
0xa005
,
0x0000
,
0xffff
,
"PNY/Datafab"
,
"PNY/Datafab"
,
"PNY/Datafab CF+SM Reader"
,
"PNY/Datafab CF+SM Reader"
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
),
US_FL_MODE_XLATE
),
UNUSUAL_DEV
(
0x07c4
,
0xa006
,
0x0000
,
0xffff
,
UNUSUAL_DEV
(
0x07c4
,
0xa006
,
0x0000
,
0xffff
,
"Simple Tech/Datafab"
,
"Simple Tech/Datafab"
,
"Simple Tech/Datafab CF+SM Reader"
,
"Simple Tech/Datafab CF+SM Reader"
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
),
US_FL_MODE_XLATE
),
/* Submitted by Olaf Hering <olh@suse.de> */
/* Submitted by Olaf Hering <olh@suse.de> */
UNUSUAL_DEV
(
0x07c4
,
0xa109
,
0x0000
,
0xffff
,
UNUSUAL_DEV
(
0x07c4
,
0xa109
,
0x0000
,
0xffff
,
"Datafab Systems, Inc."
,
"Datafab Systems, Inc."
,
"USB to CF + SM Combo (LC1)"
,
"USB to CF + SM Combo (LC1)"
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_SC_SCSI
,
US_PR_DATAFAB
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
),
US_FL_MODE_XLATE
),
#endif
#endif
/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
...
@@ -451,6 +493,12 @@ UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001,
...
@@ -451,6 +493,12 @@ UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001,
US_SC_SCSI
,
US_PR_CB
,
NULL
,
US_SC_SCSI
,
US_PR_CB
,
NULL
,
US_FL_MODE_XLATE
),
US_FL_MODE_XLATE
),
UNUSUAL_DEV
(
0x0a16
,
0x8888
,
0x0100
,
0x0100
,
"IBM"
,
"IBM USB Memory Key"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_FIX_INQUIRY
),
#ifdef CONFIG_USB_STORAGE_ISD200
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV
(
0x0bf6
,
0xa001
,
0x0100
,
0x0110
,
UNUSUAL_DEV
(
0x0bf6
,
0xa001
,
0x0100
,
0x0110
,
"ATI"
,
"ATI"
,
...
@@ -459,6 +507,13 @@ UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
...
@@ -459,6 +507,13 @@ UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
0
),
0
),
#endif
#endif
/* EasyDisk support. Submitted by Stanislav Karchebny <berk@madfire.net> */
UNUSUAL_DEV
(
0x1065
,
0x2136
,
0x0000
,
0x0001
,
"Global Channel Solutions"
,
"EasyDisk EDxxxx"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
|
US_FL_FIX_INQUIRY
),
/* Submitted by Brian Hall <brihall@bigfoot.com>
/* Submitted by Brian Hall <brihall@bigfoot.com>
* Needed for START_STOP flag */
* Needed for START_STOP flag */
UNUSUAL_DEV
(
0x0c76
,
0x0003
,
0x0100
,
0x0100
,
UNUSUAL_DEV
(
0x0c76
,
0x0003
,
0x0100
,
0x0100
,
...
@@ -469,6 +524,8 @@ UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100,
...
@@ -469,6 +524,8 @@ UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100,
/* Reported by Dan Pilone <pilone@slac.com>
/* Reported by Dan Pilone <pilone@slac.com>
* The device needs the flags only.
* The device needs the flags only.
* Also reported by Brian Hall <brihall@bigfoot.com>, again for flags.
* I also suspect this device may have a broken serial number.
*/
*/
UNUSUAL_DEV
(
0x1065
,
0x2136
,
0x0000
,
0x9999
,
UNUSUAL_DEV
(
0x1065
,
0x2136
,
0x0000
,
0x9999
,
"CCYU TECHNOLOGY"
,
"CCYU TECHNOLOGY"
,
...
...
drivers/usb/storage/usb.c
View file @
58a5ae6a
/* Driver for USB Mass Storage compliant devices
/* Driver for USB Mass Storage compliant devices
*
*
* $Id: usb.c,v 1.7
0 2002/01/06 07:14:12
mdharm Exp $
* $Id: usb.c,v 1.7
5 2002/04/22 03:39:43
mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 1999
, 2000
Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999
-2002
Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
*
* Developed with the assistance of:
* Developed with the assistance of:
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
...
@@ -315,6 +315,7 @@ static int usb_stor_control_thread(void * __us)
...
@@ -315,6 +315,7 @@ static int usb_stor_control_thread(void * __us)
* so get rid of all our resources..
* so get rid of all our resources..
*/
*/
daemonize
();
daemonize
();
reparent_to_init
();
/* avoid getting signals */
/* avoid getting signals */
spin_lock_irq
(
&
current
->
sigmask_lock
);
spin_lock_irq
(
&
current
->
sigmask_lock
);
...
@@ -409,7 +410,7 @@ static int usb_stor_control_thread(void * __us)
...
@@ -409,7 +410,7 @@ static int usb_stor_control_thread(void * __us)
down
(
&
(
us
->
dev_semaphore
));
down
(
&
(
us
->
dev_semaphore
));
/* our device has gone - pretend not ready */
/* our device has gone - pretend not ready */
if
(
!
us
->
pusb_dev
)
{
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_DETACHED
)
{
US_DEBUGP
(
"Request is for removed device
\n
"
);
US_DEBUGP
(
"Request is for removed device
\n
"
);
/* For REQUEST_SENSE, it's the data. But
/* For REQUEST_SENSE, it's the data. But
* for anything else, it should look like
* for anything else, it should look like
...
@@ -433,7 +434,7 @@ static int usb_stor_control_thread(void * __us)
...
@@ -433,7 +434,7 @@ static int usb_stor_control_thread(void * __us)
sizeof
(
usb_stor_sense_notready
));
sizeof
(
usb_stor_sense_notready
));
us
->
srb
->
result
=
CHECK_CONDITION
<<
1
;
us
->
srb
->
result
=
CHECK_CONDITION
<<
1
;
}
}
}
else
{
/*
!us->pusb_dev
*/
}
else
{
/*
atomic_read(&us->sm_state) == STATE_DETACHED
*/
/* Handle those devices which need us to fake
/* Handle those devices which need us to fake
* their inquiry data */
* their inquiry data */
...
@@ -449,7 +450,9 @@ static int usb_stor_control_thread(void * __us)
...
@@ -449,7 +450,9 @@ static int usb_stor_control_thread(void * __us)
}
else
{
}
else
{
/* we've got a command, let's do it! */
/* we've got a command, let's do it! */
US_DEBUG
(
usb_stor_show_command
(
us
->
srb
));
US_DEBUG
(
usb_stor_show_command
(
us
->
srb
));
atomic_set
(
&
us
->
sm_state
,
US_STATE_RUNNING
);
us
->
proto_handler
(
us
->
srb
,
us
);
us
->
proto_handler
(
us
->
srb
,
us
);
atomic_set
(
&
us
->
sm_state
,
US_STATE_IDLE
);
}
}
}
}
...
@@ -713,6 +716,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -713,6 +716,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* establish the connection to the new device upon reconnect */
/* establish the connection to the new device upon reconnect */
ss
->
ifnum
=
ifnum
;
ss
->
ifnum
=
ifnum
;
ss
->
pusb_dev
=
dev
;
ss
->
pusb_dev
=
dev
;
atomic_set
(
&
ss
->
sm_state
,
US_STATE_IDLE
);
/* copy over the endpoint data */
/* copy over the endpoint data */
if
(
ep_in
)
if
(
ep_in
)
...
@@ -955,6 +959,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -955,6 +959,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
ss
->
protocol_name
=
"Unknown"
;
ss
->
protocol_name
=
"Unknown"
;
kfree
(
ss
->
current_urb
);
kfree
(
ss
->
current_urb
);
kfree
(
ss
);
kfree
(
ss
);
usb_dec_dev_use
(
dev
);
return
NULL
;
return
NULL
;
break
;
break
;
}
}
...
@@ -962,6 +967,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -962,6 +967,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* allocate an IRQ callback if one is needed */
/* allocate an IRQ callback if one is needed */
if
((
ss
->
protocol
==
US_PR_CBI
)
&&
usb_stor_allocate_irq
(
ss
))
{
if
((
ss
->
protocol
==
US_PR_CBI
)
&&
usb_stor_allocate_irq
(
ss
))
{
kfree
(
ss
->
current_urb
);
kfree
(
ss
);
usb_dec_dev_use
(
dev
);
usb_dec_dev_use
(
dev
);
return
NULL
;
return
NULL
;
}
}
...
@@ -990,6 +997,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -990,6 +997,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
unusual_dev
->
initFunction
(
ss
);
unusual_dev
->
initFunction
(
ss
);
/* start up our control thread */
/* start up our control thread */
atomic_set
(
&
ss
->
sm_state
,
US_STATE_IDLE
);
ss
->
pid
=
kernel_thread
(
usb_stor_control_thread
,
ss
,
ss
->
pid
=
kernel_thread
(
usb_stor_control_thread
,
ss
,
CLONE_VM
);
CLONE_VM
);
if
(
ss
->
pid
<
0
)
{
if
(
ss
->
pid
<
0
)
{
...
@@ -1006,7 +1014,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -1006,7 +1014,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* now register - our detect function will be called */
/* now register - our detect function will be called */
ss
->
htmplt
.
module
=
THIS_MODULE
;
ss
->
htmplt
.
module
=
THIS_MODULE
;
scsi_register_host
(
&
ss
->
htmplt
);
scsi_register_host
(
&
(
ss
->
htmplt
)
);
/* lock access to the data structures */
/* lock access to the data structures */
down
(
&
us_list_semaphore
);
down
(
&
us_list_semaphore
);
...
@@ -1066,6 +1074,7 @@ static void storage_disconnect(struct usb_device *dev, void *ptr)
...
@@ -1066,6 +1074,7 @@ static void storage_disconnect(struct usb_device *dev, void *ptr)
/* mark the device as gone */
/* mark the device as gone */
usb_dec_dev_use
(
ss
->
pusb_dev
);
usb_dec_dev_use
(
ss
->
pusb_dev
);
ss
->
pusb_dev
=
NULL
;
ss
->
pusb_dev
=
NULL
;
atomic_set
(
&
ss
->
sm_state
,
US_STATE_DETACHED
);
/* unlock access to the device data structure */
/* unlock access to the device data structure */
up
(
&
(
ss
->
dev_semaphore
));
up
(
&
(
ss
->
dev_semaphore
));
...
@@ -1112,7 +1121,7 @@ void __exit usb_stor_exit(void)
...
@@ -1112,7 +1121,7 @@ void __exit usb_stor_exit(void)
*/
*/
for
(
next
=
us_list
;
next
;
next
=
next
->
next
)
{
for
(
next
=
us_list
;
next
;
next
=
next
->
next
)
{
US_DEBUGP
(
"-- calling scsi_unregister_host()
\n
"
);
US_DEBUGP
(
"-- calling scsi_unregister_host()
\n
"
);
scsi_unregister_host
(
&
next
->
htmplt
);
scsi_unregister_host
(
&
(
next
->
htmplt
)
);
}
}
/* While there are still structures, free them. Note that we are
/* While there are still structures, free them. Note that we are
...
...
drivers/usb/storage/usb.h
View file @
58a5ae6a
/* Driver for USB Mass Storage compliant devices
/* Driver for USB Mass Storage compliant devices
* Main Header File
* Main Header File
*
*
* $Id: usb.h,v 1.
18 2001/07/30 00:2
7:59 mdharm Exp $
* $Id: usb.h,v 1.
21 2002/04/21 02:5
7:59 mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
...
@@ -102,6 +102,12 @@ struct us_unusual_dev {
...
@@ -102,6 +102,12 @@ struct us_unusual_dev {
#define US_FL_SCM_MULT_TARG 0x00000020
/* supports multiple targets */
#define US_FL_SCM_MULT_TARG 0x00000020
/* supports multiple targets */
#define US_FL_FIX_INQUIRY 0x00000040
/* INQUIRY response needs fixing */
#define US_FL_FIX_INQUIRY 0x00000040
/* INQUIRY response needs fixing */
#define US_STATE_DETACHED 1
/* State machine states */
#define US_STATE_IDLE 2
#define US_STATE_RUNNING 3
#define US_STATE_RESETTING 4
#define US_STATE_ABORTING 5
#define USB_STOR_STRING_LEN 32
#define USB_STOR_STRING_LEN 32
typedef
int
(
*
trans_cmnd
)(
Scsi_Cmnd
*
,
struct
us_data
*
);
typedef
int
(
*
trans_cmnd
)(
Scsi_Cmnd
*
,
struct
us_data
*
);
...
@@ -152,10 +158,12 @@ struct us_data {
...
@@ -152,10 +158,12 @@ struct us_data {
Scsi_Cmnd
*
queue_srb
;
/* the single queue slot */
Scsi_Cmnd
*
queue_srb
;
/* the single queue slot */
int
action
;
/* what to do */
int
action
;
/* what to do */
int
pid
;
/* control thread */
int
pid
;
/* control thread */
atomic_t
sm_state
;
/* interrupt info for CBI devices -- only good if attached */
/* interrupt info for CBI devices -- only good if attached */
struct
semaphore
ip_waitq
;
/* for CBI interrupts */
struct
semaphore
ip_waitq
;
/* for CBI interrupts */
atomic_t
ip_wanted
[
1
];
/* is an IRQ expected? */
unsigned
long
bitflags
;
/* single-bit flags: */
#define IP_WANTED 1
/* is an IRQ expected? */
/* interrupt communications data */
/* interrupt communications data */
struct
semaphore
irq_urb_sem
;
/* to protect irq_urb */
struct
semaphore
irq_urb_sem
;
/* to protect irq_urb */
...
@@ -188,4 +196,5 @@ extern struct usb_driver usb_storage_driver;
...
@@ -188,4 +196,5 @@ extern struct usb_driver usb_storage_driver;
/* Function to fill an inquiry response. See usb.c for details */
/* Function to fill an inquiry response. See usb.c for details */
extern
void
fill_inquiry_response
(
struct
us_data
*
us
,
extern
void
fill_inquiry_response
(
struct
us_data
*
us
,
unsigned
char
*
data
,
unsigned
int
data_len
);
unsigned
char
*
data
,
unsigned
int
data_len
);
#endif
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment