[PATCH] libertas: remove adapter->nullpktinterval
[safe/jmp/linux-2.6] / drivers / ide / ide-cd.c
index 74d2ab0..ca84352 100644 (file)
  
 #define IDECD_VERSION "4.61"
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/cdrom.h>
 #include <linux/ide.h>
 #include <linux/completion.h>
+#include <linux/mutex.h>
 
 #include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */
 
 
 #include "ide-cd.h"
 
-static DECLARE_MUTEX(idecd_ref_sem);
+static DEFINE_MUTEX(idecd_ref_mutex);
 
 #define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) 
 
@@ -335,11 +335,11 @@ static struct cdrom_info *ide_cd_get(struct gendisk *disk)
 {
        struct cdrom_info *cd = NULL;
 
-       down(&idecd_ref_sem);
+       mutex_lock(&idecd_ref_mutex);
        cd = ide_cd_g(disk);
        if (cd)
                kref_get(&cd->kref);
-       up(&idecd_ref_sem);
+       mutex_unlock(&idecd_ref_mutex);
        return cd;
 }
 
@@ -347,9 +347,9 @@ static void ide_cd_release(struct kref *);
 
 static void ide_cd_put(struct cdrom_info *cd)
 {
-       down(&idecd_ref_sem);
+       mutex_lock(&idecd_ref_mutex);
        kref_put(&cd->kref, ide_cd_release);
-       up(&idecd_ref_sem);
+       mutex_unlock(&idecd_ref_mutex);
 }
 
 /****************************************************************************
@@ -372,7 +372,7 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
 {
        int log = 0;
 
-       if (!sense || !rq || (rq->flags & REQ_QUIET))
+       if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
                return 0;
 
        switch (sense->sense_key) {
@@ -394,7 +394,8 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
                         * we cannot reliably check if drive can auto-close
                         */
                        if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
-                               log = 0;
+                               break;
+                       log = 1;
                        break;
                case UNIT_ATTENTION:
                        /*
@@ -416,6 +417,11 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
                              struct request *failed_command,
                              struct request_sense *sense)
 {
+       unsigned long sector;
+       unsigned long bio_sectors;
+       unsigned long valid;
+       struct cdrom_info *info = drive->driver_data;
+
        if (!cdrom_log_sense(drive, failed_command, sense))
                return;
 
@@ -428,6 +434,37 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
                if (sense->sense_key == 0x05 && sense->asc == 0x24)
                        return;
 
+       if (sense->error_code == 0x70) {        /* Current Error */
+               switch(sense->sense_key) {
+               case MEDIUM_ERROR:
+               case VOLUME_OVERFLOW:
+               case ILLEGAL_REQUEST:
+                       if (!sense->valid)
+                               break;
+                       if (failed_command == NULL ||
+                                       !blk_fs_request(failed_command))
+                               break;
+                       sector = (sense->information[0] << 24) |
+                                (sense->information[1] << 16) |
+                                (sense->information[2] <<  8) |
+                                (sense->information[3]);
+
+                       bio_sectors = bio_sectors(failed_command->bio);
+                       if (bio_sectors < 4)
+                               bio_sectors = 4;
+                       if (drive->queue->hardsect_size == 2048)
+                               sector <<= 2;   /* Device sector size is 2K */
+                       sector &= ~(bio_sectors -1);
+                       valid = (sector - failed_command->sector) << 9;
+
+                       if (valid < 0)
+                               valid = 0;
+                       if (sector < get_capacity(info->disk) &&
+                               drive->probed_capacity - sector < 4 * 75) {
+                               set_capacity(info->disk, sector);
+                       }
+               }
+       }
 #if VERBOSE_IDE_CD_ERRORS
        {
                int i;
@@ -444,7 +481,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
                else
                        printk("  Unknown Error Type: ");
 
-               if (sense->sense_key < ARY_LEN(sense_key_texts))
+               if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
                        s = sense_key_texts[sense->sense_key];
 
                printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
@@ -454,7 +491,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
                                 sense->ascq);
                        s = buf;
                } else {
-                       int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
+                       int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
                        unsigned long key = (sense->sense_key << 16);
                        key |= (sense->asc << 8);
                        if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
@@ -487,7 +524,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
 
                if (failed_command != NULL) {
 
-                       int lo=0, mid, hi= ARY_LEN (packet_command_texts);
+                       int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
                        s = NULL;
 
                        while (hi > lo) {
@@ -560,7 +597,7 @@ static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq)
        struct cdrom_info *cd = drive->driver_data;
 
        ide_init_drive_cmd(rq);
-       rq->flags = REQ_PC;
+       rq->cmd_type = REQ_TYPE_ATA_PC;
        rq->rq_disk = cd->disk;
 }
 
@@ -580,7 +617,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
        rq->cmd[0] = GPCMD_REQUEST_SENSE;
        rq->cmd[4] = rq->data_len = 18;
 
-       rq->flags = REQ_SENSE;
+       rq->cmd_type = REQ_TYPE_SENSE;
 
        /* NOTE! Save the failed command in "rq->buffer" */
        rq->buffer = (void *) failed_command;
@@ -593,10 +630,10 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
        struct request *rq = HWGROUP(drive)->rq;
        int nsectors = rq->hard_cur_sectors;
 
-       if ((rq->flags & REQ_SENSE) && uptodate) {
+       if (blk_sense_request(rq) && uptodate) {
                /*
-                * For REQ_SENSE, "rq->buffer" points to the original failed
-                * request
+                * For REQ_TYPE_SENSE, "rq->buffer" points to the original
+                * failed request
                 */
                struct request *failed = (struct request *) rq->buffer;
                struct cdrom_info *info = drive->driver_data;
@@ -608,17 +645,23 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
                                sense = failed->sense;
                                failed->sense_len = rq->sense_len;
                        }
-
+                       cdrom_analyze_sense_data(drive, failed, sense);
                        /*
                         * now end failed request
                         */
-                       spin_lock_irqsave(&ide_lock, flags);
-                       end_that_request_chunk(failed, 0, failed->data_len);
-                       end_that_request_last(failed);
-                       spin_unlock_irqrestore(&ide_lock, flags);
-               }
-
-               cdrom_analyze_sense_data(drive, failed, sense);
+                       if (blk_fs_request(failed)) {
+                               if (ide_end_dequeued_request(drive, failed, 0,
+                                               failed->hard_nr_sectors))
+                                       BUG();
+                       } else {
+                               spin_lock_irqsave(&ide_lock, flags);
+                               end_that_request_chunk(failed, 0,
+                                                       failed->data_len);
+                               end_that_request_last(failed, 0);
+                               spin_unlock_irqrestore(&ide_lock, flags);
+                       }
+               } else
+                       cdrom_analyze_sense_data(drive, NULL, sense);
        }
 
        if (!rq->current_nr_sectors && blk_fs_request(rq))
@@ -632,6 +675,13 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
        ide_end_request(drive, uptodate, nsectors);
 }
 
+static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
+{
+       if (stat & 0x80)
+               return;
+       ide_dump_status(drive, msg, stat);
+}
+
 /* Returns 0 if the request should be continued.
    Returns 1 if the request was ended. */
 static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
@@ -656,17 +706,17 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                return 1;
        }
 
-       if (rq->flags & REQ_SENSE) {
+       if (blk_sense_request(rq)) {
                /* We got an error trying to get sense info
                   from the drive (probably while trying
                   to recover from a former error).  Just give up. */
 
-               rq->flags |= REQ_FAILED;
+               rq->cmd_flags |= REQ_FAILED;
                cdrom_end_request(drive, 0);
                ide_error(drive, "request sense failure", stat);
                return 1;
 
-       } else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) {
+       } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
                /* All other functions, except for READ. */
                unsigned long flags;
 
@@ -674,7 +724,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                 * if we have an error, pass back CHECK_CONDITION as the
                 * scsi status byte
                 */
-               if ((rq->flags & REQ_BLOCK_PC) && !rq->errors)
+               if (blk_pc_request(rq) && !rq->errors)
                        rq->errors = SAM_STAT_CHECK_CONDITION;
 
                /* Check for tray open. */
@@ -685,12 +735,21 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                        cdrom_saw_media_change (drive);
                        /*printk("%s: media changed\n",drive->name);*/
                        return 0;
-               } else if (!(rq->flags & REQ_QUIET)) {
+               } else if ((sense_key == ILLEGAL_REQUEST) &&
+                          (rq->cmd[0] == GPCMD_START_STOP_UNIT)) {
+                       /*
+                        * Don't print error message for this condition--
+                        * SFF8090i indicates that 5/24/00 is the correct
+                        * response to a request to close the tray if the
+                        * drive doesn't have that capability.
+                        * cdrom_log_sense() knows this!
+                        */
+               } else if (!(rq->cmd_flags & REQ_QUIET)) {
                        /* Otherwise, print an error. */
                        ide_dump_status(drive, "packet command error", stat);
                }
                
-               rq->flags |= REQ_FAILED;
+               rq->cmd_flags |= REQ_FAILED;
 
                /*
                 * instead of playing games with moving completions around,
@@ -760,16 +819,16 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                           sense_key == DATA_PROTECT) {
                        /* No point in retrying after an illegal
                           request or data protect error.*/
-                       ide_dump_status (drive, "command error", stat);
+                       ide_dump_status_no_sense (drive, "command error", stat);
                        do_end_request = 1;
                } else if (sense_key == MEDIUM_ERROR) {
                        /* No point in re-trying a zillion times on a bad 
                         * sector...  If we got here the error is not correctable */
-                       ide_dump_status (drive, "media error (bad sector)", stat);
+                       ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
                        do_end_request = 1;
                } else if (sense_key == BLANK_CHECK) {
                        /* Disk appears blank ?? */
-                       ide_dump_status (drive, "media error (blank)", stat);
+                       ide_dump_status_no_sense (drive, "media error (blank)", stat);
                        do_end_request = 1;
                } else if ((err & ~ABRT_ERR) != 0) {
                        /* Go to the default handler
@@ -781,13 +840,27 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                        do_end_request = 1;
                }
 
-               if (do_end_request)
-                       cdrom_end_request(drive, 0);
-
-               /* If we got a CHECK_CONDITION status,
-                  queue a request sense command. */
-               if ((stat & ERR_STAT) != 0)
-                       cdrom_queue_request_sense(drive, NULL, NULL);
+               /* End a request through request sense analysis when we have
+                  sense data. We need this in order to perform end of media
+                  processing */
+
+               if (do_end_request) {
+                       if (stat & ERR_STAT) {
+                               unsigned long flags;
+                               spin_lock_irqsave(&ide_lock, flags);
+                               blkdev_dequeue_request(rq);
+                               HWGROUP(drive)->rq = NULL;
+                               spin_unlock_irqrestore(&ide_lock, flags);
+
+                               cdrom_queue_request_sense(drive, rq->sense, rq);
+                       } else
+                               cdrom_end_request(drive, 0);
+               } else {
+                       /* If we got a CHECK_CONDITION status,
+                          queue a request sense command. */
+                       if (stat & ERR_STAT)
+                               cdrom_queue_request_sense(drive, NULL, NULL);
+               }
        } else {
                blk_dump_rq_flags(rq, "ide-cd: bad rq");
                cdrom_end_request(drive, 0);
@@ -817,7 +890,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
                        wait = ATAPI_WAIT_PC;
                        break;
                default:
-                       if (!(rq->flags & REQ_QUIET))
+                       if (!(rq->cmd_flags & REQ_QUIET))
                                printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
                        wait = 0;
                        break;
@@ -859,6 +932,10 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
                HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
  
        if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
+               /* waiting for CDB interrupt, not DMA yet. */
+               if (info->dma)
+                       drive->waiting_for_dma = 0;
+
                /* packet command */
                ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
                return ide_started;
@@ -901,6 +978,10 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
                /* Check for errors. */
                if (cdrom_decode_status(drive, DRQ_STAT, NULL))
                        return ide_stopped;
+
+               /* Ok, next interrupt will be DMA interrupt. */
+               if (info->dma)
+                       drive->waiting_for_dma = 1;
        } else {
                /* Otherwise, we must wait for DRQ to get set. */
                if (ide_wait_stat(&startstop, drive, DRQ_STAT,
@@ -980,7 +1061,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
  * and attempt to recover if there are problems.  Returns  0 if everything's
  * ok; nonzero if the request has been terminated.
  */
-static inline
+static
 int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
 {
        if (ireason == 2)
@@ -1032,7 +1113,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
        if (dma) {
                info->dma = 0;
                if ((dma_error = HWIF(drive)->ide_dma_end(drive)))
-                       __ide_dma_off(drive);
+                       ide_dma_off(drive);
        }
 
        if (cdrom_decode_status(drive, 0, &stat))
@@ -1060,7 +1141,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
                if (rq->current_nr_sectors > 0) {
                        printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n",
                                drive->name, rq->current_nr_sectors);
-                       rq->flags |= REQ_FAILED;
+                       rq->cmd_flags |= REQ_FAILED;
                        cdrom_end_request(drive, 0);
                } else
                        cdrom_end_request(drive, 1);
@@ -1292,7 +1373,6 @@ static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
        struct cdrom_info *info = drive->driver_data;
 
        info->dma = 0;
-       info->cmd = 0;
        info->start_seek = jiffies;
        return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation);
 }
@@ -1333,8 +1413,6 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
        if (cdrom_read_from_buffer(drive))
                return ide_stopped;
 
-       blk_attempt_remerge(drive->queue, rq);
-
        /* Clear the local sector buffer. */
        info->nsectors_buffered = 0;
 
@@ -1344,8 +1422,6 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
            (rq->nr_sectors & (sectors_per_frame - 1)))
                info->dma = 0;
 
-       info->cmd = READ;
-
        /* Start sending the read request to the drive. */
        return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
 }
@@ -1397,7 +1473,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
                        printk ("%s: cdrom_pc_intr: data underrun %d\n",
                                drive->name, pc->buflen);
                        */
-                       rq->flags |= REQ_FAILED;
+                       rq->cmd_flags |= REQ_FAILED;
                        cdrom_end_request(drive, 0);
                }
                return ide_stopped;
@@ -1450,14 +1526,17 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
                rq->data += thislen;
                rq->data_len -= thislen;
 
-               if (rq->flags & REQ_SENSE)
+               if (blk_sense_request(rq))
                        rq->sense_len += thislen;
        } else {
 confused:
                printk (KERN_ERR "%s: cdrom_pc_intr: The drive "
-                       "appears confused (ireason = 0x%02x)\n",
+                       "appears confused (ireason = 0x%02x). "
+                       "Trying to recover by ending request.\n",
                        drive->name, ireason);
-               rq->flags |= REQ_FAILED;
+               rq->cmd_flags |= REQ_FAILED;
+               cdrom_end_request(drive, 0);
+               return ide_stopped;
        }
 
        /* Now we wait for another interrupt. */
@@ -1484,8 +1563,7 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
        struct cdrom_info *info = drive->driver_data;
 
        info->dma = 0;
-       info->cmd = 0;
-       rq->flags &= ~REQ_FAILED;
+       rq->cmd_flags &= ~REQ_FAILED;
        len = rq->data_len;
 
        /* Start sending the command to the drive. */
@@ -1493,12 +1571,11 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
 }
 
 
-static
-int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
+static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
 {
        struct request_sense sense;
        int retries = 10;
-       unsigned int flags = rq->flags;
+       unsigned int flags = rq->cmd_flags;
 
        if (rq->sense == NULL)
                rq->sense = &sense;
@@ -1507,14 +1584,14 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
        do {
                int error;
                unsigned long time = jiffies;
-               rq->flags = flags;
+               rq->cmd_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 (rq->flags & REQ_FAILED) {
+               if (rq->cmd_flags & REQ_FAILED) {
                        /* The request failed.  Retry if it was due to a unit
                           attention status
                           (usually means media was changed). */
@@ -1536,16 +1613,16 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
                }
 
                /* End of retry loop. */
-       } while ((rq->flags & REQ_FAILED) && retries >= 0);
+       } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
 
        /* Return an error if the command failed. */
-       return (rq->flags & REQ_FAILED) ? -EIO : 0;
+       return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
 }
 
 /*
  * Write handling
  */
-static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
+static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
 {
        /* Two notes about IDE interrupt reason here - 0 means that
         * the drive wants to receive data from us, 2 means that
@@ -1632,7 +1709,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
        if (dma) {
                if (dma_error) {
                        printk(KERN_ERR "ide-cd: dma error\n");
-                       __ide_dma_off(drive);
+                       ide_dma_off(drive);
                        return ide_error(drive, "dma error", stat);
                }
 
@@ -1727,8 +1804,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                }
        }
 
-       if (HWGROUP(drive)->handler != NULL)
-               BUG();
+       BUG_ON(HWGROUP(drive)->handler != NULL);
 
        ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL);
        return ide_started;
@@ -1739,7 +1815,7 @@ end_request:
 
        spin_lock_irqsave(&ide_lock, flags);
        blkdev_dequeue_request(rq);
-       end_that_request_last(rq);
+       end_that_request_last(rq, 1);
        HWGROUP(drive)->rq = NULL;
        spin_unlock_irqrestore(&ide_lock, flags);
        return ide_stopped;
@@ -1759,7 +1835,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
                info->dma = 0;
                if ((dma_error = HWIF(drive)->ide_dma_end(drive))) {
                        printk(KERN_ERR "ide-cd: write dma error\n");
-                       __ide_dma_off(drive);
+                       ide_dma_off(drive);
                }
        }
 
@@ -1878,20 +1954,11 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
                return ide_stopped;
        }
 
-       /*
-        * for dvd-ram and such media, it's a really big deal to get
-        * big writes all the time. so scour the queue and attempt to
-        * remerge requests, often the plugging will not have had time
-        * to do this properly
-        */
-       blk_attempt_remerge(drive->queue, rq);
-
        info->nsectors_buffered = 0;
 
        /* use dma, if possible. we don't need to check more, since we
         * know that the transfer is always (at least!) frame aligned */
        info->dma = drive->using_dma ? 1 : 0;
-       info->cmd = WRITE;
 
        info->devinfo.media_written = 1;
 
@@ -1913,10 +1980,9 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
 {
        struct cdrom_info *info = drive->driver_data;
 
-       rq->flags |= REQ_QUIET;
+       rq->cmd_flags |= REQ_QUIET;
 
        info->dma = 0;
-       info->cmd = 0;
 
        /*
         * sg request
@@ -1925,7 +1991,6 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
                int mask = drive->queue->dma_alignment;
                unsigned long addr = (unsigned long) page_address(bio_page(rq->bio));
 
-               info->cmd = rq_data_dir(rq);
                info->dma = drive->using_dma;
 
                /*
@@ -1975,11 +2040,12 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
                }
                info->last_block = block;
                return action;
-       } else if (rq->flags & (REQ_PC | REQ_SENSE)) {
+       } else if (rq->cmd_type == REQ_TYPE_SENSE ||
+                  rq->cmd_type == REQ_TYPE_ATA_PC) {
                return cdrom_do_packet_command(drive);
-       } else if (rq->flags & REQ_BLOCK_PC) {
+       } else if (blk_pc_request(rq)) {
                return cdrom_do_block_pc(drive, rq);
-       } else if (rq->flags & REQ_SPECIAL) {
+       } else if (blk_special_request(rq)) {
                /*
                 * right now this can only be a reset...
                 */
@@ -2057,7 +2123,7 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
 
        req.sense = sense;
        req.cmd[0] = GPCMD_TEST_UNIT_READY;
-       req.flags |= REQ_QUIET;
+       req.cmd_flags |= REQ_QUIET;
 
 #if ! STANDARD_ATAPI
         /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to 
@@ -2159,6 +2225,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
        req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
        req.data = (char *)&capbuf;
        req.data_len = sizeof(capbuf);
+       req.cmd_flags |= REQ_QUIET;
 
        stat = cdrom_queue_packet_command(drive, &req);
        if (stat == 0) {
@@ -2181,7 +2248,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
        req.sense = sense;
        req.data =  buf;
        req.data_len = buflen;
-       req.flags |= REQ_QUIET;
+       req.cmd_flags |= REQ_QUIET;
        req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
        req.cmd[6] = trackno;
        req.cmd[7] = (buflen >> 8);
@@ -2233,6 +2300,9 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
                toc->capacity = 0x1fffff;
 
        set_capacity(info->disk, toc->capacity * sectors_per_frame);
+       /* Save a private copy of te TOC capacity for error handling */
+       drive->probed_capacity = toc->capacity * sectors_per_frame;
+
        blk_queue_hardsect_size(drive->queue,
                                sectors_per_frame << SECTOR_BITS);
 
@@ -2355,6 +2425,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
        if (!stat && (last_written > toc->capacity)) {
                toc->capacity = last_written;
                set_capacity(info->disk, toc->capacity * sectors_per_frame);
+               drive->probed_capacity = toc->capacity * sectors_per_frame;
        }
 
        /* Remember that we've read this stuff. */
@@ -2478,7 +2549,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
        req.timeout = cgc->timeout;
 
        if (cgc->quiet)
-               req.flags |= REQ_QUIET;
+               req.cmd_flags |= REQ_QUIET;
 
        req.sense = cgc->sense;
        cgc->stat = cdrom_queue_packet_command(drive, &req);
@@ -2488,52 +2559,6 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
 }
 
 static
-int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
-                        unsigned int cmd, unsigned long arg)
-{
-       struct packet_command cgc;
-       char buffer[16];
-       int stat;
-
-       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
-
-       /* These will be moved into the Uniform layer shortly... */
-       switch (cmd) {
-       case CDROMSETSPINDOWN: {
-               char spindown;
-               if (copy_from_user(&spindown, (void __user *) arg, sizeof(char)))
-                       return -EFAULT;
-                if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
-                       return stat;
-
-               buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
-
-               return cdrom_mode_select(cdi, &cgc);
-       } 
-       case CDROMGETSPINDOWN: {
-               char spindown;
-                if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
-                       return stat;
-               spindown = buffer[11] & 0x0f;
-               if (copy_to_user((void __user *) arg, &spindown, sizeof (char)))
-                       return -EFAULT;
-               return 0;
-       }
-  
-       default:
-               return -EINVAL;
-       }
-
-}
-
-static
 int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
                           unsigned int cmd, void *arg)
                           
@@ -2622,7 +2647,8 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi)
        int ret;
 
        cdrom_prepare_request(drive, &req);
-       req.flags = REQ_SPECIAL | REQ_QUIET;
+       req.cmd_type = REQ_TYPE_SPECIAL;
+       req.cmd_flags = REQ_QUIET;
        ret = ide_do_drive_cmd(drive, &req, ide_wait);
 
        /*
@@ -2757,14 +2783,11 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
         * any other way to detect this...
         */
        if (sense.sense_key == NOT_READY) {
-               if (sense.asc == 0x3a) {
-                       if (sense.ascq == 1)
-                               return CDS_NO_DISC;
-                       else if (sense.ascq == 0 || sense.ascq == 2)
-                               return CDS_TRAY_OPEN;
-               }
+               if (sense.asc == 0x3a && sense.ascq == 1)
+                       return CDS_NO_DISC;
+               else
+                       return CDS_TRAY_OPEN;
        }
-
        return CDS_DRIVE_NOT_READY;
 }
 
@@ -2869,12 +2892,11 @@ static struct cdrom_device_ops ide_cdrom_dops = {
        .get_mcn                = ide_cdrom_get_mcn,
        .reset                  = ide_cdrom_reset,
        .audio_ioctl            = ide_cdrom_audio_ioctl,
-       .dev_ioctl              = ide_cdrom_dev_ioctl,
        .capability             = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
                                CDC_SELECT_SPEED | CDC_SELECT_DISC |
                                CDC_MULTI_SESSION | CDC_MCN |
                                CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
-                               CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R |
+                               CDC_DRIVE_STATUS | CDC_CD_R |
                                CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
                                CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW |
                                CDC_MRW_W | CDC_RAM,
@@ -2912,6 +2934,8 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
                devinfo->mask |= CDC_CLOSE_TRAY;
        if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
                devinfo->mask |= CDC_MO_DRIVE;
+       if (!CDROM_CONFIG_FLAGS(drive)->ram)
+               devinfo->mask |= CDC_RAM;
 
        devinfo->disk = info->disk;
        return register_cdrom(devinfo);
@@ -3035,15 +3059,19 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
        return nslots;
 }
 
+#ifdef CONFIG_IDE_PROC_FS
 static void ide_cdrom_add_settings(ide_drive_t *drive)
 {
-       ide_add_setting(drive,  "dsc_overlap",          SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
+       ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
 }
+#else
+static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
+#endif
 
 /*
  * standard prep_rq_fn that builds 10 byte cmds
  */
-static int ide_cdrom_prep_fs(request_queue_t *q, struct request *rq)
+static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
 {
        int hard_sect = queue_hardsect_size(q);
        long block = (long)rq->hard_sector / (hard_sect >> 9);
@@ -3109,11 +3137,11 @@ static int ide_cdrom_prep_pc(struct request *rq)
        return BLKPREP_OK;
 }
 
-static int ide_cdrom_prep_fn(request_queue_t *q, struct request *rq)
+static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
 {
-       if (rq->flags & REQ_CMD)
+       if (blk_fs_request(rq))
                return ide_cdrom_prep_fs(q, rq);
-       else if (rq->flags & REQ_BLOCK_PC)
+       else if (blk_pc_request(rq))
                return ide_cdrom_prep_pc(rq);
 
        return 0;
@@ -3240,14 +3268,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
        if (drive->autotune == IDE_TUNE_DEFAULT ||
            drive->autotune == IDE_TUNE_AUTO)
                drive->dsc_overlap = (drive->next != drive);
-#if 0
-       drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1;
-       if (HWIF(drive)->no_dsc) {
-               printk(KERN_INFO "ide-cd: %s: disabling DSC overlap\n",
-                       drive->name);
-               drive->dsc_overlap = 0;
-       }
-#endif
 
        if (ide_cdrom_register(drive, nslots)) {
                printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
@@ -3258,7 +3278,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
        return 0;
 }
 
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_IDE_PROC_FS
 static
 sector_t ide_cdrom_capacity (ide_drive_t *drive)
 {
@@ -3271,18 +3291,15 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
 }
 #endif
 
-static int ide_cd_remove(struct device *dev)
+static void ide_cd_remove(ide_drive_t *drive)
 {
-       ide_drive_t *drive = to_ide_device(dev);
        struct cdrom_info *info = drive->driver_data;
 
-       ide_unregister_subdriver(drive, info->driver);
+       ide_proc_unregister_driver(drive, info->driver);
 
        del_gendisk(info->disk);
 
        ide_cd_put(info);
-
-       return 0;
 }
 
 static void ide_cd_release(struct kref *kref)
@@ -3292,12 +3309,9 @@ static void ide_cd_release(struct kref *kref)
        ide_drive_t *drive = info->drive;
        struct gendisk *g = info->disk;
 
-       if (info->buffer != NULL)
-               kfree(info->buffer);
-       if (info->toc != NULL)
-               kfree(info->toc);
-       if (info->changer_info != NULL)
-               kfree(info->changer_info);
+       kfree(info->buffer);
+       kfree(info->toc);
+       kfree(info->changer_info);
        if (devinfo->handle == drive && unregister_cdrom(devinfo))
                printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
                                "driver.\n", __FUNCTION__, drive->name);
@@ -3309,9 +3323,9 @@ static void ide_cd_release(struct kref *kref)
        kfree(info);
 }
 
-static int ide_cd_probe(struct device *);
+static int ide_cd_probe(ide_drive_t *);
 
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_IDE_PROC_FS
 static int proc_idecd_read_capacity
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
@@ -3326,18 +3340,16 @@ static ide_proc_entry_t idecd_proc[] = {
        { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
        { NULL, 0, NULL, NULL }
 };
-#else
-# define idecd_proc    NULL
 #endif
 
 static ide_driver_t ide_cdrom_driver = {
-       .owner                  = THIS_MODULE,
        .gen_driver = {
+               .owner          = THIS_MODULE,
                .name           = "ide-cdrom",
                .bus            = &ide_bus_type,
-               .probe          = ide_cd_probe,
-               .remove         = ide_cd_remove,
        },
+       .probe                  = ide_cd_probe,
+       .remove                 = ide_cd_remove,
        .version                = IDECD_VERSION,
        .media                  = ide_cdrom,
        .supports_dsc_overlap   = 1,
@@ -3345,28 +3357,25 @@ static ide_driver_t ide_cdrom_driver = {
        .end_request            = ide_end_request,
        .error                  = __ide_error,
        .abort                  = __ide_abort,
+#ifdef CONFIG_IDE_PROC_FS
        .proc                   = idecd_proc,
+#endif
 };
 
 static int idecd_open(struct inode * inode, struct file * file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct cdrom_info *info;
-       ide_drive_t *drive;
        int rc = -ENOMEM;
 
        if (!(info = ide_cd_get(disk)))
                return -ENXIO;
 
-       drive = info->drive;
-
-       drive->usage++;
-
        if (!info->buffer)
-               info->buffer = kmalloc(SECTOR_BUFFER_SIZE,
-                                       GFP_KERNEL|__GFP_REPEAT);
-        if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file)))
-               drive->usage--;
+               info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
+
+       if (info->buffer)
+               rc = cdrom_open(&info->devinfo, inode, file);
 
        if (rc < 0)
                ide_cd_put(info);
@@ -3378,16 +3387,53 @@ static int idecd_release(struct inode * inode, struct file * file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct cdrom_info *info = ide_cd_g(disk);
-       ide_drive_t *drive = info->drive;
 
        cdrom_release (&info->devinfo, file);
-       drive->usage--;
 
        ide_cd_put(info);
 
        return 0;
 }
 
+static int idecd_set_spindown(struct cdrom_device_info *cdi, unsigned long arg)
+{
+       struct packet_command cgc;
+       char buffer[16];
+       int stat;
+       char spindown;
+
+       if (copy_from_user(&spindown, (void __user *)arg, sizeof(char)))
+               return -EFAULT;
+
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
+
+       stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
+       if (stat)
+               return stat;
+
+       buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
+       return cdrom_mode_select(cdi, &cgc);
+}
+
+static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
+{
+       struct packet_command cgc;
+       char buffer[16];
+       int stat;
+       char spindown;
+
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
+
+       stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
+       if (stat)
+               return stat;
+
+       spindown = buffer[11] & 0x0f;
+       if (copy_to_user((void __user *)arg, &spindown, sizeof (char)))
+               return -EFAULT;
+       return 0;
+}
+
 static int idecd_ioctl (struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
@@ -3395,7 +3441,16 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
        struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
        int err;
 
-       err  = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
+       switch (cmd) {
+       case CDROMSETSPINDOWN:
+               return idecd_set_spindown(&info->devinfo, arg);
+       case CDROMGETSPINDOWN:
+               return idecd_get_spindown(&info->devinfo, arg);
+       default:
+               break;
+       }
+
+       err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
        if (err == -EINVAL)
                err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg);
 
@@ -3431,9 +3486,8 @@ static char *ignore = NULL;
 module_param(ignore, charp, 0400);
 MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
 
-static int ide_cd_probe(struct device *dev)
+static int ide_cd_probe(ide_drive_t *drive)
 {
-       ide_drive_t *drive = to_ide_device(dev);
        struct cdrom_info *info;
        struct gendisk *g;
        struct request_sense sense;
@@ -3467,7 +3521,7 @@ static int ide_cd_probe(struct device *dev)
 
        ide_init_disk(g, drive);
 
-       ide_register_subdriver(drive, &ide_cdrom_driver);
+       ide_proc_register_driver(drive, &ide_cdrom_driver);
 
        kref_init(&info->kref);
 
@@ -3480,19 +3534,14 @@ static int ide_cd_probe(struct device *dev)
        drive->driver_data = info;
 
        g->minors = 1;
-       snprintf(g->devfs_name, sizeof(g->devfs_name),
-                       "%s/cd", drive->devfs_name);
        g->driverfs_dev = &drive->gendev;
        g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
        if (ide_cdrom_setup(drive)) {
                struct cdrom_device_info *devinfo = &info->devinfo;
-               ide_unregister_subdriver(drive, &ide_cdrom_driver);
-               if (info->buffer != NULL)
-                       kfree(info->buffer);
-               if (info->toc != NULL)
-                       kfree(info->toc);
-               if (info->changer_info != NULL)
-                       kfree(info->changer_info);
+               ide_proc_unregister_driver(drive, &ide_cdrom_driver);
+               kfree(info->buffer);
+               kfree(info->toc);
+               kfree(info->changer_info);
                if (devinfo->handle == drive && unregister_cdrom(devinfo))
                        printk (KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
                kfree(info);
@@ -3516,12 +3565,13 @@ static void __exit ide_cdrom_exit(void)
 {
        driver_unregister(&ide_cdrom_driver.gen_driver);
 }
-static int ide_cdrom_init(void)
+
+static int __init ide_cdrom_init(void)
 {
        return driver_register(&ide_cdrom_driver.gen_driver);
 }
 
+MODULE_ALIAS("ide:*m-cdrom*");
 module_init(ide_cdrom_init);
 module_exit(ide_cdrom_exit);
 MODULE_LICENSE("GPL");