]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-io.c
ide: Remove ide_spin_wait_hwgroup() and use special requests instead
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-io.c
index 661b75a89d4dc4d2227a09d3ce69819a6132e42e..1c51949833be5ed17e71bde14a0fa8b55b0e47ee 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>
@@ -183,18 +184,18 @@ 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 (!drive->wcache || ata_id_flush_enabled(drive->id) == 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 +210,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) */
@@ -322,7 +323,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;
@@ -330,7 +331,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
                        tf->error = err;
                        tf->status = stat;
 
-                       drive->hwif->tf_read(drive, task);
+                       drive->hwif->tp_ops->tf_read(drive, task);
 
                        if (task->tf_flags & IDE_TFLAG_DYN)
                                kfree(task);
@@ -373,30 +374,29 @@ 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->nowerr)) {
                /* 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 (err == ATA_ABORTED) {
                        if (drive->select.b.lba &&
-                           /* some newer drives don't support WIN_SPECIFY */
-                           hwif->INB(hwif->io_ports.command_addr) ==
-                               WIN_SPECIFY)
+                           /* 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;
 
@@ -408,7 +408,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
                return ide_stopped;
        }
 
-       if (ide_read_status(drive) & (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) {
@@ -428,17 +428,16 @@ 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->nowerr)) {
                /* other bits are useless when BUSY */
                rq->errors |= ERROR_RESET;
        } else {
                /* add decoding error stuff */
        }
 
-       if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+       if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
                /* force an abort */
-               hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE,
-                              hwif->io_ports.command_addr);
+               hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
 
        if (rq->errors >= ERROR_MAX) {
                ide_kill_rq(drive, rq);
@@ -511,19 +510,19 @@ static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
        tf->lbam    = drive->cyl;
        tf->lbah    = drive->cyl >> 8;
        tf->device  = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
-       tf->command = WIN_SPECIFY;
+       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)
@@ -542,8 +541,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;
@@ -588,9 +585,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)
@@ -712,14 +710,55 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
 #ifdef DEBUG
        printk("%s: DRIVE_CMD (null)\n", drive->name);
 #endif
-       ide_end_drive_cmd(drive, ide_read_status(drive), ide_read_error(drive));
+       ide_end_drive_cmd(drive, hwif->tp_ops->read_status(hwif),
+                         ide_read_error(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:
@@ -747,16 +786,17 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
                 * the bus may be broken enough to walk on our toes at this
                 * point.
                 */
+               ide_hwif_t *hwif = drive->hwif;
                int rc;
 #ifdef DEBUG_PM
                printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
 #endif
-               rc = ide_wait_not_busy(HWIF(drive), 35000);
+               rc = ide_wait_not_busy(hwif, 35000);
                if (rc)
                        printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
                SELECT_DRIVE(drive);
-               ide_set_irq(drive, 1);
-               rc = ide_wait_not_busy(HWIF(drive), 100000);
+               hwif->tp_ops->set_irq(hwif, 1);
+               rc = ide_wait_not_busy(hwif, 100000);
                if (rc)
                        printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
        }
@@ -766,9 +806,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 +814,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 +828,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 +872,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:
@@ -1042,7 +1071,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
                         * quirk_list may not like intr setups/cleanups
                         */
                        if (drive->quirk_list != 1)
-                               ide_set_irq(drive, 0);
+                               hwif->tp_ops->set_irq(hwif, 0);
                }
                hwgroup->hwif = hwif;
                hwgroup->drive = drive;
@@ -1142,7 +1171,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
                printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
                (void)hwif->dma_ops->dma_end(drive);
                ret = ide_error(drive, "dma timeout error",
-                               ide_read_status(drive));
+                               hwif->tp_ops->read_status(hwif));
        } else {
                printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
                hwif->dma_ops->dma_timeout(drive);
@@ -1267,7 +1296,7 @@ void ide_timer_expiry (unsigned long data)
                                } else
                                        startstop =
                                        ide_error(drive, "irq timeout",
-                                                 ide_read_status(drive));
+                                                 hwif->tp_ops->read_status(hwif));
                        }
                        drive->service_time = jiffies - drive->service_start;
                        spin_lock_irq(&ide_lock);
@@ -1323,8 +1352,9 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
         */
        do {
                if (hwif->irq == irq) {
-                       stat = hwif->INB(hwif->io_ports.status_addr);
-                       if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
+                       stat = hwif->tp_ops->read_status(hwif);
+
+                       if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
                                /* Try to not flood the console with msgs */
                                static unsigned long last_msgtime, count;
                                ++count;
@@ -1413,7 +1443,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
                         * Whack the status register, just in case
                         * we have a leftover pending IRQ.
                         */
-                       (void) hwif->INB(hwif->io_ports.status_addr);
+                       (void)hwif->tp_ops->read_status(hwif);
 #endif /* CONFIG_BLK_DEV_IDEPCI */
                }
                spin_unlock_irqrestore(&ide_lock, flags);
@@ -1519,6 +1549,7 @@ EXPORT_SYMBOL(ide_do_drive_cmd);
 
 void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
 {
+       ide_hwif_t *hwif = drive->hwif;
        ide_task_t task;
 
        memset(&task, 0, sizeof(task));
@@ -1529,9 +1560,9 @@ void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
        task.tf.lbah    = (bcount >> 8) & 0xff;
 
        ide_tf_dump(drive->name, &task.tf);
-       ide_set_irq(drive, 1);
+       hwif->tp_ops->set_irq(hwif, 1);
        SELECT_MASK(drive, 0);
-       drive->hwif->tf_load(drive, &task);
+       hwif->tp_ops->tf_load(drive, &task);
 }
 
 EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
@@ -1543,9 +1574,9 @@ void ide_pad_transfer(ide_drive_t *drive, int write, int len)
 
        while (len > 0) {
                if (write)
-                       hwif->output_data(drive, NULL, buf, min(4, len));
+                       hwif->tp_ops->output_data(drive, NULL, buf, min(4, len));
                else
-                       hwif->input_data(drive, NULL, buf, min(4, len));
+                       hwif->tp_ops->input_data(drive, NULL, buf, min(4, len));
                len -= 4;
        }
 }