Commit 40d1b71b authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-bt.bkbits.net/bt-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 4c9eb495 0c8aab5d
...@@ -9,9 +9,9 @@ ...@@ -9,9 +9,9 @@
# #
export-objs := elevator.o ll_rw_blk.o loop.o genhd.o acsi.o \ 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_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o
......
...@@ -305,6 +305,6 @@ int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg) ...@@ -305,6 +305,6 @@ int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return 0; return 0;
default: default:
return -EINVAL; return -ENOTTY;
} }
} }
...@@ -27,8 +27,12 @@ ...@@ -27,8 +27,12 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/cdrom.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) 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) ...@@ -50,7 +54,114 @@ int blk_do_rq(request_queue_t *q, struct request *rq)
return err; 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; request_queue_t *q;
struct request *rq; struct request *rq;
...@@ -61,11 +172,32 @@ int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg) ...@@ -61,11 +172,32 @@ int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return -ENXIO; return -ENXIO;
switch (cmd) { 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: case CDROMCLOSETRAY:
close = 1; close = 1;
case CDROMEJECT: case CDROMEJECT:
rq = blk_get_request(q, WRITE, __GFP_WAIT); rq = blk_get_request(q, WRITE, __GFP_WAIT);
rq->flags = REQ_BLOCK_PC; rq->flags = REQ_BLOCK_PC;
rq->data = NULL;
rq->data_len = 0;
rq->timeout = 60*HZ;
memset(rq->cmd, 0, sizeof(rq->cmd)); memset(rq->cmd, 0, sizeof(rq->cmd));
rq->cmd[0] = GPCMD_START_STOP_UNIT; rq->cmd[0] = GPCMD_START_STOP_UNIT;
rq->cmd[4] = 0x02 + (close != 0); rq->cmd[4] = 0x02 + (close != 0);
...@@ -80,4 +212,4 @@ int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg) ...@@ -80,4 +212,4 @@ int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return err; return err;
} }
EXPORT_SYMBOL(block_ioctl); EXPORT_SYMBOL(scsi_cmd_ioctl);
...@@ -309,6 +309,8 @@ ...@@ -309,6 +309,8 @@
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
...@@ -332,12 +334,12 @@ static void cdrom_saw_media_change (ide_drive_t *drive) ...@@ -332,12 +334,12 @@ static void cdrom_saw_media_change (ide_drive_t *drive)
info->nsectors_buffered = 0; 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) struct request_sense *sense)
{ {
int log = 0; int log = 0;
if (sense == NULL || pc == NULL || pc->quiet) if (!sense || !rq || (rq->flags & REQ_QUIET))
return 0; return 0;
switch (sense->sense_key) { switch (sense->sense_key) {
...@@ -370,10 +372,9 @@ static int cdrom_log_sense(ide_drive_t *drive, struct packet_command *pc, ...@@ -370,10 +372,9 @@ static int cdrom_log_sense(ide_drive_t *drive, struct packet_command *pc,
static static
void cdrom_analyze_sense_data(ide_drive_t *drive, void cdrom_analyze_sense_data(ide_drive_t *drive,
struct packet_command *failed_command, struct request *failed_command,
struct request_sense *sense) struct request_sense *sense)
{ {
if (!cdrom_log_sense(drive, failed_command, sense)) if (!cdrom_log_sense(drive, failed_command, sense))
return; return;
...@@ -382,7 +383,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, ...@@ -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 * the first toc has not been recorded yet, it will fail with
* 05/24/00 (which is a confusing error) * 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->cmd[0] == GPCMD_READ_TOC_PMA_ATIP)
if (sense->sense_key == 0x05 && sense->asc == 0x24) if (sense->sense_key == 0x05 && sense->asc == 0x24)
return; return;
...@@ -453,20 +454,20 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, ...@@ -453,20 +454,20 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
while (hi > lo) { while (hi > lo) {
mid = (lo + hi) / 2; mid = (lo + hi) / 2;
if (packet_command_texts[mid].packet_command == if (packet_command_texts[mid].packet_command ==
failed_command->c[0]) { failed_command->cmd[0]) {
s = packet_command_texts[mid].text; s = packet_command_texts[mid].text;
break; break;
} }
if (packet_command_texts[mid].packet_command > if (packet_command_texts[mid].packet_command >
failed_command->c[0]) failed_command->cmd[0])
hi = mid; hi = mid;
else else
lo = mid+1; lo = mid+1;
} }
printk (" The failed \"%s\" packet command was: \n \"", s); printk (" The failed \"%s\" packet command was: \n \"", s);
for (i=0; i<sizeof (failed_command->c); i++) for (i=0; i<sizeof (failed_command->cmd); i++)
printk ("%02x ", failed_command->c[i]); printk ("%02x ", failed_command->cmd[i]);
printk ("\"\n"); printk ("\"\n");
} }
...@@ -512,30 +513,39 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, ...@@ -512,30 +513,39 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
#endif /* not VERBOSE_IDE_CD_ERRORS */ #endif /* not VERBOSE_IDE_CD_ERRORS */
} }
/*
* Initialize a ide-cd packet command request
*/
static void cdrom_prepare_request(struct request *rq)
{
ide_init_drive_cmd(rq);
rq->flags = REQ_PC;
}
static void cdrom_queue_request_sense(ide_drive_t *drive, static void cdrom_queue_request_sense(ide_drive_t *drive,
struct completion *wait, struct completion *wait,
struct request_sense *sense, void *sense,
struct packet_command *failed_command) struct request *failed_command)
{ {
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
struct packet_command *pc = &info->request_sense_pc; struct request *rq = &info->request_sense_request;
struct request *rq;
if (sense == NULL) if (sense == NULL)
sense = &info->sense_data; 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 */ /* stuff the sense request in front of our current request */
rq = &info->request_sense_request; cdrom_prepare_request(rq);
ide_init_drive_cmd(rq);
rq->data = sense;
rq->cmd[0] = GPCMD_REQUEST_SENSE;
rq->cmd[4] = rq->data_len = 18;
rq->flags = REQ_SENSE; rq->flags = REQ_SENSE;
rq->buffer = (char *) pc;
rq->waiting = wait; 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); (void) ide_do_drive_cmd(drive, rq, ide_preempt);
} }
...@@ -630,17 +640,26 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate) ...@@ -630,17 +640,26 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
if ((rq->flags & REQ_SENSE) && uptodate) { if ((rq->flags & REQ_SENSE) && uptodate) {
struct packet_command *pc = (struct packet_command *) rq->buffer; /* For REQ_SENSE, "rq->buffer" points to the original failed request */
cdrom_analyze_sense_data(drive, struct request *failed = (struct request *) rq->buffer;
(struct packet_command *) pc->sense, struct cdrom_info *info = drive->driver_data;
(struct request_sense *) (pc->buffer - pc->c[4])); 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) if (blk_fs_request(rq) && !rq->current_nr_sectors)
uptodate = 1; uptodate = 1;
ide_end_request(drive, uptodate, rq->hard_cur_sectors); 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 0 if the request should be continued.
Returns 1 if the request was ended. */ Returns 1 if the request was ended. */
...@@ -649,7 +668,6 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, ...@@ -649,7 +668,6 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
{ {
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
int stat, err, sense_key; int stat, err, sense_key;
struct packet_command *pc;
/* Check for errors. */ /* Check for errors. */
*stat_ret = stat = HWIF(drive)->INB(IDE_STATUS_REG); *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, ...@@ -672,16 +690,18 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
from the drive (probably while trying from the drive (probably while trying
to recover from a former error). Just give up. */ to recover from a former error). Just give up. */
pc = (struct packet_command *) rq->buffer; rq->flags |= REQ_FAILED;
pc->stat = 1; cdrom_end_request(drive, 0);
cdrom_end_request(drive, 1);
*startstop = DRIVER(drive)->error(drive, "request sense failure", stat); *startstop = DRIVER(drive)->error(drive, "request sense failure", stat);
return 1; return 1;
} else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) { } else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) {
/* All other functions, except for READ. */ /* All other functions, except for READ. */
struct completion *wait = NULL; 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. */ /* Check for tray open. */
if (sense_key == NOT_READY) { if (sense_key == NOT_READY) {
...@@ -691,7 +711,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, ...@@ -691,7 +711,7 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
cdrom_saw_media_change (drive); cdrom_saw_media_change (drive);
/*printk("%s: media changed\n",drive->name);*/ /*printk("%s: media changed\n",drive->name);*/
return 0; return 0;
} else if (!pc->quiet) { } else if (!(rq->flags & REQ_QUIET)) {
/* Otherwise, print an error. */ /* Otherwise, print an error. */
ide_dump_status(drive, "packet command error", stat); 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, ...@@ -710,11 +730,11 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
rq->waiting = NULL; rq->waiting = NULL;
} }
pc->stat = 1; rq->flags |= REQ_FAILED;
cdrom_end_request(drive, 1); cdrom_end_request(drive, 0);
if ((stat & ERR_STAT) != 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)) { } else if (blk_fs_request(rq)) {
/* Handle errors from READ and WRITE requests. */ /* Handle errors from READ and WRITE requests. */
...@@ -770,7 +790,6 @@ static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, ...@@ -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) static int cdrom_timer_expiry(ide_drive_t *drive)
{ {
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
struct packet_command *pc = (struct packet_command *) rq->buffer;
unsigned long wait = 0; unsigned long wait = 0;
/* /*
...@@ -779,7 +798,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive) ...@@ -779,7 +798,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
* this, but not all commands/drives support that. Let * this, but not all commands/drives support that. Let
* ide_timer_expiry keep polling us for these. * ide_timer_expiry keep polling us for these.
*/ */
switch (pc->c[0]) { switch (rq->cmd[0]) {
case GPCMD_BLANK: case GPCMD_BLANK:
case GPCMD_FORMAT_UNIT: case GPCMD_FORMAT_UNIT:
case GPCMD_RESERVE_RZONE_TRACK: case GPCMD_RESERVE_RZONE_TRACK:
...@@ -854,12 +873,12 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, ...@@ -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; * struct packet_command *pc; now packet_command_t *pc;
*/ */
static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
struct packet_command *pc, struct request *rq,
ide_handler_t *handler) ide_handler_t *handler)
{ {
unsigned char *cmd_buf = pc->c; unsigned char *cmd_buf = rq->cmd;
int cmd_len = sizeof(pc->c); int cmd_len = sizeof(rq->cmd);
unsigned int timeout = pc->timeout; unsigned int timeout = rq->timeout;
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
ide_startstop_t startstop; ide_startstop_t startstop;
...@@ -1029,6 +1048,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) ...@@ -1029,6 +1048,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
if (rq->current_nr_sectors > 0) { if (rq->current_nr_sectors > 0) {
printk ("%s: cdrom_read_intr: data underrun (%d blocks)\n", printk ("%s: cdrom_read_intr: data underrun (%d blocks)\n",
drive->name, rq->current_nr_sectors); drive->name, rq->current_nr_sectors);
rq->flags |= REQ_FAILED;
cdrom_end_request(drive, 0); cdrom_end_request(drive, 0);
} else } else
cdrom_end_request(drive, 1); cdrom_end_request(drive, 1);
...@@ -1179,7 +1199,6 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) ...@@ -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) static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
{ {
struct packet_command pc;
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
int nsect, sector, nframes, frame, nskip; int nsect, sector, nframes, frame, nskip;
...@@ -1222,11 +1241,10 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) ...@@ -1222,11 +1241,10 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
(65534 / CD_FRAMESIZE) : 65535); (65534 / CD_FRAMESIZE) : 65535);
/* Set up the command */ /* Set up the command */
memcpy(pc.c, rq->cmd, sizeof(pc.c)); rq->timeout = WAIT_CMD;
pc.timeout = WAIT_CMD;
/* Send the command to the drive and return. */ /* 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) ...@@ -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) static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
{ {
struct packet_command pc;
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
int sector, frame, nskip; int sector, frame, nskip;
...@@ -1273,11 +1290,11 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive) ...@@ -1273,11 +1290,11 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
frame = sector / SECTORS_PER_FRAME; frame = sector / SECTORS_PER_FRAME;
memset(rq->cmd, 0, sizeof(rq->cmd)); memset(rq->cmd, 0, sizeof(rq->cmd));
pc.c[0] = GPCMD_SEEK; rq->cmd[0] = GPCMD_SEEK;
put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
pc.timeout = WAIT_CMD; rq->timeout = WAIT_CMD;
return cdrom_transfer_packet_command(drive, &pc, &cdrom_seek_intr); return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
} }
static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block) 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) ...@@ -1296,6 +1313,7 @@ static void restore_request (struct request *rq)
{ {
if (rq->buffer != bio_data(rq->bio)) { if (rq->buffer != bio_data(rq->bio)) {
sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE; sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;
rq->buffer = bio_data(rq->bio); rq->buffer = bio_data(rq->bio);
rq->nr_sectors += n; rq->nr_sectors += n;
rq->sector -= n; rq->sector -= n;
...@@ -1352,7 +1370,6 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) ...@@ -1352,7 +1370,6 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
{ {
int ireason, len, stat, thislen; int ireason, len, stat, thislen;
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
struct packet_command *pc = (struct packet_command *)rq->buffer;
ide_startstop_t startstop; ide_startstop_t startstop;
u8 lowcyl = 0, highcyl = 0; u8 lowcyl = 0, highcyl = 0;
...@@ -1372,16 +1389,16 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) ...@@ -1372,16 +1389,16 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
if ((stat & DRQ_STAT) == 0) { if ((stat & DRQ_STAT) == 0) {
/* Some of the trailing request sense fields are optional, and /* Some of the trailing request sense fields are optional, and
some drives don't send them. Sigh. */ some drives don't send them. Sigh. */
if (pc->c[0] == GPCMD_REQUEST_SENSE && if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
pc->buflen > 0 && rq->data_len > 0 &&
pc->buflen <= 5) { rq->data_len <= 5) {
while (pc->buflen > 0) { while (rq->data_len > 0) {
*pc->buffer++ = 0; *(unsigned char *)rq->data++ = 0;
--pc->buflen; --rq->data_len;
} }
} }
if (pc->buflen == 0) if (rq->data_len == 0)
cdrom_end_request(drive, 1); cdrom_end_request(drive, 1);
else { else {
/* Comment this out, because this always happens /* Comment this out, because this always happens
...@@ -1391,20 +1408,22 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) ...@@ -1391,20 +1408,22 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
printk ("%s: cdrom_pc_intr: data underrun %d\n", printk ("%s: cdrom_pc_intr: data underrun %d\n",
drive->name, pc->buflen); drive->name, pc->buflen);
*/ */
pc->stat = 1; rq->flags |= REQ_FAILED;
cdrom_end_request(drive, 1); cdrom_end_request(drive, 0);
} }
return ide_stopped; return ide_stopped;
} }
/* Figure out how much data to transfer. */ /* Figure out how much data to transfer. */
thislen = pc->buflen; thislen = rq->data_len;
if (thislen > len) thislen = len; if (thislen > len) thislen = len;
/* The drive wants to be written to. */ /* The drive wants to be written to. */
if ((ireason & 3) == 0) { if ((ireason & 3) == 0) {
if (!rq->data)
goto confused;
/* Transfer the data. */ /* 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, /* If we haven't moved enough data to satisfy the drive,
add some padding. */ add some padding. */
...@@ -1415,15 +1434,16 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) ...@@ -1415,15 +1434,16 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
} }
/* Keep count of how much data we've moved. */ /* Keep count of how much data we've moved. */
pc->buffer += thislen; rq->data += thislen;
pc->buflen -= thislen; rq->data_len -= thislen;
} }
/* Same drill for reading. */ /* Same drill for reading. */
else if ((ireason & 3) == 2) { else if ((ireason & 3) == 2) {
if (!rq->data)
goto confused;
/* Transfer the data. */ /* 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, /* If we haven't moved enough data to satisfy the drive,
add some padding. */ add some padding. */
...@@ -1434,13 +1454,14 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) ...@@ -1434,13 +1454,14 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
} }
/* Keep count of how much data we've moved. */ /* Keep count of how much data we've moved. */
pc->buffer += thislen; rq->data += thislen;
pc->buflen -= thislen; rq->data_len -= thislen;
} else { } else {
confused:
printk ("%s: cdrom_pc_intr: The drive " printk ("%s: cdrom_pc_intr: The drive "
"appears confused (ireason = 0x%2x)\n", "appears confused (ireason = 0x%2x)\n",
drive->name, ireason); drive->name, ireason);
pc->stat = 1; rq->flags |= REQ_FAILED;
} }
if (HWGROUP(drive)->handler != NULL) if (HWGROUP(drive)->handler != NULL)
...@@ -1455,13 +1476,12 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) ...@@ -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) static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
{ {
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
struct packet_command *pc = (struct packet_command *)rq->buffer;
if (!pc->timeout) if (!rq->timeout)
pc->timeout = WAIT_CMD; rq->timeout = WAIT_CMD;
/* Send the command to the drive and return. */ /* 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) ...@@ -1469,13 +1489,12 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
{ {
int len; int len;
struct request *rq = HWGROUP(drive)->rq; struct request *rq = HWGROUP(drive)->rq;
struct packet_command *pc = (struct packet_command *)rq->buffer;
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
info->dma = 0; info->dma = 0;
info->cmd = 0; info->cmd = 0;
pc->stat = 0; rq->flags &= ~REQ_FAILED;
len = pc->buflen; len = rq->data_len;
/* Start sending the command to the drive. */ /* Start sending the command to the drive. */
return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation); return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation);
...@@ -1496,28 +1515,31 @@ void cdrom_sleep (int time) ...@@ -1496,28 +1515,31 @@ void cdrom_sleep (int time)
} }
static 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_sense sense;
struct request req;
int retries = 10; int retries = 10;
unsigned int flags = rq->flags;
if (pc->sense == NULL) if (rq->sense == NULL)
pc->sense = &sense; rq->sense = &sense;
/* Start of retry loop. */ /* Start of retry loop. */
do { do {
ide_init_drive_cmd (&req); int error;
req.flags = REQ_PC; unsigned long time = jiffies;
req.buffer = (char *)pc; rq->flags = flags;
ide_do_drive_cmd(drive, &req, ide_wait);
error = ide_do_drive_cmd(drive, rq, ide_wait);
time = jiffies - time;
/* FIXME: we should probably abort/retry or something /* FIXME: we should probably abort/retry or something
* in case of failure */ * in case of failure */
if (pc->stat != 0) { if (rq->flags & REQ_FAILED) {
/* The request failed. Retry if it was due to a unit /* The request failed. Retry if it was due to a unit
attention status attention status
(usually means media was changed). */ (usually means media was changed). */
struct request_sense *reqbuf = pc->sense; struct request_sense *reqbuf = rq->sense;
if (reqbuf->sense_key == UNIT_ATTENTION) if (reqbuf->sense_key == UNIT_ATTENTION)
cdrom_saw_media_change(drive); cdrom_saw_media_change(drive);
...@@ -1535,10 +1557,10 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc) ...@@ -1535,10 +1557,10 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
} }
/* End of retry loop. */ /* 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 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) ...@@ -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) 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; struct request *rq = HWGROUP(drive)->rq;
unsigned nframes, frame; unsigned nframes, frame;
nframes = rq->nr_sectors >> 2; nframes = rq->nr_sectors >> 2;
frame = rq->sector >> 2; frame = rq->sector >> 2;
memcpy(pc.c, rq->cmd, sizeof(pc.c));
#if 0 /* the immediate bit */ #if 0 /* the immediate bit */
pc.c[1] = 1 << 3; rq->cmd[1] = 1 << 3;
#endif #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) 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) ...@@ -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); 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) static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{ {
struct packet_command pc;
ide_startstop_t startstop; ide_startstop_t startstop;
struct cdrom_info *info;
memset(&pc, 0, sizeof(pc)); if (pre_transform_command(rq) < 0) {
memcpy(pc.c, rq->cmd, sizeof(pc.c)); cdrom_end_request(drive, 0);
pc.quiet = 1; return ide_stopped;
pc.timeout = 60 * HZ; }
rq->buffer = (char *) &pc;
rq->flags |= REQ_QUIET;
startstop = cdrom_do_packet_command(drive); info = drive->driver_data;
if (pc.stat) info->dma = 0;
rq->errors++; 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; return startstop;
} }
...@@ -1757,11 +1811,11 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) ...@@ -1757,11 +1811,11 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
if (blk_fs_request(rq)) { if (blk_fs_request(rq)) {
if (CDROM_CONFIG_FLAGS(drive)->seeking) { if (CDROM_CONFIG_FLAGS(drive)->seeking) {
unsigned long elpased = jiffies - info->start_seek; unsigned long elapsed = jiffies - info->start_seek;
int stat = HWIF(drive)->INB(IDE_STATUS_REG); int stat = HWIF(drive)->INB(IDE_STATUS_REG);
if ((stat & SEEK_STAT) != SEEK_STAT) { if ((stat & SEEK_STAT) != SEEK_STAT) {
if (elpased < IDECD_SEEK_TIMEOUT) { if (elapsed < IDECD_SEEK_TIMEOUT) {
ide_stall_queue(drive, IDECD_SEEK_TIMER); ide_stall_queue(drive, IDECD_SEEK_TIMER);
return ide_stopped; return ide_stopped;
} }
...@@ -1781,14 +1835,14 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) ...@@ -1781,14 +1835,14 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
return action; return action;
} else if (rq->flags & (REQ_PC | REQ_SENSE)) { } else if (rq->flags & (REQ_PC | REQ_SENSE)) {
return cdrom_do_packet_command(drive); 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) { } else if (rq->flags & REQ_SPECIAL) {
/* /*
* right now this can only be a reset... * right now this can only be a reset...
*/ */
cdrom_end_request(drive, 1); cdrom_end_request(drive, 1);
return ide_stopped; 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"); blk_dump_rq_flags(rq, "ide-cd bad flags");
...@@ -1853,23 +1907,23 @@ int msf_to_lba (byte m, byte s, byte f) ...@@ -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) 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_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo; struct cdrom_device_info *cdi = &info->devinfo;
memset(&pc, 0, sizeof(pc)); cdrom_prepare_request(&req);
pc.sense = sense;
pc.c[0] = GPCMD_TEST_UNIT_READY; req.sense = sense;
req.cmd[0] = GPCMD_TEST_UNIT_READY;
#if ! STANDARD_ATAPI #if ! STANDARD_ATAPI
/* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
switch CDs instead of supporting the LOAD_UNLOAD opcode */ 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 */ #endif /* not STANDARD_ATAPI */
return cdrom_queue_packet_command(drive, &pc); return cdrom_queue_packet_command(drive, &req);
} }
...@@ -1878,7 +1932,7 @@ static int ...@@ -1878,7 +1932,7 @@ static int
cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense) cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
{ {
struct request_sense my_sense; struct request_sense my_sense;
struct packet_command pc; struct request req;
int stat; int stat;
if (sense == NULL) if (sense == NULL)
...@@ -1888,11 +1942,11 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense) ...@@ -1888,11 +1942,11 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) { if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
stat = 0; stat = 0;
} else { } else {
memset(&pc, 0, sizeof(pc)); cdrom_prepare_request(&req);
pc.sense = sense; req.sense = sense;
pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
pc.c[4] = lockflag ? 1 : 0; req.cmd[4] = lockflag ? 1 : 0;
stat = cdrom_queue_packet_command(drive, &pc); stat = cdrom_queue_packet_command(drive, &req);
} }
/* If we got an illegal field error, the drive /* 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) ...@@ -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, static int cdrom_eject(ide_drive_t *drive, int ejectflag,
struct request_sense *sense) struct request_sense *sense)
{ {
struct packet_command pc; struct request req;
if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag) if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)
return -EDRIVE_CANT_DO_THIS; return -EDRIVE_CANT_DO_THIS;
...@@ -1931,12 +1985,12 @@ static int cdrom_eject(ide_drive_t *drive, int ejectflag, ...@@ -1931,12 +1985,12 @@ static int cdrom_eject(ide_drive_t *drive, int ejectflag,
if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag) if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
return 0; return 0;
memset(&pc, 0, sizeof (pc)); cdrom_prepare_request(&req);
pc.sense = sense;
pc.c[0] = GPCMD_START_STOP_UNIT; req.sense = sense;
pc.c[4] = 0x02 + (ejectflag != 0); req.cmd[0] = GPCMD_START_STOP_UNIT;
return cdrom_queue_packet_command(drive, &pc); 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, 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, ...@@ -1948,16 +2002,16 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
} capbuf; } capbuf;
int stat; int stat;
struct packet_command pc; struct request req;
memset(&pc, 0, sizeof(pc)); cdrom_prepare_request(&req);
pc.sense = sense;
pc.c[0] = GPCMD_READ_CDVD_CAPACITY; req.sense = sense;
pc.buffer = (char *)&capbuf; req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
pc.buflen = sizeof(capbuf); 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) if (stat == 0)
*capacity = 1 + be32_to_cpu(capbuf.lba); *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, ...@@ -1968,24 +2022,24 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
int format, char *buf, int buflen, int format, char *buf, int buflen,
struct request_sense *sense) struct request_sense *sense)
{ {
struct packet_command pc; struct request req;
memset(&pc, 0, sizeof(pc)); cdrom_prepare_request(&req);
pc.sense = sense;
pc.buffer = buf; req.sense = sense;
pc.buflen = buflen; req.data = buf;
pc.quiet = 1; req.data_len = buflen;
pc.c[0] = GPCMD_READ_TOC_PMA_ATIP; req.flags |= REQ_QUIET;
pc.c[6] = trackno; req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
pc.c[7] = (buflen >> 8); req.cmd[6] = trackno;
pc.c[8] = (buflen & 0xff); req.cmd[7] = (buflen >> 8);
pc.c[9] = (format << 6); req.cmd[8] = (buflen & 0xff);
req.cmd[9] = (format << 6);
if (msf_flag) 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) ...@@ -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, static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
int buflen, struct request_sense *sense) int buflen, struct request_sense *sense)
{ {
struct packet_command pc; struct request req;
memset(&pc, 0, sizeof(pc)); cdrom_prepare_request(&req);
pc.sense = sense;
pc.buffer = buf; req.sense = sense;
pc.buflen = buflen; req.data = buf;
pc.c[0] = GPCMD_READ_SUBCHANNEL; req.data_len = buflen;
pc.c[1] = 2; /* MSF addressing */ req.cmd[0] = GPCMD_READ_SUBCHANNEL;
pc.c[2] = 0x40; /* request subQ data */ req.cmd[1] = 2; /* MSF addressing */
pc.c[3] = format; req.cmd[2] = 0x40; /* request subQ data */
pc.c[7] = (buflen >> 8); req.cmd[3] = format;
pc.c[8] = (buflen & 0xff); req.cmd[7] = (buflen >> 8);
return cdrom_queue_packet_command(drive, &pc); 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 /* 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, ...@@ -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, static int cdrom_select_speed(ide_drive_t *drive, int speed,
struct request_sense *sense) struct request_sense *sense)
{ {
struct packet_command pc; struct request req;
memset(&pc, 0, sizeof(pc)); cdrom_prepare_request(&req);
pc.sense = sense;
req.sense = sense;
if (speed == 0) if (speed == 0)
speed = 0xffff; /* set to max */ speed = 0xffff; /* set to max */
else else
speed *= 177; /* Nx to kbytes/s */ 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 */ /* 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 */ /* Read Drive speed in kbytes/second LSB */
pc.c[3] = speed & 0xff; req.cmd[3] = speed & 0xff;
if (CDROM_CONFIG_FLAGS(drive)->cd_r || if (CDROM_CONFIG_FLAGS(drive)->cd_r ||
CDROM_CONFIG_FLAGS(drive)->cd_rw || CDROM_CONFIG_FLAGS(drive)->cd_rw ||
CDROM_CONFIG_FLAGS(drive)->dvd_r) { CDROM_CONFIG_FLAGS(drive)->dvd_r) {
/* Write Drive speed in kbytes/second MSB */ /* 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 */ /* 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) static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
{ {
struct request_sense sense; struct request_sense sense;
struct packet_command pc; struct request req;
memset(&pc, 0, sizeof (pc)); cdrom_prepare_request(&req);
pc.sense = &sense;
pc.c[0] = GPCMD_PLAY_AUDIO_MSF; req.sense = &sense;
lba_to_msf(lba_start, &pc.c[3], &pc.c[4], &pc.c[5]); req.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
lba_to_msf(lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]); 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, 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, ...@@ -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, static int ide_cdrom_packet(struct cdrom_device_info *cdi,
struct cdrom_generic_command *cgc) struct cdrom_generic_command *cgc)
{ {
struct packet_command pc; struct request req;
ide_drive_t *drive = (ide_drive_t*) cdi->handle; ide_drive_t *drive = (ide_drive_t*) cdi->handle;
if (cgc->timeout <= 0) if (cgc->timeout <= 0)
...@@ -2246,18 +2300,21 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi, ...@@ -2246,18 +2300,21 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
/* here we queue the commands from the uniform CD-ROM /* here we queue the commands from the uniform CD-ROM
layer. the packet must be complete, as we do not layer. the packet must be complete, as we do not
touch it at all. */ touch it at all. */
memset(&pc, 0, sizeof(pc)); cdrom_prepare_request(&req);
memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE); memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
if (cgc->sense) if (cgc->sense)
memset(cgc->sense, 0, sizeof(struct request_sense)); memset(cgc->sense, 0, sizeof(struct request_sense));
pc.buffer = cgc->buffer; req.data = cgc->buffer;
pc.buflen = cgc->buflen; req.data_len = cgc->buflen;
pc.quiet = cgc->quiet; req.timeout = cgc->timeout;
pc.timeout = cgc->timeout;
pc.sense = cgc->sense; if (cgc->quiet)
cgc->stat = cdrom_queue_packet_command(drive, &pc); req.flags |= REQ_QUIET;
req.sense = cgc->sense;
cgc->stat = cdrom_queue_packet_command(drive, &req);
if (!cgc->stat) if (!cgc->stat)
cgc->buflen -= pc.buflen; cgc->buflen -= req.data_len;
return cgc->stat; return cgc->stat;
} }
...@@ -2393,7 +2450,7 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi) ...@@ -2393,7 +2450,7 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi)
struct request req; struct request req;
int ret; int ret;
ide_init_drive_cmd (&req); cdrom_prepare_request(&req);
req.flags = REQ_SPECIAL; req.flags = REQ_SPECIAL;
ret = ide_do_drive_cmd(drive, &req, ide_wait); ret = ide_do_drive_cmd(drive, &req, ide_wait);
...@@ -2969,6 +3026,14 @@ int ide_cdrom_ioctl (ide_drive_t *drive, ...@@ -2969,6 +3026,14 @@ int ide_cdrom_ioctl (ide_drive_t *drive,
struct inode *inode, struct file *file, struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) 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); return cdrom_ioctl(inode, file, cmd, arg);
} }
......
...@@ -105,13 +105,6 @@ struct ide_cd_state_flags { ...@@ -105,13 +105,6 @@ struct ide_cd_state_flags {
#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags)) #define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
struct packet_command { 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. */ /* Structure of a MSF cdrom address. */
......
...@@ -2639,7 +2639,7 @@ static int ide_ioctl (struct inode *inode, struct file *file, ...@@ -2639,7 +2639,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case CDROMEJECT: case CDROMEJECT:
case CDROMCLOSETRAY: case CDROMCLOSETRAY:
return block_ioctl(inode->i_bdev, cmd, arg); return scsi_cmd_ioctl(inode->i_bdev, cmd, arg);
case HDIO_GET_BUSSTATE: case HDIO_GET_BUSSTATE:
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
......
...@@ -824,44 +824,9 @@ static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, ...@@ -824,44 +824,9 @@ static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
unsigned long arg) unsigned long arg)
{ {
struct block_device *bdev = inode->i_bdev; struct block_device *bdev = inode->i_bdev;
int ret = -EINVAL; int ret = blk_ioctl(bdev, cmd, arg);
switch (cmd) { if (ret == -ENOTTY && bdev->bd_op->ioctl)
/* ret = bdev->bd_op->ioctl(inode, file, cmd, arg);
* 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;
}
}
}
return ret; return ret;
} }
......
...@@ -60,6 +60,12 @@ struct request { ...@@ -60,6 +60,12 @@ struct request {
int tag; int tag;
void *special; void *special;
char *buffer; char *buffer;
/* For packet commands */
unsigned int data_len;
void *data, *sense;
unsigned int timeout;
struct completion *waiting; struct completion *waiting;
struct bio *bio, *biotail; struct bio *bio, *biotail;
request_queue_t *q; request_queue_t *q;
...@@ -85,6 +91,8 @@ enum rq_flag_bits { ...@@ -85,6 +91,8 @@ enum rq_flag_bits {
__REQ_BLOCK_PC, /* queued down pc from block layer */ __REQ_BLOCK_PC, /* queued down pc from block layer */
__REQ_SENSE, /* sense retrival */ __REQ_SENSE, /* sense retrival */
__REQ_FAILED, /* set if the request failed */
__REQ_QUIET, /* don't worry about errors */
__REQ_SPECIAL, /* driver suplied command */ __REQ_SPECIAL, /* driver suplied command */
__REQ_DRIVE_CMD, __REQ_DRIVE_CMD,
__REQ_DRIVE_TASK, __REQ_DRIVE_TASK,
...@@ -103,6 +111,8 @@ enum rq_flag_bits { ...@@ -103,6 +111,8 @@ enum rq_flag_bits {
#define REQ_PC (1 << __REQ_PC) #define REQ_PC (1 << __REQ_PC)
#define REQ_BLOCK_PC (1 << __REQ_BLOCK_PC) #define REQ_BLOCK_PC (1 << __REQ_BLOCK_PC)
#define REQ_SENSE (1 << __REQ_SENSE) #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_SPECIAL (1 << __REQ_SPECIAL)
#define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD) #define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD)
#define REQ_DRIVE_TASK (1 << __REQ_DRIVE_TASK) #define REQ_DRIVE_TASK (1 << __REQ_DRIVE_TASK)
...@@ -301,7 +311,7 @@ extern int blk_remove_plug(request_queue_t *); ...@@ -301,7 +311,7 @@ extern int blk_remove_plug(request_queue_t *);
extern void blk_recount_segments(request_queue_t *, struct bio *); 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_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 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_start_queue(request_queue_t *q);
extern void blk_stop_queue(request_queue_t *q); extern void blk_stop_queue(request_queue_t *q);
extern void __blk_stop_queue(request_queue_t *q); extern void __blk_stop_queue(request_queue_t *q);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment