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
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
Show 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
;
startstop
=
cdrom_do_packet_command
(
drive
);
if
(
pc
.
stat
)
rq
->
errors
++
;
info
=
drive
->
driver_data
;
info
->
dma
=
0
;
info
->
cmd
=
0
;
/* 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