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
Expand all
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
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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