]> Pileus Git - ~andy/linux/blobdiff - drivers/ide/ide-io.c
ide: remove IDE_ARCH_LOCK (v2)
[~andy/linux] / drivers / ide / ide-io.c
index a9a6c208288a27173970b705de620fea3e076294..030b0ea1a1e1c98f42386149432d1fd820054f86 100644 (file)
@@ -196,7 +196,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
 }
 EXPORT_SYMBOL(ide_end_drive_cmd);
 
-static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
+void ide_kill_rq(ide_drive_t *drive, struct request *rq)
 {
        if (rq->rq_disk) {
                struct ide_driver *drv;
@@ -207,133 +207,6 @@ static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
                ide_end_request(drive, 0, 0);
 }
 
-static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
-       ide_hwif_t *hwif = drive->hwif;
-
-       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 & ATA_ERR) {
-               /* err has different meaning on cdrom and tape */
-               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 & (ATA_BBK | ATA_UNC)) {
-                       /* retries won't help these */
-                       rq->errors = ERROR_MAX;
-               } else if (err & ATA_TRK0NF) {
-                       /* help it find track zero */
-                       rq->errors |= ERROR_RECAL;
-               }
-       }
-
-       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;
-
-               ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE);
-       }
-
-       if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
-               ide_kill_rq(drive, rq);
-               return ide_stopped;
-       }
-
-       if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
-               rq->errors |= ERROR_RESET;
-
-       if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
-               ++rq->errors;
-               return ide_do_reset(drive);
-       }
-
-       if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
-               drive->special.b.recalibrate = 1;
-
-       ++rq->errors;
-
-       return ide_stopped;
-}
-
-static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
-       ide_hwif_t *hwif = drive->hwif;
-
-       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) & (ATA_BUSY | ATA_DRQ))
-               /* force an abort */
-               hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
-
-       if (rq->errors >= ERROR_MAX) {
-               ide_kill_rq(drive, rq);
-       } else {
-               if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
-                       ++rq->errors;
-                       return ide_do_reset(drive);
-               }
-               ++rq->errors;
-       }
-
-       return ide_stopped;
-}
-
-static ide_startstop_t
-__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
-       if (drive->media == ide_disk)
-               return ide_ata_error(drive, rq, stat, err);
-       return ide_atapi_error(drive, rq, stat, err);
-}
-
-/**
- *     ide_error       -       handle an error on the IDE
- *     @drive: drive the error occurred on
- *     @msg: message to report
- *     @stat: status bits
- *
- *     ide_error() takes action based on the error returned by the drive.
- *     For normal I/O that may well include retries. We deal with
- *     both new-style (taskfile) and old style command handling here.
- *     In the case of taskfile command handling there is work left to
- *     do
- */
-ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
-{
-       struct request *rq;
-       u8 err;
-
-       err = ide_dump_status(drive, msg, stat);
-
-       rq = drive->hwif->rq;
-       if (rq == NULL)
-               return ide_stopped;
-
-       /* retry only "normal" I/O: */
-       if (!blk_fs_request(rq)) {
-               rq->errors = 1;
-               ide_end_drive_cmd(drive, stat, err);
-               return ide_stopped;
-       }
-
-       return __ide_error(drive, rq, stat, err);
-}
-EXPORT_SYMBOL_GPL(ide_error);
-
 static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
 {
        tf->nsect   = drive->sect;
@@ -490,71 +363,16 @@ 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_WAIT);
-       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)
 {
        u8 cmd = rq->cmd[0];
 
-       if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) {
-               ide_task_t task;
-               struct ide_taskfile *tf = &task.tf;
-
-               memset(&task, 0, sizeof(task));
-               if (cmd == REQ_PARK_HEADS) {
-                       drive->sleep = *(unsigned long *)rq->special;
-                       drive->dev_flags |= IDE_DFLAG_SLEEPING;
-                       tf->command = ATA_CMD_IDLEIMMEDIATE;
-                       tf->feature = 0x44;
-                       tf->lbal = 0x4c;
-                       tf->lbam = 0x4e;
-                       tf->lbah = 0x55;
-                       task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
-               } else          /* cmd == REQ_UNPARK_HEADS */
-                       tf->command = ATA_CMD_CHK_POWER;
-
-               task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-               task.rq = rq;
-               drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
-               return do_rw_taskfile(drive, &task);
-       }
-
        switch (cmd) {
+       case REQ_PARK_HEADS:
+       case REQ_UNPARK_HEADS:
+               return ide_do_park_unpark(drive, rq);
        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;
-       }
+               return ide_do_devset(drive, rq);
        case REQ_DRIVE_RESET:
                return ide_do_reset(drive);
        default:
@@ -683,8 +501,8 @@ static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif)
        if (host->host_flags & IDE_HFLAG_SERIALIZE) {
                rc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy);
                if (rc == 0) {
-                       /* for atari only */
-                       ide_get_lock(ide_intr, hwif);
+                       if (host->get_lock)
+                               host->get_lock(ide_intr, hwif);
                }
        }
        return rc;
@@ -693,8 +511,8 @@ static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif)
 static inline void ide_unlock_host(struct ide_host *host)
 {
        if (host->host_flags & IDE_HFLAG_SERIALIZE) {
-               /* for atari only */
-               ide_release_lock();
+               if (host->release_lock)
+                       host->release_lock();
                clear_bit_unlock(IDE_HOST_BUSY, &host->host_busy);
        }
 }
@@ -820,63 +638,6 @@ plug_device_2:
                blk_plug_device(q);
 }
 
-/*
- * un-busy the port etc, and clear any pending DMA status. we want to
- * retry the current request in pio mode instead of risking tossing it
- * all away
- */
-static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct request *rq;
-       ide_startstop_t ret = ide_stopped;
-
-       /*
-        * end current dma transaction
-        */
-
-       if (error < 0) {
-               printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
-               (void)hwif->dma_ops->dma_end(drive);
-               ret = ide_error(drive, "dma timeout error",
-                               hwif->tp_ops->read_status(hwif));
-       } else {
-               printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
-               hwif->dma_ops->dma_timeout(drive);
-       }
-
-       /*
-        * disable dma for now, but remember that we did so because of
-        * 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++;
-       ide_dma_off_quietly(drive);
-
-       /*
-        * un-busy drive etc and make sure request is sane
-        */
-
-       rq = hwif->rq;
-       if (!rq)
-               goto out;
-
-       hwif->rq = NULL;
-
-       rq->errors = 0;
-
-       if (!rq->bio)
-               goto out;
-
-       rq->sector = rq->bio->bi_sector;
-       rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
-       rq->hard_cur_sectors = rq->current_nr_sectors;
-       rq->buffer = bio_data(rq->bio);
-out:
-       return ret;
-}
-
 static void ide_plug_device(ide_drive_t *drive)
 {
        struct request_queue *q = drive->queue;
@@ -888,6 +649,29 @@ static void ide_plug_device(ide_drive_t *drive)
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
+static int drive_is_ready(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 stat = 0;
+
+       if (drive->waiting_for_dma)
+               return hwif->dma_ops->dma_test_irq(drive);
+
+       if (hwif->io_ports.ctl_addr &&
+           (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0)
+               stat = hwif->tp_ops->read_altstatus(hwif);
+       else
+               /* Note: this may clear a pending IRQ!! */
+               stat = hwif->tp_ops->read_status(hwif);
+
+       if (stat & ATA_BUSY)
+               /* drive busy: definitely not interrupting */
+               return 0;
+
+       /* drive ready: *might* be interrupting */
+       return 1;
+}
+
 /**
  *     ide_timer_expiry        -       handle lack of an IDE interrupt
  *     @data: timer callback magic (hwif)
@@ -955,7 +739,8 @@ void ide_timer_expiry (unsigned long data)
                } else if (drive_is_ready(drive)) {
                        if (drive->waiting_for_dma)
                                hwif->dma_ops->dma_lost_irq(drive);
-                       (void)ide_ack_intr(hwif);
+                       if (hwif->ack_intr)
+                               hwif->ack_intr(hwif);
                        printk(KERN_WARNING "%s: lost interrupt\n",
                                drive->name);
                        startstop = handler(drive);
@@ -1070,7 +855,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
 
        spin_lock_irqsave(&hwif->lock, flags);
 
-       if (!ide_ack_intr(hwif))
+       if (hwif->ack_intr && hwif->ack_intr(hwif) == 0)
                goto out;
 
        handler = hwif->handler;
@@ -1164,54 +949,6 @@ out_early:
 }
 EXPORT_SYMBOL_GPL(ide_intr);
 
-/**
- *     ide_do_drive_cmd        -       issue IDE special command
- *     @drive: device to issue command
- *     @rq: request to issue
- *
- *     This function issues a special IDE device request
- *     onto the request queue.
- *
- *     the rq is queued at the head of the request queue, displacing
- *     the currently-being-processed request and this function
- *     returns immediately without waiting for the new rq to be
- *     completed.  This is VERY DANGEROUS, and is intended for
- *     careful use by the ATAPI tape/cdrom driver code.
- */
-
-void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq)
-{
-       struct request_queue *q = drive->queue;
-       unsigned long flags;
-
-       drive->hwif->rq = NULL;
-
-       spin_lock_irqsave(q->queue_lock, flags);
-       __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
-       spin_unlock_irqrestore(q->queue_lock, flags);
-}
-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));
-       task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
-                       IDE_TFLAG_OUT_FEATURE | tf_flags;
-       task.tf.feature = dma;          /* Use PIO/DMA */
-       task.tf.lbam    = bcount & 0xff;
-       task.tf.lbah    = (bcount >> 8) & 0xff;
-
-       ide_tf_dump(drive->name, &task.tf);
-       hwif->tp_ops->set_irq(hwif, 1);
-       SELECT_MASK(drive, 0);
-       hwif->tp_ops->tf_load(drive, &task);
-}
-
-EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
-
 void ide_pad_transfer(ide_drive_t *drive, int write, int len)
 {
        ide_hwif_t *hwif = drive->hwif;