summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@tove.transmeta.com>2002-10-14 21:53:34 -0700
committerLinus Torvalds <torvalds@tove.transmeta.com>2002-10-14 21:53:34 -0700
commitde224587e2b11ebb2ca867842251d61790b09c8c (patch)
tree1ee1533cffffe66bb8319ea5a03882c25e252bf9
parent138753d72c79ad1db4cdae80dce0820f43ec23dc (diff)
Remove ide-cd reliance on "struct packet_struct", make it use
the native "struct request" fields instead. Simplify and clean up sense data handling. This makes IDE CD-RW burning possible without ide-scsi.c
-rw-r--r--drivers/ide/ide-cd.c431
-rw-r--r--drivers/ide/ide-cd.h7
2 files changed, 248 insertions, 190 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 012381dd73d9..8bb068c7755f 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -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->cmd[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->cmd[0]) {
s = packet_command_texts[mid].text;
break;
}
if (packet_command_texts[mid].packet_command >
- failed_command->c[0])
+ failed_command->cmd[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->cmd); i++)
+ printk ("%02x ", failed_command->cmd[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->buflen > 0 &&
- pc->buflen <= 5) {
- while (pc->buflen > 0) {
- *pc->buffer++ = 0;
- --pc->buflen;
+ 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->buflen == 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->buflen;
+ 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->buflen -= 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->buflen -= 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->buflen;
+ 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 elpased = jiffies - info->start_seek;
+ unsigned long elapsed = jiffies - info->start_seek;
int stat = HWIF(drive)->INB(IDE_STATUS_REG);
if ((stat & SEEK_STAT) != SEEK_STAT) {
- if (elpased < IDECD_SEEK_TIMEOUT) {
+ if (elapsed < 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.buflen;
+ 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);
}
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 2455e002bfad..1126c6824bef 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -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. */