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
34d3616d
Commit
34d3616d
authored
Oct 12, 2002
by
Alan Cox
Committed by
Linus Torvalds
Oct 12, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] forward port of the various scsi fixes from 2.4
parent
4108966a
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
473 additions
and
348 deletions
+473
-348
drivers/scsi/scsi.c
drivers/scsi/scsi.c
+4
-8
drivers/scsi/scsi.h
drivers/scsi/scsi.h
+3
-1
drivers/scsi/scsi_error.c
drivers/scsi/scsi_error.c
+166
-111
drivers/scsi/scsi_ioctl.c
drivers/scsi/scsi_ioctl.c
+25
-17
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_lib.c
+25
-28
drivers/scsi/scsi_syms.c
drivers/scsi/scsi_syms.c
+1
-0
drivers/scsi/sd.c
drivers/scsi/sd.c
+3
-3
drivers/scsi/sr.c
drivers/scsi/sr.c
+17
-9
drivers/scsi/sr.h
drivers/scsi/sr.h
+5
-1
drivers/scsi/sr_ioctl.c
drivers/scsi/sr_ioctl.c
+152
-127
drivers/scsi/sr_vendor.c
drivers/scsi/sr_vendor.c
+72
-43
No files found.
drivers/scsi/scsi.c
View file @
34d3616d
...
@@ -1399,14 +1399,10 @@ static void scsi_softirq(struct softirq_action *h)
...
@@ -1399,14 +1399,10 @@ static void scsi_softirq(struct softirq_action *h)
*/
*/
int
scsi_retry_command
(
Scsi_Cmnd
*
SCpnt
)
int
scsi_retry_command
(
Scsi_Cmnd
*
SCpnt
)
{
{
memcpy
((
void
*
)
SCpnt
->
cmnd
,
(
void
*
)
SCpnt
->
data_cmnd
,
/*
sizeof
(
SCpnt
->
data_cmnd
));
* Restore the SCSI command state.
SCpnt
->
request_buffer
=
SCpnt
->
buffer
;
*/
SCpnt
->
request_bufflen
=
SCpnt
->
bufflen
;
scsi_setup_cmd_retry
(
SCpnt
);
SCpnt
->
use_sg
=
SCpnt
->
old_use_sg
;
SCpnt
->
cmd_len
=
SCpnt
->
old_cmd_len
;
SCpnt
->
sc_data_direction
=
SCpnt
->
sc_old_data_direction
;
SCpnt
->
underflow
=
SCpnt
->
old_underflow
;
/*
/*
* Zero the sense information from the last time we tried
* Zero the sense information from the last time we tried
...
...
drivers/scsi/scsi.h
View file @
34d3616d
...
@@ -467,6 +467,7 @@ extern Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate,
...
@@ -467,6 +467,7 @@ extern Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate,
int
sectors
);
int
sectors
);
extern
struct
Scsi_Device_Template
*
scsi_get_request_dev
(
struct
request
*
);
extern
struct
Scsi_Device_Template
*
scsi_get_request_dev
(
struct
request
*
);
extern
int
scsi_init_cmd_errh
(
Scsi_Cmnd
*
SCpnt
);
extern
int
scsi_init_cmd_errh
(
Scsi_Cmnd
*
SCpnt
);
extern
void
scsi_setup_cmd_retry
(
Scsi_Cmnd
*
SCpnt
);
extern
int
scsi_insert_special_cmd
(
Scsi_Cmnd
*
SCpnt
,
int
);
extern
int
scsi_insert_special_cmd
(
Scsi_Cmnd
*
SCpnt
,
int
);
extern
void
scsi_io_completion
(
Scsi_Cmnd
*
SCpnt
,
int
good_sectors
,
extern
void
scsi_io_completion
(
Scsi_Cmnd
*
SCpnt
,
int
good_sectors
,
int
block_sectors
);
int
block_sectors
);
...
@@ -597,9 +598,10 @@ struct scsi_device {
...
@@ -597,9 +598,10 @@ struct scsi_device {
unsigned
changed
:
1
;
/* Data invalid due to media change */
unsigned
changed
:
1
;
/* Data invalid due to media change */
unsigned
busy
:
1
;
/* Used to prevent races */
unsigned
busy
:
1
;
/* Used to prevent races */
unsigned
lockable
:
1
;
/* Able to prevent media removal */
unsigned
lockable
:
1
;
/* Able to prevent media removal */
unsigned
locked
:
1
;
/* Media removal disabled */
unsigned
borken
:
1
;
/* Tell the Seagate driver to be
unsigned
borken
:
1
;
/* Tell the Seagate driver to be
* painfully slow on this device */
* painfully slow on this device */
//
unsigned disconnect:1; /* can disconnect */
unsigned
disconnect
:
1
;
/* can disconnect */
unsigned
soft_reset
:
1
;
/* Uses soft reset option */
unsigned
soft_reset
:
1
;
/* Uses soft reset option */
unsigned
sdtr
:
1
;
/* Device supports SDTR messages */
unsigned
sdtr
:
1
;
/* Device supports SDTR messages */
unsigned
wdtr
:
1
;
/* Device supports WDTR messages */
unsigned
wdtr
:
1
;
/* Device supports WDTR messages */
...
...
drivers/scsi/scsi_error.c
View file @
34d3616d
...
@@ -8,6 +8,10 @@
...
@@ -8,6 +8,10 @@
*
*
* Restructured scsi_unjam_host and associated functions.
* Restructured scsi_unjam_host and associated functions.
* September 04, 2002 Mike Anderson (andmike@us.ibm.com)
* September 04, 2002 Mike Anderson (andmike@us.ibm.com)
*
* Forward port of Russell King's (rmk@arm.linux.org.uk) changes and
* minor cleanups.
* September 30, 2002 Mike Anderson (andmike@us.ibm.com)
*/
*/
#include <linux/module.h>
#include <linux/module.h>
...
@@ -35,6 +39,8 @@
...
@@ -35,6 +39,8 @@
#include "scsi.h"
#include "scsi.h"
#include "hosts.h"
#include "hosts.h"
#include <scsi/scsi_ioctl.h>
/* grr */
/*
/*
* We must always allow SHUTDOWN_SIGS. Even if we are not a module,
* We must always allow SHUTDOWN_SIGS. Even if we are not a module,
* the host drivers that we are using may be loaded as modules, and
* the host drivers that we are using may be loaded as modules, and
...
@@ -59,7 +65,7 @@
...
@@ -59,7 +65,7 @@
* These should *probably* be handled by the host itself.
* These should *probably* be handled by the host itself.
* Since it is allowed to sleep, it probably should.
* Since it is allowed to sleep, it probably should.
*/
*/
#define BUS_RESET_SETTLE_TIME
5
*HZ
#define BUS_RESET_SETTLE_TIME
10
*HZ
#define HOST_RESET_SETTLE_TIME 10*HZ
#define HOST_RESET_SETTLE_TIME 10*HZ
/**
/**
...
@@ -91,9 +97,9 @@ void scsi_add_timer(Scsi_Cmnd *scmd, int timeout, void (*complete)
...
@@ -91,9 +97,9 @@ void scsi_add_timer(Scsi_Cmnd *scmd, int timeout, void (*complete)
scmd
->
eh_timeout
.
expires
=
jiffies
+
timeout
;
scmd
->
eh_timeout
.
expires
=
jiffies
+
timeout
;
scmd
->
eh_timeout
.
function
=
(
void
(
*
)(
unsigned
long
))
complete
;
scmd
->
eh_timeout
.
function
=
(
void
(
*
)(
unsigned
long
))
complete
;
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"
Adding timer for command %p at
"
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"
%s: scmd: %p, time:
"
"
%d (%p)
\n
"
,
scmd
,
timeout
,
"
%d, (%p)
\n
"
,
__FUNCTION__
,
complete
));
scmd
,
timeout
,
complete
));
add_timer
(
&
scmd
->
eh_timeout
);
add_timer
(
&
scmd
->
eh_timeout
);
...
@@ -116,8 +122,9 @@ int scsi_delete_timer(Scsi_Cmnd *scmd)
...
@@ -116,8 +122,9 @@ int scsi_delete_timer(Scsi_Cmnd *scmd)
rtn
=
del_timer
(
&
scmd
->
eh_timeout
);
rtn
=
del_timer
(
&
scmd
->
eh_timeout
);
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"Clearing timer for command %p"
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"%s: scmd: %p,"
" %d
\n
"
,
scmd
,
rtn
));
" rtn: %d
\n
"
,
__FUNCTION__
,
scmd
,
rtn
));
scmd
->
eh_timeout
.
data
=
(
unsigned
long
)
NULL
;
scmd
->
eh_timeout
.
data
=
(
unsigned
long
)
NULL
;
scmd
->
eh_timeout
.
function
=
NULL
;
scmd
->
eh_timeout
.
function
=
NULL
;
...
@@ -150,7 +157,7 @@ void scsi_times_out(Scsi_Cmnd *scmd)
...
@@ -150,7 +157,7 @@ void scsi_times_out(Scsi_Cmnd *scmd)
scsi_host_failed_inc_and_test
(
scmd
->
host
);
scsi_host_failed_inc_and_test
(
scmd
->
host
);
SCSI_LOG_TIMEOUT
(
3
,
printk
(
"Command timed out active=%d busy=%d "
SCSI_LOG_TIMEOUT
(
3
,
printk
(
"Command timed out active=%d busy=%d "
"failed=%d
\n
"
,
"
failed=%d
\n
"
,
atomic_read
(
&
scmd
->
host
->
host_active
),
atomic_read
(
&
scmd
->
host
->
host_active
),
scmd
->
host
->
host_busy
,
scmd
->
host
->
host_busy
,
scmd
->
host
->
host_failed
));
scmd
->
host
->
host_failed
));
...
@@ -173,7 +180,7 @@ int scsi_block_when_processing_errors(Scsi_Device *sdev)
...
@@ -173,7 +180,7 @@ int scsi_block_when_processing_errors(Scsi_Device *sdev)
SCSI_SLEEP
(
&
sdev
->
host
->
host_wait
,
sdev
->
host
->
in_recovery
);
SCSI_SLEEP
(
&
sdev
->
host
->
host_wait
,
sdev
->
host
->
in_recovery
);
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"
Open returning %d
\n
"
,
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"
%s: rtn: %d
\n
"
,
__FUNCTION__
,
sdev
->
online
));
sdev
->
online
));
return
sdev
->
online
;
return
sdev
->
online
;
...
@@ -209,10 +216,10 @@ static void scsi_eh_prt_fail_stats(Scsi_Cmnd *sc_list, struct Scsi_Host *shost)
...
@@ -209,10 +216,10 @@ static void scsi_eh_prt_fail_stats(Scsi_Cmnd *sc_list, struct Scsi_Host *shost)
if
(
cmd_timed_out
||
cmd_failed
)
{
if
(
cmd_timed_out
||
cmd_failed
)
{
SCSI_LOG_ERROR_RECOVERY
(
3
,
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"
scsi_eh
: %d:%d:%d:%d cmds failed: %d,"
printk
(
"
%s
: %d:%d:%d:%d cmds failed: %d,"
"timedout: %d
\n
"
,
"
timedout: %d
\n
"
,
shost
->
host_no
,
sdev
->
channel
,
__FUNCTION__
,
shost
->
host_no
,
sdev
->
id
,
sdev
->
lun
,
sdev
->
channel
,
sdev
->
id
,
sdev
->
lun
,
cmd_failed
,
cmd_timed_out
));
cmd_failed
,
cmd_timed_out
));
cmd_timed_out
=
0
;
cmd_timed_out
=
0
;
cmd_failed
=
0
;
cmd_failed
=
0
;
...
@@ -220,8 +227,8 @@ static void scsi_eh_prt_fail_stats(Scsi_Cmnd *sc_list, struct Scsi_Host *shost)
...
@@ -220,8 +227,8 @@ static void scsi_eh_prt_fail_stats(Scsi_Cmnd *sc_list, struct Scsi_Host *shost)
}
}
}
}
SCSI_LOG_ERROR_RECOVERY
(
2
,
printk
(
"Total of %d commands on %d
"
SCSI_LOG_ERROR_RECOVERY
(
2
,
printk
(
"Total of %d commands on %d"
"devices require eh work
\n
"
,
"
devices require eh work
\n
"
,
total_failures
,
devices_failed
));
total_failures
,
devices_failed
));
}
}
#endif
#endif
...
@@ -265,10 +272,10 @@ static void scsi_eh_get_failed(Scsi_Cmnd **sc_list, struct Scsi_Host *shost)
...
@@ -265,10 +272,10 @@ static void scsi_eh_get_failed(Scsi_Cmnd **sc_list, struct Scsi_Host *shost)
* queued and will be finished along the
* queued and will be finished along the
* way.
* way.
*/
*/
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error hdlr
"
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error hdlr"
"
prematurely woken
"
"
prematurely woken
"
"
cmds still active
"
"
cmds still active
"
"(%p %x %d)
\n
"
,
"
(%p %x %d)
\n
"
,
scmd
,
scmd
->
state
,
scmd
,
scmd
->
state
,
scmd
->
target
));
scmd
->
target
));
}
}
...
@@ -278,12 +285,17 @@ static void scsi_eh_get_failed(Scsi_Cmnd **sc_list, struct Scsi_Host *shost)
...
@@ -278,12 +285,17 @@ static void scsi_eh_get_failed(Scsi_Cmnd **sc_list, struct Scsi_Host *shost)
SCSI_LOG_ERROR_RECOVERY
(
1
,
scsi_eh_prt_fail_stats
(
*
sc_list
,
shost
));
SCSI_LOG_ERROR_RECOVERY
(
1
,
scsi_eh_prt_fail_stats
(
*
sc_list
,
shost
));
BUG_ON
(
shost
->
host_failed
!=
found
);
if
(
shost
->
host_failed
!=
found
)
printk
(
KERN_ERR
"%s: host_failed: %d != found: %d
\n
"
,
__FUNCTION__
,
shost
->
host_failed
,
found
);
}
}
/**
/**
* scsi_check_sense - Examine scsi cmd sense
* scsi_check_sense - Examine scsi cmd sense
* @scmd: Cmd to have sense checked.
* @scmd: Cmd to have sense checked.
*
* Return value:
* SUCCESS or FAILED or NEEDS_RETRY
**/
**/
static
int
scsi_check_sense
(
Scsi_Cmnd
*
scmd
)
static
int
scsi_check_sense
(
Scsi_Cmnd
*
scmd
)
{
{
...
@@ -353,7 +365,6 @@ static int scsi_check_sense(Scsi_Cmnd *scmd)
...
@@ -353,7 +365,6 @@ static int scsi_check_sense(Scsi_Cmnd *scmd)
**/
**/
static
int
scsi_eh_completed_normally
(
Scsi_Cmnd
*
scmd
)
static
int
scsi_eh_completed_normally
(
Scsi_Cmnd
*
scmd
)
{
{
int
rtn
;
/*
/*
* first check the host byte, to see if there is anything in there
* first check the host byte, to see if there is anything in there
...
@@ -369,7 +380,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
...
@@ -369,7 +380,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
* SUCCESS.
* SUCCESS.
*/
*/
scmd
->
flags
&=
~
IS_RESETTING
;
scmd
->
flags
&=
~
IS_RESETTING
;
goto
maybe_retry
;
return
NEEDS_RETRY
;
}
}
/*
/*
* rats. we are already in the error handler, so we now
* rats. we are already in the error handler, so we now
...
@@ -377,10 +388,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
...
@@ -377,10 +388,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
* is valid, we have a pretty good idea of what to do.
* is valid, we have a pretty good idea of what to do.
* if not, we mark it as FAILED.
* if not, we mark it as FAILED.
*/
*/
rtn
=
scsi_check_sense
(
scmd
);
return
scsi_check_sense
(
scmd
);
if
(
rtn
==
NEEDS_RETRY
)
goto
maybe_retry
;
return
rtn
;
}
}
if
(
host_byte
(
scmd
->
result
)
!=
DID_OK
)
{
if
(
host_byte
(
scmd
->
result
)
!=
DID_OK
)
{
return
FAILED
;
return
FAILED
;
...
@@ -400,10 +408,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
...
@@ -400,10 +408,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
case
COMMAND_TERMINATED
:
case
COMMAND_TERMINATED
:
return
SUCCESS
;
return
SUCCESS
;
case
CHECK_CONDITION
:
case
CHECK_CONDITION
:
rtn
=
scsi_check_sense
(
scmd
);
return
scsi_check_sense
(
scmd
);
if
(
rtn
==
NEEDS_RETRY
)
goto
maybe_retry
;
return
rtn
;
case
CONDITION_GOOD
:
case
CONDITION_GOOD
:
case
INTERMEDIATE_GOOD
:
case
INTERMEDIATE_GOOD
:
case
INTERMEDIATE_C_GOOD
:
case
INTERMEDIATE_C_GOOD
:
...
@@ -418,14 +423,6 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
...
@@ -418,14 +423,6 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
return
FAILED
;
return
FAILED
;
}
}
return
FAILED
;
return
FAILED
;
maybe_retry:
if
((
++
scmd
->
retries
)
<
scmd
->
allowed
)
{
return
NEEDS_RETRY
;
}
else
{
/* no more retries - report this one back to upper level */
return
SUCCESS
;
}
}
}
/**
/**
...
@@ -440,12 +437,13 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
...
@@ -440,12 +437,13 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
static
void
scsi_eh_times_out
(
Scsi_Cmnd
*
scmd
)
static
void
scsi_eh_times_out
(
Scsi_Cmnd
*
scmd
)
{
{
scsi_eh_eflags_set
(
scmd
,
SCSI_EH_REC_TIMEOUT
);
scsi_eh_eflags_set
(
scmd
,
SCSI_EH_REC_TIMEOUT
);
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"in scsi_eh_times_out %p
\n
"
,
scmd
));
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: scmd:%p
\n
"
,
__FUNCTION__
,
scmd
));
if
(
scmd
->
host
->
eh_action
!=
NULL
)
if
(
scmd
->
host
->
eh_action
!=
NULL
)
up
(
scmd
->
host
->
eh_action
);
up
(
scmd
->
host
->
eh_action
);
else
else
printk
(
"
missing scsi error handler thread
\n
"
);
printk
(
"
%s: eh_action NULL
\n
"
,
__FUNCTION__
);
}
}
/**
/**
...
@@ -471,8 +469,8 @@ static void scsi_eh_done(Scsi_Cmnd *scmd)
...
@@ -471,8 +469,8 @@ static void scsi_eh_done(Scsi_Cmnd *scmd)
scmd
->
owner
=
SCSI_OWNER_ERROR_HANDLER
;
scmd
->
owner
=
SCSI_OWNER_ERROR_HANDLER
;
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"
in eh_done %p result:%x
\n
"
,
scmd
,
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"
%s scmd: %p result: %x
\n
"
,
scmd
->
result
));
__FUNCTION__
,
scmd
,
scmd
->
result
));
if
(
scmd
->
host
->
eh_action
!=
NULL
)
if
(
scmd
->
host
->
eh_action
!=
NULL
)
up
(
scmd
->
host
->
eh_action
);
up
(
scmd
->
host
->
eh_action
);
...
@@ -488,7 +486,7 @@ static void scsi_eh_done(Scsi_Cmnd *scmd)
...
@@ -488,7 +486,7 @@ static void scsi_eh_done(Scsi_Cmnd *scmd)
* this case, and furthermore, there is a different completion handler
* this case, and furthermore, there is a different completion handler
* vs scsi_dispatch_cmd.
* vs scsi_dispatch_cmd.
* Return value:
* Return value:
* SUCCESS
/FAILED
* SUCCESS
or FAILED or NEEDS_RETRY
**/
**/
static
int
scsi_send_eh_cmnd
(
Scsi_Cmnd
*
scmd
,
int
timeout
)
static
int
scsi_send_eh_cmnd
(
Scsi_Cmnd
*
scmd
,
int
timeout
)
{
{
...
@@ -498,7 +496,6 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
...
@@ -498,7 +496,6 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
ASSERT_LOCK
(
host
->
host_lock
,
0
);
ASSERT_LOCK
(
host
->
host_lock
,
0
);
retry:
/*
/*
* we will use a queued command if possible, otherwise we will
* we will use a queued command if possible, otherwise we will
* emulate the queuing and calling of completion function ourselves.
* emulate the queuing and calling of completion function ourselves.
...
@@ -552,9 +549,8 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
...
@@ -552,9 +549,8 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
rtn
=
FAILED
;
rtn
=
FAILED
;
}
}
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: %p rtn:%x
\n
"
,
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: scmd: %p, rtn:%x
\n
"
,
__FUNCTION__
,
scmd
,
__FUNCTION__
,
scmd
,
rtn
));
rtn
));
}
else
{
}
else
{
int
temp
;
int
temp
;
...
@@ -576,16 +572,15 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
...
@@ -576,16 +572,15 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
* actually did complete normally.
* actually did complete normally.
*/
*/
if
(
rtn
==
SUCCESS
)
{
if
(
rtn
==
SUCCESS
)
{
int
r
et
=
scsi_eh_completed_normally
(
scmd
);
int
r
tn
=
scsi_eh_completed_normally
(
scmd
);
SCSI_LOG_ERROR_RECOVERY
(
3
,
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: scsi_eh_completed_normally %x
\n
"
,
printk
(
"%s: scsi_eh_completed_normally %x
\n
"
,
__FUNCTION__
,
r
et
));
__FUNCTION__
,
r
tn
));
switch
(
r
et
)
{
switch
(
r
tn
)
{
case
SUCCESS
:
case
SUCCESS
:
break
;
case
NEEDS_RETRY
:
case
NEEDS_RETRY
:
goto
retry
;
case
FAILED
:
case
FAILED
:
break
;
default:
default:
rtn
=
FAILED
;
rtn
=
FAILED
;
break
;
break
;
...
@@ -622,7 +617,7 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
...
@@ -622,7 +617,7 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
?
&
scsi_result0
[
0
]
:
kmalloc
(
512
,
GFP_ATOMIC
|
GFP_DMA
);
?
&
scsi_result0
[
0
]
:
kmalloc
(
512
,
GFP_ATOMIC
|
GFP_DMA
);
if
(
scsi_result
==
NULL
)
{
if
(
scsi_result
==
NULL
)
{
printk
(
"
cannot allocate scsi_result in scsi_request_sense.
\n
"
);
printk
(
"
%s: cannot allocate scsi_result.
\n
"
,
__FUNCTION__
);
return
FAILED
;
return
FAILED
;
}
}
/*
/*
...
@@ -657,15 +652,8 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
...
@@ -657,15 +652,8 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
* when we eventually call scsi_finish, we really wish to complete
* when we eventually call scsi_finish, we really wish to complete
* the original request, so let's restore the original data. (db)
* the original request, so let's restore the original data. (db)
*/
*/
memcpy
((
void
*
)
scmd
->
cmnd
,
(
void
*
)
scmd
->
data_cmnd
,
scsi_setup_cmd_retry
(
scmd
);
sizeof
(
scmd
->
data_cmnd
));
scmd
->
result
=
saved_result
;
scmd
->
result
=
saved_result
;
scmd
->
request_buffer
=
scmd
->
buffer
;
scmd
->
request_bufflen
=
scmd
->
bufflen
;
scmd
->
use_sg
=
scmd
->
old_use_sg
;
scmd
->
cmd_len
=
scmd
->
old_cmd_len
;
scmd
->
sc_data_direction
=
scmd
->
sc_old_data_direction
;
scmd
->
underflow
=
scmd
->
old_underflow
;
/*
/*
* hey, we are done. let's look to see what happened.
* hey, we are done. let's look to see what happened.
...
@@ -683,16 +671,16 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
...
@@ -683,16 +671,16 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
**/
**/
static
int
scsi_eh_retry_cmd
(
Scsi_Cmnd
*
scmd
)
static
int
scsi_eh_retry_cmd
(
Scsi_Cmnd
*
scmd
)
{
{
memcpy
((
void
*
)
scmd
->
cmnd
,
(
void
*
)
scmd
->
data_cmnd
,
int
rtn
=
SUCCESS
;
sizeof
(
scmd
->
data_cmnd
));
scmd
->
request_buffer
=
scmd
->
buffer
;
for
(;
scmd
->
retries
<
scmd
->
allowed
;
scmd
->
retries
++
)
{
scmd
->
request_bufflen
=
scmd
->
bufflen
;
scsi_setup_cmd_retry
(
scmd
)
;
scmd
->
use_sg
=
scmd
->
old_use_sg
;
rtn
=
scsi_send_eh_cmnd
(
scmd
,
scmd
->
timeout_per_command
)
;
scmd
->
cmd_len
=
scmd
->
old_cmd_len
;
if
(
rtn
!=
NEEDS_RETRY
)
scmd
->
sc_data_direction
=
scmd
->
sc_old_data_direction
;
break
;
scmd
->
underflow
=
scmd
->
old_underflow
;
}
return
scsi_send_eh_cmnd
(
scmd
,
scmd
->
timeout_per_command
)
;
return
rtn
;
}
}
/**
/**
...
@@ -717,9 +705,7 @@ static void scsi_eh_finish_cmd(Scsi_Cmnd *scmd, struct Scsi_Host *shost)
...
@@ -717,9 +705,7 @@ static void scsi_eh_finish_cmd(Scsi_Cmnd *scmd, struct Scsi_Host *shost)
* set this back so that the upper level can correctly free up
* set this back so that the upper level can correctly free up
* things.
* things.
*/
*/
scmd
->
use_sg
=
scmd
->
old_use_sg
;
scsi_setup_cmd_retry
(
scmd
);
scmd
->
sc_data_direction
=
scmd
->
sc_old_data_direction
;
scmd
->
underflow
=
scmd
->
old_underflow
;
}
}
/**
/**
...
@@ -758,14 +744,14 @@ static int scsi_eh_get_sense(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
...
@@ -758,14 +744,14 @@ static int scsi_eh_get_sense(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
continue
;
continue
;
SCSI_LOG_ERROR_RECOVERY
(
2
,
printk
(
"%s: requesting sense"
SCSI_LOG_ERROR_RECOVERY
(
2
,
printk
(
"%s: requesting sense"
"
for %d
\n
"
,
__FUNCTION__
,
"
for tgt: %d
\n
"
,
scmd
->
target
));
__FUNCTION__
,
scmd
->
target
));
rtn
=
scsi_request_sense
(
scmd
);
rtn
=
scsi_request_sense
(
scmd
);
if
(
rtn
!=
SUCCESS
)
if
(
rtn
!=
SUCCESS
)
continue
;
continue
;
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"sense requested for %p"
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"sense requested for %p"
"
-
result %x
\n
"
,
scmd
,
" result %x
\n
"
,
scmd
,
scmd
->
result
));
scmd
->
result
));
SCSI_LOG_ERROR_RECOVERY
(
3
,
print_sense
(
"bh"
,
scmd
));
SCSI_LOG_ERROR_RECOVERY
(
3
,
print_sense
(
"bh"
,
scmd
));
...
@@ -847,7 +833,9 @@ static int scsi_eh_tur(Scsi_Cmnd *scmd)
...
@@ -847,7 +833,9 @@ static int scsi_eh_tur(Scsi_Cmnd *scmd)
static
unsigned
char
tur_command
[
6
]
=
static
unsigned
char
tur_command
[
6
]
=
{
TEST_UNIT_READY
,
0
,
0
,
0
,
0
,
0
};
{
TEST_UNIT_READY
,
0
,
0
,
0
,
0
,
0
};
int
rtn
;
int
rtn
;
int
retry_cnt
=
1
;
retry_tur:
memcpy
((
void
*
)
scmd
->
cmnd
,
(
void
*
)
tur_command
,
memcpy
((
void
*
)
scmd
->
cmnd
,
(
void
*
)
tur_command
,
sizeof
(
tur_command
));
sizeof
(
tur_command
));
...
@@ -873,32 +861,18 @@ static int scsi_eh_tur(Scsi_Cmnd *scmd)
...
@@ -873,32 +861,18 @@ static int scsi_eh_tur(Scsi_Cmnd *scmd)
* when we eventually call scsi_finish, we really wish to complete
* when we eventually call scsi_finish, we really wish to complete
* the original request, so let's restore the original data. (db)
* the original request, so let's restore the original data. (db)
*/
*/
memcpy
((
void
*
)
scmd
->
cmnd
,
(
void
*
)
scmd
->
data_cmnd
,
scsi_setup_cmd_retry
(
scmd
);
sizeof
(
scmd
->
data_cmnd
));
scmd
->
request_buffer
=
scmd
->
buffer
;
scmd
->
request_bufflen
=
scmd
->
bufflen
;
scmd
->
use_sg
=
scmd
->
old_use_sg
;
scmd
->
cmd_len
=
scmd
->
old_cmd_len
;
scmd
->
sc_data_direction
=
scmd
->
sc_old_data_direction
;
scmd
->
underflow
=
scmd
->
old_underflow
;
/*
/*
* hey, we are done. let's look to see what happened.
* hey, we are done. let's look to see what happened.
*/
*/
SCSI_LOG_ERROR_RECOVERY
(
3
,
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: scmd %p rtn %x
\n
"
,
printk
(
"%s: scmd %p rtn %x
\n
"
,
__FUNCTION__
,
scmd
,
rtn
));
__FUNCTION__
,
scmd
,
rtn
));
if
((
rtn
==
SUCCESS
)
&&
scmd
->
result
)
{
if
(
rtn
==
SUCCESS
)
if
(((
driver_byte
(
scmd
->
result
)
&
DRIVER_SENSE
)
||
(
status_byte
(
scmd
->
result
)
&
CHECK_CONDITION
))
&&
(
SCSI_SENSE_VALID
(
scmd
)))
{
if
(((
scmd
->
sense_buffer
[
2
]
&
0xf
)
!=
NOT_READY
)
&&
((
scmd
->
sense_buffer
[
2
]
&
0xf
)
!=
UNIT_ATTENTION
)
&&
((
scmd
->
sense_buffer
[
2
]
&
0xf
)
!=
ILLEGAL_REQUEST
))
{
return
0
;
return
0
;
}
else
if
(
rtn
==
NEEDS_RETRY
)
}
if
(
retry_cnt
--
)
}
goto
retry_tur
;
return
1
;
return
1
;
}
}
...
@@ -929,7 +903,7 @@ static int scsi_eh_abort_cmd(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
...
@@ -929,7 +903,7 @@ static int scsi_eh_abort_cmd(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
rtn
=
scsi_try_to_abort_cmd
(
scmd
);
rtn
=
scsi_try_to_abort_cmd
(
scmd
);
if
(
rtn
==
SUCCESS
)
{
if
(
rtn
==
SUCCESS
)
{
if
(
scsi_eh_tur
(
scmd
))
{
if
(
!
scsi_eh_tur
(
scmd
))
{
rtn
=
scsi_eh_retry_cmd
(
scmd
);
rtn
=
scsi_eh_retry_cmd
(
scmd
);
if
(
rtn
==
SUCCESS
)
if
(
rtn
==
SUCCESS
)
scsi_eh_finish_cmd
(
scmd
,
shost
);
scsi_eh_finish_cmd
(
scmd
,
shost
);
...
@@ -963,6 +937,11 @@ static int scsi_try_bus_device_reset(Scsi_Cmnd *scmd)
...
@@ -963,6 +937,11 @@ static int scsi_try_bus_device_reset(Scsi_Cmnd *scmd)
rtn
=
scmd
->
host
->
hostt
->
eh_device_reset_handler
(
scmd
);
rtn
=
scmd
->
host
->
hostt
->
eh_device_reset_handler
(
scmd
);
spin_unlock_irqrestore
(
scmd
->
host
->
host_lock
,
flags
);
spin_unlock_irqrestore
(
scmd
->
host
->
host_lock
,
flags
);
if
(
rtn
==
SUCCESS
)
{
scmd
->
device
->
was_reset
=
1
;
scmd
->
device
->
expecting_cc_ua
=
1
;
}
return
rtn
;
return
rtn
;
}
}
...
@@ -999,7 +978,7 @@ static int scsi_eh_bus_device_reset(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
...
@@ -999,7 +978,7 @@ static int scsi_eh_bus_device_reset(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
* a bus device reset to it.
* a bus device reset to it.
*/
*/
rtn
=
scsi_try_bus_device_reset
(
scmd
);
rtn
=
scsi_try_bus_device_reset
(
scmd
);
if
((
rtn
==
SUCCESS
)
&&
(
scsi_eh_tur
(
scmd
)))
if
((
rtn
==
SUCCESS
)
&&
(
!
scsi_eh_tur
(
scmd
)))
for
(
scmd
=
sc_todo
;
scmd
;
scmd
=
scmd
->
bh_next
)
for
(
scmd
=
sc_todo
;
scmd
;
scmd
=
scmd
->
bh_next
)
if
((
scmd
->
device
==
sdev
)
&&
if
((
scmd
->
device
==
sdev
)
&&
scsi_eh_eflags_chk
(
scmd
,
SCSI_EH_CMD_ERR
))
{
scsi_eh_eflags_chk
(
scmd
,
SCSI_EH_CMD_ERR
))
{
...
@@ -1141,7 +1120,7 @@ static int scsi_eh_bus_host_reset(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
...
@@ -1141,7 +1120,7 @@ static int scsi_eh_bus_host_reset(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
if
(
!
scsi_eh_eflags_chk
(
scmd
,
SCSI_EH_CMD_ERR
)
if
(
!
scsi_eh_eflags_chk
(
scmd
,
SCSI_EH_CMD_ERR
)
||
channel
!=
scmd
->
channel
)
||
channel
!=
scmd
->
channel
)
continue
;
continue
;
if
(
scsi_eh_tur
(
scmd
))
{
if
(
!
scsi_eh_tur
(
scmd
))
{
rtn
=
scsi_eh_retry_cmd
(
scmd
);
rtn
=
scsi_eh_retry_cmd
(
scmd
);
if
(
rtn
==
SUCCESS
)
if
(
rtn
==
SUCCESS
)
...
@@ -1168,10 +1147,10 @@ static void scsi_eh_offline_sdevs(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
...
@@ -1168,10 +1147,10 @@ static void scsi_eh_offline_sdevs(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
if
(
!
scsi_eh_eflags_chk
(
scmd
,
SCSI_EH_CMD_ERR
))
if
(
!
scsi_eh_eflags_chk
(
scmd
,
SCSI_EH_CMD_ERR
))
continue
;
continue
;
printk
(
KERN_INFO
"%s: Device
set offline
- not"
printk
(
KERN_INFO
"%s: Device
offlined
- not"
"ready or command retry failed"
"
ready or command retry failed"
"after error recovery: host"
"
after error recovery: host"
"%d channel %d id %d lun %d
\n
"
,
"
%d channel %d id %d lun %d
\n
"
,
__FUNCTION__
,
shost
->
host_no
,
__FUNCTION__
,
shost
->
host_no
,
scmd
->
device
->
channel
,
scmd
->
device
->
channel
,
scmd
->
device
->
id
,
scmd
->
device
->
id
,
...
@@ -1243,7 +1222,7 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
...
@@ -1243,7 +1222,7 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
*/
*/
if
(
scmd
->
device
->
online
==
FALSE
)
{
if
(
scmd
->
device
->
online
==
FALSE
)
{
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"%s: device offline - report"
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"%s: device offline - report"
"as SUCCESS
\n
"
,
"
as SUCCESS
\n
"
,
__FUNCTION__
));
__FUNCTION__
));
return
SUCCESS
;
return
SUCCESS
;
}
}
...
@@ -1388,6 +1367,75 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
...
@@ -1388,6 +1367,75 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
}
}
}
}
/**
* scsi_eh_lock_done - done function for eh door lock request
* @scmd: SCSI command block for the door lock request
*
* Notes:
* We completed the asynchronous door lock request, and it has either
* locked the door or failed. We must free the command structures
* associated with this request.
**/
static
void
scsi_eh_lock_done
(
struct
scsi_cmnd
*
scmd
)
{
struct
scsi_request
*
sreq
=
scmd
->
sc_request
;
scmd
->
sc_request
=
NULL
;
sreq
->
sr_command
=
NULL
;
scsi_release_command
(
scmd
);
scsi_release_request
(
sreq
);
}
/**
* scsi_eh_lock_door - Prevent medium removal for the specified device
* @sdev: SCSI device to prevent medium removal
*
* Locking:
* We must be called from process context; scsi_allocate_request()
* may sleep.
*
* Notes:
* We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request on the
* head of the devices request queue, and continue.
*
* Bugs:
* scsi_allocate_request() may sleep waiting for existing requests to
* be processed. However, since we haven't kicked off any request
* processing for this host, this may deadlock.
*
* If scsi_allocate_request() fails for what ever reason, we
* completely forget to lock the door.
**/
static
void
scsi_eh_lock_door
(
struct
scsi_device
*
sdev
)
{
struct
scsi_request
*
sreq
=
scsi_allocate_request
(
sdev
);
if
(
sreq
==
NULL
)
{
printk
(
KERN_ERR
"%s: request allocate failed,"
"prevent media removal cmd not sent"
,
__FUNCTION__
);
return
;
}
sreq
->
sr_cmnd
[
0
]
=
ALLOW_MEDIUM_REMOVAL
;
sreq
->
sr_cmnd
[
1
]
=
(
sdev
->
scsi_level
<=
SCSI_2
)
?
(
sdev
->
lun
<<
5
)
:
0
;
sreq
->
sr_cmnd
[
2
]
=
0
;
sreq
->
sr_cmnd
[
3
]
=
0
;
sreq
->
sr_cmnd
[
4
]
=
SCSI_REMOVAL_PREVENT
;
sreq
->
sr_cmnd
[
5
]
=
0
;
sreq
->
sr_data_direction
=
SCSI_DATA_NONE
;
sreq
->
sr_bufflen
=
0
;
sreq
->
sr_buffer
=
NULL
;
sreq
->
sr_allowed
=
5
;
sreq
->
sr_done
=
scsi_eh_lock_done
;
sreq
->
sr_timeout_per_command
=
10
*
HZ
;
sreq
->
sr_cmd_len
=
COMMAND_SIZE
(
sreq
->
sr_cmnd
[
0
]);
scsi_insert_special_req
(
sreq
,
1
);
}
/**
/**
* scsi_restart_operations - restart io operations to the specified host.
* scsi_restart_operations - restart io operations to the specified host.
* @shost: Host we are restarting.
* @shost: Host we are restarting.
...
@@ -1403,6 +1451,15 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
...
@@ -1403,6 +1451,15 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
ASSERT_LOCK
(
shost
->
host_lock
,
0
);
ASSERT_LOCK
(
shost
->
host_lock
,
0
);
/*
* If the door was locked, we need to insert a door lock request
* onto the head of the SCSI request queue for the device. There
* is no point trying to lock the door of an off-line device.
*/
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
if
(
sdev
->
online
&&
sdev
->
locked
)
scsi_eh_lock_door
(
sdev
);
/*
/*
* next free up anything directly waiting upon the host. this
* next free up anything directly waiting upon the host. this
* will be requests for character device operations, and also for
* will be requests for character device operations, and also for
...
@@ -1426,8 +1483,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
...
@@ -1426,8 +1483,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
if
((
shost
->
can_queue
>
0
&&
if
((
shost
->
can_queue
>
0
&&
(
shost
->
host_busy
>=
shost
->
can_queue
))
(
shost
->
host_busy
>=
shost
->
can_queue
))
||
(
shost
->
host_blocked
)
||
(
shost
->
host_blocked
)
||
(
shost
->
host_self_blocked
)
||
(
shost
->
host_self_blocked
))
{
||
(
sdev
->
device_blocked
))
{
break
;
break
;
}
}
...
@@ -1475,7 +1531,7 @@ static void scsi_unjam_host(struct Scsi_Host *shost)
...
@@ -1475,7 +1531,7 @@ static void scsi_unjam_host(struct Scsi_Host *shost)
if
(
scsi_eh_get_sense
(
sc_todo
,
shost
))
if
(
scsi_eh_get_sense
(
sc_todo
,
shost
))
if
(
scsi_eh_abort_cmd
(
sc_todo
,
shost
))
if
(
scsi_eh_abort_cmd
(
sc_todo
,
shost
))
if
(
scsi_eh_bus_device_reset
(
sc_todo
,
shost
))
if
(
scsi_eh_bus_device_reset
(
sc_todo
,
shost
))
if
(
scsi_eh_bus_host_reset
(
sc_todo
,
shost
))
if
(
scsi_eh_bus_host_reset
(
sc_todo
,
shost
))
scsi_eh_offline_sdevs
(
sc_todo
,
shost
);
scsi_eh_offline_sdevs
(
sc_todo
,
shost
);
BUG_ON
(
shost
->
host_failed
);
BUG_ON
(
shost
->
host_failed
);
...
@@ -1563,8 +1619,7 @@ void scsi_error_handler(void *data)
...
@@ -1563,8 +1619,7 @@ void scsi_error_handler(void *data)
/*
/*
* Wake up the thread that created us.
* Wake up the thread that created us.
*/
*/
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"Wake up parent %d
\n
"
,
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"Wake up parent
\n
"
));
shost
->
eh_notify
->
count
.
counter
));
up
(
shost
->
eh_notify
);
up
(
shost
->
eh_notify
);
...
...
drivers/scsi/scsi_ioctl.c
View file @
34d3616d
...
@@ -151,6 +151,29 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
...
@@ -151,6 +151,29 @@ static int ioctl_internal_command(Scsi_Device * dev, char *cmd,
return
result
;
return
result
;
}
}
int
scsi_set_medium_removal
(
Scsi_Device
*
dev
,
char
state
)
{
char
scsi_cmd
[
MAX_COMMAND_SIZE
];
int
ret
;
if
(
!
dev
->
removable
||
!
dev
->
lockable
)
return
0
;
scsi_cmd
[
0
]
=
ALLOW_MEDIUM_REMOVAL
;
scsi_cmd
[
1
]
=
(
dev
->
scsi_level
<=
SCSI_2
)
?
(
dev
->
lun
<<
5
)
:
0
;
scsi_cmd
[
2
]
=
0
;
scsi_cmd
[
3
]
=
0
;
scsi_cmd
[
4
]
=
state
;
scsi_cmd
[
5
]
=
0
;
ret
=
ioctl_internal_command
(
dev
,
scsi_cmd
,
IOCTL_NORMAL_TIMEOUT
,
NORMAL_RETRIES
);
if
(
ret
==
0
)
dev
->
locked
=
state
==
SCSI_REMOVAL_PREVENT
;
return
ret
;
}
/*
/*
* This interface is deprecated - users should use the scsi generic (sg)
* This interface is deprecated - users should use the scsi generic (sg)
* interface instead, as this is a more flexible approach to performing
* interface instead, as this is a more flexible approach to performing
...
@@ -456,24 +479,9 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
...
@@ -456,24 +479,9 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
return
scsi_ioctl_send_command
((
Scsi_Device
*
)
dev
,
return
scsi_ioctl_send_command
((
Scsi_Device
*
)
dev
,
(
Scsi_Ioctl_Command
*
)
arg
);
(
Scsi_Ioctl_Command
*
)
arg
);
case
SCSI_IOCTL_DOORLOCK
:
case
SCSI_IOCTL_DOORLOCK
:
if
(
!
dev
->
removable
||
!
dev
->
lockable
)
return
scsi_set_medium_removal
(
dev
,
SCSI_REMOVAL_PREVENT
);
return
0
;
scsi_cmd
[
0
]
=
ALLOW_MEDIUM_REMOVAL
;
scsi_cmd
[
1
]
=
cmd_byte1
;
scsi_cmd
[
2
]
=
scsi_cmd
[
3
]
=
scsi_cmd
[
5
]
=
0
;
scsi_cmd
[
4
]
=
SCSI_REMOVAL_PREVENT
;
return
ioctl_internal_command
((
Scsi_Device
*
)
dev
,
scsi_cmd
,
IOCTL_NORMAL_TIMEOUT
,
NORMAL_RETRIES
);
break
;
case
SCSI_IOCTL_DOORUNLOCK
:
case
SCSI_IOCTL_DOORUNLOCK
:
if
(
!
dev
->
removable
||
!
dev
->
lockable
)
return
scsi_set_medium_removal
(
dev
,
SCSI_REMOVAL_ALLOW
);
return
0
;
scsi_cmd
[
0
]
=
ALLOW_MEDIUM_REMOVAL
;
scsi_cmd
[
1
]
=
cmd_byte1
;
scsi_cmd
[
2
]
=
scsi_cmd
[
3
]
=
scsi_cmd
[
5
]
=
0
;
scsi_cmd
[
4
]
=
SCSI_REMOVAL_ALLOW
;
return
ioctl_internal_command
((
Scsi_Device
*
)
dev
,
scsi_cmd
,
IOCTL_NORMAL_TIMEOUT
,
NORMAL_RETRIES
);
case
SCSI_IOCTL_TEST_UNIT_READY
:
case
SCSI_IOCTL_TEST_UNIT_READY
:
scsi_cmd
[
0
]
=
TEST_UNIT_READY
;
scsi_cmd
[
0
]
=
TEST_UNIT_READY
;
scsi_cmd
[
1
]
=
cmd_byte1
;
scsi_cmd
[
1
]
=
cmd_byte1
;
...
...
drivers/scsi/scsi_lib.c
View file @
34d3616d
...
@@ -159,6 +159,30 @@ int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt)
...
@@ -159,6 +159,30 @@ int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt)
return
1
;
return
1
;
}
}
/*
* Function: scsi_setup_cmd_retry()
*
* Purpose: Restore the command state for a retry
*
* Arguments: SCpnt - command to be restored
*
* Returns: Nothing
*
* Notes: Immediately prior to retrying a command, we need
* to restore certain fields that we saved above.
*/
void
scsi_setup_cmd_retry
(
Scsi_Cmnd
*
SCpnt
)
{
memcpy
((
void
*
)
SCpnt
->
cmnd
,
(
void
*
)
SCpnt
->
data_cmnd
,
sizeof
(
SCpnt
->
data_cmnd
));
SCpnt
->
request_buffer
=
SCpnt
->
buffer
;
SCpnt
->
request_bufflen
=
SCpnt
->
bufflen
;
SCpnt
->
use_sg
=
SCpnt
->
old_use_sg
;
SCpnt
->
cmd_len
=
SCpnt
->
old_cmd_len
;
SCpnt
->
sc_data_direction
=
SCpnt
->
sc_old_data_direction
;
SCpnt
->
underflow
=
SCpnt
->
old_underflow
;
}
/*
/*
* Function: scsi_queue_next_request()
* Function: scsi_queue_next_request()
*
*
...
@@ -614,7 +638,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
...
@@ -614,7 +638,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
printk
(
"scsi%d: ERROR on channel %d, id %d, lun %d, CDB: "
,
printk
(
"scsi%d: ERROR on channel %d, id %d, lun %d, CDB: "
,
SCpnt
->
host
->
host_no
,
(
int
)
SCpnt
->
channel
,
SCpnt
->
host
->
host_no
,
(
int
)
SCpnt
->
channel
,
(
int
)
SCpnt
->
target
,
(
int
)
SCpnt
->
lun
);
(
int
)
SCpnt
->
target
,
(
int
)
SCpnt
->
lun
);
print_command
(
SCpnt
->
cmnd
);
print_command
(
SCpnt
->
data_
cmnd
);
print_sense
(
"sd"
,
SCpnt
);
print_sense
(
"sd"
,
SCpnt
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
block_sectors
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
block_sectors
);
return
;
return
;
...
@@ -798,33 +822,6 @@ void scsi_request_fn(request_queue_t * q)
...
@@ -798,33 +822,6 @@ void scsi_request_fn(request_queue_t * q)
SDpnt
->
starved
=
0
;
SDpnt
->
starved
=
0
;
}
}
/*
* FIXME(eric)
* I am not sure where the best place to do this is. We need
* to hook in a place where we are likely to come if in user
* space. Technically the error handling thread should be
* doing this crap, but the error handler isn't used by
* most hosts.
*/
if
(
SDpnt
->
was_reset
)
{
/*
* We need to relock the door, but we might
* be in an interrupt handler. Only do this
* from user space, since we do not want to
* sleep from an interrupt.
*
* FIXME(eric) - have the error handler thread do
* this work.
*/
SDpnt
->
was_reset
=
0
;
if
(
SDpnt
->
removable
&&
!
in_interrupt
())
{
spin_unlock_irq
(
q
->
queue_lock
);
scsi_ioctl
(
SDpnt
,
SCSI_IOCTL_DOORLOCK
,
0
);
spin_lock_irq
(
q
->
queue_lock
);
continue
;
}
}
/*
/*
* If we couldn't find a request that could be queued, then we
* If we couldn't find a request that could be queued, then we
* can also quit.
* can also quit.
...
...
drivers/scsi/scsi_syms.c
View file @
34d3616d
...
@@ -54,6 +54,7 @@ EXPORT_SYMBOL(scsi_release_command);
...
@@ -54,6 +54,7 @@ EXPORT_SYMBOL(scsi_release_command);
EXPORT_SYMBOL
(
print_Scsi_Cmnd
);
EXPORT_SYMBOL
(
print_Scsi_Cmnd
);
EXPORT_SYMBOL
(
scsi_block_when_processing_errors
);
EXPORT_SYMBOL
(
scsi_block_when_processing_errors
);
EXPORT_SYMBOL
(
scsi_ioctl_send_command
);
EXPORT_SYMBOL
(
scsi_ioctl_send_command
);
EXPORT_SYMBOL
(
scsi_set_medium_removal
);
#if defined(CONFIG_SCSI_LOGGING)
/* { */
#if defined(CONFIG_SCSI_LOGGING)
/* { */
EXPORT_SYMBOL
(
scsi_logging_level
);
EXPORT_SYMBOL
(
scsi_logging_level
);
#endif
#endif
...
...
drivers/scsi/sd.c
View file @
34d3616d
...
@@ -529,7 +529,7 @@ static int sd_open(struct inode *inode, struct file *filp)
...
@@ -529,7 +529,7 @@ static int sd_open(struct inode *inode, struct file *filp)
if
(
sdp
->
removable
)
if
(
sdp
->
removable
)
if
(
sdp
->
access_count
==
1
)
if
(
sdp
->
access_count
==
1
)
if
(
scsi_block_when_processing_errors
(
sdp
))
if
(
scsi_block_when_processing_errors
(
sdp
))
scsi_
ioctl
(
sdp
,
SCSI_IOCTL_DOORLOCK
,
NULL
);
scsi_
set_medium_removal
(
sdp
,
SCSI_REMOVAL_PREVENT
);
return
0
;
return
0
;
...
@@ -573,7 +573,7 @@ static int sd_release(struct inode *inode, struct file *filp)
...
@@ -573,7 +573,7 @@ static int sd_release(struct inode *inode, struct file *filp)
if
(
sdp
->
removable
)
{
if
(
sdp
->
removable
)
{
if
(
!
sdp
->
access_count
)
if
(
!
sdp
->
access_count
)
if
(
scsi_block_when_processing_errors
(
sdp
))
if
(
scsi_block_when_processing_errors
(
sdp
))
scsi_
ioctl
(
sdp
,
SCSI_IOCTL_DOORUNLOCK
,
NULL
);
scsi_
set_medium_removal
(
sdp
,
SCSI_REMOVAL_ALLOW
);
}
}
if
(
sdp
->
host
->
hostt
->
module
)
if
(
sdp
->
host
->
hostt
->
module
)
__MOD_DEC_USE_COUNT
(
sdp
->
host
->
hostt
->
module
);
__MOD_DEC_USE_COUNT
(
sdp
->
host
->
hostt
->
module
);
...
@@ -1623,7 +1623,6 @@ static int sd_synchronize_cache(int index, int verbose)
...
@@ -1623,7 +1623,6 @@ static int sd_synchronize_cache(int index, int verbose)
}
}
the_result
=
SRpnt
->
sr_result
;
the_result
=
SRpnt
->
sr_result
;
scsi_release_request
(
SRpnt
);
if
(
verbose
)
{
if
(
verbose
)
{
if
(
the_result
!=
0
)
{
if
(
the_result
!=
0
)
{
printk
(
"FAILED
\n
status = %x, message = %02x, host = %d, driver = %02x
\n
"
,
printk
(
"FAILED
\n
status = %x, message = %02x, host = %d, driver = %02x
\n
"
,
...
@@ -1636,6 +1635,7 @@ static int sd_synchronize_cache(int index, int verbose)
...
@@ -1636,6 +1635,7 @@ static int sd_synchronize_cache(int index, int verbose)
}
}
}
}
scsi_release_request
(
SRpnt
);
return
(
the_result
==
0
);
return
(
the_result
==
0
);
}
}
...
...
drivers/scsi/sr.c
View file @
34d3616d
...
@@ -575,7 +575,7 @@ static void get_sectorsize(Scsi_CD *cd)
...
@@ -575,7 +575,7 @@ static void get_sectorsize(Scsi_CD *cd)
void
get_capabilities
(
Scsi_CD
*
cd
)
void
get_capabilities
(
Scsi_CD
*
cd
)
{
{
unsigned
char
cmd
[
6
]
;
struct
cdrom_generic_command
cgc
;
unsigned
char
*
buffer
;
unsigned
char
*
buffer
;
int
rc
,
n
;
int
rc
,
n
;
...
@@ -597,13 +597,18 @@ void get_capabilities(Scsi_CD *cd)
...
@@ -597,13 +597,18 @@ void get_capabilities(Scsi_CD *cd)
printk
(
KERN_ERR
"sr: out of memory.
\n
"
);
printk
(
KERN_ERR
"sr: out of memory.
\n
"
);
return
;
return
;
}
}
cmd
[
0
]
=
MODE_SENSE
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cgc
.
cmd
[
0
]
=
MODE_SENSE
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
<<
5
)
&
0xe0
)
:
0
;
((
cd
->
device
->
lun
<<
5
)
&
0xe0
)
:
0
;
cmd
[
2
]
=
0x2a
;
cgc
.
cmd
[
2
]
=
0x2a
;
cmd
[
4
]
=
128
;
cgc
.
cmd
[
4
]
=
128
;
cmd
[
3
]
=
cmd
[
5
]
=
0
;
cgc
.
buffer
=
buffer
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
128
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
buflen
=
128
;
cgc
.
quiet
=
1
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
SR_TIMEOUT
;
rc
=
sr_do_ioctl
(
cd
,
&
cgc
);
if
(
rc
)
{
if
(
rc
)
{
/* failed, drive doesn't have capabilities mode page */
/* failed, drive doesn't have capabilities mode page */
...
@@ -680,7 +685,10 @@ static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command
...
@@ -680,7 +685,10 @@ static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command
if
(
device
->
scsi_level
<=
SCSI_2
)
if
(
device
->
scsi_level
<=
SCSI_2
)
cgc
->
cmd
[
1
]
|=
device
->
lun
<<
5
;
cgc
->
cmd
[
1
]
|=
device
->
lun
<<
5
;
cgc
->
stat
=
sr_do_ioctl
(
cdi
->
handle
,
cgc
->
cmd
,
cgc
->
buffer
,
cgc
->
buflen
,
cgc
->
quiet
,
cgc
->
data_direction
,
cgc
->
sense
);
if
(
cgc
->
timeout
<=
0
)
cgc
->
timeout
=
IOCTL_TIMEOUT
;
sr_do_ioctl
(
cdi
->
handle
,
cgc
);
return
cgc
->
stat
;
return
cgc
->
stat
;
}
}
...
...
drivers/scsi/sr.h
View file @
34d3616d
...
@@ -20,6 +20,10 @@
...
@@ -20,6 +20,10 @@
#include "scsi.h"
#include "scsi.h"
#include <linux/genhd.h>
#include <linux/genhd.h>
/* The CDROM is fairly slow, so we need a little extra time */
/* In fact, it is very slow if it has to spin up first */
#define IOCTL_TIMEOUT 30*HZ
typedef
struct
{
typedef
struct
{
unsigned
capacity
;
/* size in blocks */
unsigned
capacity
;
/* size in blocks */
Scsi_Device
*
device
;
Scsi_Device
*
device
;
...
@@ -34,7 +38,7 @@ typedef struct {
...
@@ -34,7 +38,7 @@ typedef struct {
struct
gendisk
*
disk
;
struct
gendisk
*
disk
;
}
Scsi_CD
;
}
Scsi_CD
;
int
sr_do_ioctl
(
Scsi_CD
*
,
unsigned
char
*
,
void
*
,
unsigned
,
int
,
int
,
struct
request_sense
*
);
int
sr_do_ioctl
(
Scsi_CD
*
,
struct
cdrom_generic_command
*
);
int
sr_lock_door
(
struct
cdrom_device_info
*
,
int
);
int
sr_lock_door
(
struct
cdrom_device_info
*
,
int
);
int
sr_tray_move
(
struct
cdrom_device_info
*
,
int
);
int
sr_tray_move
(
struct
cdrom_device_info
*
,
int
);
...
...
drivers/scsi/sr_ioctl.c
View file @
34d3616d
...
@@ -25,9 +25,6 @@
...
@@ -25,9 +25,6 @@
static
int
xa_test
=
0
;
static
int
xa_test
=
0
;
#define IOCTL_RETRIES 3
#define IOCTL_RETRIES 3
/* The CDROM is fairly slow, so we need a little extra time */
/* In fact, it is very slow if it has to spin up first */
#define IOCTL_TIMEOUT 30*HZ
/* ATAPI drives don't have a SCMD_PLAYAUDIO_TI command. When these drives
/* ATAPI drives don't have a SCMD_PLAYAUDIO_TI command. When these drives
are emulating a SCSI device via the idescsi module, they need to have
are emulating a SCSI device via the idescsi module, they need to have
...
@@ -37,7 +34,7 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
...
@@ -37,7 +34,7 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
{
{
struct
cdrom_tocentry
trk0_te
,
trk1_te
;
struct
cdrom_tocentry
trk0_te
,
trk1_te
;
struct
cdrom_tochdr
tochdr
;
struct
cdrom_tochdr
tochdr
;
u_char
sr_cmd
[
10
]
;
struct
cdrom_generic_command
cgc
;
int
ntracks
,
ret
;
int
ntracks
,
ret
;
if
((
ret
=
sr_audio_ioctl
(
cdi
,
CDROMREADTOCHDR
,
&
tochdr
)))
if
((
ret
=
sr_audio_ioctl
(
cdi
,
CDROMREADTOCHDR
,
&
tochdr
)))
...
@@ -60,21 +57,24 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
...
@@ -60,21 +57,24 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
if
((
ret
=
sr_audio_ioctl
(
cdi
,
CDROMREADTOCENTRY
,
&
trk1_te
)))
if
((
ret
=
sr_audio_ioctl
(
cdi
,
CDROMREADTOCENTRY
,
&
trk1_te
)))
return
ret
;
return
ret
;
sr_cmd
[
0
]
=
GPCMD_PLAY_AUDIO_MSF
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
sr_cmd
[
3
]
=
trk0_te
.
cdte_addr
.
msf
.
minute
;
cgc
.
cmd
[
0
]
=
GPCMD_PLAY_AUDIO_MSF
;
sr_cmd
[
4
]
=
trk0_te
.
cdte_addr
.
msf
.
second
;
cgc
.
cmd
[
3
]
=
trk0_te
.
cdte_addr
.
msf
.
minute
;
sr_cmd
[
5
]
=
trk0_te
.
cdte_addr
.
msf
.
frame
;
cgc
.
cmd
[
4
]
=
trk0_te
.
cdte_addr
.
msf
.
second
;
sr_cmd
[
6
]
=
trk1_te
.
cdte_addr
.
msf
.
minute
;
cgc
.
cmd
[
5
]
=
trk0_te
.
cdte_addr
.
msf
.
frame
;
sr_cmd
[
7
]
=
trk1_te
.
cdte_addr
.
msf
.
second
;
cgc
.
cmd
[
6
]
=
trk1_te
.
cdte_addr
.
msf
.
minute
;
sr_cmd
[
8
]
=
trk1_te
.
cdte_addr
.
msf
.
frame
;
cgc
.
cmd
[
7
]
=
trk1_te
.
cdte_addr
.
msf
.
second
;
return
sr_do_ioctl
(
cdi
->
handle
,
sr_cmd
,
NULL
,
0
,
0
,
SCSI_DATA_NONE
,
NULL
);
cgc
.
cmd
[
8
]
=
trk1_te
.
cdte_addr
.
msf
.
frame
;
cgc
.
data_direction
=
SCSI_DATA_NONE
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
return
sr_do_ioctl
(
cdi
->
handle
,
&
cgc
);
}
}
/* We do our own retries because we want to know what the specific
/* We do our own retries because we want to know what the specific
error code is. Normally the UNIT_ATTENTION code will automatically
error code is. Normally the UNIT_ATTENTION code will automatically
clear after one error */
clear after one error */
int
sr_do_ioctl
(
Scsi_CD
*
cd
,
unsigned
char
*
sr_cmd
,
void
*
buffer
,
unsigned
buflength
,
int
quiet
,
int
readwrite
,
struct
request_sense
*
sense
)
int
sr_do_ioctl
(
Scsi_CD
*
cd
,
struct
cdrom_generic_command
*
cgc
)
{
{
Scsi_Request
*
SRpnt
;
Scsi_Request
*
SRpnt
;
Scsi_Device
*
SDev
;
Scsi_Device
*
SDev
;
...
@@ -86,29 +86,32 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
...
@@ -86,29 +86,32 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
SRpnt
=
scsi_allocate_request
(
SDev
);
SRpnt
=
scsi_allocate_request
(
SDev
);
if
(
!
SRpnt
)
{
if
(
!
SRpnt
)
{
printk
(
"Unable to allocate SCSI request in sr_do_ioctl"
);
printk
(
"Unable to allocate SCSI request in sr_do_ioctl"
);
return
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
out
;
}
}
SRpnt
->
sr_data_direction
=
readwrite
;
SRpnt
->
sr_data_direction
=
cgc
->
data_direction
;
/* use ISA DMA buffer if necessary */
/* use ISA DMA buffer if necessary */
SRpnt
->
sr_request
->
buffer
=
buffer
;
SRpnt
->
sr_request
->
buffer
=
cgc
->
buffer
;
if
(
buffer
&&
SRpnt
->
sr_host
->
unchecked_isa_dma
&&
if
(
cgc
->
buffer
&&
SRpnt
->
sr_host
->
unchecked_isa_dma
&&
(
virt_to_phys
(
buffer
)
+
buflength
-
1
>
ISA_DMA_THRESHOLD
))
{
(
virt_to_phys
(
cgc
->
buffer
)
+
cgc
->
buflen
-
1
>
ISA_DMA_THRESHOLD
))
{
bounce_buffer
=
(
char
*
)
kmalloc
(
buflength
,
GFP_DMA
);
bounce_buffer
=
(
char
*
)
kmalloc
(
cgc
->
buflen
,
GFP_DMA
);
if
(
bounce_buffer
==
NULL
)
{
if
(
bounce_buffer
==
NULL
)
{
printk
(
"SCSI DMA pool exhausted."
);
printk
(
"SCSI DMA pool exhausted."
);
return
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
out
;
}
}
memcpy
(
bounce_buffer
,
(
char
*
)
buffer
,
buflength
);
memcpy
(
bounce_buffer
,
cgc
->
buffer
,
cgc
->
buflen
);
buffer
=
bounce_buffer
;
cgc
->
buffer
=
bounce_buffer
;
}
}
retry:
retry:
if
(
!
scsi_block_when_processing_errors
(
SDev
))
if
(
!
scsi_block_when_processing_errors
(
SDev
))
{
return
-
ENODEV
;
err
=
-
ENODEV
;
goto
out
;
}
scsi_wait_req
(
SRpnt
,
(
void
*
)
sr_cmd
,
(
void
*
)
buffer
,
buflength
,
scsi_wait_req
(
SRpnt
,
cgc
->
cmd
,
cgc
->
buffer
,
cgc
->
buflen
,
IOCTL_TIMEOUT
,
IOCTL_RETRIES
);
cgc
->
timeout
,
IOCTL_RETRIES
);
req
=
SRpnt
->
sr_request
;
req
=
SRpnt
->
sr_request
;
if
(
SRpnt
->
sr_buffer
&&
req
->
buffer
&&
SRpnt
->
sr_buffer
!=
req
->
buffer
)
{
if
(
SRpnt
->
sr_buffer
&&
req
->
buffer
&&
SRpnt
->
sr_buffer
!=
req
->
buffer
)
{
...
@@ -124,7 +127,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
...
@@ -124,7 +127,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
switch
(
SRpnt
->
sr_sense_buffer
[
2
]
&
0xf
)
{
switch
(
SRpnt
->
sr_sense_buffer
[
2
]
&
0xf
)
{
case
UNIT_ATTENTION
:
case
UNIT_ATTENTION
:
SDev
->
changed
=
1
;
SDev
->
changed
=
1
;
if
(
!
quiet
)
if
(
!
cgc
->
quiet
)
printk
(
KERN_INFO
"%s: disc change detected.
\n
"
,
cd
->
cdi
.
name
);
printk
(
KERN_INFO
"%s: disc change detected.
\n
"
,
cd
->
cdi
.
name
);
if
(
retries
++
<
10
)
if
(
retries
++
<
10
)
goto
retry
;
goto
retry
;
...
@@ -134,7 +137,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
...
@@ -134,7 +137,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
if
(
SRpnt
->
sr_sense_buffer
[
12
]
==
0x04
&&
if
(
SRpnt
->
sr_sense_buffer
[
12
]
==
0x04
&&
SRpnt
->
sr_sense_buffer
[
13
]
==
0x01
)
{
SRpnt
->
sr_sense_buffer
[
13
]
==
0x01
)
{
/* sense: Logical unit is in process of becoming ready */
/* sense: Logical unit is in process of becoming ready */
if
(
!
quiet
)
if
(
!
cgc
->
quiet
)
printk
(
KERN_INFO
"%s: CDROM not ready yet.
\n
"
,
cd
->
cdi
.
name
);
printk
(
KERN_INFO
"%s: CDROM not ready yet.
\n
"
,
cd
->
cdi
.
name
);
if
(
retries
++
<
10
)
{
if
(
retries
++
<
10
)
{
/* sleep 2 sec and try again */
/* sleep 2 sec and try again */
...
@@ -146,7 +149,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
...
@@ -146,7 +149,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
break
;
break
;
}
}
}
}
if
(
!
quiet
)
if
(
!
cgc
->
quiet
)
printk
(
KERN_INFO
"%s: CDROM not ready. Make sure there is a disc in the drive.
\n
"
,
cd
->
cdi
.
name
);
printk
(
KERN_INFO
"%s: CDROM not ready. Make sure there is a disc in the drive.
\n
"
,
cd
->
cdi
.
name
);
#ifdef DEBUG
#ifdef DEBUG
print_req_sense
(
"sr"
,
SRpnt
);
print_req_sense
(
"sr"
,
SRpnt
);
...
@@ -154,7 +157,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
...
@@ -154,7 +157,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
err
=
-
ENOMEDIUM
;
err
=
-
ENOMEDIUM
;
break
;
break
;
case
ILLEGAL_REQUEST
:
case
ILLEGAL_REQUEST
:
if
(
!
quiet
)
if
(
!
cgc
->
quiet
)
printk
(
KERN_ERR
"%s: CDROM (ioctl) reports ILLEGAL "
printk
(
KERN_ERR
"%s: CDROM (ioctl) reports ILLEGAL "
"REQUEST.
\n
"
,
cd
->
cdi
.
name
);
"REQUEST.
\n
"
,
cd
->
cdi
.
name
);
if
(
SRpnt
->
sr_sense_buffer
[
12
]
==
0x20
&&
if
(
SRpnt
->
sr_sense_buffer
[
12
]
==
0x20
&&
...
@@ -165,24 +168,26 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
...
@@ -165,24 +168,26 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
err
=
-
EINVAL
;
err
=
-
EINVAL
;
}
}
#ifdef DEBUG
#ifdef DEBUG
print_command
(
sr_
cmd
);
print_command
(
cgc
->
cmd
);
print_req_sense
(
"sr"
,
SRpnt
);
print_req_sense
(
"sr"
,
SRpnt
);
#endif
#endif
break
;
break
;
default:
default:
printk
(
KERN_ERR
"%s: CDROM (ioctl) error, command: "
,
cd
->
cdi
.
name
);
printk
(
KERN_ERR
"%s: CDROM (ioctl) error, command: "
,
cd
->
cdi
.
name
);
print_command
(
sr_
cmd
);
print_command
(
cgc
->
cmd
);
print_req_sense
(
"sr"
,
SRpnt
);
print_req_sense
(
"sr"
,
SRpnt
);
err
=
-
EIO
;
err
=
-
EIO
;
}
}
}
}
if
(
sense
)
if
(
cgc
->
sense
)
memcpy
(
sense
,
SRpnt
->
sr_sense_buffer
,
sizeof
(
*
sense
));
memcpy
(
cgc
->
sense
,
SRpnt
->
sr_sense_buffer
,
sizeof
(
*
cgc
->
sense
));
/* Wake up a process waiting for device */
/* Wake up a process waiting for device */
scsi_release_request
(
SRpnt
);
scsi_release_request
(
SRpnt
);
SRpnt
=
NULL
;
SRpnt
=
NULL
;
out:
cgc
->
stat
=
err
;
return
err
;
return
err
;
}
}
...
@@ -191,35 +196,39 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
...
@@ -191,35 +196,39 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
static
int
test_unit_ready
(
Scsi_CD
*
cd
)
static
int
test_unit_ready
(
Scsi_CD
*
cd
)
{
{
u_char
sr_cmd
[
10
]
;
struct
cdrom_generic_command
cgc
;
sr_cmd
[
0
]
=
GPCMD_TEST_UNIT_READY
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cgc
.
cmd
[
0
]
=
GPCMD_TEST_UNIT_READY
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
sr_cmd
[
3
]
=
sr_cmd
[
4
]
=
sr_cmd
[
5
]
=
0
;
cgc
.
quiet
=
1
;
return
sr_do_ioctl
(
cd
,
sr_cmd
,
NULL
,
0
,
1
,
SCSI_DATA_NONE
,
NULL
);
cgc
.
data_direction
=
SCSI_DATA_NONE
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
return
sr_do_ioctl
(
cd
,
&
cgc
);
}
}
int
sr_tray_move
(
struct
cdrom_device_info
*
cdi
,
int
pos
)
int
sr_tray_move
(
struct
cdrom_device_info
*
cdi
,
int
pos
)
{
{
Scsi_CD
*
cd
=
cdi
->
handle
;
Scsi_CD
*
cd
=
cdi
->
handle
;
u_char
sr_cmd
[
10
]
;
struct
cdrom_generic_command
cgc
;
sr_cmd
[
0
]
=
GPCMD_START_STOP_UNIT
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cgc
.
cmd
[
0
]
=
GPCMD_START_STOP_UNIT
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
sr_cmd
[
3
]
=
sr_cmd
[
5
]
=
0
;
cgc
.
cmd
[
4
]
=
(
pos
==
0
)
?
0x03
/* close */
:
0x02
/* eject */
;
sr_cmd
[
4
]
=
(
pos
==
0
)
?
0x03
/* close */
:
0x02
/* eject */
;
cgc
.
data_direction
=
SCSI_DATA_NONE
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
return
sr_do_ioctl
(
cd
,
sr_cmd
,
NULL
,
0
,
0
,
SCSI_DATA_NONE
,
NULL
);
return
sr_do_ioctl
(
cd
,
&
cgc
);
}
}
int
sr_lock_door
(
struct
cdrom_device_info
*
cdi
,
int
lock
)
int
sr_lock_door
(
struct
cdrom_device_info
*
cdi
,
int
lock
)
{
{
Scsi_CD
*
cd
=
cdi
->
handle
;
Scsi_CD
*
cd
=
cdi
->
handle
;
return
scsi_
ioctl
(
cd
->
device
,
lock
?
SCSI_IOCTL_DOORLOCK
:
return
scsi_
set_medium_removal
(
cd
->
device
,
lock
?
SCSI_IOCTL_DOORUNLOCK
,
0
);
SCSI_REMOVAL_PREVENT
:
SCSI_REMOVAL_ALLOW
);
}
}
int
sr_drive_status
(
struct
cdrom_device_info
*
cdi
,
int
slot
)
int
sr_drive_status
(
struct
cdrom_device_info
*
cdi
,
int
slot
)
...
@@ -278,22 +287,22 @@ int sr_get_last_session(struct cdrom_device_info *cdi,
...
@@ -278,22 +287,22 @@ int sr_get_last_session(struct cdrom_device_info *cdi,
int
sr_get_mcn
(
struct
cdrom_device_info
*
cdi
,
struct
cdrom_mcn
*
mcn
)
int
sr_get_mcn
(
struct
cdrom_device_info
*
cdi
,
struct
cdrom_mcn
*
mcn
)
{
{
Scsi_CD
*
cd
=
cdi
->
handle
;
Scsi_CD
*
cd
=
cdi
->
handle
;
u_char
sr_cmd
[
10
]
;
struct
cdrom_generic_command
cgc
;
char
buffer
[
32
];
char
buffer
[
32
];
int
result
;
int
result
;
sr_cmd
[
0
]
=
GPCMD_READ_SUBCHANNEL
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cgc
.
cmd
[
0
]
=
GPCMD_READ_SUBCHANNEL
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
0x40
;
/* I do want the subchannel info */
cgc
.
cmd
[
2
]
=
0x40
;
/* I do want the subchannel info */
sr_cmd
[
3
]
=
0x02
;
/* Give me medium catalog number info */
cgc
.
cmd
[
3
]
=
0x02
;
/* Give me medium catalog number info */
sr_cmd
[
4
]
=
sr_cmd
[
5
]
=
0
;
cgc
.
cmd
[
8
]
=
24
;
sr_cmd
[
6
]
=
0
;
cgc
.
buffer
=
buffer
;
sr_cmd
[
7
]
=
0
;
cgc
.
buflen
=
24
;
sr_cmd
[
8
]
=
24
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
sr_cmd
[
9
]
=
0
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
result
=
sr_do_ioctl
(
cd
,
&
cgc
);
result
=
sr_do_ioctl
(
cd
,
sr_cmd
,
buffer
,
24
,
0
,
SCSI_DATA_READ
,
NULL
);
memcpy
(
mcn
->
medium_catalog_number
,
buffer
+
9
,
13
);
memcpy
(
mcn
->
medium_catalog_number
,
buffer
+
9
,
13
);
mcn
->
medium_catalog_number
[
13
]
=
0
;
mcn
->
medium_catalog_number
[
13
]
=
0
;
...
@@ -309,21 +318,23 @@ int sr_reset(struct cdrom_device_info *cdi)
...
@@ -309,21 +318,23 @@ int sr_reset(struct cdrom_device_info *cdi)
int
sr_select_speed
(
struct
cdrom_device_info
*
cdi
,
int
speed
)
int
sr_select_speed
(
struct
cdrom_device_info
*
cdi
,
int
speed
)
{
{
Scsi_CD
*
cd
=
cdi
->
handle
;
Scsi_CD
*
cd
=
cdi
->
handle
;
u_char
sr_cmd
[
MAX_COMMAND_SIZE
]
;
struct
cdrom_generic_command
cgc
;
if
(
speed
==
0
)
if
(
speed
==
0
)
speed
=
0xffff
;
/* set to max */
speed
=
0xffff
;
/* set to max */
else
else
speed
*=
177
;
/* Nx to kbyte/s */
speed
*=
177
;
/* Nx to kbyte/s */
memset
(
sr_cmd
,
0
,
MAX_COMMAND_SIZE
);
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
)
);
sr_
cmd
[
0
]
=
GPCMD_SET_SPEED
;
/* SET CD SPEED */
cgc
.
cmd
[
0
]
=
GPCMD_SET_SPEED
;
/* SET CD SPEED */
sr_
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
(
speed
>>
8
)
&
0xff
;
/* MSB for speed (in kbytes/sec) */
cgc
.
cmd
[
2
]
=
(
speed
>>
8
)
&
0xff
;
/* MSB for speed (in kbytes/sec) */
sr_cmd
[
3
]
=
speed
&
0xff
;
/* LSB */
cgc
.
cmd
[
3
]
=
speed
&
0xff
;
/* LSB */
cgc
.
data_direction
=
SCSI_DATA_NONE
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
if
(
sr_do_ioctl
(
cd
,
sr_cmd
,
NULL
,
0
,
0
,
SCSI_DATA_NONE
,
NULL
))
if
(
sr_do_ioctl
(
cd
,
&
cgc
))
return
-
EIO
;
return
-
EIO
;
return
0
;
return
0
;
}
}
...
@@ -337,24 +348,28 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
...
@@ -337,24 +348,28 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
int
sr_audio_ioctl
(
struct
cdrom_device_info
*
cdi
,
unsigned
int
cmd
,
void
*
arg
)
int
sr_audio_ioctl
(
struct
cdrom_device_info
*
cdi
,
unsigned
int
cmd
,
void
*
arg
)
{
{
Scsi_CD
*
cd
=
cdi
->
handle
;
Scsi_CD
*
cd
=
cdi
->
handle
;
u_char
sr_cmd
[
10
]
;
struct
cdrom_generic_command
cgc
;
int
result
;
int
result
;
unsigned
char
buffer
[
32
];
unsigned
char
buffer
[
32
];
memset
(
sr_cmd
,
0
,
sizeof
(
sr_cmd
));
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
cgc
.
timeout
=
IOCTL_TIMEOUT
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
CDROMREADTOCHDR
:
case
CDROMREADTOCHDR
:
{
{
struct
cdrom_tochdr
*
tochdr
=
(
struct
cdrom_tochdr
*
)
arg
;
struct
cdrom_tochdr
*
tochdr
=
(
struct
cdrom_tochdr
*
)
arg
;
sr_
cmd
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
cgc
.
cmd
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
sr_
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
sr_cmd
[
3
]
=
sr_cmd
[
4
]
=
sr_cmd
[
5
]
=
0
;
cgc
.
cmd
[
8
]
=
12
;
/* LSB of length */
sr_cmd
[
8
]
=
12
;
/* LSB of length */
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
12
;
cgc
.
quiet
=
1
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
result
=
sr_do_ioctl
(
cd
,
sr_cmd
,
buffer
,
12
,
1
,
SCSI_DATA_READ
,
NULL
);
result
=
sr_do_ioctl
(
cd
,
&
cgc
);
tochdr
->
cdth_trk0
=
buffer
[
2
];
tochdr
->
cdth_trk0
=
buffer
[
2
];
tochdr
->
cdth_trk1
=
buffer
[
3
];
tochdr
->
cdth_trk1
=
buffer
[
3
];
...
@@ -366,15 +381,17 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
...
@@ -366,15 +381,17 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
{
{
struct
cdrom_tocentry
*
tocentry
=
(
struct
cdrom_tocentry
*
)
arg
;
struct
cdrom_tocentry
*
tocentry
=
(
struct
cdrom_tocentry
*
)
arg
;
sr_
cmd
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
cgc
.
cmd
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
sr_
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
1
]
|=
(
tocentry
->
cdte_format
==
CDROM_MSF
)
?
0x02
:
0
;
cgc
.
cmd
[
1
]
|=
(
tocentry
->
cdte_format
==
CDROM_MSF
)
?
0x02
:
0
;
sr_cmd
[
2
]
=
sr_cmd
[
3
]
=
sr_cmd
[
4
]
=
sr_cmd
[
5
]
=
0
;
cgc
.
cmd
[
6
]
=
tocentry
->
cdte_track
;
sr_cmd
[
6
]
=
tocentry
->
cdte_track
;
cgc
.
cmd
[
8
]
=
12
;
/* LSB of length */
sr_cmd
[
8
]
=
12
;
/* LSB of length */
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
12
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
result
=
sr_do_ioctl
(
cd
,
sr_cmd
,
buffer
,
12
,
0
,
SCSI_DATA_READ
,
NULL
);
result
=
sr_do_ioctl
(
cd
,
&
cgc
);
tocentry
->
cdte_ctrl
=
buffer
[
5
]
&
0xf
;
tocentry
->
cdte_ctrl
=
buffer
[
5
]
&
0xf
;
tocentry
->
cdte_adr
=
buffer
[
5
]
>>
4
;
tocentry
->
cdte_adr
=
buffer
[
5
]
>>
4
;
...
@@ -393,15 +410,16 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
...
@@ -393,15 +410,16 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
case
CDROMPLAYTRKIND
:
{
case
CDROMPLAYTRKIND
:
{
struct
cdrom_ti
*
ti
=
(
struct
cdrom_ti
*
)
arg
;
struct
cdrom_ti
*
ti
=
(
struct
cdrom_ti
*
)
arg
;
sr_
cmd
[
0
]
=
GPCMD_PLAYAUDIO_TI
;
cgc
.
cmd
[
0
]
=
GPCMD_PLAYAUDIO_TI
;
sr_
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
(
cd
->
device
->
lun
<<
5
)
:
0
;
sr_cmd
[
4
]
=
ti
->
cdti_trk0
;
cgc
.
cmd
[
4
]
=
ti
->
cdti_trk0
;
sr_cmd
[
5
]
=
ti
->
cdti_ind0
;
cgc
.
cmd
[
5
]
=
ti
->
cdti_ind0
;
sr_cmd
[
7
]
=
ti
->
cdti_trk1
;
cgc
.
cmd
[
7
]
=
ti
->
cdti_trk1
;
sr_cmd
[
8
]
=
ti
->
cdti_ind1
;
cgc
.
cmd
[
8
]
=
ti
->
cdti_ind1
;
cgc
.
data_direction
=
SCSI_DATA_NONE
;
result
=
sr_do_ioctl
(
cd
,
sr_cmd
,
NULL
,
0
,
0
,
SCSI_DATA_NONE
,
NULL
);
result
=
sr_do_ioctl
(
cd
,
&
cgc
);
if
(
result
==
-
EDRIVE_CANT_DO_THIS
)
if
(
result
==
-
EDRIVE_CANT_DO_THIS
)
result
=
sr_fake_playtrkind
(
cdi
,
ti
);
result
=
sr_fake_playtrkind
(
cdi
,
ti
);
...
@@ -436,38 +454,42 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
...
@@ -436,38 +454,42 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
static
int
sr_read_cd
(
Scsi_CD
*
cd
,
unsigned
char
*
dest
,
int
lba
,
int
format
,
int
blksize
)
static
int
sr_read_cd
(
Scsi_CD
*
cd
,
unsigned
char
*
dest
,
int
lba
,
int
format
,
int
blksize
)
{
{
unsigned
char
cmd
[
MAX_COMMAND_SIZE
]
;
struct
cdrom_generic_command
cgc
;
#ifdef DEBUG
#ifdef DEBUG
printk
(
"%s: sr_read_cd lba=%d format=%d blksize=%d
\n
"
,
printk
(
"%s: sr_read_cd lba=%d format=%d blksize=%d
\n
"
,
cd
->
cdi
.
name
,
lba
,
format
,
blksize
);
cd
->
cdi
.
name
,
lba
,
format
,
blksize
);
#endif
#endif
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
)
);
cmd
[
0
]
=
GPCMD_READ_CD
;
/* READ_CD */
c
gc
.
c
md
[
0
]
=
GPCMD_READ_CD
;
/* READ_CD */
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
c
gc
.
c
md
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
1
]
|=
((
format
&
7
)
<<
2
);
c
gc
.
c
md
[
1
]
|=
((
format
&
7
)
<<
2
);
cmd
[
2
]
=
(
unsigned
char
)
(
lba
>>
24
)
&
0xff
;
c
gc
.
c
md
[
2
]
=
(
unsigned
char
)
(
lba
>>
24
)
&
0xff
;
cmd
[
3
]
=
(
unsigned
char
)
(
lba
>>
16
)
&
0xff
;
c
gc
.
c
md
[
3
]
=
(
unsigned
char
)
(
lba
>>
16
)
&
0xff
;
cmd
[
4
]
=
(
unsigned
char
)
(
lba
>>
8
)
&
0xff
;
c
gc
.
c
md
[
4
]
=
(
unsigned
char
)
(
lba
>>
8
)
&
0xff
;
cmd
[
5
]
=
(
unsigned
char
)
lba
&
0xff
;
c
gc
.
c
md
[
5
]
=
(
unsigned
char
)
lba
&
0xff
;
cmd
[
8
]
=
1
;
c
gc
.
c
md
[
8
]
=
1
;
switch
(
blksize
)
{
switch
(
blksize
)
{
case
2336
:
case
2336
:
cmd
[
9
]
=
0x58
;
c
gc
.
c
md
[
9
]
=
0x58
;
break
;
break
;
case
2340
:
case
2340
:
cmd
[
9
]
=
0x78
;
c
gc
.
c
md
[
9
]
=
0x78
;
break
;
break
;
case
2352
:
case
2352
:
cmd
[
9
]
=
0xf8
;
c
gc
.
c
md
[
9
]
=
0xf8
;
break
;
break
;
default:
default:
cmd
[
9
]
=
0x10
;
c
gc
.
c
md
[
9
]
=
0x10
;
break
;
break
;
}
}
return
sr_do_ioctl
(
cd
,
cmd
,
dest
,
blksize
,
0
,
SCSI_DATA_READ
,
NULL
);
cgc
.
buffer
=
dest
;
cgc
.
buflen
=
blksize
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
return
sr_do_ioctl
(
cd
,
&
cgc
);
}
}
/*
/*
...
@@ -476,7 +498,7 @@ static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int
...
@@ -476,7 +498,7 @@ static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int
static
int
sr_read_sector
(
Scsi_CD
*
cd
,
int
lba
,
int
blksize
,
unsigned
char
*
dest
)
static
int
sr_read_sector
(
Scsi_CD
*
cd
,
int
lba
,
int
blksize
,
unsigned
char
*
dest
)
{
{
unsigned
char
cmd
[
MAX_COMMAND_SIZE
];
/* the scsi-command */
struct
cdrom_generic_command
cgc
;
int
rc
;
int
rc
;
/* we try the READ CD command first... */
/* we try the READ CD command first... */
...
@@ -497,16 +519,20 @@ static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest
...
@@ -497,16 +519,20 @@ static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest
printk
(
"%s: sr_read_sector lba=%d blksize=%d
\n
"
,
cd
->
cdi
.
name
,
lba
,
blksize
);
printk
(
"%s: sr_read_sector lba=%d blksize=%d
\n
"
,
cd
->
cdi
.
name
,
lba
,
blksize
);
#endif
#endif
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
)
);
cmd
[
0
]
=
GPCMD_READ_10
;
c
gc
.
c
md
[
0
]
=
GPCMD_READ_10
;
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
c
gc
.
c
md
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
2
]
=
(
unsigned
char
)
(
lba
>>
24
)
&
0xff
;
cgc
.
cmd
[
2
]
=
(
unsigned
char
)
(
lba
>>
24
)
&
0xff
;
cmd
[
3
]
=
(
unsigned
char
)
(
lba
>>
16
)
&
0xff
;
cgc
.
cmd
[
3
]
=
(
unsigned
char
)
(
lba
>>
16
)
&
0xff
;
cmd
[
4
]
=
(
unsigned
char
)
(
lba
>>
8
)
&
0xff
;
cgc
.
cmd
[
4
]
=
(
unsigned
char
)
(
lba
>>
8
)
&
0xff
;
cmd
[
5
]
=
(
unsigned
char
)
lba
&
0xff
;
cgc
.
cmd
[
5
]
=
(
unsigned
char
)
lba
&
0xff
;
cmd
[
8
]
=
1
;
cgc
.
cmd
[
8
]
=
1
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
dest
,
blksize
,
0
,
SCSI_DATA_READ
,
NULL
);
cgc
.
buffer
=
dest
;
cgc
.
buflen
=
blksize
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
rc
=
sr_do_ioctl
(
cd
,
&
cgc
);
return
rc
;
return
rc
;
}
}
...
@@ -562,7 +588,6 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
...
@@ -562,7 +588,6 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
* c-label-offset: -4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* tab-width: 8
* End:
* End:
*/
*/
drivers/scsi/sr_vendor.c
View file @
34d3616d
...
@@ -58,6 +58,8 @@
...
@@ -58,6 +58,8 @@
#define VENDOR_TOSHIBA 3
#define VENDOR_TOSHIBA 3
#define VENDOR_WRITER 4
/* pre-scsi3 writers */
#define VENDOR_WRITER 4
/* pre-scsi3 writers */
#define VENDOR_TIMEOUT 30*HZ
void
sr_vendor_init
(
Scsi_CD
*
cd
)
void
sr_vendor_init
(
Scsi_CD
*
cd
)
{
{
#ifndef CONFIG_BLK_DEV_SR_VENDOR
#ifndef CONFIG_BLK_DEV_SR_VENDOR
...
@@ -104,7 +106,7 @@ void sr_vendor_init(Scsi_CD *cd)
...
@@ -104,7 +106,7 @@ void sr_vendor_init(Scsi_CD *cd)
int
sr_set_blocklength
(
Scsi_CD
*
cd
,
int
blocklength
)
int
sr_set_blocklength
(
Scsi_CD
*
cd
,
int
blocklength
)
{
{
unsigned
char
*
buffer
;
/* the buffer for the ioctl */
unsigned
char
*
buffer
;
/* the buffer for the ioctl */
unsigned
char
cmd
[
MAX_COMMAND_SIZE
];
/* the scsi-command */
struct
cdrom_generic_command
cgc
;
struct
ccs_modesel_head
*
modesel
;
struct
ccs_modesel_head
*
modesel
;
int
rc
,
density
=
0
;
int
rc
,
density
=
0
;
...
@@ -120,19 +122,23 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength)
...
@@ -120,19 +122,23 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength)
#ifdef DEBUG
#ifdef DEBUG
printk
(
"%s: MODE SELECT 0x%x/%d
\n
"
,
cd
->
cdi
.
name
,
density
,
blocklength
);
printk
(
"%s: MODE SELECT 0x%x/%d
\n
"
,
cd
->
cdi
.
name
,
density
,
blocklength
);
#endif
#endif
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
)
);
cmd
[
0
]
=
MODE_SELECT
;
c
gc
.
c
md
[
0
]
=
MODE_SELECT
;
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
c
gc
.
c
md
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
1
]
|=
(
1
<<
4
);
c
gc
.
c
md
[
1
]
|=
(
1
<<
4
);
cmd
[
4
]
=
12
;
c
gc
.
c
md
[
4
]
=
12
;
modesel
=
(
struct
ccs_modesel_head
*
)
buffer
;
modesel
=
(
struct
ccs_modesel_head
*
)
buffer
;
memset
(
modesel
,
0
,
sizeof
(
*
modesel
));
memset
(
modesel
,
0
,
sizeof
(
*
modesel
));
modesel
->
block_desc_length
=
0x08
;
modesel
->
block_desc_length
=
0x08
;
modesel
->
density
=
density
;
modesel
->
density
=
density
;
modesel
->
block_length_med
=
(
blocklength
>>
8
)
&
0xff
;
modesel
->
block_length_med
=
(
blocklength
>>
8
)
&
0xff
;
modesel
->
block_length_lo
=
blocklength
&
0xff
;
modesel
->
block_length_lo
=
blocklength
&
0xff
;
if
(
0
==
(
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
sizeof
(
*
modesel
),
0
,
SCSI_DATA_WRITE
,
NULL
)))
{
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
sizeof
(
*
modesel
);
cgc
.
data_direction
=
SCSI_DATA_WRITE
;
cgc
.
timeout
=
VENDOR_TIMEOUT
;
if
(
0
==
(
rc
=
sr_do_ioctl
(
cd
,
&
cgc
)))
{
cd
->
device
->
sector_size
=
blocklength
;
cd
->
device
->
sector_size
=
blocklength
;
}
}
#ifdef DEBUG
#ifdef DEBUG
...
@@ -154,7 +160,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
...
@@ -154,7 +160,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
Scsi_CD
*
cd
=
cdi
->
handle
;
Scsi_CD
*
cd
=
cdi
->
handle
;
unsigned
long
sector
;
unsigned
long
sector
;
unsigned
char
*
buffer
;
/* the buffer for the ioctl */
unsigned
char
*
buffer
;
/* the buffer for the ioctl */
unsigned
char
cmd
[
MAX_COMMAND_SIZE
];
/* the scsi-command */
struct
cdrom_generic_command
cgc
;
int
rc
,
no_multi
;
int
rc
,
no_multi
;
if
(
cd
->
cdi
.
mask
&
CDC_MULTI_SESSION
)
if
(
cd
->
cdi
.
mask
&
CDC_MULTI_SESSION
)
...
@@ -168,16 +174,22 @@ int sr_cd_check(struct cdrom_device_info *cdi)
...
@@ -168,16 +174,22 @@ int sr_cd_check(struct cdrom_device_info *cdi)
no_multi
=
0
;
/* flag: the drive can't handle multisession */
no_multi
=
0
;
/* flag: the drive can't handle multisession */
rc
=
0
;
rc
=
0
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
switch
(
cd
->
vendor
)
{
switch
(
cd
->
vendor
)
{
case
VENDOR_SCSI3
:
case
VENDOR_SCSI3
:
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cgc
.
cmd
[
0
]
=
READ_TOC
;
cmd
[
0
]
=
READ_TOC
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
8
]
=
12
;
cgc
.
cmd
[
8
]
=
12
;
cmd
[
9
]
=
0x40
;
cgc
.
cmd
[
9
]
=
0x40
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
12
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
12
;
cgc
.
quiet
=
1
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
VENDOR_TIMEOUT
;
rc
=
sr_do_ioctl
(
cd
,
&
cgc
);
if
(
rc
!=
0
)
if
(
rc
!=
0
)
break
;
break
;
if
((
buffer
[
0
]
<<
8
)
+
buffer
[
1
]
<
0x0a
)
{
if
((
buffer
[
0
]
<<
8
)
+
buffer
[
1
]
<
0x0a
)
{
...
@@ -197,13 +209,17 @@ int sr_cd_check(struct cdrom_device_info *cdi)
...
@@ -197,13 +209,17 @@ int sr_cd_check(struct cdrom_device_info *cdi)
#ifdef CONFIG_BLK_DEV_SR_VENDOR
#ifdef CONFIG_BLK_DEV_SR_VENDOR
case
VENDOR_NEC
:{
case
VENDOR_NEC
:{
unsigned
long
min
,
sec
,
frame
;
unsigned
long
min
,
sec
,
frame
;
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cgc
.
cmd
[
0
]
=
0xde
;
cmd
[
0
]
=
0xde
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
1
]
|=
0x03
;
cgc
.
cmd
[
1
]
|=
0x03
;
cmd
[
2
]
=
0xb0
;
cgc
.
cmd
[
2
]
=
0xb0
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
0x16
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
0x16
;
cgc
.
quiet
=
1
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
VENDOR_TIMEOUT
;
rc
=
sr_do_ioctl
(
cd
,
&
cgc
);
if
(
rc
!=
0
)
if
(
rc
!=
0
)
break
;
break
;
if
(
buffer
[
14
]
!=
0
&&
buffer
[
14
]
!=
0xb0
)
{
if
(
buffer
[
14
]
!=
0
&&
buffer
[
14
]
!=
0xb0
)
{
...
@@ -225,12 +241,16 @@ int sr_cd_check(struct cdrom_device_info *cdi)
...
@@ -225,12 +241,16 @@ int sr_cd_check(struct cdrom_device_info *cdi)
/* we request some disc information (is it a XA-CD ?,
/* we request some disc information (is it a XA-CD ?,
* where starts the last session ?) */
* where starts the last session ?) */
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cgc
.
cmd
[
0
]
=
0xc7
;
cmd
[
0
]
=
0xc7
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
1
]
|=
0x03
;
cgc
.
cmd
[
1
]
|=
0x03
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
4
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
4
;
cgc
.
quiet
=
1
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
VENDOR_TIMEOUT
;
rc
=
sr_do_ioctl
(
cd
,
&
cgc
);
if
(
rc
==
-
EINVAL
)
{
if
(
rc
==
-
EINVAL
)
{
printk
(
KERN_INFO
"%s: Hmm, seems the drive "
printk
(
KERN_INFO
"%s: Hmm, seems the drive "
"doesn't support multisession CD's
\n
"
,
"doesn't support multisession CD's
\n
"
,
...
@@ -251,13 +271,17 @@ int sr_cd_check(struct cdrom_device_info *cdi)
...
@@ -251,13 +271,17 @@ int sr_cd_check(struct cdrom_device_info *cdi)
}
}
case
VENDOR_WRITER
:
case
VENDOR_WRITER
:
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cgc
.
cmd
[
0
]
=
READ_TOC
;
cmd
[
0
]
=
READ_TOC
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
8
]
=
0x04
;
cgc
.
cmd
[
8
]
=
0x04
;
cmd
[
9
]
=
0x40
;
cgc
.
cmd
[
9
]
=
0x40
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
0x04
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
0x04
;
cgc
.
quiet
=
1
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
VENDOR_TIMEOUT
;
rc
=
sr_do_ioctl
(
cd
,
&
cgc
);
if
(
rc
!=
0
)
{
if
(
rc
!=
0
)
{
break
;
break
;
}
}
...
@@ -266,13 +290,18 @@ int sr_cd_check(struct cdrom_device_info *cdi)
...
@@ -266,13 +290,18 @@ int sr_cd_check(struct cdrom_device_info *cdi)
"%s: No finished session
\n
"
,
cd
->
cdi
.
name
);
"%s: No finished session
\n
"
,
cd
->
cdi
.
name
);
break
;
break
;
}
}
cmd
[
0
]
=
READ_TOC
;
/* Read TOC */
c
gc
.
c
md
[
0
]
=
READ_TOC
;
/* Read TOC */
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
c
gc
.
c
md
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
6
]
=
rc
&
0x7f
;
/* number of last session */
cgc
.
cmd
[
6
]
=
rc
&
0x7f
;
/* number of last session */
cmd
[
8
]
=
0x0c
;
cgc
.
cmd
[
8
]
=
0x0c
;
cmd
[
9
]
=
0x40
;
cgc
.
cmd
[
9
]
=
0x40
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
12
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
12
;
cgc
.
quiet
=
1
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
VENDOR_TIMEOUT
;
rc
=
sr_do_ioctl
(
cd
,
&
cgc
);
if
(
rc
!=
0
)
{
if
(
rc
!=
0
)
{
break
;
break
;
}
}
...
...
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