]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-cd.c
ide-atapi: split drive-specific functionality in ide_issue_pc
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-cd.c
index ac607bbde45c7b6d27be6afbe364a2f8d1cf081a..105e4d855e6ee978ad4e1b2721b23c54e5f0ba90 100644 (file)
 
 #include "ide-cd.h"
 
-#define IDECD_DEBUG_LOG                1
-
-#if IDECD_DEBUG_LOG
-#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
-#else
-#define ide_debug_log(lvl, fmt, args...) do {} while (0)
-#endif
-
 static DEFINE_MUTEX(idecd_ref_mutex);
 
 static void ide_cd_release(struct kref *);
@@ -424,16 +416,17 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                                if (time_after(jiffies, info->write_timeout))
                                        do_end_request = 1;
                                else {
+                                       struct request_queue *q = drive->queue;
                                        unsigned long flags;
 
                                        /*
                                         * take a breather relying on the unplug
                                         * timer to kick us again
                                         */
-                                       spin_lock_irqsave(&ide_lock, flags);
-                                       blk_plug_device(drive->queue);
-                                       spin_unlock_irqrestore(&ide_lock,
-                                                               flags);
+                                       spin_lock_irqsave(q->queue_lock, flags);
+                                       blk_plug_device(q);
+                                       spin_unlock_irqrestore(q->queue_lock, flags);
+
                                        return 1;
                                }
                        }
@@ -502,11 +495,12 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 
 end_request:
        if (stat & ATA_ERR) {
+               struct request_queue *q = drive->queue;
                unsigned long flags;
 
-               spin_lock_irqsave(&ide_lock, flags);
+               spin_lock_irqsave(q->queue_lock, flags);
                blkdev_dequeue_request(rq);
-               spin_unlock_irqrestore(&ide_lock, flags);
+               spin_unlock_irqrestore(q->queue_lock, flags);
 
                hwgroup->rq = NULL;
 
@@ -517,38 +511,6 @@ end_request:
        return 1;
 }
 
-static int cdrom_timer_expiry(ide_drive_t *drive)
-{
-       struct request *rq = HWGROUP(drive)->rq;
-       unsigned long wait = 0;
-
-       ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd[0]: 0x%x\n", __func__,
-                     rq->cmd[0]);
-
-       /*
-        * Some commands are *slow* and normally take a long time to complete.
-        * Usually we can use the ATAPI "disconnect" to bypass this, but not all
-        * commands/drives support that. Let ide_timer_expiry keep polling us
-        * for these.
-        */
-       switch (rq->cmd[0]) {
-       case GPCMD_BLANK:
-       case GPCMD_FORMAT_UNIT:
-       case GPCMD_RESERVE_RZONE_TRACK:
-       case GPCMD_CLOSE_TRACK:
-       case GPCMD_FLUSH_CACHE:
-               wait = ATAPI_WAIT_PC;
-               break;
-       default:
-               if (!(rq->cmd_flags & REQ_QUIET))
-                       printk(KERN_INFO PFX "cmd 0x%x timed out\n",
-                                        rq->cmd[0]);
-               wait = 0;
-               break;
-       }
-       return wait;
-}
-
 /*
  * Set up the device registers for transferring a packet command on DEV,
  * expecting to later transfer XFERLEN bytes.  HANDLER is the routine
@@ -580,7 +542,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
 
                /* packet command */
                ide_execute_command(drive, ATA_CMD_PACKET, handler,
-                                   ATAPI_WAIT_PC, cdrom_timer_expiry);
+                                   ATAPI_WAIT_PC, ide_cd_expiry);
                return ide_started;
        } else {
                ide_execute_pkt_cmd(drive);
@@ -627,7 +589,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
        }
 
        /* arm the interrupt handler */
-       ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);
+       ide_set_handler(drive, handler, rq->timeout, ide_cd_expiry);
 
        /* ATAPI commands get padded out to 12 bytes minimum */
        cmd_len = COMMAND_SIZE(rq->cmd[0]);
@@ -772,52 +734,6 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
        return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
 }
 
-#define IDECD_SEEK_THRESHOLD   (1000)                  /* 1000 blocks */
-#define IDECD_SEEK_TIMER       (5 * WAIT_MIN_SLEEP)    /* 100 ms */
-#define IDECD_SEEK_TIMEOUT     (2 * WAIT_CMD)          /* 20 sec */
-
-static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
-{
-       struct cdrom_info *info = drive->driver_data;
-       int stat;
-       static int retry = 10;
-
-       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
-
-       if (cdrom_decode_status(drive, 0, &stat))
-               return ide_stopped;
-
-       drive->atapi_flags |= IDE_AFLAG_SEEKING;
-
-       if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
-               if (--retry == 0)
-                       drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
-       }
-       return ide_stopped;
-}
-
-static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq)
-{
-       sector_t frame = rq->sector;
-
-       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
-
-       sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
-
-       memset(rq->cmd, 0, BLK_MAX_CDB);
-       rq->cmd[0] = GPCMD_SEEK;
-       put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
-
-       rq->timeout = ATAPI_WAIT_PC;
-}
-
-static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
-{
-       struct request *rq = drive->hwif->hwgroup->rq;
-
-       return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
-}
-
 /*
  * Fix up a possibly partially-processed request so that we can start it over
  * entirely, or even put it back on the request queue.
@@ -1140,7 +1056,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
        } else {
                timeout = ATAPI_WAIT_PC;
                if (!blk_fs_request(rq))
-                       expiry = cdrom_timer_expiry;
+                       expiry = ide_cd_expiry;
        }
 
        ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
@@ -1258,7 +1174,6 @@ static void cdrom_do_block_pc(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)
 {
-       struct cdrom_info *info = drive->driver_data;
        ide_handler_t *fn;
        int xferlen;
 
@@ -1267,48 +1182,18 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
                      __func__, rq->cmd[0], rq->cmd_type,
                      (unsigned long long)block);
 
-       if (blk_fs_request(rq)) {
-               if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
-                       ide_hwif_t *hwif = drive->hwif;
-                       unsigned long elapsed = jiffies - info->start_seek;
-                       int stat = hwif->tp_ops->read_status(hwif);
-
-                       if ((stat & ATA_DSC) != ATA_DSC) {
-                               if (elapsed < IDECD_SEEK_TIMEOUT) {
-                                       ide_stall_queue(drive,
-                                                       IDECD_SEEK_TIMER);
-                                       return ide_stopped;
-                               }
-                               printk(KERN_ERR PFX "%s: DSC timeout\n",
-                                               drive->name);
-                       }
-                       drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
-               }
-               if (rq_data_dir(rq) == READ &&
-                   IDE_LARGE_SEEK(info->last_block, block,
-                           IDECD_SEEK_THRESHOLD) &&
-                   (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)) {
-                       xferlen = 0;
-                       fn = cdrom_start_seek_continuation;
-
-                       drive->dma = 0;
-                       info->start_seek = jiffies;
+       xferlen = ide_cd_get_xferlen(rq);
 
-                       ide_cd_prepare_seek_request(drive, rq);
-               } else {
-                       xferlen = 32768;
-                       fn = cdrom_start_rw_cont;
+       if (blk_fs_request(rq)) {
+               fn = cdrom_start_rw_cont;
 
-                       if (cdrom_start_rw(drive, rq) == ide_stopped)
-                               return ide_stopped;
+               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;
+               if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped)
+                       return ide_stopped;
        } else if (blk_sense_request(rq) || blk_pc_request(rq) ||
                   rq->cmd_type == REQ_TYPE_ATA_PC) {
-               xferlen = rq->data_len;
                fn = cdrom_do_newpc_cont;
 
                if (!rq->timeout)
@@ -1906,13 +1791,6 @@ static ide_proc_entry_t idecd_proc[] = {
        { NULL, 0, NULL, NULL }
 };
 
-ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
-
-static const struct ide_proc_devset idecd_settings[] = {
-       IDE_PROC_DEVSET(dsc_overlap, 0, 1),
-       { 0 },
-};
-
 static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive)
 {
        return idecd_proc;
@@ -1920,7 +1798,7 @@ static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive)
 
 static const struct ide_proc_devset *ide_cd_proc_devsets(ide_drive_t *drive)
 {
-       return idecd_settings;
+       return NULL;
 }
 #endif
 
@@ -2020,11 +1898,6 @@ static int ide_cdrom_setup(ide_drive_t *drive)
        /* set correct block size */
        blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
 
-       if (drive->next != drive)
-               drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
-       else
-               drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
-
        if (ide_cdrom_register(drive, nslots)) {
                printk(KERN_ERR PFX "%s: %s failed to register device with the"
                                " cdrom driver.\n", drive->name, __func__);
@@ -2061,7 +1934,6 @@ static void ide_cd_release(struct kref *kref)
        kfree(info->toc);
        if (devinfo->handle == drive)
                unregister_cdrom(devinfo);
-       drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
        drive->driver_data = NULL;
        blk_queue_prep_rq(drive->queue, NULL);
        g->private_data = NULL;