aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-cd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-cd.c')
-rw-r--r--drivers/ide/ide-cd.c474
1 files changed, 241 insertions, 233 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 68e7f19dc036..e617cf08aef6 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -57,23 +57,29 @@ static DEFINE_MUTEX(idecd_ref_mutex);
#define ide_cd_g(disk) \
container_of((disk)->private_data, struct cdrom_info, driver)
+static void ide_cd_release(struct kref *);
+
static struct cdrom_info *ide_cd_get(struct gendisk *disk)
{
struct cdrom_info *cd = NULL;
mutex_lock(&idecd_ref_mutex);
cd = ide_cd_g(disk);
- if (cd)
+ if (cd) {
kref_get(&cd->kref);
+ if (ide_device_get(cd->drive)) {
+ kref_put(&cd->kref, ide_cd_release);
+ cd = NULL;
+ }
+ }
mutex_unlock(&idecd_ref_mutex);
return cd;
}
-static void ide_cd_release(struct kref *);
-
static void ide_cd_put(struct cdrom_info *cd)
{
mutex_lock(&idecd_ref_mutex);
+ ide_device_put(cd->drive);
kref_put(&cd->kref, ide_cd_release);
mutex_unlock(&idecd_ref_mutex);
}
@@ -85,10 +91,8 @@ static void ide_cd_put(struct cdrom_info *cd)
/* Mark that we've seen a media change and invalidate our internal buffers. */
static void cdrom_saw_media_change(ide_drive_t *drive)
{
- struct cdrom_info *cd = drive->driver_data;
-
- cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
- cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
+ drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
}
static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
@@ -188,16 +192,6 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
ide_cd_log_error(drive->name, failed_command, sense);
}
-/* Initialize a ide-cd packet command request */
-void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
-{
- struct cdrom_info *cd = drive->driver_data;
-
- ide_init_drive_cmd(rq);
- rq->cmd_type = REQ_TYPE_ATA_PC;
- rq->rq_disk = cd->disk;
-}
-
static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
struct request *failed_command)
{
@@ -208,7 +202,9 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
sense = &info->sense_data;
/* stuff the sense request in front of our current request */
- ide_cd_init_rq(drive, rq);
+ blk_rq_init(NULL, rq);
+ rq->cmd_type = REQ_TYPE_ATA_PC;
+ rq->rq_disk = info->disk;
rq->data = sense;
rq->cmd[0] = GPCMD_REQUEST_SENSE;
@@ -216,11 +212,12 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
rq->data_len = 18;
rq->cmd_type = REQ_TYPE_SENSE;
+ rq->cmd_flags |= REQ_PREEMPT;
/* NOTE! Save the failed command in "rq->buffer" */
rq->buffer = (void *) failed_command;
- (void) ide_do_drive_cmd(drive, rq, ide_preempt);
+ ide_do_drive_cmd(drive, rq);
}
static void cdrom_end_request(ide_drive_t *drive, int uptodate)
@@ -287,11 +284,12 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
*/
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
- struct request *rq = HWGROUP(drive)->rq;
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
int stat, err, sense_key;
/* check for errors */
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat_ret)
*stat_ret = stat;
@@ -524,23 +522,18 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
int xferlen,
ide_handler_t *handler)
{
- ide_startstop_t startstop;
struct cdrom_info *info = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
- /* wait for the controller to be idle */
- if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
- return startstop;
-
/* FIXME: for Virtual DMA we must check harder */
if (info->dma)
info->dma = !hwif->dma_ops->dma_setup(drive);
/* set up the controller registers */
- ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
- IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
+ ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
+ xferlen, info->dma);
- if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/* waiting for CDB interrupt, not DMA yet. */
if (info->dma)
drive->waiting_for_dma = 0;
@@ -572,7 +565,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
struct cdrom_info *info = drive->driver_data;
ide_startstop_t startstop;
- if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/*
* Here we should have been called after receiving an interrupt
* from the device. DRQ should how be set.
@@ -601,7 +594,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
cmd_len = ATAPI_MIN_CDB_BYTES;
/* send the command to the device */
- hwif->output_data(drive, NULL, rq->cmd, cmd_len);
+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
/* start the DMA if need be */
if (info->dma)
@@ -611,28 +604,6 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
}
/*
- * Block read functions.
- */
-static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
-{
- while (len > 0) {
- int dum = 0;
- xf(drive, NULL, &dum, sizeof(dum));
- len -= sizeof(dum);
- }
-}
-
-static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
-{
- while (nsects > 0) {
- static char dum[SECTOR_SIZE];
-
- drive->hwif->input_data(drive, NULL, dum, sizeof(dum));
- nsects--;
- }
-}
-
-/*
* Check the contents of the interrupt reason register from the cdrom
* and attempt to recover if there are problems. Returns 0 if everything's
* ok; nonzero if the request has been terminated.
@@ -640,6 +611,8 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
int len, int ireason, int rw)
{
+ ide_hwif_t *hwif = drive->hwif;
+
/*
* ireason == 0: the drive wants to receive data from us
* ireason == 2: the drive is expecting to transfer data to us
@@ -647,21 +620,18 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
if (ireason == (!rw << 1))
return 0;
else if (ireason == (rw << 1)) {
- ide_hwif_t *hwif = drive->hwif;
- xfer_func_t *xf;
/* whoops... */
printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
drive->name, __func__);
- xf = rw ? hwif->output_data : hwif->input_data;
- ide_cd_pad_transfer(drive, xf, len);
+ ide_pad_transfer(drive, rw, len);
} else if (rw == 0 && ireason == 1) {
/*
* Some drives (ASUS) seem to tell us that status info is
* available. Just get it and ignore.
*/
- (void)ide_read_status(drive);
+ (void)hwif->tp_ops->read_status(hwif);
return 0;
} else {
/* drive wants a command packet, or invalid ireason... */
@@ -682,20 +652,18 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
*/
static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
{
- struct cdrom_info *cd = drive->driver_data;
-
if ((len % SECTOR_SIZE) == 0)
return 0;
printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
drive->name, __func__, len);
- if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
+ if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
printk(KERN_ERR " This drive is not supported by "
"this version of the driver\n");
else {
printk(KERN_ERR " Trying to limit transfer sizes\n");
- cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
+ drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
}
return 1;
@@ -703,16 +671,9 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
-/*
- * Routine to send a read/write packet command to the drive. This is usually
- * called directly from cdrom_start_{read,write}(). However, for drq_interrupt
- * devices, it is called from an interrupt when the drive is ready to accept
- * the command.
- */
-static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
+ struct request *rq)
{
- struct request *rq = HWGROUP(drive)->rq;
-
if (rq_data_dir(rq) == READ) {
unsigned short sectors_per_frame =
queue_hardsect_size(drive->queue) >> SECTOR_BITS;
@@ -749,6 +710,19 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
/* set up the command */
rq->timeout = ATAPI_WAIT_PC;
+ return ide_started;
+}
+
+/*
+ * Routine to send a read/write packet command to the drive. This is usually
+ * called directly from cdrom_start_{read,write}(). However, for drq_interrupt
+ * devices, it is called from an interrupt when the drive is ready to accept
+ * the command.
+ */
+static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+{
+ struct request *rq = drive->hwif->hwgroup->rq;
+
/* send the command to the drive and return */
return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
@@ -766,7 +740,7 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
if (cdrom_decode_status(drive, 0, &stat))
return ide_stopped;
- info->cd_flags |= IDE_CD_FLAG_SEEKING;
+ drive->atapi_flags |= IDE_AFLAG_SEEKING;
if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
if (--retry == 0)
@@ -775,9 +749,8 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
return ide_stopped;
}
-static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
+static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq)
{
- struct request *rq = HWGROUP(drive)->rq;
sector_t frame = rq->sector;
sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
@@ -787,17 +760,13 @@ static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
rq->timeout = ATAPI_WAIT_PC;
- 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_continuation(ide_drive_t *drive)
{
- struct cdrom_info *info = drive->driver_data;
+ struct request *rq = drive->hwif->hwgroup->rq;
- info->dma = 0;
- info->start_seek = jiffies;
- return cdrom_start_packet_command(drive, 0,
- cdrom_start_seek_continuation);
+ return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
}
/*
@@ -838,34 +807,54 @@ static void ide_cd_request_sense_fixup(struct request *rq)
}
}
-int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
+int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
+ int write, void *buffer, unsigned *bufflen,
+ struct request_sense *sense, int timeout,
+ unsigned int cmd_flags)
{
- struct request_sense sense;
+ struct cdrom_info *info = drive->driver_data;
+ struct request_sense local_sense;
int retries = 10;
- unsigned int flags = rq->cmd_flags;
+ unsigned int flags = 0;
- if (rq->sense == NULL)
- rq->sense = &sense;
+ if (!sense)
+ sense = &local_sense;
/* start of retry loop */
do {
+ struct request *rq;
int error;
- unsigned long time = jiffies;
- rq->cmd_flags = flags;
- error = ide_do_drive_cmd(drive, rq, ide_wait);
- time = jiffies - time;
+ rq = blk_get_request(drive->queue, write, __GFP_WAIT);
+
+ memcpy(rq->cmd, cmd, BLK_MAX_CDB);
+ rq->cmd_type = REQ_TYPE_ATA_PC;
+ rq->sense = sense;
+ rq->cmd_flags |= cmd_flags;
+ rq->timeout = timeout;
+ if (buffer) {
+ rq->data = buffer;
+ rq->data_len = *bufflen;
+ }
+
+ error = blk_execute_rq(drive->queue, info->disk, rq, 0);
+
+ if (buffer)
+ *bufflen = rq->data_len;
+
+ flags = rq->cmd_flags;
+ blk_put_request(rq);
/*
* FIXME: we should probably abort/retry or something in case of
* failure.
*/
- if (rq->cmd_flags & REQ_FAILED) {
+ if (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 = rq->sense;
+ struct request_sense *reqbuf = sense;
if (reqbuf->sense_key == UNIT_ATTENTION)
cdrom_saw_media_change(drive);
@@ -885,10 +874,10 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
}
/* end of retry loop */
- } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
+ } while ((flags & REQ_FAILED) && retries >= 0);
/* return an error if the command failed */
- return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
+ return (flags & REQ_FAILED) ? -EIO : 0;
}
/*
@@ -908,10 +897,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
struct request *rq = HWGROUP(drive)->rq;
xfer_func_t *xferfunc;
ide_expiry_t *expiry = NULL;
- int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
+ int dma_error = 0, dma, stat, thislen, uptodate = 0;
int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
unsigned int timeout;
- u8 lowcyl, highcyl;
+ u16 len;
+ u8 ireason;
/* check for errors */
dma = info->dma;
@@ -939,12 +929,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
goto end_request;
}
- /* ok we fall to pio :/ */
- ireason = hwif->INB(hwif->io_ports.nsect_addr) & 0x3;
- lowcyl = hwif->INB(hwif->io_ports.lbam_addr);
- highcyl = hwif->INB(hwif->io_ports.lbah_addr);
-
- len = lowcyl + (256 * highcyl);
+ ide_read_bcount_and_ireason(drive, &len, &ireason);
thislen = blk_fs_request(rq) ? len : rq->data_len;
if (thislen > len)
@@ -998,7 +983,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
- bio_cur_sectors(rq->bio),
thislen >> 9);
if (nskip > 0) {
- ide_cd_drain_data(drive, nskip);
+ ide_pad_transfer(drive, write, nskip << 9);
rq->current_nr_sectors -= nskip;
thislen -= (nskip << 9);
}
@@ -1007,10 +992,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (ireason == 0) {
write = 1;
- xferfunc = hwif->output_data;
+ xferfunc = hwif->tp_ops->output_data;
} else {
write = 0;
- xferfunc = hwif->input_data;
+ xferfunc = hwif->tp_ops->input_data;
}
/* transfer data */
@@ -1035,7 +1020,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
* If the buffers are full, pipe the rest into
* oblivion.
*/
- ide_cd_drain_data(drive, thislen >> 9);
+ ide_pad_transfer(drive, 0, thislen);
else {
printk(KERN_ERR "%s: confused, missing data\n",
drive->name);
@@ -1083,7 +1068,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
/* pad, if necessary */
if (!blk_fs_request(rq) && len > 0)
- ide_cd_pad_transfer(drive, xferfunc, len);
+ ide_pad_transfer(drive, write, len);
if (blk_pc_request(rq)) {
timeout = rq->timeout;
@@ -1152,21 +1137,17 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
if (write)
cd->devinfo.media_written = 1;
- /* start sending the read/write request to the drive */
- return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
+ return ide_started;
}
static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
- if (!rq->timeout)
- rq->timeout = ATAPI_WAIT_PC;
-
return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
-static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
struct cdrom_info *info = drive->driver_data;
@@ -1178,10 +1159,16 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
info->dma = 0;
/* sg request */
- if (rq->bio) {
- int mask = drive->queue->dma_alignment;
- unsigned long addr =
- (unsigned long)page_address(bio_page(rq->bio));
+ if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
+ struct request_queue *q = drive->queue;
+ unsigned int alignment;
+ unsigned long addr;
+ unsigned long stack_mask = ~(THREAD_SIZE - 1);
+
+ if (rq->bio)
+ addr = (unsigned long)bio_data(rq->bio);
+ else
+ addr = (unsigned long)rq->data;
info->dma = drive->using_dma;
@@ -1191,28 +1178,31 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
* NOTE! The "len" and "addr" checks should possibly have
* separate masks.
*/
- if ((rq->data_len & 15) || (addr & mask))
+ alignment = queue_dma_alignment(q) | q->dma_pad_mask;
+ if (addr & alignment || rq->data_len & alignment)
info->dma = 0;
- }
- /* start sending the command to the drive */
- return cdrom_start_packet_command(drive, rq->data_len,
- cdrom_do_newpc_cont);
+ if (!((addr & stack_mask) ^
+ ((unsigned long)current->stack & stack_mask)))
+ info->dma = 0;
+ }
}
/*
* cdrom driver request routine.
*/
-static ide_startstop_t ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq,
+static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
sector_t block)
{
- ide_startstop_t action;
struct cdrom_info *info = drive->driver_data;
+ ide_handler_t *fn;
+ int xferlen;
if (blk_fs_request(rq)) {
- if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
+ if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
+ ide_hwif_t *hwif = drive->hwif;
unsigned long elapsed = jiffies - info->start_seek;
- int stat = ide_read_status(drive);
+ int stat = hwif->tp_ops->read_status(hwif);
if ((stat & SEEK_STAT) != SEEK_STAT) {
if (elapsed < IDECD_SEEK_TIMEOUT) {
@@ -1223,33 +1213,52 @@ static ide_startstop_t ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq,
printk(KERN_ERR "%s: DSC timeout\n",
drive->name);
}
- info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
+ drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
}
if (rq_data_dir(rq) == READ &&
IDE_LARGE_SEEK(info->last_block, block,
- IDECD_SEEK_THRESHOLD) &&
- drive->dsc_overlap)
- action = cdrom_start_seek(drive, block);
- else
- action = cdrom_start_rw(drive, rq);
+ IDECD_SEEK_THRESHOLD) &&
+ drive->dsc_overlap) {
+ xferlen = 0;
+ fn = cdrom_start_seek_continuation;
+
+ info->dma = 0;
+ info->start_seek = jiffies;
+
+ ide_cd_prepare_seek_request(drive, rq);
+ } else {
+ xferlen = 32768;
+ fn = cdrom_start_rw_cont;
+
+ if (cdrom_start_rw(drive, rq) == ide_stopped)
+ return ide_stopped;
+
+ if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped)
+ return ide_stopped;
+ }
info->last_block = block;
- return action;
} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
rq->cmd_type == REQ_TYPE_ATA_PC) {
- return cdrom_do_block_pc(drive, rq);
+ xferlen = rq->data_len;
+ fn = cdrom_do_newpc_cont;
+
+ if (!rq->timeout)
+ rq->timeout = ATAPI_WAIT_PC;
+
+ cdrom_do_block_pc(drive, rq);
} else if (blk_special_request(rq)) {
/* right now this can only be a reset... */
cdrom_end_request(drive, 1);
return ide_stopped;
+ } else {
+ blk_dump_rq_flags(rq, "ide-cd bad flags");
+ cdrom_end_request(drive, 0);
+ return ide_stopped;
}
- blk_dump_rq_flags(rq, "ide-cd bad flags");
- cdrom_end_request(drive, 0);
- return ide_stopped;
+ return cdrom_start_packet_command(drive, xferlen, fn);
}
-
-
/*
* Ioctl handling.
*
@@ -1268,23 +1277,20 @@ static void msf_from_bcd(struct atapi_msf *msf)
int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
{
- struct request req;
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
+ unsigned char cmd[BLK_MAX_CDB];
- ide_cd_init_rq(drive, &req);
-
- req.sense = sense;
- req.cmd[0] = GPCMD_TEST_UNIT_READY;
- req.cmd_flags |= REQ_QUIET;
+ memset(cmd, 0, BLK_MAX_CDB);
+ cmd[0] = GPCMD_TEST_UNIT_READY;
/*
* Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to switch CDs
* instead of supporting the LOAD_UNLOAD opcode.
*/
- req.cmd[7] = cdi->sanyo_slot % 3;
+ cmd[7] = cdi->sanyo_slot % 3;
- return ide_cd_queue_pc(drive, &req);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET);
}
static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
@@ -1292,53 +1298,63 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
struct request_sense *sense)
{
struct {
- __u32 lba;
- __u32 blocklen;
+ __be32 lba;
+ __be32 blocklen;
} capbuf;
int stat;
- struct request req;
+ unsigned char cmd[BLK_MAX_CDB];
+ unsigned len = sizeof(capbuf);
- ide_cd_init_rq(drive, &req);
+ memset(cmd, 0, BLK_MAX_CDB);
+ cmd[0] = GPCMD_READ_CDVD_CAPACITY;
- req.sense = sense;
- req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
- req.data = (char *)&capbuf;
- req.data_len = sizeof(capbuf);
- req.cmd_flags |= REQ_QUIET;
+ stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0,
+ REQ_QUIET);
+ if (stat)
+ return stat;
- stat = ide_cd_queue_pc(drive, &req);
- if (stat == 0) {
- *capacity = 1 + be32_to_cpu(capbuf.lba);
- *sectors_per_frame =
- be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
+ /*
+ * Sanity check the given block size
+ */
+ switch (capbuf.blocklen) {
+ case __constant_cpu_to_be32(512):
+ case __constant_cpu_to_be32(1024):
+ case __constant_cpu_to_be32(2048):
+ case __constant_cpu_to_be32(4096):
+ break;
+ default:
+ printk(KERN_ERR "%s: weird block size %u\n",
+ drive->name, capbuf.blocklen);
+ printk(KERN_ERR "%s: default to 2kb block size\n",
+ drive->name);
+ capbuf.blocklen = __constant_cpu_to_be32(2048);
+ break;
}
- return stat;
+ *capacity = 1 + be32_to_cpu(capbuf.lba);
+ *sectors_per_frame = be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
+ return 0;
}
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 request req;
+ unsigned char cmd[BLK_MAX_CDB];
- ide_cd_init_rq(drive, &req);
+ memset(cmd, 0, BLK_MAX_CDB);
- req.sense = sense;
- req.data = buf;
- req.data_len = buflen;
- req.cmd_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);
+ cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+ cmd[6] = trackno;
+ cmd[7] = (buflen >> 8);
+ cmd[8] = (buflen & 0xff);
+ cmd[9] = (format << 6);
if (msf_flag)
- req.cmd[1] = 2;
+ cmd[1] = 2;
- return ide_cd_queue_pc(drive, &req);
+ return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, REQ_QUIET);
}
/* Try to read the entire TOC for the disk into our internal buffer. */
@@ -1372,7 +1388,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
*/
(void) cdrom_check_status(drive, sense);
- if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
+ if (drive->atapi_flags & IDE_AFLAG_TOC_VALID)
return 0;
/* try to get the total cdrom capacity and sector size */
@@ -1394,7 +1410,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
return stat;
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
}
@@ -1435,7 +1451,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
return stat;
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
} else {
@@ -1449,14 +1465,14 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->hdr.toc_length = be16_to_cpu(toc->hdr.toc_length);
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
}
for (i = 0; i <= ntracks; i++) {
- if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
+ if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD)
toc->ent[i].track = BCD2BIN(toc->ent[i].track);
msf_from_bcd(&toc->ent[i].addr.msf);
}
@@ -1479,7 +1495,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
}
- if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
/* re-read multisession information using MSF format */
stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
sizeof(ms_tmp), sense);
@@ -1503,7 +1519,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
}
/* Remember that we've read this stuff. */
- info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags |= IDE_AFLAG_TOC_VALID;
return 0;
}
@@ -1515,7 +1531,7 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
struct packet_command cgc;
int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
- if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
+ if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
@@ -1533,15 +1549,12 @@ void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
struct cdrom_info *cd = drive->driver_data;
u16 curspeed, maxspeed;
- curspeed = *(u16 *)&buf[8 + 14];
- maxspeed = *(u16 *)&buf[8 + 8];
-
- if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
- curspeed = le16_to_cpu(curspeed);
- maxspeed = le16_to_cpu(maxspeed);
+ if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
+ curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
+ maxspeed = le16_to_cpup((__le16 *)&buf[8 + 8]);
} else {
- curspeed = be16_to_cpu(curspeed);
- maxspeed = be16_to_cpu(maxspeed);
+ curspeed = be16_to_cpup((__be16 *)&buf[8 + 14]);
+ maxspeed = be16_to_cpup((__be16 *)&buf[8 + 8]);
}
cd->current_speed = (curspeed + (176/2)) / 176;
@@ -1582,7 +1595,7 @@ static int ide_cdrom_register(ide_drive_t *drive, int nslots)
devinfo->handle = drive;
strcpy(devinfo->name, drive->name);
- if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
+ if (drive->atapi_flags & IDE_AFLAG_NO_SPEED_SELECT)
devinfo->mask |= CDC_SELECT_SPEED;
devinfo->disk = info->disk;
@@ -1608,8 +1621,8 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
return nslots;
}
- if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
- cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ if (drive->atapi_flags & IDE_AFLAG_PRE_ATAPI12) {
+ drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
cdi->mask &= ~CDC_PLAY_AUDIO;
return nslots;
}
@@ -1627,9 +1640,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
return 0;
if ((buf[8 + 6] & 0x01) == 0)
- cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
if (buf[8 + 6] & 0x08)
- cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
if (buf[8 + 3] & 0x01)
cdi->mask &= ~CDC_CD_R;
if (buf[8 + 3] & 0x02)
@@ -1640,7 +1653,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
if (buf[8 + 3] & 0x10)
cdi->mask &= ~CDC_DVD_R;
- if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
+ if ((buf[8 + 4] & 0x01) || (drive->atapi_flags & IDE_AFLAG_PLAY_AUDIO_OK))
cdi->mask &= ~CDC_PLAY_AUDIO;
mechtype = buf[8 + 6] >> 5;
@@ -1682,7 +1695,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
else
printk(KERN_CONT " drive");
- printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
+ printk(KERN_CONT ", %dkB Cache\n", be16_to_cpup((__be16 *)&buf[8 + 12]));
return nslots;
}
@@ -1805,43 +1818,43 @@ static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
static const struct cd_list_entry ide_cd_quirks_list[] = {
/* Limit transfer size per interrupt. */
- { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
- { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
+ { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_AFLAG_LIMIT_NFRAMES },
+ { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_AFLAG_LIMIT_NFRAMES },
/* SCR-3231 doesn't support the SET_CD_SPEED command. */
- { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_CD_FLAG_NO_SPEED_SELECT },
+ { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_AFLAG_NO_SPEED_SELECT },
/* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
- { "NEC CD-ROM DRIVE:260", "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
- IDE_CD_FLAG_PRE_ATAPI12, },
+ { "NEC CD-ROM DRIVE:260", "1.01", IDE_AFLAG_TOCADDR_AS_BCD |
+ IDE_AFLAG_PRE_ATAPI12, },
/* Vertos 300, some versions of this drive like to talk BCD. */
- { "V003S0DS", NULL, IDE_CD_FLAG_VERTOS_300_SSD, },
+ { "V003S0DS", NULL, IDE_AFLAG_VERTOS_300_SSD, },
/* Vertos 600 ESD. */
- { "V006E0DS", NULL, IDE_CD_FLAG_VERTOS_600_ESD, },
+ { "V006E0DS", NULL, IDE_AFLAG_VERTOS_600_ESD, },
/*
* Sanyo 3 CD changer uses a non-standard command for CD changing
* (by default standard ATAPI support for CD changers is used).
*/
- { "CD-ROM CDR-C3 G", NULL, IDE_CD_FLAG_SANYO_3CD },
- { "CD-ROM CDR-C3G", NULL, IDE_CD_FLAG_SANYO_3CD },
- { "CD-ROM CDR_C36", NULL, IDE_CD_FLAG_SANYO_3CD },
+ { "CD-ROM CDR-C3 G", NULL, IDE_AFLAG_SANYO_3CD },
+ { "CD-ROM CDR-C3G", NULL, IDE_AFLAG_SANYO_3CD },
+ { "CD-ROM CDR_C36", NULL, IDE_AFLAG_SANYO_3CD },
/* Stingray 8X CD-ROM. */
- { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
+ { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_AFLAG_PRE_ATAPI12 },
/*
* ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
* mode sense page capabilities size, but older drives break.
*/
- { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
- { "WPI CDS-32X", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
+ { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_AFLAG_FULL_CAPS_PAGE },
+ { "WPI CDS-32X", NULL, IDE_AFLAG_FULL_CAPS_PAGE },
/* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
- { "", "241N", IDE_CD_FLAG_LE_SPEED_FIELDS },
+ { "", "241N", IDE_AFLAG_LE_SPEED_FIELDS },
/*
* Some drives used by Apple don't advertise audio play
* but they do support reading TOC & audio datas.
*/
- { "MATSHITADVD-ROM SR-8187", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "MATSHITADVD-ROM SR-8186", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "MATSHITADVD-ROM SR-8176", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "MATSHITADVD-ROM SR-8174", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "Optiarc DVD RW AD-5200A", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8187", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8186", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8176", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8174", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
{ NULL, NULL, 0 }
};
@@ -1869,26 +1882,27 @@ static int ide_cdrom_setup(ide_drive_t *drive)
blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
blk_queue_dma_alignment(drive->queue, 31);
+ blk_queue_update_dma_pad(drive->queue, 15);
drive->queue->unplug_delay = (1 * HZ) / 1000;
if (!drive->queue->unplug_delay)
drive->queue->unplug_delay = 1;
drive->special.all = 0;
- cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
+ drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
ide_cd_flags(id);
if ((id->config & 0x0060) == 0x20)
- cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
- if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
+ if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
- cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
- IDE_CD_FLAG_TOCADDR_AS_BCD);
- else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
+ drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
+ IDE_AFLAG_TOCADDR_AS_BCD);
+ else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) &&
id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
- cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
- else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
+ drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD;
+ else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD)
/* 3 => use CD in slot 0 */
cdi->sanyo_slot = 3;
@@ -1951,10 +1965,9 @@ static ide_driver_t ide_cdrom_driver = {
.version = IDECD_VERSION,
.media = ide_cdrom,
.supports_dsc_overlap = 1,
- .do_request = ide_do_rw_cdrom,
+ .do_request = ide_cd_do_request,
.end_request = ide_end_request,
.error = __ide_error,
- .abort = __ide_abort,
#ifdef CONFIG_IDE_PROC_FS
.proc = idecd_proc,
#endif
@@ -2103,11 +2116,6 @@ static int ide_cd_probe(ide_drive_t *drive)
goto failed;
}
}
- if (drive->scsi) {
- printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi "
- "emulation.\n", drive->name);
- goto failed;
- }
info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
printk(KERN_ERR "%s: Can't allocate a cdrom structure\n",