]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-io.c
ide: fix HDIO_DRIVE_TASK[FILE] ioctls for CHS commands on LBA devices
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-io.c
index a896a283f27fdd04d7e211c2c2d81b3924d8bd9f..623f6c246cf50deef82dd6a595ebb658f96b2c38 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
+#include <linux/hdreg.h>
 #include <linux/completion.h>
 #include <linux/reboot.h>
 #include <linux/cdrom.h>
@@ -77,8 +78,9 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
         * decide whether to reenable DMA -- 3 is a random magic for now,
         * if we DMA timeout more than 3 times, just stay in PIO
         */
-       if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
-               drive->state = 0;
+       if ((drive->dev_flags & IDE_DFLAG_DMA_PIO_RETRY) &&
+           drive->retry_pio <= 3) {
+               drive->dev_flags &= ~IDE_DFLAG_DMA_PIO_RETRY;
                ide_dma_on(drive);
        }
 
@@ -183,18 +185,19 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
                if (drive->media != ide_disk)
                        break;
                /* Not supported? Switch to next step now. */
-               if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) {
+               if (ata_id_flush_enabled(drive->id) == 0 ||
+                   (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
                        ide_complete_power_step(drive, rq, 0, 0);
                        return ide_stopped;
                }
-               if (ide_id_has_flush_cache_ext(drive->id))
-                       args->tf.command = WIN_FLUSH_CACHE_EXT;
+               if (ata_id_flush_ext_enabled(drive->id))
+                       args->tf.command = ATA_CMD_FLUSH_EXT;
                else
-                       args->tf.command = WIN_FLUSH_CACHE;
+                       args->tf.command = ATA_CMD_FLUSH;
                goto out_do_tf;
 
        case idedisk_pm_standby:        /* Suspend step 2 (standby) */
-               args->tf.command = WIN_STANDBYNOW1;
+               args->tf.command = ATA_CMD_STANDBYNOW1;
                goto out_do_tf;
 
        case idedisk_pm_restore_pio:    /* Resume step 1 (restore PIO) */
@@ -209,7 +212,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
                return ide_stopped;
 
        case idedisk_pm_idle:           /* Resume step 2 (idle) */
-               args->tf.command = WIN_IDLEIMMEDIATE;
+               args->tf.command = ATA_CMD_IDLEIMMEDIATE;
                goto out_do_tf;
 
        case ide_pm_restore_dma:        /* Resume step 3 (restore DMA) */
@@ -221,7 +224,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
                if (drive->hwif->dma_ops == NULL)
                        break;
                /*
-                * TODO: respect ->using_dma setting
+                * TODO: respect IDE_DFLAG_USING_DMA
                 */
                ide_set_dma(drive);
                break;
@@ -286,7 +289,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
        if (blk_pm_suspend_request(rq)) {
                blk_stop_queue(drive->queue);
        } else {
-               drive->blocked = 0;
+               drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
                blk_start_queue(drive->queue);
        }
        HWGROUP(drive)->rq = NULL;
@@ -322,7 +325,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
                ide_task_t *task = (ide_task_t *)rq->special;
 
                if (rq->errors == 0)
-                       rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT);
+                       rq->errors = !OK_STAT(stat, ATA_DRDY, BAD_STAT);
 
                if (task) {
                        struct ide_taskfile *tf = &task->tf;
@@ -373,29 +376,30 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
+       if ((stat & ATA_BUSY) ||
+           ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
                /* other bits are useless when BUSY */
                rq->errors |= ERROR_RESET;
-       } else if (stat & ERR_STAT) {
+       } else if (stat & ATA_ERR) {
                /* err has different meaning on cdrom and tape */
-               if (err == ABRT_ERR) {
-                       if (drive->select.b.lba &&
-                           /* some newer drives don't support WIN_SPECIFY */
-                           hwif->tp_ops->read_status(hwif) == WIN_SPECIFY)
+               if (err == ATA_ABORTED) {
+                       if ((drive->dev_flags & IDE_DFLAG_LBA) &&
+                           /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
+                           hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
                                return ide_stopped;
                } else if ((err & BAD_CRC) == BAD_CRC) {
                        /* UDMA crc error, just retry the operation */
                        drive->crc_count++;
-               } else if (err & (BBD_ERR | ECC_ERR)) {
+               } else if (err & (ATA_BBK | ATA_UNC)) {
                        /* retries won't help these */
                        rq->errors = ERROR_MAX;
-               } else if (err & TRK0_ERR) {
+               } else if (err & ATA_TRK0NF) {
                        /* help it find track zero */
                        rq->errors |= ERROR_RECAL;
                }
        }
 
-       if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ &&
+       if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
            (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
                int nsect = drive->mult_count ? drive->mult_count : 1;
 
@@ -407,7 +411,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
                return ide_stopped;
        }
 
-       if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
+       if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
                rq->errors |= ERROR_RESET;
 
        if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
@@ -427,16 +431,17 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
+       if ((stat & ATA_BUSY) ||
+           ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
                /* other bits are useless when BUSY */
                rq->errors |= ERROR_RESET;
        } else {
                /* add decoding error stuff */
        }
 
-       if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
+       if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
                /* force an abort */
-               hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
+               hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
 
        if (rq->errors >= ERROR_MAX) {
                ide_kill_rq(drive, rq);
@@ -508,20 +513,20 @@ static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
        tf->lbal    = drive->sect;
        tf->lbam    = drive->cyl;
        tf->lbah    = drive->cyl >> 8;
-       tf->device  = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
-       tf->command = WIN_SPECIFY;
+       tf->device  = (drive->head - 1) | drive->select.all;
+       tf->command = ATA_CMD_INIT_DEV_PARAMS;
 }
 
 static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
 {
        tf->nsect   = drive->sect;
-       tf->command = WIN_RESTORE;
+       tf->command = ATA_CMD_RESTORE;
 }
 
 static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
 {
        tf->nsect   = drive->mult_req;
-       tf->command = WIN_SETMULT;
+       tf->command = ATA_CMD_SET_MULTI;
 }
 
 static ide_startstop_t ide_disk_special(ide_drive_t *drive)
@@ -540,8 +545,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
                ide_tf_set_restore_cmd(drive, &args.tf);
        } else if (s->b.set_multmode) {
                s->b.set_multmode = 0;
-               if (drive->mult_req > drive->id->max_multsect)
-                       drive->mult_req = drive->id->max_multsect;
                ide_tf_set_setmult_cmd(drive, &args.tf);
        } else if (s->all) {
                int special = s->all;
@@ -586,9 +589,10 @@ static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
  *     do_special              -       issue some special commands
  *     @drive: drive the command is for
  *
- *     do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
- *     commands to a drive.  It used to do much more, but has been scaled
- *     back.
+ *     do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS,
+ *     ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive.
+ *
+ *     It used to do much more, but has been scaled back.
  */
 
 static ide_startstop_t do_special (ide_drive_t *drive)
@@ -607,7 +611,7 @@ static ide_startstop_t do_special (ide_drive_t *drive)
 
                if (set_pio_mode_abuse(drive->hwif, req_pio)) {
                        /*
-                        * take ide_lock for drive->[no_]unmask/[no_]io_32bit
+                        * take ide_lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT
                         */
                        if (req_pio == 8 || req_pio == 9) {
                                unsigned long flags;
@@ -618,7 +622,8 @@ static ide_startstop_t do_special (ide_drive_t *drive)
                        } else
                                port_ops->set_pio_mode(drive, req_pio);
                } else {
-                       int keep_dma = drive->using_dma;
+                       int keep_dma =
+                               !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 
                        ide_set_pio(drive, req_pio);
 
@@ -716,9 +721,49 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
        return ide_stopped;
 }
 
+int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
+                      int arg)
+{
+       struct request_queue *q = drive->queue;
+       struct request *rq;
+       int ret = 0;
+
+       if (!(setting->flags & DS_SYNC))
+               return setting->set(drive, arg);
+
+       rq = blk_get_request(q, READ, GFP_KERNEL);
+       if (!rq)
+               return -ENOMEM;
+
+       rq->cmd_type = REQ_TYPE_SPECIAL;
+       rq->cmd_len = 5;
+       rq->cmd[0] = REQ_DEVSET_EXEC;
+       *(int *)&rq->cmd[1] = arg;
+       rq->special = setting->set;
+
+       if (blk_execute_rq(q, NULL, rq, 0))
+               ret = rq->errors;
+       blk_put_request(rq);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ide_devset_execute);
+
 static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
 {
        switch (rq->cmd[0]) {
+       case REQ_DEVSET_EXEC:
+       {
+               int err, (*setfunc)(ide_drive_t *, int) = rq->special;
+
+               err = setfunc(drive, *(int *)&rq->cmd[1]);
+               if (err)
+                       rq->errors = err;
+               else
+                       err = 1;
+               ide_end_request(drive, err, 0);
+               return ide_stopped;
+       }
        case REQ_DRIVE_RESET:
                return ide_do_reset(drive);
        default:
@@ -735,7 +780,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
        if (blk_pm_suspend_request(rq) &&
            pm->pm_step == ide_pm_state_start_suspend)
                /* Mark drive blocked when starting the suspend sequence. */
-               drive->blocked = 1;
+               drive->dev_flags |= IDE_DFLAG_BLOCKED;
        else if (blk_pm_resume_request(rq) &&
                 pm->pm_step == ide_pm_state_start_resume) {
                /* 
@@ -766,9 +811,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
  *     start_request   -       start of I/O and command issuing for IDE
  *
  *     start_request() initiates handling of a new I/O request. It
- *     accepts commands and I/O (read/write) requests. It also does
- *     the final remapping for weird stuff like EZDrive. Once 
- *     device mapper can work sector level the EZDrive stuff can go away
+ *     accepts commands and I/O (read/write) requests.
  *
  *     FIXME: this function needs a rename
  */
@@ -776,7 +819,6 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
 static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
 {
        ide_startstop_t startstop;
-       sector_t block;
 
        BUG_ON(!blk_rq_started(rq));
 
@@ -791,21 +833,12 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
                goto kill_rq;
        }
 
-       block    = rq->sector;
-       if (blk_fs_request(rq) &&
-           (drive->media == ide_disk || drive->media == ide_floppy)) {
-               block += drive->sect0;
-       }
-       /* Yecch - this will shift the entire interval,
-          possibly killing some innocent following sector */
-       if (block == 0 && drive->remap_0_to_1 == 1)
-               block = 1;  /* redirect MBR access to EZ-Drive partn table */
-
        if (blk_pm_request(rq))
                ide_check_pm_state(drive, rq);
 
        SELECT_DRIVE(drive);
-       if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
+       if (ide_wait_stat(&startstop, drive, drive->ready_stat,
+                         ATA_BUSY | ATA_DRQ, WAIT_READY)) {
                printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
                return startstop;
        }
@@ -844,7 +877,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
                        return ide_special_rq(drive, rq);
 
                drv = *(ide_driver_t **)rq->rq_disk->private_data;
-               return drv->do_request(drive, rq, block);
+
+               return drv->do_request(drive, rq, rq->sector);
        }
        return do_special(drive);
 kill_rq:
@@ -866,7 +900,7 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
        if (timeout > WAIT_WORSTCASE)
                timeout = WAIT_WORSTCASE;
        drive->sleep = timeout + jiffies;
-       drive->sleeping = 1;
+       drive->dev_flags |= IDE_DFLAG_SLEEPING;
 }
 
 EXPORT_SYMBOL(ide_stall_queue);
@@ -906,18 +940,23 @@ repeat:
        }
 
        do {
-               if ((!drive->sleeping || time_after_eq(jiffies, drive->sleep))
-                   && !elv_queue_empty(drive->queue)) {
-                       if (!best
-                        || (drive->sleeping && (!best->sleeping || time_before(drive->sleep, best->sleep)))
-                        || (!best->sleeping && time_before(WAKEUP(drive), WAKEUP(best))))
-                       {
+               u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING);
+               u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING));
+
+               if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) &&
+                   !elv_queue_empty(drive->queue)) {
+                       if (best == NULL ||
+                           (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) ||
+                           (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) {
                                if (!blk_queue_plugged(drive->queue))
                                        best = drive;
                        }
                }
        } while ((drive = drive->next) != hwgroup->drive);
-       if (best && best->nice1 && !best->sleeping && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
+
+       if (best && (best->dev_flags & IDE_DFLAG_NICE1) &&
+           (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 &&
+           best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
                long t = (signed long)(WAKEUP(best) - jiffies);
                if (t >= WAIT_MIN_SLEEP) {
                /*
@@ -926,7 +965,7 @@ repeat:
                 */
                        drive = best->next;
                        do {
-                               if (!drive->sleeping
+                               if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0
                                 && time_before(jiffies - best->service_time, WAKEUP(drive))
                                 && time_before(WAKEUP(drive), jiffies + t))
                                {
@@ -997,7 +1036,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
                        hwgroup->rq = NULL;
                        drive = hwgroup->drive;
                        do {
-                               if (drive->sleeping && (!sleeping || time_before(drive->sleep, sleep))) {
+                               if ((drive->dev_flags & IDE_DFLAG_SLEEPING) &&
+                                   (sleeping == 0 ||
+                                    time_before(drive->sleep, sleep))) {
                                        sleeping = 1;
                                        sleep = drive->sleep;
                                }
@@ -1046,7 +1087,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
                }
                hwgroup->hwif = hwif;
                hwgroup->drive = drive;
-               drive->sleeping = 0;
+               drive->dev_flags &= ~IDE_DFLAG_SLEEPING;
                drive->service_start = jiffies;
 
                if (blk_queue_plugged(drive->queue)) {
@@ -1080,7 +1121,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
                 * We count how many times we loop here to make sure we service
                 * all drives in the hwgroup without looping for ever
                 */
-               if (drive->blocked && !blk_pm_request(rq) && !(rq->cmd_flags & REQ_PREEMPT)) {
+               if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
+                   blk_pm_request(rq) == 0 &&
+                   (rq->cmd_flags & REQ_PREEMPT) == 0) {
                        drive = drive->next ? drive->next : hwgroup->drive;
                        if (loops++ < 4 && !blk_queue_plugged(drive->queue))
                                goto again;
@@ -1153,8 +1196,8 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
         * a timeout -- we'll reenable after we finish this next request
         * (or rather the first chunk of it) in pio.
         */
+       drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
        drive->retry_pio++;
-       drive->state = DMA_PIO_RETRY;
        ide_dma_off_quietly(drive);
 
        /*
@@ -1325,7 +1368,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
                if (hwif->irq == irq) {
                        stat = hwif->tp_ops->read_status(hwif);
 
-                       if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
+                       if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
                                /* Try to not flood the console with msgs */
                                static unsigned long last_msgtime, count;
                                ++count;
@@ -1462,7 +1505,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
                 */
                hwif->ide_dma_clear_irq(drive);
 
-       if (drive->unmask)
+       if (drive->dev_flags & IDE_DFLAG_UNMASK)
                local_irq_enable_in_hardirq();
        /* service this interrupt, may set handler for next interrupt */
        startstop = handler(drive);