SSB PCI core driver: use new SPROM data structure
[safe/jmp/linux-2.6] / drivers / ide / ide-io.c
index f4f7e3d..7153796 100644 (file)
@@ -58,15 +58,19 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
                             int uptodate, unsigned int nr_bytes, int dequeue)
 {
        int ret = 1;
+       int error = 0;
+
+       if (uptodate <= 0)
+               error = uptodate ? uptodate : -EIO;
 
        /*
         * if failfast is set on a request, override number of sectors and
         * complete the whole request right now
         */
-       if (blk_noretry_request(rq) && end_io_error(uptodate))
+       if (blk_noretry_request(rq) && error)
                nr_bytes = rq->hard_nr_sectors << 9;
 
-       if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
+       if (!blk_fs_request(rq) && error && !rq->errors)
                rq->errors = -EIO;
 
        /*
@@ -75,17 +79,12 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
         */
        if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
                drive->state = 0;
-               HWGROUP(drive)->hwif->ide_dma_on(drive);
+               ide_dma_on(drive);
        }
 
-       if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
-               add_disk_randomness(rq->rq_disk);
-               if (dequeue) {
-                       if (!list_empty(&rq->queuelist))
-                               blkdev_dequeue_request(rq);
+       if (!__blk_end_request(rq, error, nr_bytes)) {
+               if (dequeue)
                        HWGROUP(drive)->rq = NULL;
-               }
-               end_that_request_last(rq, uptodate);
                ret = 0;
        }
 
@@ -219,9 +218,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
                 * we could be smarter and check for current xfer_speed
                 * in struct drive etc...
                 */
-               if (drive->hwif->ide_dma_on == NULL)
+               if (drive->hwif->dma_host_set == NULL)
                        break;
-               drive->hwif->dma_off_quietly(drive);
                /*
                 * TODO: respect ->using_dma setting
                 */
@@ -232,9 +230,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
        return ide_stopped;
 
 out_do_tf:
-       args->tf_flags   = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
+       args->tf_flags   = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
        args->data_phase = TASKFILE_NO_DATA;
-       args->handler    = task_no_data_intr;
        return do_rw_taskfile(drive, args);
 }
 
@@ -292,12 +289,54 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
                drive->blocked = 0;
                blk_start_queue(drive->queue);
        }
-       blkdev_dequeue_request(rq);
        HWGROUP(drive)->rq = NULL;
-       end_that_request_last(rq, 1);
+       if (__blk_end_request(rq, 0, 0))
+               BUG();
        spin_unlock_irqrestore(&ide_lock, flags);
 }
 
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_taskfile *tf = &task->tf;
+
+       if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+               u16 data = hwif->INW(IDE_DATA_REG);
+
+               tf->data = data & 0xff;
+               tf->hob_data = (data >> 8) & 0xff;
+       }
+
+       /* be sure we're looking at the low order bits */
+       hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
+
+       if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+               tf->nsect  = hwif->INB(IDE_NSECTOR_REG);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+               tf->lbal   = hwif->INB(IDE_SECTOR_REG);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+               tf->lbam   = hwif->INB(IDE_LCYL_REG);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+               tf->lbah   = hwif->INB(IDE_HCYL_REG);
+       if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+               tf->device = hwif->INB(IDE_SELECT_REG);
+
+       if (task->tf_flags & IDE_TFLAG_LBA48) {
+               hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
+
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+                       tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+                       tf->hob_nsect   = hwif->INB(IDE_NSECTOR_REG);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+                       tf->hob_lbal    = hwif->INB(IDE_SECTOR_REG);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+                       tf->hob_lbam    = hwif->INB(IDE_LCYL_REG);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+                       tf->hob_lbah    = hwif->INB(IDE_HCYL_REG);
+       }
+}
+
 /**
  *     ide_end_drive_cmd       -       end an explicit drive command
  *     @drive: command 
@@ -314,7 +353,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
  
 void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
 {
-       ide_hwif_t *hwif = HWIF(drive);
        unsigned long flags;
        struct request *rq;
 
@@ -322,48 +360,22 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
        rq = HWGROUP(drive)->rq;
        spin_unlock_irqrestore(&ide_lock, flags);
 
-       if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
-               u8 *args = (u8 *) rq->buffer;
-               if (rq->errors == 0)
-                       rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+       if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
+               ide_task_t *task = (ide_task_t *)rq->special;
 
-               if (args) {
-                       args[0] = stat;
-                       args[1] = err;
-                       args[2] = hwif->INB(IDE_NSECTOR_REG);
-               }
-       } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-               ide_task_t *args = (ide_task_t *) rq->special;
                if (rq->errors == 0)
-                       rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-                       
-               if (args) {
-                       struct ide_taskfile *tf = &args->tf;
+                       rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT);
 
-                       if (args->tf_in_flags.b.data) {
-                               u16 data = hwif->INW(IDE_DATA_REG);
+               if (task) {
+                       struct ide_taskfile *tf = &task->tf;
 
-                               tf->data = data & 0xff;
-                               tf->hob_data = (data >> 8) & 0xff;
-                       }
                        tf->error = err;
-                       /* be sure we're looking at the low order bits */
-                       hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
-                       tf->nsect  = hwif->INB(IDE_NSECTOR_REG);
-                       tf->lbal   = hwif->INB(IDE_SECTOR_REG);
-                       tf->lbam   = hwif->INB(IDE_LCYL_REG);
-                       tf->lbah   = hwif->INB(IDE_HCYL_REG);
-                       tf->device = hwif->INB(IDE_SELECT_REG);
                        tf->status = stat;
 
-                       if (args->tf_flags & IDE_TFLAG_LBA48) {
-                               hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
-                               tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
-                               tf->hob_nsect   = hwif->INB(IDE_NSECTOR_REG);
-                               tf->hob_lbal    = hwif->INB(IDE_SECTOR_REG);
-                               tf->hob_lbam    = hwif->INB(IDE_LCYL_REG);
-                               tf->hob_lbah    = hwif->INB(IDE_HCYL_REG);
-                       }
+                       ide_tf_read(drive, task);
+
+                       if (task->tf_flags & IDE_TFLAG_DYN)
+                               kfree(task);
                }
        } else if (blk_pm_request(rq)) {
                struct request_pm_state *pm = rq->data;
@@ -378,10 +390,11 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
        }
 
        spin_lock_irqsave(&ide_lock, flags);
-       blkdev_dequeue_request(rq);
        HWGROUP(drive)->rq = NULL;
        rq->errors = err;
-       end_that_request_last(rq, !rq->errors);
+       if (unlikely(__blk_end_request(rq, (rq->errors ? -EIO : 0),
+                                      blk_rq_bytes(rq))))
+               BUG();
        spin_unlock_irqrestore(&ide_lock, flags);
 }
 
@@ -458,7 +471,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
                return ide_stopped;
        }
 
-       if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
+       if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
                rq->errors |= ERROR_RESET;
 
        if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
@@ -485,7 +498,7 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
                /* add decoding error stuff */
        }
 
-       if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
+       if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
                /* force an abort */
                hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
 
@@ -602,68 +615,26 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
                return __ide_abort(drive, rq);
 }
 
-/**
- *     drive_cmd_intr          -       drive command completion interrupt
- *     @drive: drive the completion interrupt occurred on
- *
- *     drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
- *     We do any necessary data reading and then wait for the drive to
- *     go non busy. At that point we may read the error data and complete
- *     the request
- */
-static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
+static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
 {
-       struct request *rq = HWGROUP(drive)->rq;
-       ide_hwif_t *hwif = HWIF(drive);
-       u8 *args = (u8 *) rq->buffer;
-       u8 stat = hwif->INB(IDE_STATUS_REG);
-       int retries = 10;
-
-       local_irq_enable_in_hardirq();
-       if (rq->cmd_type == REQ_TYPE_ATA_CMD &&
-           (stat & DRQ_STAT) && args && args[3]) {
-               u8 io_32bit = drive->io_32bit;
-               drive->io_32bit = 0;
-               hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS);
-               drive->io_32bit = io_32bit;
-               while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
-                       udelay(100);
-       }
-
-       if (!OK_STAT(stat, READY_STAT, BAD_STAT))
-               return ide_error(drive, "drive_cmd", stat);
-               /* calls ide_end_drive_cmd */
-       ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
-       return ide_stopped;
+       tf->nsect   = drive->sect;
+       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;
 }
 
-static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task)
+static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
 {
-       task->tf.nsect   = drive->sect;
-       task->tf.lbal    = drive->sect;
-       task->tf.lbam    = drive->cyl;
-       task->tf.lbah    = drive->cyl >> 8;
-       task->tf.device  = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
-       task->tf.command = WIN_SPECIFY;
-
-       task->handler = &set_geometry_intr;
+       tf->nsect   = drive->sect;
+       tf->command = WIN_RESTORE;
 }
 
-static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task)
+static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
 {
-       task->tf.nsect   = drive->sect;
-       task->tf.command = WIN_RESTORE;
-
-       task->handler = &recal_intr;
-}
-
-static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task)
-{
-       task->tf.nsect   = drive->mult_req;
-       task->tf.command = WIN_SETMULT;
-
-       task->handler = &set_multmode_intr;
+       tf->nsect   = drive->mult_req;
+       tf->command = WIN_SETMULT;
 }
 
 static ide_startstop_t ide_disk_special(ide_drive_t *drive)
@@ -676,15 +647,15 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
 
        if (s->b.set_geometry) {
                s->b.set_geometry = 0;
-               ide_init_specify_cmd(drive, &args);
+               ide_tf_set_specify_cmd(drive, &args.tf);
        } else if (s->b.recalibrate) {
                s->b.recalibrate = 0;
-               ide_init_restore_cmd(drive, &args);
+               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_init_setmult_cmd(drive, &args);
+               ide_tf_set_setmult_cmd(drive, &args.tf);
        } else if (s->all) {
                int special = s->all;
                s->all = 0;
@@ -692,7 +663,8 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
                return ide_stopped;
        }
 
-       args.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
+       args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE |
+                       IDE_TFLAG_CUSTOM_HANDLER;
 
        do_rw_taskfile(drive, &args);
 
@@ -768,7 +740,7 @@ static ide_startstop_t do_special (ide_drive_t *drive)
 
                        if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
                                if (keep_dma)
-                                       hwif->ide_dma_on(drive);
+                                       ide_dma_on(drive);
                        }
                }
 
@@ -828,16 +800,9 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
                struct request *rq)
 {
        ide_hwif_t *hwif = HWIF(drive);
-       u8 *args = rq->buffer;
-       ide_task_t ltask;
-       struct ide_taskfile *tf = &ltask.tf;
-
-       if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-               ide_task_t *task = rq->special;
-               if (task == NULL)
-                       goto done;
+       ide_task_t *task = rq->special;
 
+       if (task) {
                hwif->data_phase = task->data_phase;
 
                switch (hwif->data_phase) {
@@ -851,39 +816,9 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
                        break;
                }
 
-               if (task->tf_flags & IDE_TFLAG_FLAGGED)
-                       return flagged_taskfile(drive, task);
-
                return do_rw_taskfile(drive, task);
        }
 
-       if (args == NULL)
-               goto done;
-
-       memset(&ltask, 0, sizeof(ltask));
-       if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
-#ifdef DEBUG
-               printk("%s: DRIVE_CMD\n", drive->name);
-#endif
-               tf->feature = args[2];
-               if (args[0] == WIN_SMART) {
-                       tf->nsect = args[3];
-                       tf->lbal  = args[1];
-                       tf->lbam  = 0x4f;
-                       tf->lbah  = 0xc2;
-                       ltask.tf_flags = IDE_TFLAG_OUT_TF;
-               } else {
-                       tf->nsect = args[1];
-                       ltask.tf_flags = IDE_TFLAG_OUT_FEATURE |
-                                        IDE_TFLAG_OUT_NSECT;
-               }
-       }
-       tf->command = args[0];
-       ide_tf_load(drive, &ltask);
-       ide_execute_command(drive, args[0], &drive_cmd_intr, WAIT_WORSTCASE, NULL);
-       return ide_started;
-
-done:
        /*
         * NULL is actually a valid way of waiting for
         * all current requests to be flushed from the queue.
@@ -891,9 +826,8 @@ done:
 #ifdef DEBUG
        printk("%s: DRIVE_CMD (null)\n", drive->name);
 #endif
-       ide_end_drive_cmd(drive,
-                       hwif->INB(IDE_STATUS_REG),
-                       hwif->INB(IDE_ERROR_REG));
+       ide_end_drive_cmd(drive, ide_read_status(drive), ide_read_error(drive));
+
        return ide_stopped;
 }
 
@@ -923,8 +857,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
                if (rc)
                        printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
                SELECT_DRIVE(drive);
-               if (IDE_CONTROL_REG)
-                       HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
+               ide_set_irq(drive, 1);
                rc = ide_wait_not_busy(HWIF(drive), 100000);
                if (rc)
                        printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
@@ -988,8 +921,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
                if (drive->current_speed == 0xff)
                        ide_config_drive_speed(drive, drive->desired_speed);
 
-               if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
-                   rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
+               if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
                        return execute_drive_cmd(drive, rq);
                else if (blk_pm_request(rq)) {
                        struct request_pm_state *pm = rq->data;
@@ -1197,15 +1129,13 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
                }
        again:
                hwif = HWIF(drive);
-               if (hwgroup->hwif->sharing_irq &&
-                   hwif != hwgroup->hwif &&
-                   hwif->io_ports[IDE_CONTROL_OFFSET]) {
+               if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) {
                        /*
                         * set nIEN for previous hwif, drives in the
                         * quirk_list may not like intr setups/cleanups
                         */
                        if (drive->quirk_list != 1)
-                               hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);
+                               ide_set_irq(drive, 0);
                }
                hwgroup->hwif = hwif;
                hwgroup->drive = drive;
@@ -1305,7 +1235,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(drive)->ide_dma_end(drive);
                ret = ide_error(drive, "dma timeout error",
-                                               hwif->INB(IDE_STATUS_REG));
+                               ide_read_status(drive));
        } else {
                printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
                hwif->dma_timeout(drive);
@@ -1318,7 +1248,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
         */
        drive->retry_pio++;
        drive->state = DMA_PIO_RETRY;
-       hwif->dma_off_quietly(drive);
+       ide_dma_off_quietly(drive);
 
        /*
         * un-busy drive etc (hwgroup->busy is cleared on return) and
@@ -1429,7 +1359,8 @@ void ide_timer_expiry (unsigned long data)
                                        startstop = ide_dma_timeout_retry(drive, wait);
                                } else
                                        startstop =
-                                       ide_error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
+                                       ide_error(drive, "irq timeout",
+                                                 ide_read_status(drive));
                        }
                        drive->service_time = jiffies - drive->service_start;
                        spin_lock_irq(&ide_lock);
@@ -1561,7 +1492,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
                 * remove all the ifdef PCI crap
                 */
 #ifdef CONFIG_BLK_DEV_IDEPCI
-               if (hwif->pci_dev && !hwif->pci_dev->vendor)
+               if (hwif->chipset != ide_pci)
 #endif /* CONFIG_BLK_DEV_IDEPCI */
                {
                        /*
@@ -1663,7 +1594,6 @@ irqreturn_t ide_intr (int irq, void *dev_id)
 void ide_init_drive_cmd (struct request *rq)
 {
        memset(rq, 0, sizeof(*rq));
-       rq->cmd_type = REQ_TYPE_ATA_CMD;
        rq->ref_count = 1;
 }