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
Kirill Smelkov
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
Hide 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)
*/
int
scsi_retry_command
(
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
;
/*
* Restore the SCSI command state.
*/
scsi_setup_cmd_retry
(
SCpnt
);
/*
* 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,
int
sectors
);
extern
struct
Scsi_Device_Template
*
scsi_get_request_dev
(
struct
request
*
);
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
void
scsi_io_completion
(
Scsi_Cmnd
*
SCpnt
,
int
good_sectors
,
int
block_sectors
);
...
...
@@ -597,9 +598,10 @@ struct scsi_device {
unsigned
changed
:
1
;
/* Data invalid due to media change */
unsigned
busy
:
1
;
/* Used to prevent races */
unsigned
lockable
:
1
;
/* Able to prevent media removal */
unsigned
locked
:
1
;
/* Media removal disabled */
unsigned
borken
:
1
;
/* Tell the Seagate driver to be
* painfully slow on this device */
//
unsigned disconnect:1; /* can disconnect */
unsigned
disconnect
:
1
;
/* can disconnect */
unsigned
soft_reset
:
1
;
/* Uses soft reset option */
unsigned
sdtr
:
1
;
/* Device supports SDTR messages */
unsigned
wdtr
:
1
;
/* Device supports WDTR messages */
...
...
drivers/scsi/scsi_error.c
View file @
34d3616d
...
...
@@ -8,6 +8,10 @@
*
* Restructured scsi_unjam_host and associated functions.
* 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>
...
...
@@ -35,6 +39,8 @@
#include "scsi.h"
#include "hosts.h"
#include <scsi/scsi_ioctl.h>
/* grr */
/*
* 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
...
...
@@ -59,7 +65,7 @@
* These should *probably* be handled by the host itself.
* 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
/**
...
...
@@ -91,9 +97,9 @@ void scsi_add_timer(Scsi_Cmnd *scmd, int timeout, void (*complete)
scmd
->
eh_timeout
.
expires
=
jiffies
+
timeout
;
scmd
->
eh_timeout
.
function
=
(
void
(
*
)(
unsigned
long
))
complete
;
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"
Adding timer for command %p at
"
"
%d (%p)
\n
"
,
scmd
,
timeout
,
complete
));
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"
%s: scmd: %p, time:
"
"
%d, (%p)
\n
"
,
__FUNCTION__
,
scmd
,
timeout
,
complete
));
add_timer
(
&
scmd
->
eh_timeout
);
...
...
@@ -116,8 +122,9 @@ int scsi_delete_timer(Scsi_Cmnd *scmd)
rtn
=
del_timer
(
&
scmd
->
eh_timeout
);
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"Clearing timer for command %p"
" %d
\n
"
,
scmd
,
rtn
));
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"%s: scmd: %p,"
" rtn: %d
\n
"
,
__FUNCTION__
,
scmd
,
rtn
));
scmd
->
eh_timeout
.
data
=
(
unsigned
long
)
NULL
;
scmd
->
eh_timeout
.
function
=
NULL
;
...
...
@@ -150,7 +157,7 @@ void scsi_times_out(Scsi_Cmnd *scmd)
scsi_host_failed_inc_and_test
(
scmd
->
host
);
SCSI_LOG_TIMEOUT
(
3
,
printk
(
"Command timed out active=%d busy=%d "
"failed=%d
\n
"
,
"
failed=%d
\n
"
,
atomic_read
(
&
scmd
->
host
->
host_active
),
scmd
->
host
->
host_busy
,
scmd
->
host
->
host_failed
));
...
...
@@ -173,7 +180,7 @@ int scsi_block_when_processing_errors(Scsi_Device *sdev)
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
));
return
sdev
->
online
;
...
...
@@ -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
)
{
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"
scsi_eh
: %d:%d:%d:%d cmds failed: %d,"
"timedout: %d
\n
"
,
shost
->
host_no
,
sdev
->
channel
,
sdev
->
id
,
sdev
->
lun
,
printk
(
"
%s
: %d:%d:%d:%d cmds failed: %d,"
"
timedout: %d
\n
"
,
__FUNCTION__
,
shost
->
host_no
,
sdev
->
channel
,
sdev
->
id
,
sdev
->
lun
,
cmd_failed
,
cmd_timed_out
));
cmd_timed_out
=
0
;
cmd_failed
=
0
;
...
...
@@ -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
"
"devices require eh work
\n
"
,
SCSI_LOG_ERROR_RECOVERY
(
2
,
printk
(
"Total of %d commands on %d"
"
devices require eh work
\n
"
,
total_failures
,
devices_failed
));
}
#endif
...
...
@@ -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
* way.
*/
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error hdlr
"
"
prematurely woken
"
"
cmds still active
"
"(%p %x %d)
\n
"
,
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error hdlr"
"
prematurely woken
"
"
cmds still active
"
"
(%p %x %d)
\n
"
,
scmd
,
scmd
->
state
,
scmd
->
target
));
}
...
...
@@ -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
));
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
* @scmd: Cmd to have sense checked.
*
* Return value:
* SUCCESS or FAILED or NEEDS_RETRY
**/
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
)
{
int
rtn
;
/*
* 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)
* SUCCESS.
*/
scmd
->
flags
&=
~
IS_RESETTING
;
goto
maybe_retry
;
return
NEEDS_RETRY
;
}
/*
* rats. we are already in the error handler, so we now
...
...
@@ -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.
* if not, we mark it as FAILED.
*/
rtn
=
scsi_check_sense
(
scmd
);
if
(
rtn
==
NEEDS_RETRY
)
goto
maybe_retry
;
return
rtn
;
return
scsi_check_sense
(
scmd
);
}
if
(
host_byte
(
scmd
->
result
)
!=
DID_OK
)
{
return
FAILED
;
...
...
@@ -400,10 +408,7 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
case
COMMAND_TERMINATED
:
return
SUCCESS
;
case
CHECK_CONDITION
:
rtn
=
scsi_check_sense
(
scmd
);
if
(
rtn
==
NEEDS_RETRY
)
goto
maybe_retry
;
return
rtn
;
return
scsi_check_sense
(
scmd
);
case
CONDITION_GOOD
:
case
INTERMEDIATE_GOOD
:
case
INTERMEDIATE_C_GOOD
:
...
...
@@ -418,14 +423,6 @@ static int scsi_eh_completed_normally(Scsi_Cmnd *scmd)
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)
static
void
scsi_eh_times_out
(
Scsi_Cmnd
*
scmd
)
{
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
)
up
(
scmd
->
host
->
eh_action
);
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)
scmd
->
owner
=
SCSI_OWNER_ERROR_HANDLER
;
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"
in eh_done %p result:%x
\n
"
,
scmd
,
scmd
->
result
));
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"
%s scmd: %p result: %x
\n
"
,
__FUNCTION__
,
scmd
,
scmd
->
result
));
if
(
scmd
->
host
->
eh_action
!=
NULL
)
up
(
scmd
->
host
->
eh_action
);
...
...
@@ -488,7 +486,7 @@ static void scsi_eh_done(Scsi_Cmnd *scmd)
* this case, and furthermore, there is a different completion handler
* vs scsi_dispatch_cmd.
* Return value:
* SUCCESS
/FAILED
* SUCCESS
or FAILED or NEEDS_RETRY
**/
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
);
retry:
/*
* we will use a queued command if possible, otherwise we will
* emulate the queuing and calling of completion function ourselves.
...
...
@@ -552,9 +549,8 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
rtn
=
FAILED
;
}
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: %p rtn:%x
\n
"
,
__FUNCTION__
,
scmd
,
rtn
));
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: scmd: %p, rtn:%x
\n
"
,
__FUNCTION__
,
scmd
,
rtn
));
}
else
{
int
temp
;
...
...
@@ -576,16 +572,15 @@ static int scsi_send_eh_cmnd(Scsi_Cmnd *scmd, int timeout)
* actually did complete normally.
*/
if
(
rtn
==
SUCCESS
)
{
int
r
et
=
scsi_eh_completed_normally
(
scmd
);
int
r
tn
=
scsi_eh_completed_normally
(
scmd
);
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: scsi_eh_completed_normally %x
\n
"
,
__FUNCTION__
,
r
et
));
switch
(
r
et
)
{
__FUNCTION__
,
r
tn
));
switch
(
r
tn
)
{
case
SUCCESS
:
break
;
case
NEEDS_RETRY
:
goto
retry
;
case
FAILED
:
break
;
default:
rtn
=
FAILED
;
break
;
...
...
@@ -622,7 +617,7 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
?
&
scsi_result0
[
0
]
:
kmalloc
(
512
,
GFP_ATOMIC
|
GFP_DMA
);
if
(
scsi_result
==
NULL
)
{
printk
(
"
cannot allocate scsi_result in scsi_request_sense.
\n
"
);
printk
(
"
%s: cannot allocate scsi_result.
\n
"
,
__FUNCTION__
);
return
FAILED
;
}
/*
...
...
@@ -657,15 +652,8 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
* when we eventually call scsi_finish, we really wish to complete
* the original request, so let's restore the original data. (db)
*/
memcpy
((
void
*
)
scmd
->
cmnd
,
(
void
*
)
scmd
->
data_cmnd
,
sizeof
(
scmd
->
data_cmnd
));
scsi_setup_cmd_retry
(
scmd
);
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.
...
...
@@ -683,16 +671,16 @@ static int scsi_request_sense(Scsi_Cmnd *scmd)
**/
static
int
scsi_eh_retry_cmd
(
Scsi_Cmnd
*
scmd
)
{
memcpy
((
void
*
)
scmd
->
cmnd
,
(
void
*
)
scmd
->
data_cmnd
,
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
;
return
scsi_send_eh_cmnd
(
scmd
,
scmd
->
timeout_per_command
)
;
int
rtn
=
SUCCESS
;
for
(;
scmd
->
retries
<
scmd
->
allowed
;
scmd
->
retries
++
)
{
scsi_setup_cmd_retry
(
scmd
)
;
rtn
=
scsi_send_eh_cmnd
(
scmd
,
scmd
->
timeout_per_command
)
;
if
(
rtn
!=
NEEDS_RETRY
)
break
;
}
return
rtn
;
}
/**
...
...
@@ -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
* things.
*/
scmd
->
use_sg
=
scmd
->
old_use_sg
;
scmd
->
sc_data_direction
=
scmd
->
sc_old_data_direction
;
scmd
->
underflow
=
scmd
->
old_underflow
;
scsi_setup_cmd_retry
(
scmd
);
}
/**
...
...
@@ -758,14 +744,14 @@ static int scsi_eh_get_sense(Scsi_Cmnd *sc_todo, struct Scsi_Host *shost)
continue
;
SCSI_LOG_ERROR_RECOVERY
(
2
,
printk
(
"%s: requesting sense"
"
for %d
\n
"
,
__FUNCTION__
,
scmd
->
target
));
"
for tgt: %d
\n
"
,
__FUNCTION__
,
scmd
->
target
));
rtn
=
scsi_request_sense
(
scmd
);
if
(
rtn
!=
SUCCESS
)
continue
;
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"sense requested for %p"
"
-
result %x
\n
"
,
scmd
,
" result %x
\n
"
,
scmd
,
scmd
->
result
));
SCSI_LOG_ERROR_RECOVERY
(
3
,
print_sense
(
"bh"
,
scmd
));
...
...
@@ -847,7 +833,9 @@ static int scsi_eh_tur(Scsi_Cmnd *scmd)
static
unsigned
char
tur_command
[
6
]
=
{
TEST_UNIT_READY
,
0
,
0
,
0
,
0
,
0
};
int
rtn
;
int
retry_cnt
=
1
;
retry_tur:
memcpy
((
void
*
)
scmd
->
cmnd
,
(
void
*
)
tur_command
,
sizeof
(
tur_command
));
...
...
@@ -873,32 +861,18 @@ static int scsi_eh_tur(Scsi_Cmnd *scmd)
* when we eventually call scsi_finish, we really wish to complete
* the original request, so let's restore the original data. (db)
*/
memcpy
((
void
*
)
scmd
->
cmnd
,
(
void
*
)
scmd
->
data_cmnd
,
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
;
scsi_setup_cmd_retry
(
scmd
);
/*
* hey, we are done. let's look to see what happened.
*/
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: scmd %p rtn %x
\n
"
,
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"%s: scmd %p rtn %x
\n
"
,
__FUNCTION__
,
scmd
,
rtn
));
if
((
rtn
==
SUCCESS
)
&&
scmd
->
result
)
{
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
;
}
}
}
if
(
rtn
==
SUCCESS
)
return
0
;
else
if
(
rtn
==
NEEDS_RETRY
)
if
(
retry_cnt
--
)
goto
retry_tur
;
return
1
;
}
...
...
@@ -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
);
if
(
rtn
==
SUCCESS
)
{
if
(
scsi_eh_tur
(
scmd
))
{
if
(
!
scsi_eh_tur
(
scmd
))
{
rtn
=
scsi_eh_retry_cmd
(
scmd
);
if
(
rtn
==
SUCCESS
)
scsi_eh_finish_cmd
(
scmd
,
shost
);
...
...
@@ -963,6 +937,11 @@ static int scsi_try_bus_device_reset(Scsi_Cmnd *scmd)
rtn
=
scmd
->
host
->
hostt
->
eh_device_reset_handler
(
scmd
);
spin_unlock_irqrestore
(
scmd
->
host
->
host_lock
,
flags
);
if
(
rtn
==
SUCCESS
)
{
scmd
->
device
->
was_reset
=
1
;
scmd
->
device
->
expecting_cc_ua
=
1
;
}
return
rtn
;
}
...
...
@@ -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.
*/
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
)
if
((
scmd
->
device
==
sdev
)
&&
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)
if
(
!
scsi_eh_eflags_chk
(
scmd
,
SCSI_EH_CMD_ERR
)
||
channel
!=
scmd
->
channel
)
continue
;
if
(
scsi_eh_tur
(
scmd
))
{
if
(
!
scsi_eh_tur
(
scmd
))
{
rtn
=
scsi_eh_retry_cmd
(
scmd
);
if
(
rtn
==
SUCCESS
)
...
...
@@ -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
))
continue
;
printk
(
KERN_INFO
"%s: Device
set offline
- not"
"ready or command retry failed"
"after error recovery: host"
"%d channel %d id %d lun %d
\n
"
,
printk
(
KERN_INFO
"%s: Device
offlined
- not"
"
ready or command retry failed"
"
after error recovery: host"
"
%d channel %d id %d lun %d
\n
"
,
__FUNCTION__
,
shost
->
host_no
,
scmd
->
device
->
channel
,
scmd
->
device
->
id
,
...
...
@@ -1243,7 +1222,7 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
*/
if
(
scmd
->
device
->
online
==
FALSE
)
{
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"%s: device offline - report"
"as SUCCESS
\n
"
,
"
as SUCCESS
\n
"
,
__FUNCTION__
));
return
SUCCESS
;
}
...
...
@@ -1367,7 +1346,7 @@ int scsi_decide_disposition(Scsi_Cmnd *scmd)
return
SUCCESS
;
case
RESERVATION_CONFLICT
:
printk
(
"scsi%d (%d,%d,%d) : reservation conflict
\n
"
,
printk
(
"scsi%d (%d,%d,%d) : reservation conflict
\n
"
,
scmd
->
host
->
host_no
,
scmd
->
channel
,
scmd
->
device
->
id
,
scmd
->
device
->
lun
);
return
SUCCESS
;
/* causes immediate i/o error */
...
...
@@ -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.
* @shost: Host we are restarting.
...
...
@@ -1403,6 +1451,15 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
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
* will be requests for character device operations, and also for
...
...
@@ -1426,8 +1483,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
if
((
shost
->
can_queue
>
0
&&
(
shost
->
host_busy
>=
shost
->
can_queue
))
||
(
shost
->
host_blocked
)
||
(
shost
->
host_self_blocked
)
||
(
sdev
->
device_blocked
))
{
||
(
shost
->
host_self_blocked
))
{
break
;
}
...
...
@@ -1475,7 +1531,7 @@ static void scsi_unjam_host(struct Scsi_Host *shost)
if
(
scsi_eh_get_sense
(
sc_todo
,
shost
))
if
(
scsi_eh_abort_cmd
(
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
);
BUG_ON
(
shost
->
host_failed
);
...
...
@@ -1563,8 +1619,7 @@ void scsi_error_handler(void *data)
/*
* Wake up the thread that created us.
*/
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"Wake up parent %d
\n
"
,
shost
->
eh_notify
->
count
.
counter
));
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"Wake up parent
\n
"
));
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,
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)
* 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)
return
scsi_ioctl_send_command
((
Scsi_Device
*
)
dev
,
(
Scsi_Ioctl_Command
*
)
arg
);
case
SCSI_IOCTL_DOORLOCK
:
if
(
!
dev
->
removable
||
!
dev
->
lockable
)
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
;
return
scsi_set_medium_removal
(
dev
,
SCSI_REMOVAL_PREVENT
);
case
SCSI_IOCTL_DOORUNLOCK
:
if
(
!
dev
->
removable
||
!
dev
->
lockable
)
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
);
return
scsi_set_medium_removal
(
dev
,
SCSI_REMOVAL_ALLOW
);
case
SCSI_IOCTL_TEST_UNIT_READY
:
scsi_cmd
[
0
]
=
TEST_UNIT_READY
;
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)
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()
*
...
...
@@ -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: "
,
SCpnt
->
host
->
host_no
,
(
int
)
SCpnt
->
channel
,
(
int
)
SCpnt
->
target
,
(
int
)
SCpnt
->
lun
);
print_command
(
SCpnt
->
cmnd
);
print_command
(
SCpnt
->
data_
cmnd
);
print_sense
(
"sd"
,
SCpnt
);
SCpnt
=
scsi_end_request
(
SCpnt
,
0
,
block_sectors
);
return
;
...
...
@@ -798,33 +822,6 @@ void scsi_request_fn(request_queue_t * q)
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
* can also quit.
...
...
drivers/scsi/scsi_syms.c
View file @
34d3616d
...
...
@@ -54,6 +54,7 @@ EXPORT_SYMBOL(scsi_release_command);
EXPORT_SYMBOL
(
print_Scsi_Cmnd
);
EXPORT_SYMBOL
(
scsi_block_when_processing_errors
);
EXPORT_SYMBOL
(
scsi_ioctl_send_command
);
EXPORT_SYMBOL
(
scsi_set_medium_removal
);
#if defined(CONFIG_SCSI_LOGGING)
/* { */
EXPORT_SYMBOL
(
scsi_logging_level
);
#endif
...
...
drivers/scsi/sd.c
View file @
34d3616d
...
...
@@ -529,7 +529,7 @@ static int sd_open(struct inode *inode, struct file *filp)
if
(
sdp
->
removable
)
if
(
sdp
->
access_count
==
1
)
if
(
scsi_block_when_processing_errors
(
sdp
))
scsi_
ioctl
(
sdp
,
SCSI_IOCTL_DOORLOCK
,
NULL
);
scsi_
set_medium_removal
(
sdp
,
SCSI_REMOVAL_PREVENT
);
return
0
;
...
...
@@ -573,7 +573,7 @@ static int sd_release(struct inode *inode, struct file *filp)
if
(
sdp
->
removable
)
{
if
(
!
sdp
->
access_count
)
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
)
__MOD_DEC_USE_COUNT
(
sdp
->
host
->
hostt
->
module
);
...
...
@@ -1623,7 +1623,6 @@ static int sd_synchronize_cache(int index, int verbose)
}
the_result
=
SRpnt
->
sr_result
;
scsi_release_request
(
SRpnt
);
if
(
verbose
)
{
if
(
the_result
!=
0
)
{
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)
}
}
scsi_release_request
(
SRpnt
);
return
(
the_result
==
0
);
}
...
...
drivers/scsi/sr.c
View file @
34d3616d
...
...
@@ -575,7 +575,7 @@ static void get_sectorsize(Scsi_CD *cd)
void
get_capabilities
(
Scsi_CD
*
cd
)
{
unsigned
char
cmd
[
6
]
;
struct
cdrom_generic_command
cgc
;
unsigned
char
*
buffer
;
int
rc
,
n
;
...
...
@@ -597,13 +597,18 @@ void get_capabilities(Scsi_CD *cd)
printk
(
KERN_ERR
"sr: out of memory.
\n
"
);
return
;
}
cmd
[
0
]
=
MODE_SENSE
;
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
<<
5
)
&
0xe0
)
:
0
;
cmd
[
2
]
=
0x2a
;
cmd
[
4
]
=
128
;
cmd
[
3
]
=
cmd
[
5
]
=
0
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
128
,
1
,
SCSI_DATA_READ
,
NULL
);
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
cgc
.
cmd
[
0
]
=
MODE_SENSE
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
<<
5
)
&
0xe0
)
:
0
;
cgc
.
cmd
[
2
]
=
0x2a
;
cgc
.
cmd
[
4
]
=
128
;
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
128
;
cgc
.
quiet
=
1
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
SR_TIMEOUT
;
rc
=
sr_do_ioctl
(
cd
,
&
cgc
);
if
(
rc
)
{
/* 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
if
(
device
->
scsi_level
<=
SCSI_2
)
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
;
}
...
...
drivers/scsi/sr.h
View file @
34d3616d
...
...
@@ -20,6 +20,10 @@
#include "scsi.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
{
unsigned
capacity
;
/* size in blocks */
Scsi_Device
*
device
;
...
...
@@ -34,7 +38,7 @@ typedef struct {
struct
gendisk
*
disk
;
}
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_tray_move
(
struct
cdrom_device_info
*
,
int
);
...
...
drivers/scsi/sr_ioctl.c
View file @
34d3616d
...
...
@@ -25,9 +25,6 @@
static
int
xa_test
=
0
;
#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
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
{
struct
cdrom_tocentry
trk0_te
,
trk1_te
;
struct
cdrom_tochdr
tochdr
;
u_char
sr_cmd
[
10
]
;
struct
cdrom_generic_command
cgc
;
int
ntracks
,
ret
;
if
((
ret
=
sr_audio_ioctl
(
cdi
,
CDROMREADTOCHDR
,
&
tochdr
)))
...
...
@@ -59,22 +56,25 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
return
ret
;
if
((
ret
=
sr_audio_ioctl
(
cdi
,
CDROMREADTOCENTRY
,
&
trk1_te
)))
return
ret
;
sr_cmd
[
0
]
=
GPCMD_PLAY_AUDIO_MSF
;
sr_cmd
[
3
]
=
trk0_te
.
cdte_addr
.
msf
.
minute
;
sr_cmd
[
4
]
=
trk0_te
.
cdte_addr
.
msf
.
second
;
sr_cmd
[
5
]
=
trk0_te
.
cdte_addr
.
msf
.
frame
;
sr_cmd
[
6
]
=
trk1_te
.
cdte_addr
.
msf
.
minute
;
sr_cmd
[
7
]
=
trk1_te
.
cdte_addr
.
msf
.
second
;
sr_cmd
[
8
]
=
trk1_te
.
cdte_addr
.
msf
.
frame
;
return
sr_do_ioctl
(
cdi
->
handle
,
sr_cmd
,
NULL
,
0
,
0
,
SCSI_DATA_NONE
,
NULL
);
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
cgc
.
cmd
[
0
]
=
GPCMD_PLAY_AUDIO_MSF
;
cgc
.
cmd
[
3
]
=
trk0_te
.
cdte_addr
.
msf
.
minute
;
cgc
.
cmd
[
4
]
=
trk0_te
.
cdte_addr
.
msf
.
second
;
cgc
.
cmd
[
5
]
=
trk0_te
.
cdte_addr
.
msf
.
frame
;
cgc
.
cmd
[
6
]
=
trk1_te
.
cdte_addr
.
msf
.
minute
;
cgc
.
cmd
[
7
]
=
trk1_te
.
cdte_addr
.
msf
.
second
;
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
error code is. Normally the UNIT_ATTENTION code will automatically
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_Device
*
SDev
;
...
...
@@ -86,29 +86,32 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
SRpnt
=
scsi_allocate_request
(
SDev
);
if
(
!
SRpnt
)
{
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 */
SRpnt
->
sr_request
->
buffer
=
buffer
;
if
(
buffer
&&
SRpnt
->
sr_host
->
unchecked_isa_dma
&&
(
virt_to_phys
(
buffer
)
+
buflength
-
1
>
ISA_DMA_THRESHOLD
))
{
bounce_buffer
=
(
char
*
)
kmalloc
(
buflength
,
GFP_DMA
);
SRpnt
->
sr_request
->
buffer
=
cgc
->
buffer
;
if
(
cgc
->
buffer
&&
SRpnt
->
sr_host
->
unchecked_isa_dma
&&
(
virt_to_phys
(
cgc
->
buffer
)
+
cgc
->
buflen
-
1
>
ISA_DMA_THRESHOLD
))
{
bounce_buffer
=
(
char
*
)
kmalloc
(
cgc
->
buflen
,
GFP_DMA
);
if
(
bounce_buffer
==
NULL
)
{
printk
(
"SCSI DMA pool exhausted."
);
return
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
out
;
}
memcpy
(
bounce_buffer
,
(
char
*
)
buffer
,
buflength
);
buffer
=
bounce_buffer
;
memcpy
(
bounce_buffer
,
cgc
->
buffer
,
cgc
->
buflen
);
cgc
->
buffer
=
bounce_buffer
;
}
retry:
if
(
!
scsi_block_when_processing_errors
(
SDev
))
return
-
ENODEV
;
if
(
!
scsi_block_when_processing_errors
(
SDev
))
{
err
=
-
ENODEV
;
goto
out
;
}
scsi_wait_req
(
SRpnt
,
(
void
*
)
sr_cmd
,
(
void
*
)
buffer
,
buflength
,
IOCTL_TIMEOUT
,
IOCTL_RETRIES
);
scsi_wait_req
(
SRpnt
,
cgc
->
cmd
,
cgc
->
buffer
,
cgc
->
buflen
,
cgc
->
timeout
,
IOCTL_RETRIES
);
req
=
SRpnt
->
sr_request
;
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
switch
(
SRpnt
->
sr_sense_buffer
[
2
]
&
0xf
)
{
case
UNIT_ATTENTION
:
SDev
->
changed
=
1
;
if
(
!
quiet
)
if
(
!
cgc
->
quiet
)
printk
(
KERN_INFO
"%s: disc change detected.
\n
"
,
cd
->
cdi
.
name
);
if
(
retries
++
<
10
)
goto
retry
;
...
...
@@ -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
&&
SRpnt
->
sr_sense_buffer
[
13
]
==
0x01
)
{
/* 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
);
if
(
retries
++
<
10
)
{
/* 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
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
);
#ifdef DEBUG
print_req_sense
(
"sr"
,
SRpnt
);
...
...
@@ -154,7 +157,7 @@ int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned bufle
err
=
-
ENOMEDIUM
;
break
;
case
ILLEGAL_REQUEST
:
if
(
!
quiet
)
if
(
!
cgc
->
quiet
)
printk
(
KERN_ERR
"%s: CDROM (ioctl) reports ILLEGAL "
"REQUEST.
\n
"
,
cd
->
cdi
.
name
);
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
err
=
-
EINVAL
;
}
#ifdef DEBUG
print_command
(
sr_
cmd
);
print_command
(
cgc
->
cmd
);
print_req_sense
(
"sr"
,
SRpnt
);
#endif
break
;
default:
printk
(
KERN_ERR
"%s: CDROM (ioctl) error, command: "
,
cd
->
cdi
.
name
);
print_command
(
sr_
cmd
);
print_command
(
cgc
->
cmd
);
print_req_sense
(
"sr"
,
SRpnt
);
err
=
-
EIO
;
}
}
if
(
sense
)
memcpy
(
sense
,
SRpnt
->
sr_sense_buffer
,
sizeof
(
*
sense
));
if
(
cgc
->
sense
)
memcpy
(
cgc
->
sense
,
SRpnt
->
sr_sense_buffer
,
sizeof
(
*
cgc
->
sense
));
/* Wake up a process waiting for device */
scsi_release_request
(
SRpnt
);
SRpnt
=
NULL
;
out:
cgc
->
stat
=
err
;
return
err
;
}
...
...
@@ -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
)
{
u_char
sr_cmd
[
10
];
sr_cmd
[
0
]
=
GPCMD_TEST_UNIT_READY
;
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
sr_cmd
[
3
]
=
sr_cmd
[
4
]
=
sr_cmd
[
5
]
=
0
;
return
sr_do_ioctl
(
cd
,
sr_cmd
,
NULL
,
0
,
1
,
SCSI_DATA_NONE
,
NULL
);
struct
cdrom_generic_command
cgc
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
cgc
.
cmd
[
0
]
=
GPCMD_TEST_UNIT_READY
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
cgc
.
quiet
=
1
;
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
)
{
Scsi_CD
*
cd
=
cdi
->
handle
;
u_char
sr_cmd
[
10
];
sr_cmd
[
0
]
=
GPCMD_START_STOP_UNIT
;
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
sr_cmd
[
3
]
=
sr_cmd
[
5
]
=
0
;
sr_cmd
[
4
]
=
(
pos
==
0
)
?
0x03
/* close */
:
0x02
/* eject */
;
return
sr_do_ioctl
(
cd
,
sr_cmd
,
NULL
,
0
,
0
,
SCSI_DATA_NONE
,
NULL
);
struct
cdrom_generic_command
cgc
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
cgc
.
cmd
[
0
]
=
GPCMD_START_STOP_UNIT
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
cgc
.
cmd
[
4
]
=
(
pos
==
0
)
?
0x03
/* close */
:
0x02
/* eject */
;
cgc
.
data_direction
=
SCSI_DATA_NONE
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
return
sr_do_ioctl
(
cd
,
&
cgc
);
}
int
sr_lock_door
(
struct
cdrom_device_info
*
cdi
,
int
lock
)
{
Scsi_CD
*
cd
=
cdi
->
handle
;
return
scsi_
ioctl
(
cd
->
device
,
lock
?
SCSI_IOCTL_DOORLOCK
:
SCSI_IOCTL_DOORUNLOCK
,
0
);
return
scsi_
set_medium_removal
(
cd
->
device
,
lock
?
SCSI_REMOVAL_PREVENT
:
SCSI_REMOVAL_ALLOW
);
}
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,
int
sr_get_mcn
(
struct
cdrom_device_info
*
cdi
,
struct
cdrom_mcn
*
mcn
)
{
Scsi_CD
*
cd
=
cdi
->
handle
;
u_char
sr_cmd
[
10
]
;
struct
cdrom_generic_command
cgc
;
char
buffer
[
32
];
int
result
;
sr_cmd
[
0
]
=
GPCMD_READ_SUBCHANNEL
;
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
0x40
;
/* I do want the subchannel info */
sr_cmd
[
3
]
=
0x02
;
/* Give me medium catalog number
info */
sr_cmd
[
4
]
=
sr_cmd
[
5
]
=
0
;
sr_cmd
[
6
]
=
0
;
sr_cmd
[
7
]
=
0
;
sr_cmd
[
8
]
=
24
;
sr_cmd
[
9
]
=
0
;
result
=
sr_do_ioctl
(
cd
,
sr_cmd
,
buffer
,
24
,
0
,
SCSI_DATA_READ
,
NULL
);
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
))
;
cgc
.
cmd
[
0
]
=
GPCMD_READ_SUBCHANNEL
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
cgc
.
cmd
[
2
]
=
0x40
;
/* I do want the subchannel
info */
cgc
.
cmd
[
3
]
=
0x02
;
/* Give me medium catalog number info */
cgc
.
cmd
[
8
]
=
24
;
cgc
.
buffer
=
buffer
;
cgc
.
buflen
=
24
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
result
=
sr_do_ioctl
(
cd
,
&
cgc
);
memcpy
(
mcn
->
medium_catalog_number
,
buffer
+
9
,
13
);
mcn
->
medium_catalog_number
[
13
]
=
0
;
...
...
@@ -309,21 +318,23 @@ int sr_reset(struct cdrom_device_info *cdi)
int
sr_select_speed
(
struct
cdrom_device_info
*
cdi
,
int
speed
)
{
Scsi_CD
*
cd
=
cdi
->
handle
;
u_char
sr_cmd
[
MAX_COMMAND_SIZE
]
;
struct
cdrom_generic_command
cgc
;
if
(
speed
==
0
)
speed
=
0xffff
;
/* set to max */
else
speed
*=
177
;
/* Nx to kbyte/s */
memset
(
sr_cmd
,
0
,
MAX_COMMAND_SIZE
);
sr_cmd
[
0
]
=
GPCMD_SET_SPEED
;
/* SET CD SPEED */
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
(
speed
>>
8
)
&
0xff
;
/* MSB for speed (in kbytes/sec) */
sr_cmd
[
3
]
=
speed
&
0xff
;
/* LSB */
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
cgc
.
cmd
[
0
]
=
GPCMD_SET_SPEED
;
/* SET CD SPEED */
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
cgc
.
cmd
[
2
]
=
(
speed
>>
8
)
&
0xff
;
/* MSB for speed (in kbytes/sec) */
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
0
;
}
...
...
@@ -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
)
{
Scsi_CD
*
cd
=
cdi
->
handle
;
u_char
sr_cmd
[
10
]
;
struct
cdrom_generic_command
cgc
;
int
result
;
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
)
{
case
CDROMREADTOCHDR
:
{
struct
cdrom_tochdr
*
tochdr
=
(
struct
cdrom_tochdr
*
)
arg
;
sr_cmd
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
2
]
=
sr_cmd
[
3
]
=
sr_cmd
[
4
]
=
sr_cmd
[
5
]
=
0
;
sr_cmd
[
8
]
=
12
;
/* LSB of length */
cgc
.
cmd
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
cgc
.
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_trk1
=
buffer
[
3
];
...
...
@@ -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
;
sr_cmd
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
sr_cmd
[
1
]
|=
(
tocentry
->
cdte_format
==
CDROM_MSF
)
?
0x02
:
0
;
sr_cmd
[
2
]
=
sr_cmd
[
3
]
=
sr_cmd
[
4
]
=
sr_cmd
[
5
]
=
0
;
sr_cmd
[
6
]
=
tocentry
->
cdte_track
;
sr_cmd
[
8
]
=
12
;
/* LSB of length */
cgc
.
cmd
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
((
cd
->
device
->
lun
)
<<
5
)
:
0
;
cgc
.
cmd
[
1
]
|=
(
tocentry
->
cdte_format
==
CDROM_MSF
)
?
0x02
:
0
;
cgc
.
cmd
[
6
]
=
tocentry
->
cdte_track
;
cgc
.
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_adr
=
buffer
[
5
]
>>
4
;
...
...
@@ -393,15 +410,16 @@ int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
case
CDROMPLAYTRKIND
:
{
struct
cdrom_ti
*
ti
=
(
struct
cdrom_ti
*
)
arg
;
sr_cmd
[
0
]
=
GPCMD_PLAYAUDIO_TI
;
sr_cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
sr_cmd
[
4
]
=
ti
->
cdti_trk0
;
sr_cmd
[
5
]
=
ti
->
cdti_ind0
;
sr_cmd
[
7
]
=
ti
->
cdti_trk1
;
sr_cmd
[
8
]
=
ti
->
cdti_ind1
;
cgc
.
cmd
[
0
]
=
GPCMD_PLAYAUDIO_TI
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cgc
.
cmd
[
4
]
=
ti
->
cdti_trk0
;
cgc
.
cmd
[
5
]
=
ti
->
cdti_ind0
;
cgc
.
cmd
[
7
]
=
ti
->
cdti_trk1
;
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
)
result
=
sr_fake_playtrkind
(
cdi
,
ti
);
...
...
@@ -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
)
{
unsigned
char
cmd
[
MAX_COMMAND_SIZE
]
;
struct
cdrom_generic_command
cgc
;
#ifdef DEBUG
printk
(
"%s: sr_read_cd lba=%d format=%d blksize=%d
\n
"
,
cd
->
cdi
.
name
,
lba
,
format
,
blksize
);
#endif
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cmd
[
0
]
=
GPCMD_READ_CD
;
/* READ_CD */
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
1
]
|=
((
format
&
7
)
<<
2
);
cmd
[
2
]
=
(
unsigned
char
)
(
lba
>>
24
)
&
0xff
;
cmd
[
3
]
=
(
unsigned
char
)
(
lba
>>
16
)
&
0xff
;
cmd
[
4
]
=
(
unsigned
char
)
(
lba
>>
8
)
&
0xff
;
cmd
[
5
]
=
(
unsigned
char
)
lba
&
0xff
;
cmd
[
8
]
=
1
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
)
);
c
gc
.
c
md
[
0
]
=
GPCMD_READ_CD
;
/* READ_CD */
c
gc
.
c
md
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
c
gc
.
c
md
[
1
]
|=
((
format
&
7
)
<<
2
);
c
gc
.
c
md
[
2
]
=
(
unsigned
char
)
(
lba
>>
24
)
&
0xff
;
c
gc
.
c
md
[
3
]
=
(
unsigned
char
)
(
lba
>>
16
)
&
0xff
;
c
gc
.
c
md
[
4
]
=
(
unsigned
char
)
(
lba
>>
8
)
&
0xff
;
c
gc
.
c
md
[
5
]
=
(
unsigned
char
)
lba
&
0xff
;
c
gc
.
c
md
[
8
]
=
1
;
switch
(
blksize
)
{
case
2336
:
cmd
[
9
]
=
0x58
;
c
gc
.
c
md
[
9
]
=
0x58
;
break
;
case
2340
:
cmd
[
9
]
=
0x78
;
c
gc
.
c
md
[
9
]
=
0x78
;
break
;
case
2352
:
cmd
[
9
]
=
0xf8
;
c
gc
.
c
md
[
9
]
=
0xf8
;
break
;
default:
cmd
[
9
]
=
0x10
;
c
gc
.
c
md
[
9
]
=
0x10
;
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
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
;
/* 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
printk
(
"%s: sr_read_sector lba=%d blksize=%d
\n
"
,
cd
->
cdi
.
name
,
lba
,
blksize
);
#endif
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cmd
[
0
]
=
GPCMD_READ_10
;
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
2
]
=
(
unsigned
char
)
(
lba
>>
24
)
&
0xff
;
cmd
[
3
]
=
(
unsigned
char
)
(
lba
>>
16
)
&
0xff
;
cmd
[
4
]
=
(
unsigned
char
)
(
lba
>>
8
)
&
0xff
;
cmd
[
5
]
=
(
unsigned
char
)
lba
&
0xff
;
cmd
[
8
]
=
1
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
dest
,
blksize
,
0
,
SCSI_DATA_READ
,
NULL
);
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
cgc
.
cmd
[
0
]
=
GPCMD_READ_10
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cgc
.
cmd
[
2
]
=
(
unsigned
char
)
(
lba
>>
24
)
&
0xff
;
cgc
.
cmd
[
3
]
=
(
unsigned
char
)
(
lba
>>
16
)
&
0xff
;
cgc
.
cmd
[
4
]
=
(
unsigned
char
)
(
lba
>>
8
)
&
0xff
;
cgc
.
cmd
[
5
]
=
(
unsigned
char
)
lba
&
0xff
;
cgc
.
cmd
[
8
]
=
1
;
cgc
.
buffer
=
dest
;
cgc
.
buflen
=
blksize
;
cgc
.
data_direction
=
SCSI_DATA_READ
;
cgc
.
timeout
=
IOCTL_TIMEOUT
;
rc
=
sr_do_ioctl
(
cd
,
&
cgc
);
return
rc
;
}
...
...
@@ -562,7 +588,6 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
drivers/scsi/sr_vendor.c
View file @
34d3616d
...
...
@@ -58,6 +58,8 @@
#define VENDOR_TOSHIBA 3
#define VENDOR_WRITER 4
/* pre-scsi3 writers */
#define VENDOR_TIMEOUT 30*HZ
void
sr_vendor_init
(
Scsi_CD
*
cd
)
{
#ifndef CONFIG_BLK_DEV_SR_VENDOR
...
...
@@ -104,7 +106,7 @@ void sr_vendor_init(Scsi_CD *cd)
int
sr_set_blocklength
(
Scsi_CD
*
cd
,
int
blocklength
)
{
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
;
int
rc
,
density
=
0
;
...
...
@@ -120,19 +122,23 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength)
#ifdef DEBUG
printk
(
"%s: MODE SELECT 0x%x/%d
\n
"
,
cd
->
cdi
.
name
,
density
,
blocklength
);
#endif
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cmd
[
0
]
=
MODE_SELECT
;
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
1
]
|=
(
1
<<
4
);
cmd
[
4
]
=
12
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
)
);
c
gc
.
c
md
[
0
]
=
MODE_SELECT
;
c
gc
.
c
md
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
c
gc
.
c
md
[
1
]
|=
(
1
<<
4
);
c
gc
.
c
md
[
4
]
=
12
;
modesel
=
(
struct
ccs_modesel_head
*
)
buffer
;
memset
(
modesel
,
0
,
sizeof
(
*
modesel
));
modesel
->
block_desc_length
=
0x08
;
modesel
->
density
=
density
;
modesel
->
block_length_med
=
(
blocklength
>>
8
)
&
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
;
}
#ifdef DEBUG
...
...
@@ -154,7 +160,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
Scsi_CD
*
cd
=
cdi
->
handle
;
unsigned
long
sector
;
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
;
if
(
cd
->
cdi
.
mask
&
CDC_MULTI_SESSION
)
...
...
@@ -168,16 +174,22 @@ int sr_cd_check(struct cdrom_device_info *cdi)
no_multi
=
0
;
/* flag: the drive can't handle multisession */
rc
=
0
;
memset
(
&
cgc
,
0
,
sizeof
(
struct
cdrom_generic_command
));
switch
(
cd
->
vendor
)
{
case
VENDOR_SCSI3
:
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cmd
[
0
]
=
READ_TOC
;
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
8
]
=
12
;
cmd
[
9
]
=
0x40
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
12
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
cmd
[
0
]
=
READ_TOC
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cgc
.
cmd
[
8
]
=
12
;
cgc
.
cmd
[
9
]
=
0x40
;
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
)
break
;
if
((
buffer
[
0
]
<<
8
)
+
buffer
[
1
]
<
0x0a
)
{
...
...
@@ -197,13 +209,17 @@ int sr_cd_check(struct cdrom_device_info *cdi)
#ifdef CONFIG_BLK_DEV_SR_VENDOR
case
VENDOR_NEC
:{
unsigned
long
min
,
sec
,
frame
;
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cmd
[
0
]
=
0xde
;
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
1
]
|=
0x03
;
cmd
[
2
]
=
0xb0
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
0x16
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
cmd
[
0
]
=
0xde
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cgc
.
cmd
[
1
]
|=
0x03
;
cgc
.
cmd
[
2
]
=
0xb0
;
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
)
break
;
if
(
buffer
[
14
]
!=
0
&&
buffer
[
14
]
!=
0xb0
)
{
...
...
@@ -225,12 +241,16 @@ int sr_cd_check(struct cdrom_device_info *cdi)
/* we request some disc information (is it a XA-CD ?,
* where starts the last session ?) */
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cmd
[
0
]
=
0xc7
;
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
1
]
|=
0x03
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
4
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
cmd
[
0
]
=
0xc7
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cgc
.
cmd
[
1
]
|=
0x03
;
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
)
{
printk
(
KERN_INFO
"%s: Hmm, seems the drive "
"doesn't support multisession CD's
\n
"
,
...
...
@@ -251,13 +271,17 @@ int sr_cd_check(struct cdrom_device_info *cdi)
}
case
VENDOR_WRITER
:
memset
(
cmd
,
0
,
MAX_COMMAND_SIZE
);
cmd
[
0
]
=
READ_TOC
;
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
8
]
=
0x04
;
cmd
[
9
]
=
0x40
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
0x04
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
cmd
[
0
]
=
READ_TOC
;
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cgc
.
cmd
[
8
]
=
0x04
;
cgc
.
cmd
[
9
]
=
0x40
;
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
)
{
break
;
}
...
...
@@ -266,13 +290,18 @@ int sr_cd_check(struct cdrom_device_info *cdi)
"%s: No finished session
\n
"
,
cd
->
cdi
.
name
);
break
;
}
cmd
[
0
]
=
READ_TOC
;
/* Read TOC */
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cmd
[
6
]
=
rc
&
0x7f
;
/* number of last session */
cmd
[
8
]
=
0x0c
;
cmd
[
9
]
=
0x40
;
rc
=
sr_do_ioctl
(
cd
,
cmd
,
buffer
,
12
,
1
,
SCSI_DATA_READ
,
NULL
);
cgc
.
cmd
[
0
]
=
READ_TOC
;
/* Read TOC */
cgc
.
cmd
[
1
]
=
(
cd
->
device
->
scsi_level
<=
SCSI_2
)
?
(
cd
->
device
->
lun
<<
5
)
:
0
;
cgc
.
cmd
[
6
]
=
rc
&
0x7f
;
/* number of last session */
cgc
.
cmd
[
8
]
=
0x0c
;
cgc
.
cmd
[
9
]
=
0x40
;
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
)
{
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