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
59aa7245
Commit
59aa7245
authored
Oct 14, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge tove:v2.5/linux into home.transmeta.com:/home/torvalds/v2.5/linux
parents
71660e15
de224587
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
481 additions
and
233 deletions
+481
-233
drivers/block/Makefile
drivers/block/Makefile
+2
-2
drivers/block/blkpg.c
drivers/block/blkpg.c
+1
-1
drivers/block/scsi_ioctl.c
drivers/block/scsi_ioctl.c
+215
-0
drivers/ide/ide-cd.c
drivers/ide/ide-cd.c
+248
-183
drivers/ide/ide-cd.h
drivers/ide/ide-cd.h
+0
-7
drivers/ide/ide.c
drivers/ide/ide.c
+1
-1
fs/block_dev.c
fs/block_dev.c
+3
-38
include/linux/blkdev.h
include/linux/blkdev.h
+11
-1
No files found.
drivers/block/Makefile
View file @
59aa7245
...
...
@@ -9,9 +9,9 @@
#
export-objs
:=
elevator.o ll_rw_blk.o loop.o genhd.o acsi.o
\
block
_ioctl.o deadline-iosched.o
scsi
_ioctl.o deadline-iosched.o
obj-y
:=
elevator.o ll_rw_blk.o blkpg.o genhd.o
block
_ioctl.o deadline-iosched.o
obj-y
:=
elevator.o ll_rw_blk.o blkpg.o genhd.o
scsi
_ioctl.o deadline-iosched.o
obj-$(CONFIG_MAC_FLOPPY)
+=
swim3.o
obj-$(CONFIG_BLK_DEV_FD)
+=
floppy.o
...
...
drivers/block/blkpg.c
View file @
59aa7245
...
...
@@ -305,6 +305,6 @@ int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return
0
;
default:
return
-
E
INVAL
;
return
-
E
NOTTY
;
}
}
drivers/block/
block
_ioctl.c
→
drivers/block/
scsi
_ioctl.c
View file @
59aa7245
...
...
@@ -27,8 +27,12 @@
#include <linux/module.h>
#include <linux/blk.h>
#include <linux/completion.h>
#include <linux/cdrom.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
#include <asm/uaccess.h>
int
blk_do_rq
(
request_queue_t
*
q
,
struct
request
*
rq
)
{
...
...
@@ -50,7 +54,114 @@ int blk_do_rq(request_queue_t *q, struct request *rq)
return
err
;
}
int
block_ioctl
(
struct
block_device
*
bdev
,
unsigned
int
cmd
,
unsigned
long
arg
)
#include <scsi/sg.h>
static
int
sg_get_version
(
int
*
p
)
{
static
int
sg_version_num
=
30527
;
return
put_user
(
sg_version_num
,
p
);
}
static
int
scsi_get_idlun
(
request_queue_t
*
q
,
int
*
p
)
{
return
put_user
(
0
,
p
);
}
static
int
scsi_get_bus
(
request_queue_t
*
q
,
int
*
p
)
{
return
put_user
(
0
,
p
);
}
static
int
sg_get_timeout
(
request_queue_t
*
q
)
{
return
HZ
;
}
static
int
sg_set_timeout
(
request_queue_t
*
q
,
int
*
p
)
{
int
timeout
;
int
error
=
get_user
(
timeout
,
p
);
return
error
;
}
static
int
reserved_size
=
0
;
static
int
sg_get_reserved_size
(
request_queue_t
*
q
,
int
*
p
)
{
return
put_user
(
reserved_size
,
p
);
}
static
int
sg_set_reserved_size
(
request_queue_t
*
q
,
int
*
p
)
{
int
size
;
int
error
=
get_user
(
size
,
p
);
if
(
!
error
)
reserved_size
=
size
;
return
error
;
}
static
int
sg_emulated_host
(
request_queue_t
*
q
,
int
*
p
)
{
return
put_user
(
1
,
p
);
}
static
int
sg_io
(
request_queue_t
*
q
,
struct
sg_io_hdr
*
uptr
)
{
int
err
;
struct
sg_io_hdr
hdr
;
struct
request
*
rq
;
void
*
buffer
;
if
(
!
access_ok
(
VERIFY_WRITE
,
uptr
,
sizeof
(
*
uptr
)))
return
-
EFAULT
;
if
(
copy_from_user
(
&
hdr
,
uptr
,
sizeof
(
*
uptr
)))
return
-
EFAULT
;
if
(
hdr
.
cmd_len
>
sizeof
(
rq
->
cmd
)
)
return
-
EINVAL
;
buffer
=
NULL
;
if
(
hdr
.
dxfer_len
)
{
unsigned
int
bytes
=
(
hdr
.
dxfer_len
+
511
)
&
~
511
;
switch
(
hdr
.
dxfer_direction
)
{
default:
return
-
EINVAL
;
case
SG_DXFER_TO_DEV
:
case
SG_DXFER_FROM_DEV
:
case
SG_DXFER_TO_FROM_DEV
:
break
;
}
buffer
=
kmalloc
(
bytes
,
GFP_USER
);
if
(
!
buffer
)
return
-
ENOMEM
;
if
(
hdr
.
dxfer_direction
==
SG_DXFER_TO_DEV
||
hdr
.
dxfer_direction
==
SG_DXFER_TO_FROM_DEV
)
copy_from_user
(
buffer
,
hdr
.
dxferp
,
hdr
.
dxfer_len
);
}
rq
=
blk_get_request
(
q
,
WRITE
,
__GFP_WAIT
);
rq
->
timeout
=
60
*
HZ
;
rq
->
data
=
buffer
;
rq
->
data_len
=
hdr
.
dxfer_len
;
rq
->
flags
=
REQ_BLOCK_PC
;
memset
(
rq
->
cmd
,
0
,
sizeof
(
rq
->
cmd
));
copy_from_user
(
rq
->
cmd
,
hdr
.
cmdp
,
hdr
.
cmd_len
);
err
=
blk_do_rq
(
q
,
rq
);
blk_put_request
(
rq
);
copy_to_user
(
uptr
,
&
hdr
,
sizeof
(
*
uptr
));
if
(
buffer
)
{
if
(
hdr
.
dxfer_direction
==
SG_DXFER_FROM_DEV
||
hdr
.
dxfer_direction
==
SG_DXFER_TO_FROM_DEV
)
copy_to_user
(
hdr
.
dxferp
,
buffer
,
hdr
.
dxfer_len
);
kfree
(
buffer
);
}
return
err
;
}
int
scsi_cmd_ioctl
(
struct
block_device
*
bdev
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
request_queue_t
*
q
;
struct
request
*
rq
;
...
...
@@ -61,11 +172,32 @@ int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return
-
ENXIO
;
switch
(
cmd
)
{
case
SG_GET_VERSION_NUM
:
return
sg_get_version
((
int
*
)
arg
);
case
SCSI_IOCTL_GET_IDLUN
:
return
scsi_get_idlun
(
q
,
(
int
*
)
arg
);
case
SCSI_IOCTL_GET_BUS_NUMBER
:
return
scsi_get_bus
(
q
,
(
int
*
)
arg
);
case
SG_SET_TIMEOUT
:
return
sg_set_timeout
(
q
,
(
int
*
)
arg
);
case
SG_GET_TIMEOUT
:
return
sg_get_timeout
(
q
);
case
SG_GET_RESERVED_SIZE
:
return
sg_get_reserved_size
(
q
,
(
int
*
)
arg
);
case
SG_SET_RESERVED_SIZE
:
return
sg_set_reserved_size
(
q
,
(
int
*
)
arg
);
case
SG_EMULATED_HOST
:
return
sg_emulated_host
(
q
,
(
int
*
)
arg
);
case
SG_IO
:
return
sg_io
(
q
,
(
struct
sg_io_hdr
*
)
arg
);
case
CDROMCLOSETRAY
:
close
=
1
;
case
CDROMEJECT
:
rq
=
blk_get_request
(
q
,
WRITE
,
__GFP_WAIT
);
rq
->
flags
=
REQ_BLOCK_PC
;
rq
->
data
=
NULL
;
rq
->
data_len
=
0
;
rq
->
timeout
=
60
*
HZ
;
memset
(
rq
->
cmd
,
0
,
sizeof
(
rq
->
cmd
));
rq
->
cmd
[
0
]
=
GPCMD_START_STOP_UNIT
;
rq
->
cmd
[
4
]
=
0x02
+
(
close
!=
0
);
...
...
@@ -80,4 +212,4 @@ int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return
err
;
}
EXPORT_SYMBOL
(
block
_ioctl
);
EXPORT_SYMBOL
(
scsi_cmd
_ioctl
);
drivers/ide/ide-cd.c
View file @
59aa7245
...
...
@@ -309,6 +309,8 @@
#include <linux/ide.h>
#include <linux/completion.h>
#include <scsi/scsi.h>
/* For SCSI -> ATAPI command conversion */
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/byteorder.h>
...
...
@@ -332,12 +334,12 @@ static void cdrom_saw_media_change (ide_drive_t *drive)
info
->
nsectors_buffered
=
0
;
}
static
int
cdrom_log_sense
(
ide_drive_t
*
drive
,
struct
packet_command
*
pc
,
static
int
cdrom_log_sense
(
ide_drive_t
*
drive
,
struct
request
*
rq
,
struct
request_sense
*
sense
)
{
int
log
=
0
;
if
(
sense
==
NULL
||
pc
==
NULL
||
pc
->
quiet
)
if
(
!
sense
||
!
rq
||
(
rq
->
flags
&
REQ_QUIET
)
)
return
0
;
switch
(
sense
->
sense_key
)
{
...
...
@@ -370,10 +372,9 @@ static int cdrom_log_sense(ide_drive_t *drive, struct packet_command *pc,
static
void
cdrom_analyze_sense_data
(
ide_drive_t
*
drive
,
struct
packet_command
*
failed_command
,
struct
request
*
failed_command
,
struct
request_sense
*
sense
)
{
if
(
!
cdrom_log_sense
(
drive
,
failed_command
,
sense
))
return
;
...
...
@@ -382,7 +383,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
* the first toc has not been recorded yet, it will fail with
* 05/24/00 (which is a confusing error)
*/
if
(
failed_command
&&
failed_command
->
c
[
0
]
==
GPCMD_READ_TOC_PMA_ATIP
)
if
(
failed_command
&&
failed_command
->
c
md
[
0
]
==
GPCMD_READ_TOC_PMA_ATIP
)
if
(
sense
->
sense_key
==
0x05
&&
sense
->
asc
==
0x24
)
return
;
...
...
@@ -453,20 +454,20 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
while
(
hi
>
lo
)
{
mid
=
(
lo
+
hi
)
/
2
;
if
(
packet_command_texts
[
mid
].
packet_command
==
failed_command
->
c
[
0
])
{
failed_command
->
c
md
[
0
])
{
s
=
packet_command_texts
[
mid
].
text
;
break
;
}
if
(
packet_command_texts
[
mid
].
packet_command
>
failed_command
->
c
[
0
])
failed_command
->
c
md
[
0
])
hi
=
mid
;
else
lo
=
mid
+
1
;
}
printk
(
" The failed
\"
%s
\"
packet command was:
\n
\"
"
,
s
);
for
(
i
=
0
;
i
<
sizeof
(
failed_command
->
c
);
i
++
)
printk
(
"%02x "
,
failed_command
->
c
[
i
]);
for
(
i
=
0
;
i
<
sizeof
(
failed_command
->
c
md
);
i
++
)
printk
(
"%02x "
,
failed_command
->
c
md
[
i
]);
printk
(
"
\"\n
"
);
}
...
...
@@ -512,30 +513,39 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
#endif
/* not VERBOSE_IDE_CD_ERRORS */
}
/*
* Initialize a ide-cd packet command request
*/
static
void
cdrom_prepare_request
(
struct
request
*
rq
)
{
cdrom_prepare_request
(
rq
);
rq
->
flags
=
REQ_PC
;
}
static
void
cdrom_queue_request_sense
(
ide_drive_t
*
drive
,
struct
completion
*
wait
,
struct
request_sense
*
sense
,
struct
packet_command
*
failed_command
)
void
*
sense
,
struct
request
*
failed_command
)
{
struct
cdrom_info
*
info
=
drive
->
driver_data
;
struct
packet_command
*
pc
=
&
info
->
request_sense_pc
;
struct
request
*
rq
;
struct
request
*
rq
=
&
info
->
request_sense_request
;
if
(
sense
==
NULL
)
sense
=
&
info
->
sense_data
;
memset
(
pc
,
0
,
sizeof
(
struct
packet_command
));
pc
->
c
[
0
]
=
GPCMD_REQUEST_SENSE
;
pc
->
c
[
4
]
=
pc
->
buflen
=
18
;
pc
->
buffer
=
(
char
*
)
sense
;
pc
->
sense
=
(
struct
request_sense
*
)
failed_command
;
/* stuff the sense request in front of our current request */
rq
=
&
info
->
request_sense_request
;
ide_init_drive_cmd
(
rq
);
cdrom_prepare_request
(
rq
);
rq
->
data
=
sense
;
rq
->
cmd
[
0
]
=
GPCMD_REQUEST_SENSE
;
rq
->
cmd
[
4
]
=
rq
->
data_len
=
18
;
rq
->
flags
=
REQ_SENSE
;
rq
->
buffer
=
(
char
*
)
pc
;
rq
->
waiting
=
wait
;
/* NOTE! Save the failed command in "rq->buffer" */
rq
->
buffer
=
(
void
*
)
failed_command
;
(
void
)
ide_do_drive_cmd
(
drive
,
rq
,
ide_preempt
);
}
...
...
@@ -630,17 +640,26 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
struct
request
*
rq
=
HWGROUP
(
drive
)
->
rq
;
if
((
rq
->
flags
&
REQ_SENSE
)
&&
uptodate
)
{
struct
packet_command
*
pc
=
(
struct
packet_command
*
)
rq
->
buffer
;
cdrom_analyze_sense_data
(
drive
,
(
struct
packet_command
*
)
pc
->
sense
,
(
struct
request_sense
*
)
(
pc
->
buffer
-
pc
->
c
[
4
]));
/* For REQ_SENSE, "rq->buffer" points to the original failed request */
struct
request
*
failed
=
(
struct
request
*
)
rq
->
buffer
;
struct
cdrom_info
*
info
=
drive
->
driver_data
;
void
*
sense
=
&
info
->
sense_data
;
if
(
failed
&&
failed
->
sense
)
sense
=
failed
->
sense
;
cdrom_analyze_sense_data
(
drive
,
failed
,
sense
);
}
if
(
blk_fs_request
(
rq
)
&&
!
rq
->
current_nr_sectors
)
uptodate
=
1
;
ide_end_request
(
drive
,
uptodate
,
rq
->
hard_cur_sectors
);
}
/* Handle differences between SCSI and ATAPI packet commands */
static
int
pre_transform_command
(
struct
request
*
);
static
void
post_transform_command
(
struct
request
*
);
/* Returns 0 if the request should be continued.
Returns 1 if the request was ended. */
...
...
@@ -649,7 +668,6 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
{
struct
request
*
rq
=
HWGROUP
(
drive
)
->
rq
;
int
stat
,
err
,
sense_key
;
struct
packet_command
*
pc
;
/* Check for errors. */
*
stat_ret
=
stat
=
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
);
...
...
@@ -672,16 +690,18 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
from the drive (probably while trying
to recover from a former error). Just give up. */
pc
=
(
struct
packet_command
*
)
rq
->
buffer
;
pc
->
stat
=
1
;
cdrom_end_request
(
drive
,
1
);
rq
->
flags
|=
REQ_FAILED
;
cdrom_end_request
(
drive
,
0
);
*
startstop
=
DRIVER
(
drive
)
->
error
(
drive
,
"request sense failure"
,
stat
);
return
1
;
}
else
if
(
rq
->
flags
&
(
REQ_PC
|
REQ_BLOCK_PC
))
{
/* All other functions, except for READ. */
struct
completion
*
wait
=
NULL
;
pc
=
(
struct
packet_command
*
)
rq
->
buffer
;
/* Fix up any SCSI command differences.. */
if
(
rq
->
flags
&
REQ_BLOCK_PC
)
post_transform_command
(
rq
);
/* Check for tray open. */
if
(
sense_key
==
NOT_READY
)
{
...
...
@@ -691,7 +711,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
cdrom_saw_media_change
(
drive
);
/*printk("%s: media changed\n",drive->name);*/
return
0
;
}
else
if
(
!
pc
->
quiet
)
{
}
else
if
(
!
(
rq
->
flags
&
REQ_QUIET
)
)
{
/* Otherwise, print an error. */
ide_dump_status
(
drive
,
"packet command error"
,
stat
);
}
...
...
@@ -710,11 +730,11 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
rq
->
waiting
=
NULL
;
}
pc
->
stat
=
1
;
cdrom_end_request
(
drive
,
1
);
rq
->
flags
|=
REQ_FAILED
;
cdrom_end_request
(
drive
,
0
);
if
((
stat
&
ERR_STAT
)
!=
0
)
cdrom_queue_request_sense
(
drive
,
wait
,
pc
->
sense
,
pc
);
cdrom_queue_request_sense
(
drive
,
wait
,
rq
->
sense
,
rq
);
}
else
if
(
blk_fs_request
(
rq
))
{
/* Handle errors from READ and WRITE requests. */
...
...
@@ -770,7 +790,6 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
static
int
cdrom_timer_expiry
(
ide_drive_t
*
drive
)
{
struct
request
*
rq
=
HWGROUP
(
drive
)
->
rq
;
struct
packet_command
*
pc
=
(
struct
packet_command
*
)
rq
->
buffer
;
unsigned
long
wait
=
0
;
/*
...
...
@@ -779,7 +798,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
* this, but not all commands/drives support that. Let
* ide_timer_expiry keep polling us for these.
*/
switch
(
pc
->
c
[
0
])
{
switch
(
rq
->
cmd
[
0
])
{
case
GPCMD_BLANK
:
case
GPCMD_FORMAT_UNIT
:
case
GPCMD_RESERVE_RZONE_TRACK
:
...
...
@@ -854,12 +873,12 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
* struct packet_command *pc; now packet_command_t *pc;
*/
static
ide_startstop_t
cdrom_transfer_packet_command
(
ide_drive_t
*
drive
,
struct
packet_command
*
pc
,
struct
request
*
rq
,
ide_handler_t
*
handler
)
{
unsigned
char
*
cmd_buf
=
pc
->
c
;
int
cmd_len
=
sizeof
(
pc
->
c
);
unsigned
int
timeout
=
pc
->
timeout
;
unsigned
char
*
cmd_buf
=
rq
->
cmd
;
int
cmd_len
=
sizeof
(
rq
->
cmd
);
unsigned
int
timeout
=
rq
->
timeout
;
struct
cdrom_info
*
info
=
drive
->
driver_data
;
ide_startstop_t
startstop
;
...
...
@@ -1029,6 +1048,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
if
(
rq
->
current_nr_sectors
>
0
)
{
printk
(
"%s: cdrom_read_intr: data underrun (%d blocks)
\n
"
,
drive
->
name
,
rq
->
current_nr_sectors
);
rq
->
flags
|=
REQ_FAILED
;
cdrom_end_request
(
drive
,
0
);
}
else
cdrom_end_request
(
drive
,
1
);
...
...
@@ -1179,7 +1199,6 @@ static int cdrom_read_from_buffer (ide_drive_t *drive)
*/
static
ide_startstop_t
cdrom_start_read_continuation
(
ide_drive_t
*
drive
)
{
struct
packet_command
pc
;
struct
request
*
rq
=
HWGROUP
(
drive
)
->
rq
;
int
nsect
,
sector
,
nframes
,
frame
,
nskip
;
...
...
@@ -1222,11 +1241,10 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
(
65534
/
CD_FRAMESIZE
)
:
65535
);
/* Set up the command */
memcpy
(
pc
.
c
,
rq
->
cmd
,
sizeof
(
pc
.
c
));
pc
.
timeout
=
WAIT_CMD
;
rq
->
timeout
=
WAIT_CMD
;
/* Send the command to the drive and return. */
return
cdrom_transfer_packet_command
(
drive
,
&
pc
,
&
cdrom_read_intr
);
return
cdrom_transfer_packet_command
(
drive
,
rq
,
&
cdrom_read_intr
);
}
...
...
@@ -1262,7 +1280,6 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
static
ide_startstop_t
cdrom_start_seek_continuation
(
ide_drive_t
*
drive
)
{
struct
packet_command
pc
;
struct
request
*
rq
=
HWGROUP
(
drive
)
->
rq
;
int
sector
,
frame
,
nskip
;
...
...
@@ -1273,11 +1290,11 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
frame
=
sector
/
SECTORS_PER_FRAME
;
memset
(
rq
->
cmd
,
0
,
sizeof
(
rq
->
cmd
));
pc
.
c
[
0
]
=
GPCMD_SEEK
;
put_unaligned
(
cpu_to_be32
(
frame
),
(
unsigned
int
*
)
&
pc
.
c
[
2
]);
rq
->
cmd
[
0
]
=
GPCMD_SEEK
;
put_unaligned
(
cpu_to_be32
(
frame
),
(
unsigned
int
*
)
&
rq
->
cmd
[
2
]);
pc
.
timeout
=
WAIT_CMD
;
return
cdrom_transfer_packet_command
(
drive
,
&
pc
,
&
cdrom_seek_intr
);
rq
->
timeout
=
WAIT_CMD
;
return
cdrom_transfer_packet_command
(
drive
,
rq
,
&
cdrom_seek_intr
);
}
static
ide_startstop_t
cdrom_start_seek
(
ide_drive_t
*
drive
,
unsigned
int
block
)
...
...
@@ -1296,6 +1313,7 @@ static void restore_request (struct request *rq)
{
if
(
rq
->
buffer
!=
bio_data
(
rq
->
bio
))
{
sector_t
n
=
(
rq
->
buffer
-
(
char
*
)
bio_data
(
rq
->
bio
))
/
SECTOR_SIZE
;
rq
->
buffer
=
bio_data
(
rq
->
bio
);
rq
->
nr_sectors
+=
n
;
rq
->
sector
-=
n
;
...
...
@@ -1352,7 +1370,6 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
{
int
ireason
,
len
,
stat
,
thislen
;
struct
request
*
rq
=
HWGROUP
(
drive
)
->
rq
;
struct
packet_command
*
pc
=
(
struct
packet_command
*
)
rq
->
buffer
;
ide_startstop_t
startstop
;
u8
lowcyl
=
0
,
highcyl
=
0
;
...
...
@@ -1372,16 +1389,16 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
if
((
stat
&
DRQ_STAT
)
==
0
)
{
/* Some of the trailing request sense fields are optional, and
some drives don't send them. Sigh. */
if
(
pc
->
c
[
0
]
==
GPCMD_REQUEST_SENSE
&&
pc
->
buf
len
>
0
&&
pc
->
buf
len
<=
5
)
{
while
(
pc
->
buf
len
>
0
)
{
*
pc
->
buffer
++
=
0
;
--
pc
->
buf
len
;
if
(
rq
->
cmd
[
0
]
==
GPCMD_REQUEST_SENSE
&&
rq
->
data_
len
>
0
&&
rq
->
data_
len
<=
5
)
{
while
(
rq
->
data_
len
>
0
)
{
*
(
unsigned
char
*
)
rq
->
data
++
=
0
;
--
rq
->
data_
len
;
}
}
if
(
pc
->
buf
len
==
0
)
if
(
rq
->
data_
len
==
0
)
cdrom_end_request
(
drive
,
1
);
else
{
/* Comment this out, because this always happens
...
...
@@ -1391,20 +1408,22 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
printk ("%s: cdrom_pc_intr: data underrun %d\n",
drive->name, pc->buflen);
*/
pc
->
stat
=
1
;
cdrom_end_request
(
drive
,
1
);
rq
->
flags
|=
REQ_FAILED
;
cdrom_end_request
(
drive
,
0
);
}
return
ide_stopped
;
}
/* Figure out how much data to transfer. */
thislen
=
pc
->
buf
len
;
thislen
=
rq
->
data_
len
;
if
(
thislen
>
len
)
thislen
=
len
;
/* The drive wants to be written to. */
if
((
ireason
&
3
)
==
0
)
{
if
(
!
rq
->
data
)
goto
confused
;
/* Transfer the data. */
HWIF
(
drive
)
->
atapi_output_bytes
(
drive
,
pc
->
buffer
,
thislen
);
HWIF
(
drive
)
->
atapi_output_bytes
(
drive
,
rq
->
data
,
thislen
);
/* If we haven't moved enough data to satisfy the drive,
add some padding. */
...
...
@@ -1415,15 +1434,16 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
}
/* Keep count of how much data we've moved. */
pc
->
buffer
+=
thislen
;
pc
->
buf
len
-=
thislen
;
rq
->
data
+=
thislen
;
rq
->
data_
len
-=
thislen
;
}
/* Same drill for reading. */
else
if
((
ireason
&
3
)
==
2
)
{
if
(
!
rq
->
data
)
goto
confused
;
/* Transfer the data. */
HWIF
(
drive
)
->
atapi_input_bytes
(
drive
,
pc
->
buffer
,
thislen
);
HWIF
(
drive
)
->
atapi_input_bytes
(
drive
,
rq
->
data
,
thislen
);
/* If we haven't moved enough data to satisfy the drive,
add some padding. */
...
...
@@ -1434,13 +1454,14 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
}
/* Keep count of how much data we've moved. */
pc
->
buffer
+=
thislen
;
pc
->
buf
len
-=
thislen
;
rq
->
data
+=
thislen
;
rq
->
data_
len
-=
thislen
;
}
else
{
confused:
printk
(
"%s: cdrom_pc_intr: The drive "
"appears confused (ireason = 0x%2x)
\n
"
,
drive
->
name
,
ireason
);
pc
->
stat
=
1
;
rq
->
flags
|=
REQ_FAILED
;
}
if
(
HWGROUP
(
drive
)
->
handler
!=
NULL
)
...
...
@@ -1455,13 +1476,12 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
static
ide_startstop_t
cdrom_do_pc_continuation
(
ide_drive_t
*
drive
)
{
struct
request
*
rq
=
HWGROUP
(
drive
)
->
rq
;
struct
packet_command
*
pc
=
(
struct
packet_command
*
)
rq
->
buffer
;
if
(
!
pc
->
timeout
)
pc
->
timeout
=
WAIT_CMD
;
if
(
!
rq
->
timeout
)
rq
->
timeout
=
WAIT_CMD
;
/* Send the command to the drive and return. */
return
cdrom_transfer_packet_command
(
drive
,
pc
,
&
cdrom_pc_intr
);
return
cdrom_transfer_packet_command
(
drive
,
rq
,
&
cdrom_pc_intr
);
}
...
...
@@ -1469,13 +1489,12 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
{
int
len
;
struct
request
*
rq
=
HWGROUP
(
drive
)
->
rq
;
struct
packet_command
*
pc
=
(
struct
packet_command
*
)
rq
->
buffer
;
struct
cdrom_info
*
info
=
drive
->
driver_data
;
info
->
dma
=
0
;
info
->
cmd
=
0
;
pc
->
stat
=
0
;
len
=
pc
->
buf
len
;
rq
->
flags
&=
~
REQ_FAILED
;
len
=
rq
->
data_
len
;
/* Start sending the command to the drive. */
return
cdrom_start_packet_command
(
drive
,
len
,
cdrom_do_pc_continuation
);
...
...
@@ -1496,28 +1515,31 @@ void cdrom_sleep (int time)
}
static
int
cdrom_queue_packet_command
(
ide_drive_t
*
drive
,
struct
packet_command
*
pc
)
int
cdrom_queue_packet_command
(
ide_drive_t
*
drive
,
struct
request
*
rq
)
{
struct
request_sense
sense
;
struct
request
req
;
int
retries
=
10
;
unsigned
int
flags
=
rq
->
flags
;
if
(
pc
->
sense
==
NULL
)
pc
->
sense
=
&
sense
;
if
(
rq
->
sense
==
NULL
)
rq
->
sense
=
&
sense
;
/* Start of retry loop. */
do
{
ide_init_drive_cmd
(
&
req
);
req
.
flags
=
REQ_PC
;
req
.
buffer
=
(
char
*
)
pc
;
ide_do_drive_cmd
(
drive
,
&
req
,
ide_wait
);
int
error
;
unsigned
long
time
=
jiffies
;
rq
->
flags
=
flags
;
error
=
ide_do_drive_cmd
(
drive
,
rq
,
ide_wait
);
time
=
jiffies
-
time
;
/* FIXME: we should probably abort/retry or something
* in case of failure */
if
(
pc
->
stat
!=
0
)
{
if
(
rq
->
flags
&
REQ_FAILED
)
{
/* The request failed. Retry if it was due to a unit
attention status
(usually means media was changed). */
struct
request_sense
*
reqbuf
=
pc
->
sense
;
struct
request_sense
*
reqbuf
=
rq
->
sense
;
if
(
reqbuf
->
sense_key
==
UNIT_ATTENTION
)
cdrom_saw_media_change
(
drive
);
...
...
@@ -1535,10 +1557,10 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
}
/* End of retry loop. */
}
while
(
pc
->
stat
!=
0
&&
retries
>=
0
);
}
while
(
(
rq
->
flags
&
REQ_FAILED
)
&&
retries
>=
0
);
/* Return an error if the command failed. */
return
pc
->
stat
?
-
EIO
:
0
;
return
(
rq
->
flags
&
REQ_FAILED
)
?
-
EIO
:
0
;
}
/*
...
...
@@ -1681,20 +1703,18 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
static
ide_startstop_t
cdrom_start_write_cont
(
ide_drive_t
*
drive
)
{
struct
packet_command
pc
;
/* packet_command_t pc; */
struct
request
*
rq
=
HWGROUP
(
drive
)
->
rq
;
unsigned
nframes
,
frame
;
nframes
=
rq
->
nr_sectors
>>
2
;
frame
=
rq
->
sector
>>
2
;
memcpy
(
pc
.
c
,
rq
->
cmd
,
sizeof
(
pc
.
c
));
#if 0 /* the immediate bit */
pc.c
[1] = 1 << 3;
rq->cmd
[1] = 1 << 3;
#endif
pc
.
timeout
=
2
*
WAIT_CMD
;
rq
->
timeout
=
2
*
WAIT_CMD
;
return
cdrom_transfer_packet_command
(
drive
,
&
pc
,
cdrom_write_intr
);
return
cdrom_transfer_packet_command
(
drive
,
rq
,
cdrom_write_intr
);
}
static
ide_startstop_t
cdrom_start_write
(
ide_drive_t
*
drive
,
struct
request
*
rq
)
...
...
@@ -1728,20 +1748,54 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
return
cdrom_start_packet_command
(
drive
,
32768
,
cdrom_start_write_cont
);
}
/*
* Most of the SCSI commands are supported directly by ATAPI devices.
* This transform handles the few exceptions.
*/
static
int
pre_transform_command
(
struct
request
*
req
)
{
u8
*
c
=
req
->
cmd
;
/* Transform 6-byte read/write commands to the 10-byte version. */
if
(
c
[
0
]
==
READ_6
||
c
[
0
]
==
WRITE_6
)
{
c
[
8
]
=
c
[
4
];
c
[
5
]
=
c
[
3
];
c
[
4
]
=
c
[
2
];
c
[
3
]
=
c
[
1
]
&
0x1f
;
c
[
2
]
=
0
;
c
[
1
]
&=
0xe0
;
c
[
0
]
+=
(
READ_10
-
READ_6
);
return
0
;
}
/* These also need fixup, not done yet */
if
(
c
[
0
]
==
MODE_SENSE
||
c
[
0
]
==
MODE_SELECT
)
return
-
EINVAL
;
return
0
;
}
static
void
post_transform_command
(
struct
request
*
req
)
{
}
static
ide_startstop_t
cdrom_do_block_pc
(
ide_drive_t
*
drive
,
struct
request
*
rq
)
{
struct
packet_command
pc
;
ide_startstop_t
startstop
;
struct
cdrom_info
*
info
;
memset
(
&
pc
,
0
,
sizeof
(
pc
));
memcpy
(
pc
.
c
,
rq
->
cmd
,
sizeof
(
pc
.
c
));
pc
.
quiet
=
1
;
pc
.
timeout
=
60
*
HZ
;
rq
->
buffer
=
(
char
*
)
&
pc
;
if
(
pre_transform_command
(
rq
)
<
0
)
{
cdrom_end_request
(
drive
,
0
);
return
ide_stopped
;
}
rq
->
flags
|=
REQ_QUIET
;
info
=
drive
->
driver_data
;
info
->
dma
=
0
;
info
->
cmd
=
0
;
startstop
=
cdrom_do_packet_command
(
drive
);
if
(
pc
.
stat
)
rq
->
errors
++
;
/* Start sending the command to the drive. */
startstop
=
cdrom_start_packet_command
(
drive
,
rq
->
data_len
,
cdrom_do_pc_continuation
);
return
startstop
;
}
...
...
@@ -1757,11 +1811,11 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
if
(
blk_fs_request
(
rq
))
{
if
(
CDROM_CONFIG_FLAGS
(
drive
)
->
seeking
)
{
unsigned
long
el
pa
sed
=
jiffies
-
info
->
start_seek
;
unsigned
long
el
ap
sed
=
jiffies
-
info
->
start_seek
;
int
stat
=
HWIF
(
drive
)
->
INB
(
IDE_STATUS_REG
);
if
((
stat
&
SEEK_STAT
)
!=
SEEK_STAT
)
{
if
(
el
pa
sed
<
IDECD_SEEK_TIMEOUT
)
{
if
(
el
ap
sed
<
IDECD_SEEK_TIMEOUT
)
{
ide_stall_queue
(
drive
,
IDECD_SEEK_TIMER
);
return
ide_stopped
;
}
...
...
@@ -1781,14 +1835,14 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
return
action
;
}
else
if
(
rq
->
flags
&
(
REQ_PC
|
REQ_SENSE
))
{
return
cdrom_do_packet_command
(
drive
);
}
else
if
(
rq
->
flags
&
REQ_BLOCK_PC
)
{
return
cdrom_do_block_pc
(
drive
,
rq
);
}
else
if
(
rq
->
flags
&
REQ_SPECIAL
)
{
/*
* right now this can only be a reset...
*/
cdrom_end_request
(
drive
,
1
);
return
ide_stopped
;
}
else
if
(
rq
->
flags
&
REQ_BLOCK_PC
)
{
return
cdrom_do_block_pc
(
drive
,
rq
);
}
blk_dump_rq_flags
(
rq
,
"ide-cd bad flags"
);
...
...
@@ -1853,23 +1907,23 @@ int msf_to_lba (byte m, byte s, byte f)
static
int
cdrom_check_status
(
ide_drive_t
*
drive
,
struct
request_sense
*
sense
)
{
struct
packet_command
pc
;
struct
request
req
;
struct
cdrom_info
*
info
=
drive
->
driver_data
;
struct
cdrom_device_info
*
cdi
=
&
info
->
devinfo
;
memset
(
&
pc
,
0
,
sizeof
(
pc
));
pc
.
sense
=
sense
;
cdrom_prepare_request
(
&
req
);
pc
.
c
[
0
]
=
GPCMD_TEST_UNIT_READY
;
req
.
sense
=
sense
;
req
.
cmd
[
0
]
=
GPCMD_TEST_UNIT_READY
;
#if ! STANDARD_ATAPI
/* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
switch CDs instead of supporting the LOAD_UNLOAD opcode */
pc
.
c
[
7
]
=
cdi
->
sanyo_slot
%
3
;
req
.
cmd
[
7
]
=
cdi
->
sanyo_slot
%
3
;
#endif
/* not STANDARD_ATAPI */
return
cdrom_queue_packet_command
(
drive
,
&
pc
);
return
cdrom_queue_packet_command
(
drive
,
&
req
);
}
...
...
@@ -1878,7 +1932,7 @@ static int
cdrom_lockdoor
(
ide_drive_t
*
drive
,
int
lockflag
,
struct
request_sense
*
sense
)
{
struct
request_sense
my_sense
;
struct
packet_command
pc
;
struct
request
req
;
int
stat
;
if
(
sense
==
NULL
)
...
...
@@ -1888,11 +1942,11 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
if
(
CDROM_CONFIG_FLAGS
(
drive
)
->
no_doorlock
)
{
stat
=
0
;
}
else
{
memset
(
&
pc
,
0
,
sizeof
(
pc
)
);
pc
.
sense
=
sense
;
pc
.
c
[
0
]
=
GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL
;
pc
.
c
[
4
]
=
lockflag
?
1
:
0
;
stat
=
cdrom_queue_packet_command
(
drive
,
&
pc
);
cdrom_prepare_request
(
&
req
);
req
.
sense
=
sense
;
req
.
cmd
[
0
]
=
GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL
;
req
.
cmd
[
4
]
=
lockflag
?
1
:
0
;
stat
=
cdrom_queue_packet_command
(
drive
,
&
req
);
}
/* If we got an illegal field error, the drive
...
...
@@ -1922,7 +1976,7 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
static
int
cdrom_eject
(
ide_drive_t
*
drive
,
int
ejectflag
,
struct
request_sense
*
sense
)
{
struct
packet_command
pc
;
struct
request
req
;
if
(
CDROM_CONFIG_FLAGS
(
drive
)
->
no_eject
&&
!
ejectflag
)
return
-
EDRIVE_CANT_DO_THIS
;
...
...
@@ -1931,12 +1985,12 @@ static int cdrom_eject(ide_drive_t *drive, int ejectflag,
if
(
CDROM_STATE_FLAGS
(
drive
)
->
door_locked
&&
ejectflag
)
return
0
;
memset
(
&
pc
,
0
,
sizeof
(
pc
));
pc
.
sense
=
sense
;
cdrom_prepare_request
(
&
req
);
pc
.
c
[
0
]
=
GPCMD_START_STOP_UNIT
;
pc
.
c
[
4
]
=
0x02
+
(
ejectflag
!=
0
);
return
cdrom_queue_packet_command
(
drive
,
&
pc
);
req
.
sense
=
sense
;
req
.
cmd
[
0
]
=
GPCMD_START_STOP_UNIT
;
req
.
cmd
[
4
]
=
0x02
+
(
ejectflag
!=
0
);
return
cdrom_queue_packet_command
(
drive
,
&
req
);
}
static
int
cdrom_read_capacity
(
ide_drive_t
*
drive
,
unsigned
long
*
capacity
,
...
...
@@ -1948,16 +2002,16 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
}
capbuf
;
int
stat
;
struct
packet_command
pc
;
struct
request
req
;
memset
(
&
pc
,
0
,
sizeof
(
pc
));
pc
.
sense
=
sense
;
cdrom_prepare_request
(
&
req
);
pc
.
c
[
0
]
=
GPCMD_READ_CDVD_CAPACITY
;
pc
.
buffer
=
(
char
*
)
&
capbuf
;
pc
.
buflen
=
sizeof
(
capbuf
);
req
.
sense
=
sense
;
req
.
cmd
[
0
]
=
GPCMD_READ_CDVD_CAPACITY
;
req
.
data
=
(
char
*
)
&
capbuf
;
req
.
data_len
=
sizeof
(
capbuf
);
stat
=
cdrom_queue_packet_command
(
drive
,
&
pc
);
stat
=
cdrom_queue_packet_command
(
drive
,
&
req
);
if
(
stat
==
0
)
*
capacity
=
1
+
be32_to_cpu
(
capbuf
.
lba
);
...
...
@@ -1968,24 +2022,24 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
int
format
,
char
*
buf
,
int
buflen
,
struct
request_sense
*
sense
)
{
struct
packet_command
pc
;
struct
request
req
;
memset
(
&
pc
,
0
,
sizeof
(
pc
));
pc
.
sense
=
sense
;
cdrom_prepare_request
(
&
req
);
pc
.
buffer
=
buf
;
pc
.
buflen
=
buflen
;
pc
.
quiet
=
1
;
pc
.
c
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
pc
.
c
[
6
]
=
trackno
;
pc
.
c
[
7
]
=
(
buflen
>>
8
);
pc
.
c
[
8
]
=
(
buflen
&
0xff
);
pc
.
c
[
9
]
=
(
format
<<
6
);
req
.
sense
=
sense
;
req
.
data
=
buf
;
req
.
data_len
=
buflen
;
req
.
flags
|=
REQ_QUIET
;
req
.
cmd
[
0
]
=
GPCMD_READ_TOC_PMA_ATIP
;
req
.
cmd
[
6
]
=
trackno
;
req
.
cmd
[
7
]
=
(
buflen
>>
8
);
req
.
cmd
[
8
]
=
(
buflen
&
0xff
);
req
.
cmd
[
9
]
=
(
format
<<
6
);
if
(
msf_flag
)
pc
.
c
[
1
]
=
2
;
req
.
cmd
[
1
]
=
2
;
return
cdrom_queue_packet_command
(
drive
,
&
pc
);
return
cdrom_queue_packet_command
(
drive
,
&
req
);
}
...
...
@@ -2144,20 +2198,20 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
static
int
cdrom_read_subchannel
(
ide_drive_t
*
drive
,
int
format
,
char
*
buf
,
int
buflen
,
struct
request_sense
*
sense
)
{
struct
packet_command
pc
;
struct
request
req
;
memset
(
&
pc
,
0
,
sizeof
(
pc
));
pc
.
sense
=
sense
;
cdrom_prepare_request
(
&
req
);
pc
.
buffer
=
buf
;
pc
.
buflen
=
buflen
;
pc
.
c
[
0
]
=
GPCMD_READ_SUBCHANNEL
;
pc
.
c
[
1
]
=
2
;
/* MSF addressing */
pc
.
c
[
2
]
=
0x40
;
/* request subQ data */
pc
.
c
[
3
]
=
format
;
pc
.
c
[
7
]
=
(
buflen
>>
8
);
pc
.
c
[
8
]
=
(
buflen
&
0xff
);
return
cdrom_queue_packet_command
(
drive
,
&
pc
);
req
.
sense
=
sense
;
req
.
data
=
buf
;
req
.
data_len
=
buflen
;
req
.
cmd
[
0
]
=
GPCMD_READ_SUBCHANNEL
;
req
.
cmd
[
1
]
=
2
;
/* MSF addressing */
req
.
cmd
[
2
]
=
0x40
;
/* request subQ data */
req
.
cmd
[
3
]
=
format
;
req
.
cmd
[
7
]
=
(
buflen
>>
8
);
req
.
cmd
[
8
]
=
(
buflen
&
0xff
);
return
cdrom_queue_packet_command
(
drive
,
&
req
);
}
/* ATAPI cdrom drives are free to select the speed you request or any slower
...
...
@@ -2165,45 +2219,45 @@ static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
static
int
cdrom_select_speed
(
ide_drive_t
*
drive
,
int
speed
,
struct
request_sense
*
sense
)
{
struct
packet_command
pc
;
memset
(
&
pc
,
0
,
sizeof
(
pc
));
pc
.
sense
=
sense
;
struct
request
req
;
cdrom_prepare_request
(
&
req
);
req
.
sense
=
sense
;
if
(
speed
==
0
)
speed
=
0xffff
;
/* set to max */
else
speed
*=
177
;
/* Nx to kbytes/s */
pc
.
c
[
0
]
=
GPCMD_SET_SPEED
;
req
.
cmd
[
0
]
=
GPCMD_SET_SPEED
;
/* Read Drive speed in kbytes/second MSB */
pc
.
c
[
2
]
=
(
speed
>>
8
)
&
0xff
;
req
.
cmd
[
2
]
=
(
speed
>>
8
)
&
0xff
;
/* Read Drive speed in kbytes/second LSB */
pc
.
c
[
3
]
=
speed
&
0xff
;
req
.
cmd
[
3
]
=
speed
&
0xff
;
if
(
CDROM_CONFIG_FLAGS
(
drive
)
->
cd_r
||
CDROM_CONFIG_FLAGS
(
drive
)
->
cd_rw
||
CDROM_CONFIG_FLAGS
(
drive
)
->
dvd_r
)
{
/* Write Drive speed in kbytes/second MSB */
pc
.
c
[
4
]
=
(
speed
>>
8
)
&
0xff
;
req
.
cmd
[
4
]
=
(
speed
>>
8
)
&
0xff
;
/* Write Drive speed in kbytes/second LSB */
pc
.
c
[
5
]
=
speed
&
0xff
;
req
.
cmd
[
5
]
=
speed
&
0xff
;
}
return
cdrom_queue_packet_command
(
drive
,
&
pc
);
return
cdrom_queue_packet_command
(
drive
,
&
req
);
}
static
int
cdrom_play_audio
(
ide_drive_t
*
drive
,
int
lba_start
,
int
lba_end
)
{
struct
request_sense
sense
;
struct
packet_command
pc
;
struct
request
req
;
memset
(
&
pc
,
0
,
sizeof
(
pc
));
pc
.
sense
=
&
sense
;
cdrom_prepare_request
(
&
req
);
pc
.
c
[
0
]
=
GPCMD_PLAY_AUDIO_MSF
;
lba_to_msf
(
lba_start
,
&
pc
.
c
[
3
],
&
pc
.
c
[
4
],
&
pc
.
c
[
5
]);
lba_to_msf
(
lba_end
-
1
,
&
pc
.
c
[
6
],
&
pc
.
c
[
7
],
&
pc
.
c
[
8
]);
req
.
sense
=
&
sense
;
req
.
cmd
[
0
]
=
GPCMD_PLAY_AUDIO_MSF
;
lba_to_msf
(
lba_start
,
&
req
.
cmd
[
3
],
&
req
.
cmd
[
4
],
&
req
.
cmd
[
5
]);
lba_to_msf
(
lba_end
-
1
,
&
req
.
cmd
[
6
],
&
req
.
cmd
[
7
],
&
req
.
cmd
[
8
]);
return
cdrom_queue_packet_command
(
drive
,
&
pc
);
return
cdrom_queue_packet_command
(
drive
,
&
req
);
}
static
int
cdrom_get_toc_entry
(
ide_drive_t
*
drive
,
int
track
,
...
...
@@ -2237,7 +2291,7 @@ static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
static
int
ide_cdrom_packet
(
struct
cdrom_device_info
*
cdi
,
struct
cdrom_generic_command
*
cgc
)
{
struct
packet_command
pc
;
struct
request
req
;
ide_drive_t
*
drive
=
(
ide_drive_t
*
)
cdi
->
handle
;
if
(
cgc
->
timeout
<=
0
)
...
...
@@ -2246,18 +2300,21 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
/* here we queue the commands from the uniform CD-ROM
layer. the packet must be complete, as we do not
touch it at all. */
memset
(
&
pc
,
0
,
sizeof
(
pc
)
);
memcpy
(
pc
.
c
,
cgc
->
cmd
,
CDROM_PACKET_SIZE
);
cdrom_prepare_request
(
&
req
);
memcpy
(
req
.
cmd
,
cgc
->
cmd
,
CDROM_PACKET_SIZE
);
if
(
cgc
->
sense
)
memset
(
cgc
->
sense
,
0
,
sizeof
(
struct
request_sense
));
pc
.
buffer
=
cgc
->
buffer
;
pc
.
buflen
=
cgc
->
buflen
;
pc
.
quiet
=
cgc
->
quiet
;
pc
.
timeout
=
cgc
->
timeout
;
pc
.
sense
=
cgc
->
sense
;
cgc
->
stat
=
cdrom_queue_packet_command
(
drive
,
&
pc
);
req
.
data
=
cgc
->
buffer
;
req
.
data_len
=
cgc
->
buflen
;
req
.
timeout
=
cgc
->
timeout
;
if
(
cgc
->
quiet
)
req
.
flags
|=
REQ_QUIET
;
req
.
sense
=
cgc
->
sense
;
cgc
->
stat
=
cdrom_queue_packet_command
(
drive
,
&
req
);
if
(
!
cgc
->
stat
)
cgc
->
buflen
-=
pc
.
buf
len
;
cgc
->
buflen
-=
req
.
data_
len
;
return
cgc
->
stat
;
}
...
...
@@ -2393,7 +2450,7 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi)
struct
request
req
;
int
ret
;
ide_init_drive_cmd
(
&
req
);
cdrom_prepare_request
(
&
req
);
req
.
flags
=
REQ_SPECIAL
;
ret
=
ide_do_drive_cmd
(
drive
,
&
req
,
ide_wait
);
...
...
@@ -2969,6 +3026,14 @@ int ide_cdrom_ioctl (ide_drive_t *drive,
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
int
error
;
/* Try the generic SCSI command ioctl's first.. */
error
=
scsi_cmd_ioctl
(
inode
->
i_bdev
,
cmd
,
arg
);
if
(
error
!=
-
ENOTTY
)
return
error
;
/* Then the generic cdrom ioctl's.. */
return
cdrom_ioctl
(
inode
,
file
,
cmd
,
arg
);
}
...
...
drivers/ide/ide-cd.h
View file @
59aa7245
...
...
@@ -105,13 +105,6 @@ struct ide_cd_state_flags {
#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
struct
packet_command
{
char
*
buffer
;
int
buflen
;
int
stat
;
int
quiet
;
int
timeout
;
struct
request_sense
*
sense
;
unsigned
char
c
[
12
];
};
/* Structure of a MSF cdrom address. */
...
...
drivers/ide/ide.c
View file @
59aa7245
...
...
@@ -2639,7 +2639,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case
CDROMEJECT
:
case
CDROMCLOSETRAY
:
return
block
_ioctl
(
inode
->
i_bdev
,
cmd
,
arg
);
return
scsi_cmd
_ioctl
(
inode
->
i_bdev
,
cmd
,
arg
);
case
HDIO_GET_BUSSTATE
:
if
(
!
capable
(
CAP_SYS_ADMIN
))
...
...
fs/block_dev.c
View file @
59aa7245
...
...
@@ -824,44 +824,9 @@ static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
unsigned
long
arg
)
{
struct
block_device
*
bdev
=
inode
->
i_bdev
;
int
ret
=
-
EINVAL
;
switch
(
cmd
)
{
/*
* deprecated, use the /proc/iosched interface instead
*/
case
BLKELVGET
:
case
BLKELVSET
:
ret
=
-
ENOTTY
;
break
;
case
BLKRAGET
:
case
BLKROGET
:
case
BLKBSZGET
:
case
BLKSSZGET
:
case
BLKFRAGET
:
case
BLKSECTGET
:
case
BLKRASET
:
case
BLKFRASET
:
case
BLKBSZSET
:
case
BLKPG
:
ret
=
blk_ioctl
(
bdev
,
cmd
,
arg
);
break
;
case
BLKRRPART
:
ret
=
blkdev_reread_part
(
bdev
);
break
;
default:
if
(
bdev
->
bd_op
->
ioctl
)
ret
=
bdev
->
bd_op
->
ioctl
(
inode
,
file
,
cmd
,
arg
);
if
(
ret
==
-
EINVAL
)
{
switch
(
cmd
)
{
case
BLKGETSIZE
:
case
BLKGETSIZE64
:
case
BLKFLSBUF
:
case
BLKROSET
:
ret
=
blk_ioctl
(
bdev
,
cmd
,
arg
);
break
;
}
}
}
int
ret
=
blk_ioctl
(
bdev
,
cmd
,
arg
);
if
(
ret
==
-
ENOTTY
&&
bdev
->
bd_op
->
ioctl
)
ret
=
bdev
->
bd_op
->
ioctl
(
inode
,
file
,
cmd
,
arg
);
return
ret
;
}
...
...
include/linux/blkdev.h
View file @
59aa7245
...
...
@@ -60,6 +60,12 @@ struct request {
int
tag
;
void
*
special
;
char
*
buffer
;
/* For packet commands */
unsigned
int
data_len
;
void
*
data
,
*
sense
;
unsigned
int
timeout
;
struct
completion
*
waiting
;
struct
bio
*
bio
,
*
biotail
;
request_queue_t
*
q
;
...
...
@@ -85,6 +91,8 @@ enum rq_flag_bits {
__REQ_BLOCK_PC
,
/* queued down pc from block layer */
__REQ_SENSE
,
/* sense retrival */
__REQ_FAILED
,
/* set if the request failed */
__REQ_QUIET
,
/* don't worry about errors */
__REQ_SPECIAL
,
/* driver suplied command */
__REQ_DRIVE_CMD
,
__REQ_DRIVE_TASK
,
...
...
@@ -103,6 +111,8 @@ enum rq_flag_bits {
#define REQ_PC (1 << __REQ_PC)
#define REQ_BLOCK_PC (1 << __REQ_BLOCK_PC)
#define REQ_SENSE (1 << __REQ_SENSE)
#define REQ_FAILED (1 << __REQ_FAILED)
#define REQ_QUIET (1 << __REQ_QUIET)
#define REQ_SPECIAL (1 << __REQ_SPECIAL)
#define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD)
#define REQ_DRIVE_TASK (1 << __REQ_DRIVE_TASK)
...
...
@@ -301,7 +311,7 @@ extern int blk_remove_plug(request_queue_t *);
extern
void
blk_recount_segments
(
request_queue_t
*
,
struct
bio
*
);
extern
inline
int
blk_phys_contig_segment
(
request_queue_t
*
q
,
struct
bio
*
,
struct
bio
*
);
extern
inline
int
blk_hw_contig_segment
(
request_queue_t
*
q
,
struct
bio
*
,
struct
bio
*
);
extern
int
block
_ioctl
(
struct
block_device
*
,
unsigned
int
,
unsigned
long
);
extern
int
scsi_cmd
_ioctl
(
struct
block_device
*
,
unsigned
int
,
unsigned
long
);
extern
void
blk_start_queue
(
request_queue_t
*
q
);
extern
void
blk_stop_queue
(
request_queue_t
*
q
);
extern
void
__blk_stop_queue
(
request_queue_t
*
q
);
...
...
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