]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] 2.5.26 IDE 99
authorMartin Dalecki <dalecki@evision-ventures.com>
Fri, 19 Jul 2002 02:26:04 +0000 (19:26 -0700)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Fri, 19 Jul 2002 02:26:04 +0000 (19:26 -0700)
Most noticable in the patch:

1. we handle IRQ sharing now better then ever

2. survives quite a lot of testing by few people. Forexample
cat /dev/hdb > /dev/null, where /dev/hdb contains a CD-ROM
with a big cratch on the surface making sure it's broken :-).
it's BTW. amanzing how wide the cratch had to be until errors
ocurred.

3. Doesn't play with rq_rdev and friends

Fri Jul 12 05:04:32 CEST 2002 ide-clean-99

- Push nIEN disabling down at the place where we are finished with a particular
   request.

- First round of command line parser cleanups by Gerald Champagne.

- Unfold the drive eviction functions in do_request(). This allowed us to
   realize that we don't have to re-get the major/minor numbers of the device we
   are action on from the raw device field of the currently running request. One
   significant place less in kernel where major/minor data gets manipulated.

- Move the big IDE_BUSY loop out of do_request to do_ide_request().  This makes
   us realize that we don't have to clear the IDE_BUSY bit just before
   reentering do_request to look for more requests still pending on the queue
   and set it immediately again.

   This is fixing a tinny race on the code path from IRQ or timer function,
   where we had a tinny window between the clearing of the IDE_BUSY bit and
   reentering the request queue for completely unrelated requests to come in to
   our way.

- Don't return any value in do_reset1(). It's always ATA_OP_CONTINUES. Split it
   up in to two functions one for disks (well in fact channels) and one for
   ATAPI devices. It turns out that they can be moved to the places where they
   are used to clarify the code flow. The only function remaining is
   do_reset_channel() now.

- Duplicate code from ide_do_drive_code explicitely in ide_raw_taskfile().
   Simplify ide_raw_taskfile() thereafter. Realize that ide_do_drive_cmd()
   is now only used by ATAPI devices. Move it therefore to atapi.c.

- Do busy polling for ATAPI reset operations. This is much safer then the
   previous timer games played there. It simply doesn't make sense to give the
   bus up during such a subtile operation. We don't have to disable IRQs here as
   well, since we are already under the protection of the do_request mechanisms.
   (Well hopefully...)

- Remove no longer used reset_poll() function. poll_timeout and friends are now
   used only in pdc4030 code. Those function where not called from IRQ context
   but they where set as handlers and not as expiry functions.

- Return ATA_OP_CONTINUES instead of ATA_OP_FINISHED in ata_error(), to signal
   that we are willing to retry the operation until the maximal number of retry
   attempts is exceeded. Returning ATA_OP_FINISHED without prior end_request()
   hangs the system.

- Apply trivia from DJ patch set.

- Apply small configuration fix to ide-pci.c from Muli Ben-Yehuda.

- Feed add_blkdev_randomness with information we already have in struct
   ata_channel *ch->major, instead of using the major(macro) on the request in
   question.

- Make ide_raw_taskfile use the same request submission mechanism as
   tcq_invalidate_queue(). Something similar would be ideal for ioctl() code as
   well.

- Implement actual device reset. Realize that the recalibration procedure is
   doomed by the standard. Don't try to recover by recalibrating devices
   therefore -just our retry mechanism should work in those cases. And suddenly
   the error handling code is IRQ safe.

- Reinvent the ATA reset operation, since it is apparently needed. We still
   have to do the whole transfer timing reconfiguration there.

- Move drive_is_ready(), which is in reality an attempt to check for IRQ
   requesters without clearing the IRQ line, over to the place where it belongs:
   device.c, which is the direct device access abstraction place.  Rename it to
   ata_status_irq() to prevent global name space pollution.

- Updates to the pdc202xxx host chip controller setup code by Bart³omiej
   ¯o³nierkiewicz:

   Forward port 2.4 patch by Hank Yang from Promise:

- Add PDC20271 support
- Disable LBA48 support on PDC20262
- Fix ATAPI UDMA port value
- Add new quirk drive
- Adjust timings for all drives when using ATA133
- Update pdc202xx_reset() waiting time

- Mark TCQ as dangerous and add some bits about it to the help.

- Add some missing exports.

- Some small ide-scsi.c host allocation fixes by sullivan.

26 files changed:
drivers/ide/Config.help
drivers/ide/Config.in
drivers/ide/atapi.c
drivers/ide/device.c
drivers/ide/gayle.c
drivers/ide/hd.c
drivers/ide/ide-cd.c
drivers/ide/ide-disk.c
drivers/ide/ide-floppy.c
drivers/ide/ide-m8xx.c
drivers/ide/ide-pci.c
drivers/ide/ide-tape.c
drivers/ide/ide-taskfile.c
drivers/ide/ide.c
drivers/ide/main.c
drivers/ide/pcidma.c
drivers/ide/pdc202xx.c
drivers/ide/pdc4030.c
drivers/ide/pdcraid.c
drivers/ide/probe.c
drivers/ide/tcq.c
drivers/ide/umc8672.c
drivers/scsi/ide-scsi.c
include/linux/atapi.h
include/linux/ide.h
include/linux/pci_ids.h

index b1eefd90f5c0ab6bdbe1b51e7097e1d9c0cefca8..74668ed23673f5b01a75e210a761d13f344512bf 100644 (file)
@@ -708,7 +708,14 @@ CONFIG_BLK_DEV_IDE_TCQ
   Digital drives in the Expert series (by nature of really being IBM
   drives).
 
-  If you have such a drive, say Y here.
+  However, please, note that there are host chip controllers which will
+  not cooperate properly if TCQ is enabled. This may cause serious
+  data loss!
+
+  Since enabling TCQ doesn't appear to have any noticeable performance
+  impact on Linux: [feel free to correct me if you wish too please]
+  
+  Generally say N here.
 
 CONFIG_BLK_DEV_IDE_TCQ_DEPTH
   Maximum size of commands to enable per-drive. Any value between 1
index 77ebacac5de2d119f8d1ecfb3fd0b22fa0feab46..f2c8fe680de17a83904251ce62d194d58db462f9 100644 (file)
@@ -34,7 +34,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
       dep_bool '      Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI
       dep_bool '      Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO
       define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI
-      dep_bool '    ATA tagged command queueing (EXPERIMENTAL)' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
+      dep_bool '    ATA tagged command queueing (DANGEROUS)' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
       dep_bool '      TCQ on by default' CONFIG_BLK_DEV_IDE_TCQ_DEFAULT $CONFIG_BLK_DEV_IDE_TCQ
       if [ "$CONFIG_BLK_DEV_IDE_TCQ" != "n" ]; then
          int '      Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32
index 8f11dc822d28eabc45e4474116d4325f2e673fff..fdcd3c92ec8f7b77ba44024f91791a28af549a3b 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/blkdev.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/completion.h>
 #include <linux/cdrom.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
@@ -115,6 +116,66 @@ void atapi_write(struct ata_device *drive, u8 *buf, unsigned int n)
                outsw(IDE_DATA_REG, buf + (n & ~0x03), 1);
 }
 
+
+/*
+ * This function issues a special IDE device request onto the request queue.
+ *
+ * If action is ide_wait, then the rq is queued at the end of the request
+ * queue, and the function sleeps until it has been processed.  This is for use
+ * when invoked from an ioctl handler.
+ *
+ * If action is ide_preempt, then 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.
+ *
+ * If action is ide_end, then the rq is queued at the end of the request queue,
+ * and the function returns immediately without waiting for the new rq to be
+ * completed. This is again intended for careful use by the ATAPI tape/cdrom
+ * driver code.
+ */
+int ide_do_drive_cmd(struct ata_device *drive, struct request *rq, ide_action_t action)
+{
+       unsigned long flags;
+       struct ata_channel *ch = drive->channel;
+       unsigned int major = ch->major;
+       request_queue_t *q = &drive->queue;
+       struct list_head *queue_head = &q->queue_head;
+       DECLARE_COMPLETION(wait);
+
+#ifdef CONFIG_BLK_DEV_PDC4030
+       if (ch->chipset == ide_pdc4030 && rq->buffer)
+               return -ENOSYS;  /* special drive cmds not supported */
+#endif
+       rq->errors = 0;
+       rq->rq_status = RQ_ACTIVE;
+       rq->rq_dev = mk_kdev(major, (drive->select.b.unit) << PARTN_BITS);
+       if (action == ide_wait)
+               rq->waiting = &wait;
+
+       spin_lock_irqsave(ch->lock, flags);
+
+       if (action == ide_preempt)
+               drive->rq = NULL;
+       else if (!blk_queue_empty(&drive->queue))
+               queue_head = queue_head->prev;  /* ide_end and ide_wait */
+
+       __elv_add_request(q, rq, queue_head);
+
+       do_ide_request(q);
+
+       spin_unlock_irqrestore(ch->lock, flags);
+
+       if (action == ide_wait) {
+               wait_for_completion(&wait);     /* wait for it to be serviced */
+               return rq->errors ? -EIO : 0;   /* return -EIO if errors */
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(ide_do_drive_cmd);
 EXPORT_SYMBOL(atapi_discard_data);
 EXPORT_SYMBOL(atapi_write_zeros);
 EXPORT_SYMBOL(atapi_init_pc);
index cd457931a8e2ba1f965698f2f75b74acc2647d88..5cdf3f957094078d29d6250e5dbf28b7dd35d50f 100644 (file)
@@ -79,6 +79,8 @@ void ata_mask(struct ata_device *drive)
                ch->maskproc(drive);
 }
 
+EXPORT_SYMBOL(ata_mask);
+
 /*
  * Check the state of the status register.
  */
@@ -93,6 +95,39 @@ int ata_status(struct ata_device *drive, u8 good, u8 bad)
 
 EXPORT_SYMBOL(ata_status);
 
+/*
+ * This is used to check for the drive status on the IRQ handling code path.
+ */
+int ata_status_irq(struct ata_device *drive)
+{
+       if (test_bit(IDE_DMA, drive->channel->active))
+               return udma_irq_status(drive);
+
+       /* Need to guarantee 400ns since last command was issued?
+        */
+#ifdef CONFIG_IDEPCI_SHARE_IRQ
+
+       /*
+        * We do a passive status test under shared PCI interrupts on cards
+        * that truly share the ATA side interrupt, but may also share an
+        * interrupt with another pci card/device.
+        */
+
+       if (drive->channel->io_ports[IDE_CONTROL_OFFSET])
+               drive->status = IN_BYTE(drive->channel->io_ports[IDE_CONTROL_OFFSET]);
+
+       else
+#endif
+               ata_status(drive, 0, 0);        /* Note: this may clear a pending IRQ! */
+
+       if (drive->status & BUSY_STAT)
+               return 0;       /* drive busy:  definitely not interrupting */
+       else
+               return 1;       /* drive ready: *might* be interrupting */
+}
+
+EXPORT_SYMBOL(ata_status_irq);
+
 /*
  * Busy-wait for the drive status to be not "busy".  Check then the status for
  * all of the "good" bits and none of the "bad" bits, and if all is okay it
@@ -210,6 +245,8 @@ void ata_out_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf)
        OUT_BYTE(rf->high_cylinder, ch->io_ports[IDE_HCYL_OFFSET]);
 }
 
+EXPORT_SYMBOL(ata_out_regfile);
+
 /*
  * Input a complete register file.
  */
@@ -223,5 +260,4 @@ void ata_in_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf)
        rf->high_cylinder = IN_BYTE(ch->io_ports[IDE_HCYL_OFFSET]);
 }
 
-
 MODULE_LICENSE("GPL");
index caf98d595c8c659783e921048414dd3a8f090082..abfab0e8e59e6c17eb1f33eda2028f168ae136c5 100644 (file)
@@ -106,9 +106,9 @@ static int gayle_ack_intr_a1200(struct ata_channel *hwif)
     return 1;
 }
 
-    /*
    *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
    */
+/*
+ *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
+ */
 
 void __init gayle_init(void)
 {
@@ -122,7 +122,7 @@ void __init gayle_init(void)
 
     for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
        ide_ioreg_t base, ctrlport, irqport;
-       ide_ack_intr_t *ack_intr;
+       int (*ack_intr)(struct ata_channel *);
        hw_regs_t hw;
        int index;
        unsigned long phys_base, res_start, res_n;
index 7fd714eb9765229f2e20b95a7d5c65bfe4962e99..7a1663772b8754e9c74eb716b64a2dd787814776 100644 (file)
@@ -132,16 +132,16 @@ unsigned long last_req;
 
 unsigned long read_timer(void)
 {
+        extern spinlock_t i8253_lock;
        unsigned long t, flags;
        int i;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&i8253_lock, flags);
        t = jiffies * 11932;
        outb_p(0, 0x43);
        i = inb_p(0x40);
        i |= inb(0x40) << 8;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&i8253_lock, flags);
        return(t - i);
 }
 #endif
@@ -817,8 +817,19 @@ static void __init hd_geninit(void)
                NR_HD = 0;
                return;
        }
-       request_region(HD_DATA, 8, "hd");
-       request_region(HD_CMD, 1, "hd(cmd)");
+       if (!request_region(HD_DATA, 8, "hd")) {
+               printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
+               NR_HD = 0;
+               free_irq(HD_IRQ, NULL);
+               return;
+       }
+       if (!request_region(HD_CMD, 1, "hd(cmd)")) {
+               printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
+               NR_HD = 0;
+               free_irq(HD_IRQ, NULL);
+               release_region(HD_DATA, 8);
+               return;
+       }
 
        hd_gendisk.nr_real = NR_HD;
 
index 4e9b658002c23ba9a05b83eef125b8e99f4a4591..70917c42b27f8a0a49554eab9bdd343d556c192d 100644 (file)
@@ -556,7 +556,7 @@ static void cdrom_end_request(struct ata_device *drive, struct request *rq, int
        if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors)
                uptodate = 1;
 
-       __ata_end_request(drive, rq, uptodate, 0);
+       ata_end_request(drive, rq, uptodate, 0);
 }
 
 
@@ -912,7 +912,7 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request
 
        if (dma) {
                if (!dma_error) {
-                       __ata_end_request(drive, rq, 1, rq->nr_sectors);
+                       ata_end_request(drive, rq, 1, rq->nr_sectors);
 
                        return ATA_OP_FINISHED;
                } else
@@ -1497,7 +1497,7 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request
                if (dma_error)
                        return ata_error(drive, rq, "dma error");
 
-               __ata_end_request(drive, rq, 1, rq->nr_sectors);
+               ata_end_request(drive, rq, 1, rq->nr_sectors);
 
                return ATA_OP_FINISHED;
        }
@@ -1936,7 +1936,7 @@ static int cdrom_read_toc(struct ata_device *drive, struct request_sense *sense)
                   If we get an error for the regular case, we assume
                   a CDI without additional audio tracks. In this case
                   the readable TOC is empty (CDI tracks are not included)
-                  and only holds the Leadout entry. Heiko Eißfeldt */
+                  and only holds the Leadout entry. Heiko EiÃ^ßfeldt */
                ntracks = 0;
                stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
                                           (char *)&toc->hdr,
@@ -2840,11 +2840,11 @@ static int ide_cdrom_setup(struct ata_device *drive)
 }
 
 /* Forwarding functions to generic routines. */
-static int ide_cdrom_ioctl (struct ata_device *drive,
+static int ide_cdrom_ioctl(struct ata_device *drive,
                     struct inode *inode, struct file *file,
                     unsigned int cmd, unsigned long arg)
 {
-       return cdrom_ioctl (inode, file, cmd, arg);
+       return cdrom_ioctl(inode, file, cmd, arg);
 }
 
 static int ide_cdrom_open (struct inode *ip, struct file *fp, struct ata_device *drive)
index cf9a29aa0e931f1fa04e65d73fa3793586eefdc9..8ebd46f0e963863f59de41d6f8281b21aaf92209 100644 (file)
@@ -140,7 +140,7 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq
                --rq->current_nr_sectors;
 
                if (rq->current_nr_sectors <= 0) {
-                       if (!__ata_end_request(drive, rq, 1, 0)) {
+                       if (!ata_end_request(drive, rq, 1, 0)) {
                        //              printk("Request Ended stat: %02x\n", drive->status);
 
                                return ATA_OP_FINISHED;
@@ -166,7 +166,7 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r
        if (!ata_status(drive, DRIVE_READY, drive->bad_wstat))
                return ata_error(drive, rq, __FUNCTION__);
 
-       if (!rq->current_nr_sectors && !__ata_end_request(drive, rq, 1, 0)) {
+       if (!rq->current_nr_sectors && !ata_end_request(drive, rq, 1, 0)) {
                ret = ATA_OP_FINISHED;
        } else {
                if ((rq->nr_sectors == 1) != (drive->status & DRQ_STAT)) {
@@ -235,7 +235,7 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request
 
                        /* FIXME: this seems buggy */
                        if (rq->current_nr_sectors <= 0) {
-                               if (!__ata_end_request(drive, rq, 1, 0))
+                               if (!ata_end_request(drive, rq, 1, 0))
                                        return ATA_OP_FINISHED;
                        }
                        msect -= nsect;
@@ -269,7 +269,7 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request
                        return ata_error(drive, rq, __FUNCTION__);
        }
        if (!rq->nr_sectors) {
-               __ata_end_request(drive, rq, 1, rq->hard_nr_sectors);
+               ata_end_request(drive, rq, 1, rq->hard_nr_sectors);
                rq->bio = NULL;
                ret = ATA_OP_FINISHED;
        } else if (!ok) {
@@ -349,7 +349,7 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
                /* FIXME: this check doesn't make sense */
                if (!(rq->flags & REQ_CMD)) {
                        blk_dump_rq_flags(rq, "idedisk_do_request - bad command");
-                       __ata_end_request(drive, rq, 0, 0);
+                       ata_end_request(drive, rq, 0, 0);
 
                        return ATA_OP_FINISHED;
                }
@@ -514,8 +514,8 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
                printk("sectors=%ld, ", rq->nr_sectors);
                printk("buffer=%p\n", rq->buffer);
 #endif
-       ar->cmd = cmd;
-       rq->special = ar;
+               ar->cmd = cmd;
+               rq->special = ar;
        }
 
        /* (ks/hs): Moved to start, do not use for multiple out commands.
@@ -548,10 +548,9 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
                        return ATA_OP_CONTINUES;
                }
 
-               /* FIXME: Warning check for race between handler and prehandler
-                * for writing first block of data.  however since we are well
-                * inside the boundaries of the seek, we should be okay.
-                * FIXME: should be fixed  --bzolnier
+               /* FIXME: Warning check for race between handlers for writing
+                * first block of data.  However since we are well inside the
+                * boundaries of the seek, we should be okay.
                 */
                if (ar->command_type == IDE_DRIVE_TASK_RAW_WRITE) {
                        ide_startstop_t ret;
@@ -596,13 +595,15 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
                                 *
                                 * FIXME: Replace hard-coded 100, what about
                                 * error handling?
+                                *
+                                * FIXME: Whatabout the IRE clearing and not clearing case?!
                                 */
 
                                for (i = 0; i < 100; ++i) {
-                                       if (drive_is_ready(drive))
+                                       if (ata_status_irq(drive))
                                                break;
                                }
-                               if (!drive_is_ready(drive)) {
+                               if (!ata_status_irq(drive)) {
                                        /* We are compleatly missing an error
                                         * return path here.
                                         * FIXME: We have only one? -alat
@@ -1290,7 +1291,9 @@ static int idedisk_cleanup(struct ata_device *drive)
        return ret;
 }
 
-static int idedisk_ioctl(struct ata_device *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int idedisk_ioctl(struct ata_device *drive,
+               struct inode *inode, struct file *__fp,
+               unsigned int cmd, unsigned long arg)
 {
        struct hd_driveid *id = drive->id;
 
index 83cb749e243f60c485d18b10ebd1130576af69cc..9dca9511a4173f9d83c0d3f9360c495669c0138c 100644 (file)
@@ -96,6 +96,7 @@
 #include <linux/cdrom.h>
 #include <linux/ide.h>
 #include <linux/atapi.h>
+#include <linux/buffer_head.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -367,7 +368,7 @@ static int idefloppy_end_request(struct ata_device *drive, struct request *rq, i
                return 0;
 
        if (!(rq->flags & REQ_SPECIAL)) {
-               __ata_end_request(drive, rq, uptodate, 0);
+               ata_end_request(drive, rq, uptodate, 0);
                return 0;
        }
 
@@ -731,7 +732,6 @@ static ide_startstop_t idefloppy_transfer_pc2(struct ata_device *drive, struct r
 static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct request *rq)
 {
        idefloppy_floppy_t *floppy = drive->driver_data;
-       ide_startstop_t startstop;
        atapi_ireason_reg_t ireason;
        int ret;
 
index ce50d7fa49f31b83d513fae887149ca86a0f993a..a04398c9e12c453cea5214d99e426e47c8550d84 100644 (file)
@@ -50,7 +50,7 @@ static void print_fixed (volatile unsigned char *p);
 static void print_funcid (int func);
 static int check_ide_device (unsigned long base);
 
-static void ide_interrupt_ack (void *dev);
+static int ide_interrupt_ack(struct ata_channel *);
 static void m8xx_ide_tuneproc(struct ata_device *drive, byte pio);
 
 typedef        struct ide_ioport_desc {
@@ -326,7 +326,7 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
        /* register routine to tune PIO mode */
        ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc;
 
-       hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack;
+       hw->ack_intr = ide_interrupt_ack;
        /* Enable Harddisk Interrupt,
         * and make it edge sensitive
         */
@@ -401,7 +401,7 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
                        ioport_dsc[data_port].reg_off[i],
                        i, base + ioport_dsc[data_port].reg_off[i]);
 #endif
-               *p++ = base + ioport_dsc[data_port].reg_off[i];
+               *p++ = base + ioport_dsc[data_port].reg_off[i];
        }
 
        if (irq) {
@@ -412,16 +412,16 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
        /* register routine to tune PIO mode */
        ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc;
 
-       hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack;
+       hw->ack_intr = ide_interrupt_ack;
        /* Enable Harddisk Interrupt,
         * and make it edge sensitive
         */
        /* (11-18) Set edge detect for irq, no wakeup from low power mode */
        ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
                        (0x80000000 >> ioport_dsc[data_port].irq);
-}      /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */ 
+}      /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */
 
-#endif /* CONFIG_IDE_8xx_DIRECT */
+#endif
 
 
 /* -------------------------------------------------------------------- */
@@ -493,11 +493,10 @@ m8xx_ide_tuneproc(struct ata_device *drive, byte pio)
 
        printk("%s[%d] %s: not implemented yet!\n",
                __FILE__,__LINE__,__FUNCTION__);
-#endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */
+#endif
 }
 
-static void
-ide_interrupt_ack (void *dev)
+static int ide_interrupt_ack(struct ata_channel *ch)
 {
 #ifdef CONFIG_IDE_8xx_PCCARD
        u_int pscr, pipr;
@@ -529,17 +528,17 @@ ide_interrupt_ack (void *dev)
        /* clear the interrupt sources */
        ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;
 
-#else /* ! CONFIG_IDE_8xx_PCCARD */
+#else
        /*
         * Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the
         * MPC8xx's PCMCIA controller, so there is nothing to be done here
         * for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT.
         * The interrupt is handled somewhere else.     -- Steven
         */
-#endif /* CONFIG_IDE_8xx_PCCARD */
-}
-
+#endif
 
+       return 0;
+}
 
 /*
  * CIS Tupel codes
@@ -655,7 +654,7 @@ static int check_ide_device (unsigned long base)
                                q+= 2;
                        }
                }
-#endif /* DEBUG_PCMCIA */
+#endif
                switch (code) {
                case CISTPL_VERS_1:
                        ident = p + 4;
index 0b6fe40cd806bf407e27d0e46b1cbd11fef85686..fc6ccc4f6a8f76eed6a241b6751a88347af6dcd3 100644 (file)
@@ -158,6 +158,80 @@ static int __init setup_pci_baseregs(struct pci_dev *dev, const char *name)
        return 0;
 }
 
+#ifdef CONFIG_BLK_DEV_IDEDMA
+/*
+ * Setup DMA transfers on the channel.
+ */
+static void __init setup_channel_dma(struct pci_dev *dev,
+               struct ata_pci_device* d,
+               int autodma,
+               struct ata_channel *ch)
+{
+       unsigned long dma_base;
+
+       if (d->flags & ATA_F_NOADMA)
+               autodma = 0;
+
+       if (autodma)
+               ch->autodma = 1;
+
+       if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))))
+               return;
+
+       /*
+        * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
+        */
+       dma_base = pci_resource_start(dev, 4);
+       if (dma_base) {
+               /* PDC20246, PDC20262, HPT343, & HPT366 */
+               if ((ch->unit == ATA_PRIMARY) && d->extra) {
+                       request_region(dma_base + 16, d->extra, dev->name);
+                       ch->dma_extra = d->extra;
+               }
+
+               /* If we are on the second channel, the dma base address will
+                * be one entry away from the primary interface.
+                */
+               if (ch->unit == ATA_SECONDARY)
+                               dma_base += 8;
+
+               if (d->flags & ATA_F_SIMPLEX) {
+                       outb(inb(dma_base + 2) & 0x60, dma_base + 2);
+                       if (inb(dma_base + 2) & 0x80)
+                               printk(KERN_INFO "%s: simplex device: DMA forced\n", dev->name);
+               } else {
+                       /* If the device claims "simplex" DMA, this means only
+                        * one of the two interfaces can be trusted with DMA at
+                        * any point in time.  So we should enable DMA only on
+                        * one of the two interfaces.
+                        */
+                       if ((inb(dma_base + 2) & 0x80)) {
+                               if ((!ch->drives[0].present && !ch->drives[1].present) ||
+                                   ch->unit == ATA_SECONDARY) {
+                                       printk(KERN_INFO "%s: simplex device:  DMA disabled\n", dev->name);
+                                       dma_base = 0;
+                               }
+                       }
+               }
+       } else {
+               printk(KERN_INFO "%s: %s Bus-Master DMA was disabled by BIOS\n",
+                      ch->name, dev->name);
+
+               return;
+       }
+
+       /* The function below will check itself whatever there is something to
+        * be done or not. We don't have therefore to care whatever it was
+        * already enabled by the primary channel run.
+        */
+       pci_set_master(dev);
+       if (d->init_dma)
+               d->init_dma(ch, dma_base);
+       else
+               ata_init_dma(ch, dma_base);
+}
+#endif
+
 /*
  * Setup a particular port on an ATA host controller.
  *
@@ -171,7 +245,6 @@ static int __init setup_host_channel(struct pci_dev *dev,
                int autodma)
 {
        unsigned long base = 0;
-       unsigned long dma_base;
        unsigned long ctl = 0;
        ide_pci_enablebit_t *e = &(d->enablebits[port]);
        struct ata_channel *ch;
@@ -260,69 +333,13 @@ controller_ok:
        if (ch->udma_four)
                printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name);
 
+
 #ifdef CONFIG_BLK_DEV_IDEDMA
        /*
         * Setup DMA transfers on the channel.
         */
-       if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))))
-               goto no_dma;
-       /*
-        * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
-        */
-       dma_base = pci_resource_start(dev, 4);
-       if (dma_base) {
-               /* PDC20246, PDC20262, HPT343, & HPT366 */
-               if ((ch->unit == ATA_PRIMARY) && d->extra) {
-                       request_region(dma_base + 16, d->extra, dev->name);
-                       ch->dma_extra = d->extra;
-               }
-
-               /* If we are on the second channel, the dma base address will
-                * be one entry away from the primary interface.
-                */
-               if (ch->unit == ATA_SECONDARY)
-                       dma_base += 8;
-
-               if (d->flags & ATA_F_SIMPLEX) {
-                       outb(inb(dma_base + 2) & 0x60, dma_base + 2);
-                       if (inb(dma_base + 2) & 0x80)
-                               printk(KERN_INFO "%s: simplex device: DMA forced\n", dev->name);
-               } else {
-                       /* If the device claims "simplex" DMA, this means only
-                        * one of the two interfaces can be trusted with DMA at
-                        * any point in time.  So we should enable DMA only on
-                        * one of the two interfaces.
-                        */
-                       if ((inb(dma_base + 2) & 0x80)) {
-                               if ((!ch->drives[0].present && !ch->drives[1].present) ||
-                                               ch->unit == ATA_SECONDARY) {
-                                       printk(KERN_INFO "%s: simplex device:  DMA disabled\n", dev->name);
-                                       dma_base = 0;
-                               }
-                       }
-               }
-       } else {
-               printk(KERN_INFO "%s: %s Bus-Master DMA was disabled by BIOS\n",
-                               ch->name, dev->name);
-
-               goto no_dma;
-       }
-
-       /* The function below will check itself whatever there is something to
-        * be done or not. We don't have therefore to care whatever it was
-        * already enabled by the primary channel run.
-        */
-       pci_set_master(dev);
-
-       if (autodma)
-               ch->autodma = 1;
-
-       if (d->init_dma)
-               d->init_dma(ch, dma_base);
-       else
-               ata_init_dma(ch, dma_base);
+       setup_channel_dma(dev, d, autodma, ch);
 #endif
-
 no_dma:
        /* Call chipset-specific routine for each enabled channel. */
        if (d->init_channel)
index 36b8fa16ab5237bcd932171f3b213765f6a36681..70e052d6097db64c65402ba6bc87777bff96788b 100644 (file)
 #include <linux/completion.h>
 #include <linux/ide.h>
 #include <linux/atapi.h>
+#include <linux/buffer_head.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -2445,7 +2446,7 @@ static ide_startstop_t idetape_do_request(struct ata_device *drive, struct reque
                 *      We do not support buffer cache originated requests.
                 */
                printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%ld)\n", drive->name, rq->flags);
-               __ata_end_request(drive, rq, 0, 0);                     /* Let the common code handle it */
+               ata_end_request(drive, rq, 0, 0);                       /* Let the common code handle it */
                return ATA_OP_FINISHED;
        }
 
index 3d6bc592766ef21bf2ac09df47b24ac2d2c44c98..2699a3f5de9a9b14db96d5cba20daaf16e0aa001 100644 (file)
 #include <asm/io.h>
 #include <asm/bitops.h>
 
-#define DEBUG_TASKFILE 0       /* unset when fixed */
-
-#if DEBUG_TASKFILE
-#define DTF(x...) printk(##x)
-#else
-#define DTF(x...)
-#endif
-
 /*
  * Data transfer functions for polled IO.
  */
-
 static void ata_read_32(struct ata_device *drive, void *buffer, unsigned int wcount)
 {
        insl(IDE_DATA_REG, buffer, wcount);
@@ -143,103 +134,10 @@ void ata_write(struct ata_device *drive, void *buffer, unsigned int wcount)
        }
 }
 
-/*
- * Needed for PCI irq sharing
- */
-int drive_is_ready(struct ata_device *drive)
-{
-       if (test_bit(IDE_DMA, drive->channel->active))
-               return udma_irq_status(drive);
-
-       /*
-        * Need to guarantee 400ns since last command was issued?
-        */
-
-       /* FIXME: promote this to the general status read method perhaps.
-        */
-#ifdef CONFIG_IDEPCI_SHARE_IRQ
-       /*
-        * We do a passive status test under shared PCI interrupts on
-        * cards that truly share the ATA side interrupt, but may also share
-        * an interrupt with another pci card/device.  We make no assumptions
-        * about possible isa-pnp and pci-pnp issues yet.
-        */
-       if (drive->channel->io_ports[IDE_CONTROL_OFFSET])
-               drive->status = GET_ALTSTAT();
-       else
-#endif
-               ata_status(drive, 0, 0);        /* Note: this may clear a pending IRQ! */
-
-       if (drive->status & BUSY_STAT)
-               return 0;       /* drive busy:  definitely not interrupting */
-
-       return 1;       /* drive ready: *might* be interrupting */
-}
-
-/*
- * This function issues a special IDE device request onto the request queue.
- *
- * If action is ide_wait, then the rq is queued at the end of the request
- * queue, and the function sleeps until it has been processed.  This is for use
- * when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then 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.
- *
- * If action is ide_end, then the rq is queued at the end of the request queue,
- * and the function returns immediately without waiting for the new rq to be
- * completed. This is again intended for careful use by the ATAPI tape/cdrom
- * driver code.
- */
-int ide_do_drive_cmd(struct ata_device *drive, struct request *rq, ide_action_t action)
-{
-       unsigned long flags;
-       struct ata_channel *ch = drive->channel;
-       unsigned int major = ch->major;
-       request_queue_t *q = &drive->queue;
-       struct list_head *queue_head = &q->queue_head;
-       DECLARE_COMPLETION(wait);
-
-#ifdef CONFIG_BLK_DEV_PDC4030
-       if (ch->chipset == ide_pdc4030 && rq->buffer)
-               return -ENOSYS;  /* special drive cmds not supported */
-#endif
-       rq->errors = 0;
-       rq->rq_status = RQ_ACTIVE;
-       rq->rq_dev = mk_kdev(major,(drive->select.b.unit)<<PARTN_BITS);
-       if (action == ide_wait)
-               rq->waiting = &wait;
-
-       spin_lock_irqsave(ch->lock, flags);
-
-       if (action == ide_preempt)
-               drive->rq = NULL;
-       else if (!blk_queue_empty(&drive->queue))
-               queue_head = queue_head->prev;  /* ide_end and ide_wait */
-
-       __elv_add_request(q, rq, queue_head);
-
-       do_ide_request(q);
-
-       spin_unlock_irqrestore(ch->lock, flags);
-
-       if (action == ide_wait) {
-               wait_for_completion(&wait);     /* wait for it to be serviced */
-               return rq->errors ? -EIO : 0;   /* return -EIO if errors */
-       }
-
-       return 0;
-}
-
-
 /*
  * Invoked on completion of a special REQ_SPECIAL command.
  */
-static ide_startstop_t special_intr(struct ata_device *drive, struct
-               request *rq) {
+static ide_startstop_t special_intr(struct ata_device *drive, struct request *rq) {
        unsigned long flags;
        struct ata_channel *ch =drive->channel;
        struct ata_taskfile *ar = rq->special;
@@ -290,21 +188,52 @@ static ide_startstop_t special_intr(struct ata_device *drive, struct
 
 int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *ar, char *buf)
 {
-       struct request req;
+       struct request *rq;
+       unsigned long flags;
+       struct ata_channel *ch = drive->channel;
+       request_queue_t *q = &drive->queue;
+       struct list_head *queue_head = &q->queue_head;
+       DECLARE_COMPLETION(wait);
+
+#ifdef CONFIG_BLK_DEV_PDC4030
+       if (ch->chipset == ide_pdc4030 && buf)
+               return -ENOSYS;  /* special drive cmds not supported */
+#endif
+
+       rq = __blk_get_request(&drive->queue, READ);
+       if (!rq)
+               rq = __blk_get_request(&drive->queue, WRITE);
+
+       /*
+        * FIXME: Make sure there is a free slot on the list!
+        */
+
+       BUG_ON(!rq);
+
+       rq->flags = REQ_SPECIAL;
+       rq->buffer = buf;
+       rq->special = ar;
+       rq->errors = 0;
+       rq->rq_status = RQ_ACTIVE;
+       rq->waiting = &wait;
 
-       ar->command_type = IDE_DRIVE_TASK_NO_DATA;
        ar->XXX_handler = special_intr;
+       ar->command_type = IDE_DRIVE_TASK_NO_DATA;
+
+       spin_lock_irqsave(ch->lock, flags);
+
+       if (!blk_queue_empty(&drive->queue))
+               queue_head = queue_head->prev;
+       __elv_add_request(q, rq, queue_head);
+
+       q->request_fn(q);
+       spin_unlock_irqrestore(ch->lock, flags);
 
-       memset(&req, 0, sizeof(req));
-       req.flags = REQ_SPECIAL;
-       req.buffer = buf;
-       req.special = ar;
+       wait_for_completion(&wait);     /* wait for it to be serviced */
 
-       return ide_do_drive_cmd(drive, &req, ide_wait);
+       return rq->errors ? -EIO : 0;   /* return -EIO if errors */
 }
 
-EXPORT_SYMBOL(drive_is_ready);
-EXPORT_SYMBOL(ide_do_drive_cmd);
 EXPORT_SYMBOL(ata_read);
 EXPORT_SYMBOL(ata_write);
 EXPORT_SYMBOL(ide_raw_taskfile);
index d1e6c8030f07c1486b06c5fd272f13fa29560339..851ac69d6a8d2a071710a24c4b6d1f60e0b4903f 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
-#include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/blkpg.h>
@@ -106,7 +105,7 @@ int drive_is_flashcard(struct ata_device *drive)
        return 0;
 }
 
-int __ata_end_request(struct ata_device *drive, struct request *rq, int uptodate, unsigned int nr_secs)
+int ata_end_request(struct ata_device *drive, struct request *rq, int uptodate, unsigned int nr_secs)
 {
        unsigned long flags;
        struct ata_channel *ch = drive->channel;
@@ -132,7 +131,7 @@ int __ata_end_request(struct ata_device *drive, struct request *rq, int uptodate
        }
 
        if (!end_that_request_first(rq, uptodate, nr_secs)) {
-               add_blkdev_randomness(major(rq->rq_dev));
+               add_blkdev_randomness(ch->major);
                if (!blk_rq_tagged(rq))
                        blkdev_dequeue_request(rq);
                else
@@ -192,12 +191,13 @@ static void check_crc_errors(struct ata_device *drive)
                        if (mode > XFER_UDMA_0)
                                mode--;
                        else
+
                        /*
-                        * OOPS we do not goto non Ultra DMA modes
-                        * without iCRC's available we force
-                        * the system to PIO and make the user
-                        * invoke the ATA-1 ATA-2 DMA modes.
+                        * We do not do non Ultra DMA modes.  Without iCRC's
+                        * available, we force the system to PIO and make the
+                        * user select the ATA-1 ATA-2 DMA modes himself.
                         */
+
                                mode = XFER_PIO_4;
 
                        drive->channel->speedproc(drive, mode);
@@ -220,157 +220,9 @@ sector_t ata_capacity(struct ata_device *drive)
        if (ata_ops(drive) && ata_ops(drive)->capacity)
                return ata_ops(drive)->capacity(drive);
 
-       /* This used to be 0x7fffffff, but since now we use the maximal drive
-        * capacity value used by other kernel subsystems as well.
-        */
-
        return ~0UL;
 }
 
-extern struct block_device_operations ide_fops[];
-
-static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */
-
-/*
- * Poll the interface for completion every 50ms during an ATAPI drive reset
- * operation. If the drive has not yet responded, and we have not yet hit our
- * maximum waiting time, then the timer is restarted for another 50ms.
- */
-static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq)
-{
-       struct ata_channel *ch = drive->channel;
-       int ret = ATA_OP_FINISHED;
-
-       ata_select(drive, 10);
-       if (!ata_status(drive, 0, BUSY_STAT)) {
-               if (time_before(jiffies, ch->poll_timeout)) {
-                       ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
-                       ret = ATA_OP_CONTINUES; /* continue polling */
-               } else {
-                       ch->poll_timeout = 0;   /* end of polling */
-                       printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, drive->status);
-
-                       ret = do_reset1(drive, 0);      /* do it the old fashioned way */
-               }
-       } else {
-               printk("%s: ATAPI reset complete\n", drive->name);
-               ch->poll_timeout = 0;   /* done polling */
-
-               ret = ATA_OP_FINISHED;
-       }
-
-       return ret;
-}
-
-/*
- * Poll the interface for completion every 50ms during an ata reset operation.
- * If the drives have not yet responded, and we have not yet hit our maximum
- * waiting time, then the timer is restarted for another 50ms.
- */
-static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq)
-{
-       struct ata_channel *ch = drive->channel;
-       int ret;
-
-       if (!ata_status(drive, 0, BUSY_STAT)) {
-               if (time_before(jiffies, ch->poll_timeout)) {
-                       ata_set_handler(drive, reset_pollfunc, HZ/20, NULL);
-                       ret = ATA_OP_CONTINUES; /* continue polling */
-               } else {
-                       ch->poll_timeout = 0;   /* done polling */
-                       printk("%s: reset timed out, status=0x%02x\n", ch->name, drive->status);
-                       ++drive->failures;
-                       ret = ATA_OP_FINISHED;
-               }
-       } else  {
-               u8 stat;
-
-               ch->poll_timeout = 0;   /* done polling */
-               printk("%s: reset: ", ch->name);
-               if ((stat = GET_ERR()) == 1) {
-                       printk("success\n");
-                       drive->failures = 0;
-               } else {
-                       const char *msg = "";
-
-#if FANCY_STATUS_DUMPS
-                       u8 val;
-                       static const char *messages[5] = {
-                               " passed",
-                               " formatter device",
-                               " sector buffer",
-                               " ECC circuitry",
-                               " controlling MPU error"
-                       };
-
-                       printk("master:");
-                       val = stat & 0x7f;
-                       if (val >= 1 && val <= 5)
-                               msg = messages[val -1];
-                       if (stat & 0x80)
-                               printk("; slave:");
-#endif
-                       printk(KERN_ERR "%s error [%02x]\n", msg, stat);
-                       ++drive->failures;
-               }
-
-               ret = ATA_OP_FINISHED;
-       }
-
-       return ret;
-}
-
-/*
- * Attempt to recover a confused drive by resetting it.  Unfortunately,
- * resetting a disk drive actually resets all devices on the same interface, so
- * it can really be thought of as resetting the interface rather than resetting
- * the drive.
- *
- * ATAPI devices have their own reset mechanism which allows them to be
- * individually reset without clobbering other devices on the same interface.
- *
- * Unfortunately, the IDE interface does not generate an interrupt to let us
- * know when the reset operation has finished, so we must poll for this.
- * Equally poor, though, is the fact that this may a very long time to
- * complete, (up to 30 seconds worst case).  So, instead of busy-waiting here
- * for it, we set a timer to poll at 50ms intervals.
- */
-static ide_startstop_t do_reset1(struct ata_device *drive, int try_atapi)
-{
-       unsigned int unit;
-       unsigned long flags;
-       struct ata_channel *ch = drive->channel;
-
-       /* FIXME:  --bzolnier */
-       __save_flags(flags);    /* local CPU only */
-       __cli();                /* local CPU only */
-
-       /* For an ATAPI device, first try an ATAPI SRST. */
-       if (try_atapi) {
-               if (drive->type != ATA_DISK) {
-                       check_crc_errors(drive);
-                       ata_select(drive, 20);
-                       OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
-                       ch->poll_timeout = jiffies + WAIT_WORSTCASE;
-                       ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
-                       __restore_flags(flags); /* local CPU only */
-
-                       return ATA_OP_CONTINUES;
-               }
-       }
-
-       /*
-        * First, reset any device state data we were maintaining
-        * for any of the drives on this interface.
-        */
-       for (unit = 0; unit < MAX_DRIVES; ++unit)
-               check_crc_errors(&ch->drives[unit]);
-
-       __restore_flags(flags); /* local CPU only */
-
-       return ATA_OP_CONTINUES;
-}
-
 static inline u32 read_24(struct ata_device *drive)
 {
        return  (IN_BYTE(IDE_HCYL_REG) << 16) |
@@ -489,58 +341,11 @@ u8 ata_dump(struct ata_device *drive, struct request * rq, const char *msg)
        return err;
 }
 
-/*
- * This gets invoked in response to a drive unexpectedly having its DRQ_STAT
- * bit set.  As an alternative to resetting the drive, it tries to clear the
- * condition by reading a sector's worth of data from the drive.  Of course,
- * this may not help if the drive is *waiting* for data from *us*.
- */
-static void try_to_flush_leftover_data(struct ata_device *drive)
-{
-       int i;
-
-       if (drive->type != ATA_DISK)
-               return;
-
-       for (i = (drive->mult_count ? drive->mult_count : 1); i > 0; --i) {
-               u32 buffer[SECTOR_WORDS];
-
-               ata_read(drive, buffer, SECTOR_WORDS);
-       }
-}
-
-#ifdef CONFIG_BLK_DEV_PDC4030
-# define IS_PDC4030_DRIVE (drive->channel->chipset == ide_pdc4030)
-#else
-# define IS_PDC4030_DRIVE (0)  /* auto-NULLs out pdc4030 code */
-#endif
-
-/*
- * We are still on the old request path here so issuing the recalibrate command
- * directly should just work.
- */
-static int do_recalibrate(struct ata_device *drive)
-{
-
-       if (drive->type != ATA_DISK)
-               return ATA_OP_FINISHED;
-
-       if (!IS_PDC4030_DRIVE) {
-               struct ata_taskfile args;
-
-               printk(KERN_INFO "%s: recalibrating...\n", drive->name);
-               memset(&args, 0, sizeof(args));
-               args.taskfile.sector_count = drive->sect;
-               args.cmd = WIN_RESTORE;
-               ide_raw_taskfile(drive, &args, NULL);
-               printk(KERN_INFO "%s: done!\n", drive->name);
-       }
-
-       return IS_PDC4030_DRIVE ? ATA_OP_FINISHED : ATA_OP_CONTINUES;
-}
-
 /*
  * Take action based on the error returned by the drive.
+ *
+ * FIXME: Separate the error handling code out and call it only in cases where
+ * we really wan't to try to recover from the error and not just reporting.
  */
 ide_startstop_t ata_error(struct ata_device *drive, struct request *rq,        const char *msg)
 {
@@ -549,12 +354,9 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq,    const ch
 
        err = ata_dump(drive, rq, msg);
 
-       /* FIXME: at least !drive check is bogus  --bzolnier */
-       if (!drive || !rq)
-               return ATA_OP_FINISHED;
-
-       /* retry only "normal" I/O: */
-       if (!(rq->flags & REQ_CMD)) {
+       /* Only try to recover from block I/O operations.
+        */
+       if (!rq || !(rq->flags & REQ_CMD)) {
                rq->errors = 1;
 
                return ATA_OP_FINISHED;
@@ -562,10 +364,11 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq,   const ch
 
        /* other bits are useless when BUSY */
        if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr))
-               rq->errors |= ERROR_RESET; /* FIXME: What's that?! */
-       else {
-               if (drive->type == ATA_DISK && (stat & ERR_STAT)) {
-                       /* err has different meaning on cdrom and tape */
+               rq->errors |= ERROR_RESET;
+       else if (drive->type == ATA_DISK) {
+               /* The error bit has different meaning on cdrom and tape.
+                */
+               if (stat & ERR_STAT) {
                        if (err == ABRT_ERR) {
                                if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY)
                                        return ATA_OP_FINISHED; /* some newer drives don't support WIN_SPECIFY */
@@ -573,109 +376,128 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
                                drive->crc_count++; /* UDMA crc error -- just retry the operation */
                        else if (err & (BBD_ERR | ECC_ERR))     /* retries won't help these */
                                rq->errors = ERROR_MAX;
-                       else if (err & TRK0_ERR)        /* help it find track zero */
-                               rq->errors |= ERROR_RECAL;
                }
-               /* pre bio (rq->cmd != WRITE) */
-               if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)
-                       try_to_flush_leftover_data(drive);
+
+               /* As an alternative to resetting the drive, we try to clear
+                * the condition by reading a sector's worth of data from the
+                * drive.  Of course, this can not help if the drive is
+                * *waiting* for data from *us*.
+                */
+
+               if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ) {
+                       int i;
+
+                       for (i = (drive->mult_count ? drive->mult_count : 1); i > 0; --i) {
+                               u32 buffer[SECTOR_WORDS];
+
+                               ata_read(drive, buffer, SECTOR_WORDS);
+                       }
+               }
        }
 
+       /* Force an abort if not even the status data is available.  This will
+        * clear all pending IRQs on the drive as well.
+        */
        if (!ata_status(drive, 0, BUSY_STAT | DRQ_STAT))
-               OUT_BYTE(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);   /* force an abort */
+               OUT_BYTE(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
 
+       /* Bail out immediately. */
        if (rq->errors >= ERROR_MAX) {
                printk(KERN_ERR "%s: max number of retries exceeded!\n", drive->name);
                if (ata_ops(drive) && ata_ops(drive)->end_request)
                        ata_ops(drive)->end_request(drive, rq, 0);
                else
-                       __ata_end_request(drive, rq, 0, 0);
-       } else {
-               ++rq->errors;
-               if ((rq->errors & ERROR_RESET) == ERROR_RESET)
-                       return do_reset1(drive, 1);
-               if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
-                       /* FIXME: tries to acquire the channel lock -Zwane */
-                       return do_recalibrate(drive);
-       }
-
-       return ATA_OP_FINISHED;
-}
-
-/*
- * This initiates handling of a new I/O request.
- */
-static ide_startstop_t start_request(struct ata_device *drive, struct request *rq)
-{
-       struct ata_channel *ch = drive->channel;
-       sector_t block;
-       unsigned int minor = minor(rq->rq_dev);
-       unsigned int unit = minor >> PARTN_BITS;
-       ide_startstop_t ret;
-
-       BUG_ON(!(rq->flags & REQ_STARTED));
-
-#ifdef DEBUG
-       printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq);
-#endif
-
-       /* bail early if we've exceeded max_failures */
-       if (drive->max_failures && (drive->failures > drive->max_failures))
-               goto kill_rq;
+                       ata_end_request(drive, rq, 0, 0);
 
-       if (unit >= MAX_DRIVES) {
-               printk(KERN_ERR "%s: bad device number: %s\n", ch->name, kdevname(rq->rq_dev));
-               goto kill_rq;
+               return ATA_OP_FINISHED;
        }
 
-       block = rq->sector;
+       ++rq->errors;
+       printk(KERN_INFO "%s: request error, nr. %d\n", drive->name, rq->errors);
 
-       /* Strange disk manager remap.
+       /*
+        * Attempt to recover a confused drive by resetting it.  Unfortunately,
+        * resetting a disk drive actually resets all devices on the same
+        * interface, so it can really be thought of as resetting the interface
+        * rather than resetting the drive.
+        *
+        * ATAPI devices have their own reset mechanism which allows them to be
+        * individually reset without clobbering other devices on the same
+        * interface.
+        *
+        * The IDE interface does not generate an interrupt to let us know when
+        * the reset operation has finished, so we must poll for this.  This
+        * may take a very long time to complete.
+        *
+        * Maybe we can check if we are in IRQ context and schedule the CPU
+        * during this time. But for certain we should block all data transfers
+        * on the channel in question during those operations.
         */
-       if (rq->flags & REQ_CMD)
-               if (drive->type == ATA_DISK || drive->type == ATA_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 ((rq->errors & ERROR_RESET) == ERROR_RESET) {
+               unsigned int unit;
+               struct ata_channel *ch = drive->channel;
+               int ret;
 
-       ata_select(drive, 0);
-       ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
-                               WAIT_READY, rq);
-       if (ret != ATA_OP_READY) {
-               printk(KERN_WARNING "%s: drive not ready for command\n", drive->name);
+               /* For an ATAPI device, first try an ATAPI SRST.
+                */
 
-               goto kill_rq;
-       }
+               if (drive->type != ATA_DISK) {
+                       check_crc_errors(drive);
+                       ata_select(drive, 20);
+                       udelay(1);
+                       ata_irq_enable(drive, 0);
+                       OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
+                       if (drive->quirk_list == 2)
+                               ata_irq_enable(drive, 1);
+                       udelay(1);
+                       ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_WORSTCASE, NULL);
+                       ata_mask(drive);
+
+                       if (ret == ATA_OP_READY) {
+                               printk("%s: ATAPI reset complete\n", drive->name);
+
+                               return ATA_OP_CONTINUES;
+                       } else
+                               printk(KERN_ERR "%s: ATAPI reset timed out, status=0x%02x\n",
+                                               drive->name, drive->status);
+               }
 
-       if (!ata_ops(drive)) {
-               printk(KERN_WARNING "%s: device type %d not supported\n",
-                               drive->name, drive->type);
-               goto kill_rq;
-       }
+               /* Reset all devices on channel.
+                */
 
-       /* The normal way of execution is to pass and execute the request
-        * handler down to the device type driver.
-        */
+               /* First, reset any device state data we were maintaining for
+                * any of the drives on this interface.
+                */
+               for (unit = 0; unit < MAX_DRIVES; ++unit)
+                       check_crc_errors(&ch->drives[unit]);
 
-       if (ata_ops(drive)->do_request) {
-               ret = ata_ops(drive)->do_request(drive, rq, block);
-       } else {
-               __ata_end_request(drive, rq, 0, 0);
-               ret = ATA_OP_FINISHED;
-       }
-       return ret;
+               /* And now actually perform the reset operation.
+                */
+               printk("%s: ATA reset...\n", ch->name);
+               ata_select(drive, 20);
+               udelay(1);
+               ata_irq_enable(drive, 0);
 
-kill_rq:
-       if (ata_ops(drive) && ata_ops(drive)->end_request)
-               ata_ops(drive)->end_request(drive, rq, 0);
-       else
-               __ata_end_request(drive, rq, 0, 0);
+               /* This command actually looks suspicious, since I couldn't
+                * find it in any standard document.
+                */
+               OUT_BYTE(0x04, ch->io_ports[IDE_CONTROL_OFFSET]);
+               udelay(10);
+               OUT_BYTE(WIN_NOP, ch->io_ports[IDE_CONTROL_OFFSET]);
+               ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_WORSTCASE, NULL);
+               ata_mask(drive);
+
+               if (ret == ATA_OP_READY)
+                       printk("%s: ATA reset complete\n", drive->name);
+               else
+                       printk(KERN_ERR "%s: ATA reset timed out, status=0x%02x\n",
+                                       drive->name, drive->status);
+               mdelay(100);
+       }
 
-       return ATA_OP_FINISHED;
+       /* signal that we should retry this request */
+       return ATA_OP_CONTINUES;
 }
 
 /*
@@ -689,218 +511,255 @@ void ide_stall_queue(struct ata_device *drive, unsigned long timeout)
        drive->sleep = timeout + jiffies;
 }
 
-
 /*
- * Determine the longest sleep time for the devices at this channel.
+ * Issue a new request.
+ * Caller must have already done spin_lock_irqsave(channel->lock, ...)
  */
-static unsigned long longest_sleep(struct ata_channel *channel)
+static void do_request(struct ata_channel *channel)
 {
-       unsigned long sleep = 0;
-       int unit;
-
-       for (unit = 0; unit < MAX_DRIVES; ++unit) {
-               struct ata_device *drive = &channel->drives[unit];
-
-               if (!drive->present)
-                       continue;
-
-               /* This device is sleeping and waiting to be serviced
-                * later than any other device we checked thus far.
-                */
-               if (drive->sleep && (!sleep || time_after(drive->sleep, sleep)))
-                       sleep = drive->sleep;
-       }
+       struct ata_channel *ch;
+       struct ata_device *drive = NULL;
+       unsigned int unit;
+       ide_startstop_t ret;
 
-       return sleep;
-}
+       __cli();        /* necessary paranoia: ensure IRQs are masked on local CPU */
 
-/*
- * Select the next device which will be serviced.  This selects only between
- * devices on the same channel, since everything else will be scheduled on the
- * queue level.
- */
-static struct ata_device *choose_urgent_device(struct ata_channel *channel)
-{
-       struct ata_device *choice = NULL;
-       unsigned long sleep = 0;
-       int unit;
+       /*
+        * Select the next device which will be serviced.  This selects
+        * only between devices on the same channel, since everything
+        * else will be scheduled on the queue level.
+        */
 
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
-               struct ata_device *drive = &channel->drives[unit];
+               struct ata_device *tmp = &channel->drives[unit];
 
-               if (!drive->present)
+               if (!tmp->present)
                        continue;
 
-               /* There are no request pending for this device.
+               /* There are no requests pending for this device.
                 */
-               if (blk_queue_empty(&drive->queue))
+               if (blk_queue_empty(&tmp->queue))
                        continue;
 
+
                /* This device still wants to remain idle.
                 */
-               if (drive->sleep && time_after(drive->sleep, jiffies))
+               if (tmp->sleep && time_after(tmp->sleep, jiffies))
                        continue;
 
-               /* Take this device, if there is no device choosen thus far or
-                * it's more urgent.
+               /* Take this device, if there is no device choosen thus
+                * far or which is more urgent.
                 */
-               if (!choice || (drive->sleep && (!choice->sleep || time_after(choice->sleep, drive->sleep)))) {
-                       if (!blk_queue_plugged(&drive->queue))
-                               choice = drive;
+               if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) {
+                       if (!blk_queue_plugged(&tmp->queue))
+                               drive = tmp;
                }
        }
 
-       if (choice)
-               return choice;
+       if (!drive) {
+               unsigned long sleep = 0;
 
-       sleep = longest_sleep(channel);
+               for (unit = 0; unit < MAX_DRIVES; ++unit) {
+                       struct ata_device *tmp = &channel->drives[unit];
+
+                       if (!tmp->present)
+                               continue;
 
-       if (sleep) {
+                       /* This device is sleeping and waiting to be serviced
+                        * earlier than any other device we checked thus far.
+                        */
+                       if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep)))
+                               sleep = tmp->sleep;
+               }
 
-               /*
-                * Take a short snooze, and then wake up again.  Just in case
-                * there are big differences in relative throughputs.. don't
-                * want to hog the cpu too much.
-                */
+               if (sleep) {
+                       /*
+                        * Take a short snooze, and then wake up again.  Just
+                        * in case there are big differences in relative
+                        * throughputs.. don't want to hog the cpu too much.
+                        */
 
-               if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
-                       sleep = jiffies + WAIT_MIN_SLEEP;
+                       if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
+                               sleep = jiffies + WAIT_MIN_SLEEP;
 #if 1
-               if (timer_pending(&channel->timer))
-                       printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
+                       if (timer_pending(&channel->timer))
+                               printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
 #endif
-               set_bit(IDE_SLEEP, channel->active);
-               mod_timer(&channel->timer, sleep);
-               /* we purposely leave hwgroup busy while sleeping */
-       } else {
-               /* FIXME: use queue plugging instead of active to
-                * block upper layers from stomping on us */
-               /* Ugly, but how can we sleep for the lock otherwise? */
-               ide_release_lock(&ide_irq_lock);/* for atari only */
-               clear_bit(IDE_BUSY, channel->active);
-       }
+                       set_bit(IDE_SLEEP, channel->active);
+                       mod_timer(&channel->timer, sleep);
 
-       return NULL;
-}
+                       /*
+                        * We purposely leave us busy while sleeping becouse we
+                        * are prepared to handle the IRQ from it.
+                        *
+                        * FIXME: Make sure sleeping can't interferre with
+                        * operations of other devices on the same channel.
+                        */
+               } else {
+                       /* FIXME: use queue plugging instead of active to block
+                        * upper layers from stomping on us */
+                       /* Ugly, but how can we sleep for the lock otherwise?
+                        * */
+
+                       ide_release_lock(&ide_irq_lock);/* for atari only */
+                       clear_bit(IDE_BUSY, channel->active);
+
+                       /* All requests are done.
+                        *
+                        * Disable IRQs from the last drive on this channel, to
+                        * make sure that it wan't throw stones at us when we
+                        * are not prepared to take them.
+                        */
 
-/*
- * Issue a new request.
- * Caller must have already done spin_lock_irqsave(channel->lock, ...)
- */
-static void do_request(struct ata_channel *channel)
-{
-       ide_get_lock(&ide_irq_lock, ata_irq_request, channel);/* for atari only: POSSIBLY BROKEN HERE(?) */
-       __cli();        /* necessary paranoia: ensure IRQs are masked on local CPU */
+                       if (channel->drive && !channel->drive->using_tcq)
+                               ata_irq_enable(channel->drive, 0);
+               }
 
-       while (!test_and_set_bit(IDE_BUSY, channel->active)) {
-               struct ata_channel *ch;
-               struct ata_device *drive;
-               struct request *rq = NULL;
-               ide_startstop_t startstop;
-               int i;
+               return;
+       }
 
-               /* this will clear IDE_BUSY, if appropriate */
-               drive = choose_urgent_device(channel);
+       /* Remember the last drive we where acting on.
+        */
+       ch = drive->channel;
+       ch->drive = drive;
 
-               if (!drive)
-                       break;
+       /* Feed commands to a drive until it barfs.
+        */
+       do {
+               struct request *rq = NULL;
+               sector_t block;
 
-               /* Remember the last drive we where acting on.
+               /* Abort early if we can't queue another command. for non tcq,
+                * ata_can_queue is always 1 since we never get here unless the
+                * drive is idle.
                 */
-               ch = drive->channel;
-               ch->drive = drive;
 
-               /* Make sure that all drives on channels sharing the IRQ line
-                * with us won't generate IRQ's during our activity.
-                */
-               for (i = 0; i < MAX_HWIFS; ++i) {
-                       struct ata_channel *tmp = &ide_hwifs[i];
-                       int j;
+               if (!ata_can_queue(drive)) {
+                       if (!ata_pending_commands(drive)) {
+                               clear_bit(IDE_BUSY, ch->active);
+                               if (drive->using_tcq)
+                                       ata_irq_enable(drive, 0);
+                       }
+                       break;
+               }
 
-                       if (!tmp->present)
-                               continue;
+               drive->sleep = 0;
 
-                       if (ch->lock != tmp->lock)
-                               continue;
+               if (test_bit(IDE_DMA, ch->active)) {
+                       printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
+                       break;
+               }
 
-                       /* Only care if there is any drive on the channel in
-                        * question.
-                        */
-                       for (j = 0;  j < MAX_DRIVES; ++j) {
-                               struct ata_device * other = &tmp->drives[j];
+               /* There's a small window between where the queue could be
+                * replugged while we are in here when using tcq (in which case
+                * the queue is probably empty anyways...), so check and leave
+                * if appropriate. When not using tcq, this is still a severe
+                * BUG!
+                */
+
+               if (blk_queue_plugged(&drive->queue)) {
+                       BUG_ON(!drive->using_tcq);
+                       break;
+               }
 
-                               if (other->present)
-                                       ata_irq_enable(other, 0);
+               if (!(rq = elv_next_request(&drive->queue))) {
+                       if (!ata_pending_commands(drive)) {
+                               clear_bit(IDE_BUSY, ch->active);
+                               if (drive->using_tcq)
+                                       ata_irq_enable(drive, 0);
                        }
+                       drive->rq = NULL;
+
+                       break;
                }
 
+               /* If there are queued commands, we can't start a
+                * non-fs request (really, a non-queuable command)
+                * until the queue is empty.
+                */
+               if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive))
+                       break;
+
+               drive->rq = rq;
+
+               spin_unlock(ch->lock);
+               ide__sti();     /* allow other IRQs while we start this request */
+
                /*
-                * Feed commands to a drive until it barfs.
+                * This initiates handling of a new I/O request.
                 */
-               do {
-                       if (!test_bit(IDE_BUSY, ch->active))
-                               printk(KERN_ERR "%s: error: not busy while queueing!\n", drive->name);
 
-                       /* Abort early if we can't queue another command. for
-                        * non tcq, ata_can_queue is always 1 since we never
-                        * get here unless the drive is idle.
-                        */
-                       if (!ata_can_queue(drive)) {
-                               if (!ata_pending_commands(drive))
-                                       clear_bit(IDE_BUSY, ch->active);
-                               break;
-                       }
+               BUG_ON(!(rq->flags & REQ_STARTED));
 
-                       drive->sleep = 0;
+#ifdef DEBUG
+               printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq);
+#endif
 
-                       if (test_bit(IDE_DMA, ch->active)) {
-                               printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
-                               break;
-                       }
+               /* bail early if we've exceeded max_failures */
+               if (drive->max_failures && (drive->failures > drive->max_failures))
+                       goto kill_rq;
 
-                       /* There's a small window between where the queue could
-                        * be replugged while we are in here when using tcq (in
-                        * which case the queue is probably empty anyways...),
-                        * so check and leave if appropriate. When not using
-                        * tcq, this is still a severe BUG!
-                        */
-                       if (blk_queue_plugged(&drive->queue)) {
-                               BUG_ON(!drive->using_tcq);
-                               break;
-                       }
+               block = rq->sector;
 
-                       if (!(rq = elv_next_request(&drive->queue))) {
-                               if (!ata_pending_commands(drive))
-                                       clear_bit(IDE_BUSY, ch->active);
-                               drive->rq = NULL;
-                               break;
-                       }
+               /* Strange disk manager remap.
+                */
+               if (rq->flags & REQ_CMD)
+                       if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY)
+                               block += drive->sect0;
 
-                       /* If there are queued commands, we can't start a
-                        * non-fs request (really, a non-queuable command)
-                        * until the queue is empty.
-                        */
-                       if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive))
-                               break;
+               /* 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 */
+
+               ata_select(drive, 0);
+               ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
+                               WAIT_READY, rq);
+
+               if (ret != ATA_OP_READY) {
+                       printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
+
+                       goto kill_rq;
+               }
+
+               if (!ata_ops(drive)) {
+                       printk(KERN_WARNING "%s: device type %d not supported\n",
+                                       drive->name, drive->type);
+                       goto kill_rq;
+               }
 
-                       drive->rq = rq;
+               /* The normal way of execution is to pass and execute the request
+                * handler down to the device type driver.
+                */
+
+               if (ata_ops(drive)->do_request) {
+                       ret = ata_ops(drive)->do_request(drive, rq, block);
+               } else {
+kill_rq:
+                       if (ata_ops(drive) && ata_ops(drive)->end_request)
+                               ata_ops(drive)->end_request(drive, rq, 0);
+                       else
+                               ata_end_request(drive, rq, 0, 0);
+                       ret = ATA_OP_FINISHED;
 
-                       spin_unlock(ch->lock);
-                       ide__sti();     /* allow other IRQs while we start this request */
-                       startstop = start_request(drive, rq);
-                       spin_lock_irq(ch->lock);
+               }
+               spin_lock_irq(ch->lock);
 
-                       /* command started, we are busy */
-               } while (startstop != ATA_OP_CONTINUES);
-               /* make sure the BUSY bit is set */
-               /* FIXME: perhaps there is some place where we miss to set it? */
+               /* continue if command started, so we are busy */
+       } while (ret != ATA_OP_CONTINUES);
+       /* make sure the BUSY bit is set */
+       /* FIXME: perhaps there is some place where we miss to set it? */
 //             set_bit(IDE_BUSY, ch->active);
-       }
 }
 
 void do_ide_request(request_queue_t *q)
 {
-       do_request(q->queuedata);
+       struct ata_channel *ch = q->queuedata;
+
+       while (!test_and_set_bit(IDE_BUSY, ch->active)) {
+               do_request(ch);
+       }
 }
 
 /*
@@ -908,7 +767,8 @@ void do_ide_request(request_queue_t *q)
  * also be invoked as a result of a "sleep" operation triggered by the
  * mod_timer() call in do_request.
  *
- * FIXME: this should take a drive context instead of a channel.
+ * FIXME: This should take a drive context instead of a channel.
+ * FIXME: This should not explicitly reenter the request handling engine.
  */
 void ide_timer_expiry(unsigned long data)
 {
@@ -928,6 +788,8 @@ void ide_timer_expiry(unsigned long data)
                 * as timer expired), or we were "sleeping" to give other
                 * devices a chance.  Either way, we don't really want to
                 * complain about anything.
+                *
+                * FIXME: Do we really still have to clear IDE_BUSY here?
                 */
 
                if (test_and_clear_bit(IDE_SLEEP, ch->active))
@@ -979,7 +841,7 @@ void ide_timer_expiry(unsigned long data)
                __cli();        /* local CPU only, as if we were handling an interrupt */
                if (ch->poll_timeout) {
                        ret = handler(drive, drive->rq);
-               } else if (drive_is_ready(drive)) {
+               } else if (ata_status_irq(drive)) {
                        if (test_bit(IDE_DMA, ch->active))
                                udma_irq_lost(drive);
                        (void) ide_ack_intr(ch);
@@ -1026,11 +888,10 @@ void ide_timer_expiry(unsigned long data)
                enable_irq(ch->irq);
                spin_lock_irq(ch->lock);
 
-               if (ret == ATA_OP_FINISHED)
-                       clear_bit(IDE_BUSY, ch->active);
-
-               /* Reenter the request handling engine */
-               do_request(ch);
+               if (ret == ATA_OP_FINISHED) {
+                       /* Reenter the request handling engine. */
+                       do_request(ch);
+               }
        }
        spin_unlock_irqrestore(ch->lock, flags);
 }
@@ -1060,32 +921,35 @@ void ide_timer_expiry(unsigned long data)
  */
 static void unexpected_irq(int irq)
 {
+       /* Try to not flood the console with msgs */
+       static unsigned long last_msgtime; /* = 0 */
+       static int count;                  /* = 0 */
        int i;
 
        for (i = 0; i < MAX_HWIFS; ++i) {
                struct ata_channel *ch = &ide_hwifs[i];
+               int j;
                struct ata_device *drive;
 
-               if (!ch->present)
+               if (!ch->present || ch->irq != irq)
                        continue;
 
-               if (ch->irq != irq)
-                       continue;
+               for (j = 0; j < MAX_DRIVES; ++j) {
+                       drive = &ch->drives[j];
 
-               /* FIXME: this is a bit weak */
-               drive = &ch->drives[0];
-
-               if (!ata_status(drive, READY_STAT, BAD_STAT)) {
-                       /* Try to not flood the console with msgs */
-                       static unsigned long last_msgtime;
-                       static int count;
+                       /* this drive is idle */
+                       if (ata_status(drive, READY_STAT, BAD_STAT))
+                               continue;
 
                        ++count;
-                       if (time_after(jiffies, last_msgtime + HZ)) {
-                               last_msgtime = jiffies;
-                               printk("%s: unexpected interrupt, status=0x%02x, count=%d\n",
-                                               ch->name, drive->status, count);
-                       }
+
+                       /* don't report too frequently */
+                       if (!time_after(jiffies, last_msgtime + HZ))
+                               continue;
+
+                       last_msgtime = jiffies;
+                       printk("%s: unexpected interrupt, status=0x%02x, count=%d\n",
+                                       ch->name, drive->status, count);
                }
        }
 }
@@ -1099,7 +963,7 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs)
        unsigned long flags;
        struct ata_device *drive;
        ata_handler_t *handler;
-       ide_startstop_t startstop;
+       ide_startstop_t ret;
 
        spin_lock_irqsave(ch->lock, flags);
 
@@ -1107,53 +971,53 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs)
                goto out_lock;
 
        handler = ch->handler;
-       if (handler == NULL || ch->poll_timeout != 0) {
+       drive = ch->drive;
+       if (!handler || ch->poll_timeout) {
 #if 0
                printk(KERN_INFO "ide: unexpected interrupt %d %d\n", ch->unit, irq);
 #endif
+
                /*
-                * Not expecting an interrupt from this drive.
-                * That means this could be:
-                *      (1) an interrupt from another PCI device
-                *      sharing the same PCI INT# as us.
-                * or   (2) a drive just entered sleep or standby mode,
-                *      and is interrupting to let us know.
-                * or   (3) a spurious interrupt of unknown origin.
+                * Not expecting an interrupt from this drive.  That means this
+                * could be:
+                *
+                * - an interrupt from another PCI device sharing the same PCI
+                * INT# as us.
                 *
-                * For PCI, we cannot tell the difference,
-                * so in that case we just ignore it and hope it goes away.
+                * - a drive just entered sleep or standby mode, and is
+                * interrupting to let us know.
+                *
+                * - a spurious interrupt of unknown origin.
+                *
+                * For PCI, we cannot tell the difference, so in that case we
+                * just clear it and hope it goes away.
                 */
+
 #ifdef CONFIG_PCI
                if (ch->pci_dev && !ch->pci_dev->vendor)
 #endif
-               {
-                       /* Probably not a shared PCI interrupt, so we can
-                        * safely try to do something about it:
-                        */
                        unexpected_irq(irq);
 #ifdef CONFIG_PCI
-               } else {
-                       /*
-                        * Whack the status register, just in case we have a leftover pending IRQ.
-                        */
-                       IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]);
+               else
+                       ata_status(drive, READY_STAT, BAD_STAT);
 #endif
-               }
+
                goto out_lock;
        }
-       drive = ch->drive;
-       if (!drive_is_ready(drive)) {
-               /*
-                * This happens regularly when we share a PCI IRQ with another device.
+       if (!ata_status_irq(drive)) {
+               /* This happens regularly when we share a PCI IRQ with another device.
                 * Unfortunately, it can also happen with some buggy drives that trigger
                 * the IRQ before their status register is up to date.  Hopefully we have
                 * enough advance overhead that the latter isn't a problem.
                 */
+
                goto out_lock;
        }
+
        /* paranoia */
        if (!test_and_set_bit(IDE_BUSY, ch->active))
-               printk(KERN_ERR "%s: %s: hwgroup was not busy!?\n", drive->name, __FUNCTION__);
+               printk(KERN_ERR "%s: %s: channel was not busy!?\n", drive->name, __FUNCTION__);
+
        ch->handler = NULL;
        del_timer(&ch->timer);
 
@@ -1162,25 +1026,32 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs)
        if (ch->unmask)
                ide__sti();
 
-       /* service this interrupt, may set handler for next interrupt */
-       startstop = handler(drive, drive->rq);
+       /*
+        * Service this interrupt, this may setup handler for next interrupt.
+        */
+       ret = handler(drive, drive->rq);
 
        spin_lock_irq(ch->lock);
 
        /*
-        * Note that handler() may have set things up for another
-        * interrupt to occur soon, but it cannot happen until
-        * we exit from this routine, because it will be the
-        * same irq as is currently being serviced here, and Linux
-        * won't allow another of the same (on any CPU) until we return.
+        * Note that handler() may have set things up for another interrupt to
+        * occur soon, but it cannot happen until we exit from this routine,
+        * because it will be the same irq as is currently being serviced here,
+        * and Linux won't allow another of the same (on any CPU) until we
+        * return.
         */
-       if (startstop == ATA_OP_FINISHED) {
-               if (!ch->handler) {     /* paranoia */
-                       clear_bit(IDE_BUSY, ch->active);
+
+       if (ret == ATA_OP_FINISHED) {
+
+               /* Reenter the request handling engine if we are not expecting
+                * another interrupt.
+                */
+
+               if (!ch->handler)
                        do_request(ch);
-               } else {
-                       printk("%s: %s: huh? expected NULL handler on exit\n", drive->name, __FUNCTION__);
-               }
+               else
+                       printk("%s: %s: huh? expected NULL handler on exit\n",
+                                       drive->name, __FUNCTION__);
        }
 
 out_lock:
@@ -1202,7 +1073,7 @@ static int ide_open(struct inode * inode, struct file * filp)
         */
 
 #ifdef CONFIG_KMOD
-       if (drive->driver == NULL) {
+       if (!drive->driver) {
                char *module = NULL;
 
                switch (drive->type) {
@@ -1263,6 +1134,7 @@ static int ide_release(struct inode * inode, struct file * file)
        drive->usage--;
        if (ata_ops(drive) && ata_ops(drive)->release)
                ata_ops(drive)->release(inode, file, drive);
+
        return 0;
 }
 
@@ -1332,7 +1204,7 @@ EXPORT_SYMBOL(ata_set_handler);
 EXPORT_SYMBOL(ata_dump);
 EXPORT_SYMBOL(ata_error);
 
-EXPORT_SYMBOL(__ata_end_request);
+EXPORT_SYMBOL(ata_end_request);
 EXPORT_SYMBOL(ide_stall_queue);
 
 EXPORT_SYMBOL(ide_setup_ports);
index 96fb19d3f89de1f2c7f3e67da71607672a1053c2..24cc8bc9a75ec6598bf5dc00c3885bf6e374bf66 100644 (file)
@@ -140,12 +140,9 @@ struct ata_channel ide_hwifs[MAX_HWIFS];   /* master data repository */
  * Setup hw_regs_t structure described by parameters.  You may set up the hw
  * structure yourself OR use this routine to do it for you.
  */
-void ide_setup_ports(hw_regs_t *hw,
-               ide_ioreg_t base,
-               int *offsets,
-               ide_ioreg_t ctrl,
-               ide_ioreg_t intr,
-               ide_ack_intr_t *ack_intr,
+void ide_setup_ports(hw_regs_t *hw, ide_ioreg_t base, int *offsets,
+               ide_ioreg_t ctrl, ide_ioreg_t intr,
+               int (*ack_intr)(struct ata_channel *),
                int irq)
 {
        int i;
@@ -637,17 +634,6 @@ found:
  * FIXME: rewrite the following crap:
  */
 
-/*
- * stridx() returns the offset of c within s,
- * or -1 if c is '\0' or not found within s.
- */
-static int __init stridx (const char *s, char c)
-{
-       char *i = strchr(s, c);
-
-       return (i && c) ? i - s : -1;
-}
-
 /*
  * Parsing for ide_setup():
  *
@@ -657,14 +643,14 @@ static int __init stridx (const char *s, char c)
  * 3. if the remainder is a series of no more than max_vals numbers
  *     separated by commas, the numbers are saved in vals[] and a
  *     count of how many were saved is returned.  Base10 is assumed,
- *     and base16 is allowed when prefixed with "0x".
+ *     and base16 is allowed when prefixed with "0x".  The number of 
+ *     values read will be placed in vals[0], and the values read will
+ *     placed in vals[1] to vals[max_vals].
  * 4. otherwise, zero is returned.
  */
 static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals)
 {
-       static const char decimal[] = "0123456789";
-       static const char hex[] = "0123456789abcdef";
-       int i, n;
+       int i;
 
        if (*s++ == '=') {
                /*
@@ -683,23 +669,10 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
                 * or base16 when prefixed with "0x".
                 * Return a count of how many were found.
                 */
-               for (n = 0; (i = stridx(decimal, *s)) >= 0;) {
-                       vals[n] = i;
-                       while ((i = stridx(decimal, *++s)) >= 0)
-                               vals[n] = (vals[n] * 10) + i;
-                       if (*s == 'x' && !vals[n]) {
-                               while ((i = stridx(hex, *++s)) >= 0)
-                                       vals[n] = (vals[n] * 0x10) + i;
-                       }
-                       if (++n == max_vals)
-                               break;
-                       if (*s == ',' || *s == ';')
-                               ++s;
-               }
-               if (!*s)
-                       return n;
+               get_options(s, max_vals+1, vals);
+               return vals[0];
        }
-       return 0;       /* zero = nothing matched */
+       return 0;
 }
 
 /*
@@ -744,7 +717,7 @@ static void __init init_global_data(void)
  */
 int __init ide_setup(char *s)
 {
-       int i, vals[3];
+       int i, vals[4];
        struct ata_channel *ch;
        struct ata_device *drive;
        unsigned int hw, unit;
@@ -755,7 +728,6 @@ int __init ide_setup(char *s)
                return 0;
 
        if (strncmp(s,"ide",3) &&
-           strncmp(s,"idebus",6) &&
            strncmp(s,"hd",2))          /* hdx= & hdxlun= */
                return 0;
 
@@ -801,24 +773,24 @@ int __init ide_setup(char *s)
                unit = unit % MAX_DRIVES;
                ch = &ide_hwifs[hw];
                drive = &ch->drives[unit];
-               if (!strncmp(s + 4, "ide-", 4)) {
+               if (!strncmp(s+3, "=ide-", 5)) {
                        strncpy(drive->driver_req, s + 4, 9);
                        goto done;
                }
                /*
                 * Look for last lun option:  "hdxlun="
                 */
-               if (!strncmp(&s[3], "lun", 3)) {
-                       if (match_parm(&s[6], NULL, vals, 1) != 1)
+               if (!strncmp(s+3, "lun=", 4)) {
+                       if (*get_options(s+7, 2, vals) || vals[0]!=1)
                                goto bad_option;
-                       if (vals[0] >= 0 && vals[0] <= 7) {
-                               drive->last_lun = vals[0];
+                       if (vals[1] >= 0 && vals[1] <= 7) {
+                               drive->last_lun = vals[1];
                                drive->forced_lun = 1;
                        } else
                                printk(" -- BAD LAST LUN! Expected value from 0 to 7");
                        goto done;
                }
-               switch (match_parm(&s[3], hd_words, vals, 3)) {
+               switch (match_parm(s+3, hd_words, vals, 3)) {
                        case -1: /* "none" */
                                drive->nobios = 1;  /* drop into "noprobe" */
                        case -2: /* "noprobe" */
@@ -864,9 +836,9 @@ int __init ide_setup(char *s)
 #endif
                        case 3: /* cyl,head,sect */
                                drive->type     = ATA_DISK;
-                               drive->cyl      = drive->bios_cyl  = vals[0];
-                               drive->head     = drive->bios_head = vals[1];
-                               drive->sect     = drive->bios_sect = vals[2];
+                               drive->cyl      = drive->bios_cyl  = vals[1];
+                               drive->head     = drive->bios_head = vals[2];
+                               drive->sect     = drive->bios_sect = vals[3];
                                drive->present  = 1;
                                drive->forced_geom = 1;
                                ch->noprobe = 0;
@@ -879,10 +851,10 @@ int __init ide_setup(char *s)
        /*
         * Look for bus speed option:  "idebus="
         */
-       if (!strncmp(s, "idebus", 6)) {
-               if (match_parm(&s[6], NULL, vals, 1) != 1)
+       if (!strncmp(s, "idebus=", 7)) {
+               if (*get_options(s+7, 2, vals) || vals[0] != 1)
                        goto bad_option;
-               idebus_parameter = vals[0];
+               idebus_parameter = vals[1];
                goto done;
        }
 
@@ -892,33 +864,72 @@ int __init ide_setup(char *s)
        if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_ch) {
                /*
                 * Be VERY CAREFUL changing this: note hardcoded indexes below
-                * -8,-9,-10. -11 : are reserved for future idex calls to ease the hardcoding.
                 */
+               const char *ide_options[] = {
+                       "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", NULL };
                const char *ide_words[] = {
-                       "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66",
-                       "minus8", "minus9", "minus10", "minus11",
                        "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
                hw = s[3] - '0';
                ch = &ide_hwifs[hw];
 
+
+               switch (match_parm(s+4, ide_options, vals, 1)) {
+                       case -7: /* ata66 */
+#ifdef CONFIG_PCI
+                               ch->udma_four = 1;
+                               goto done;
+#else
+                               ch->udma_four = 0;
+                               goto bad_channel;
+#endif
+                       case -6: /* dma */
+                               ch->autodma = 1;
+                               goto done;
+                       case -5: /* reset */
+                               ch->reset = 1;
+                               goto done;
+                       case -4: /* noautotune */
+                               ch->drives[0].autotune = 2;
+                               ch->drives[1].autotune = 2;
+                               goto done;
+                       case -3: /* autotune */
+                               ch->drives[0].autotune = 1;
+                               ch->drives[1].autotune = 1;
+                               goto done;
+                       case -2: /* "serialize" */
+                       do_serialize:
+                               {
+                                       struct ata_channel *mate;
+
+                                       mate = &ide_hwifs[hw ^ 1];
+                                       ch->serialized = 1;
+                                       mate->serialized = 1;
+                               }
+                               goto done;
+
+                       case -1: /* "noprobe" */
+                               ch->noprobe = 1;
+                               goto done;
+               }
+
                i = match_parm(&s[4], ide_words, vals, 3);
 
                /*
                 * Cryptic check to ensure chipset not already set for a channel:
                 */
-               if (i > 0 || i <= -11) {                        /* is parameter a chipset name? */
-                       if (ch->chipset != ide_unknown)
+               if (i) {                        /* is parameter a chipset name? */
+                       if (ide_hwifs[hw].chipset != ide_unknown)
                                goto bad_option;        /* chipset already specified */
-                       if (i <= -11 && i != -18 && hw != 0)
+                       if (i != -7 && hw != 0)
                                goto bad_channel;               /* chipset drivers are for "ide0=" only */
-                       if (i <= -11 && i != -18 && ide_hwifs[hw+1].chipset != ide_unknown)
+                       if (i != -7 && ide_hwifs[1].chipset != ide_unknown)
                                goto bad_option;        /* chipset for 2nd port already specified */
                        printk("\n");
                }
 
                switch (i) {
 #ifdef CONFIG_BLK_DEV_PDC4030
-                       case -18: /* "dc4030" */
+                       case -7:  /* "dc4030" */
                        {
                                extern void init_pdc4030(void);
                                init_pdc4030();
@@ -926,7 +937,7 @@ int __init ide_setup(char *s)
                        }
 #endif
 #ifdef CONFIG_BLK_DEV_ALI14XX
-                       case -17: /* "ali14xx" */
+                       case -6:  /* "ali14xx" */
                        {
                                extern void init_ali14xx (void);
                                init_ali14xx();
@@ -934,7 +945,7 @@ int __init ide_setup(char *s)
                        }
 #endif
 #ifdef CONFIG_BLK_DEV_UMC8672
-                       case -16: /* "umc8672" */
+                       case -5:  /* "umc8672" */
                        {
                                extern void init_umc8672 (void);
                                init_umc8672();
@@ -942,7 +953,7 @@ int __init ide_setup(char *s)
                        }
 #endif
 #ifdef CONFIG_BLK_DEV_DTC2278
-                       case -15: /* "dtc2278" */
+                       case -4:  /* "dtc2278" */
                        {
                                extern void init_dtc2278 (void);
                                init_dtc2278();
@@ -950,7 +961,7 @@ int __init ide_setup(char *s)
                        }
 #endif
 #ifdef CONFIG_BLK_DEV_CMD640
-                       case -14: /* "cmd640_vlb" */
+                       case -3:  /* "cmd640_vlb" */
                        {
                                extern int cmd640_vlb; /* flag for cmd640.c */
                                cmd640_vlb = 1;
@@ -958,7 +969,7 @@ int __init ide_setup(char *s)
                        }
 #endif
 #ifdef CONFIG_BLK_DEV_HT6560B
-                       case -13: /* "ht6560b" */
+                       case -2:  /* "ht6560b" */
                        {
                                extern void init_ht6560b (void);
                                init_ht6560b();
@@ -966,64 +977,22 @@ int __init ide_setup(char *s)
                        }
 #endif
 #if CONFIG_BLK_DEV_QD65XX
-                       case -12: /* "qd65xx" */
+                       case -1 /* "qd65xx" */
                        {
                                extern void init_qd65xx (void);
                                init_qd65xx();
                                goto done;
                        }
 #endif
-                       case -11: /* minus11 */
-                       case -10: /* minus10 */
-                       case -9: /* minus9 */
-                       case -8: /* minus8 */
-                               goto bad_option;
-                       case -7: /* ata66 */
-#ifdef CONFIG_PCI
-                               ch->udma_four = 1;
-                               goto done;
-#else
-                               ch->udma_four = 0;
-                               goto bad_channel;
-#endif
-                       case -6: /* dma */
-                               ch->autodma = 1;
-                               goto done;
-                       case -5: /* reset */
-                               ch->reset = 1;
-                               goto done;
-                       case -4: /* noautotune */
-                               ch->drives[0].autotune = 2;
-                               ch->drives[1].autotune = 2;
-                               goto done;
-                       case -3: /* autotune */
-                               ch->drives[0].autotune = 1;
-                               ch->drives[1].autotune = 1;
-                               goto done;
-                       case -2: /* "serialize" */
-                       do_serialize:
-                               {
-                                       struct ata_channel *mate;
-
-                                       mate = &ide_hwifs[hw ^ 1];
-                                       ch->serialized = 1;
-                                       mate->serialized = 1;
-                               }
-                               goto done;
-
-                       case -1: /* "noprobe" */
-                               ch->noprobe = 1;
-                               goto done;
-
                        case 1: /* base */
-                               vals[1] = vals[0] + 0x206; /* default ctl */
+                               vals[2] = vals[1] + 0x206; /* default ctl */
                        case 2: /* base,ctl */
-                               vals[2] = 0;    /* default irq = probe for it */
+                               vals[3] = 0;    /* default irq = probe for it */
                        case 3: /* base,ctl,irq */
-                               ch->hw.irq = vals[2];
-                               ide_init_hwif_ports(&ch->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &ch->irq);
+                               ch->hw.irq = vals[3];
+                               ide_init_hwif_ports(&ch->hw, (ide_ioreg_t) vals[1], (ide_ioreg_t) vals[2], &ch->irq);
                                memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports));
-                               ch->irq = vals[2];
+                               ch->irq = vals[3];
                                ch->noprobe  = 0;
                                ch->chipset  = ide_generic;
                                goto done;
index 4dd11411110f1209d9925eadef5246bec966a176..a476693a382017d350efd2fa13ca414a04c5b93d 100644 (file)
@@ -46,7 +46,7 @@ ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq)
 
        if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
                if (!dma_stat) {
-                       __ata_end_request(drive, rq, 1, rq->nr_sectors);
+                       ata_end_request(drive, rq, 1, rq->nr_sectors);
 
                        return ATA_OP_FINISHED;
                }
@@ -510,7 +510,7 @@ int udma_pci_irq_status(struct ata_device *drive)
 
 void udma_pci_timeout(struct ata_device *drive)
 {
-       printk(KERN_ERR "ATA: UDMA timeout occured %s!\n", drive->name);
+       printk(KERN_ERR "%s: UDMA timeout!\n", drive->name);
 }
 
 void udma_pci_irq_lost(struct ata_device *drive)
index df7ede3b83ce5563b1e8b30a1d0a9f5bbdc60a41..940ce70f6e305969b0f7afa868bcdbf7253ec953 100644 (file)
@@ -3,10 +3,11 @@
  *  linux/drivers/ide/pdc202xx.c       Version 0.30    May. 28, 2002
  *
  *  Copyright (C) 1998-2000    Andre Hedrick <andre@linux-ide.org>
- *  Copyright (C) 2002         Bartlomiej Zolnierkiewicz
+ *  Copyright (C) 2002         BartÅ^Âomiej Å»oÅ^Ânierkiewicz
  *
- *  Portions Copyright (C) 1999 Promise Technology, Inc.
- *  Author: Frank Tiernan (frankt@promise.com)
+ *  Portions Copyright (C) 1999-2002 Promise Technology, Inc.
+ *  Author:    Frank Tiernan <frankt@promise.com>
+ *             Hank Yang <support@promise.com.tw>
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *
  *
  *  The latest chipset code will support the following ::
  *  Three Ultra33 controllers and 12 drives.
+ *
  *  8 are UDMA supported and 4 are limited to DMA mode 2 multi-word.
  *  The 8/4 ratio is a BIOS code limit by promise.
  *
  *  UNLESS you enable "CONFIG_PDC202XX_BURST"
  *
+ *  History:
+ *  Sync 2.5 driver with Promise 2.4 driver v1.20.0.7 (07/11/02):
+ *             - Add PDC20271 support
+ *             - Disable LBA48 support on PDC20262
+ *             - Fix ATAPI UDMA port value
+ *             - Add new quirk drive
+ *             - Adjust timings for all drives when using ATA133
+ *             - Update pdc202xx_reset() waiting time
+ *
  */
 
 #include <linux/config.h>
@@ -108,6 +119,8 @@ static void pdc_dump_bits(struct pdc_bit_messages *msgs, byte bits)
 }
 #endif /* PDC202XX_DECODE_REGISTER_INFO */
 
+static struct ata_device* drives[4];
+
 int check_in_drive_lists(struct ata_device *drive)
 {
        static const char *pdc_quirk_drives[] = {
@@ -115,12 +128,14 @@ int check_in_drive_lists(struct ata_device *drive)
                "QUANTUM FIREBALLP KA6.4",
                "QUANTUM FIREBALLP KA9.1",
                "QUANTUM FIREBALLP LM20.4",
+               "QUANTUM FIREBALLP KX13.6",
                "QUANTUM FIREBALLP KX20.5",
                "QUANTUM FIREBALLP KX27.3",
                "QUANTUM FIREBALLP LM20.5",
                NULL
        };
-     const char**list = pdc_quirk_drives;
+
+       const char**list = pdc_quirk_drives;
        struct hd_driveid *id = drive->id;
 
        while (*list)
@@ -136,6 +151,7 @@ static int __init pdc202xx_modes_map(struct ata_channel *ch)
        switch(ch->pci_dev->device) {
                case PCI_DEVICE_ID_PROMISE_20276:
                case PCI_DEVICE_ID_PROMISE_20275:
+               case PCI_DEVICE_ID_PROMISE_20271:
                case PCI_DEVICE_ID_PROMISE_20269:
                        map |= XFER_UDMA_133;
                case PCI_DEVICE_ID_PROMISE_20268R:
@@ -250,105 +266,125 @@ static int pdc202xx_tune_chipset(struct ata_device *drive, byte speed)
 static int pdc202xx_new_tune_chipset(struct ata_device *drive, byte speed)
 {
        struct ata_channel *hwif = drive->channel;
-#ifdef CONFIG_BLK_DEV_IDEDMA
-       unsigned long indexreg  = (hwif->dma_base + 1);
-       unsigned long datareg   = (hwif->dma_base + 3);
-#else
        u32 high_16 = pci_resource_start(hwif->pci_dev, 4);
-       unsigned long indexreg  = high_16 + (hwif->unit ? 0x09 : 0x01);
-       unsigned long datareg   = (indexreg + 2);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-       byte thold              = 0x10;
-       byte adj                = (drive->dn%2) ? 0x08 : 0x00;
+       u32 indexreg = high_16 + (hwif->unit ? 0x09 : 0x01);
+       u32 datareg = indexreg + 2;
+
+       u8 adj = (drive->dn % 2) ? 0x08 : 0x00;
+       u8 thold = 0x10;
+       int err, i, j = hwif->unit ? 2 : 0;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
+       /* Setting tHOLD bit to 0 if using UDMA mode 2 */
        if (speed == XFER_UDMA_2) {
                OUT_BYTE((thold + adj), indexreg);
                OUT_BYTE((IN_BYTE(datareg) & 0x7f), datareg);
        }
-       switch (speed) {
-               case XFER_UDMA_7:
-                       speed = XFER_UDMA_6;
-               case XFER_UDMA_6:
-                       set_2regs(0x10, 0x1a);
-                       set_2regs(0x11, 0x01);
-                       set_2regs(0x12, 0xcb);
-                       break;
-               case XFER_UDMA_5:
-                       set_2regs(0x10, 0x1a);
-                       set_2regs(0x11, 0x02);
-                       set_2regs(0x12, 0xcb);
-                       break;
-               case XFER_UDMA_4:
-                       set_2regs(0x10, 0x1a);
-                       set_2regs(0x11, 0x03);
-                       set_2regs(0x12, 0xcd);
-                       break;
-               case XFER_UDMA_3:
-                       set_2regs(0x10, 0x1a);
-                       set_2regs(0x11, 0x05);
-                       set_2regs(0x12, 0xcd);
-                       break;
-               case XFER_UDMA_2:
-                       set_2regs(0x10, 0x2a);
-                       set_2regs(0x11, 0x07);
-                       set_2regs(0x12, 0xcd);
-                       break;
-               case XFER_UDMA_1:
-                       set_2regs(0x10, 0x3a);
-                       set_2regs(0x11, 0x0a);
-                       set_2regs(0x12, 0xd0);
-                       break;
-               case XFER_UDMA_0:
-                       set_2regs(0x10, 0x4a);
-                       set_2regs(0x11, 0x0f);
-                       set_2regs(0x12, 0xd5);
-                       break;
-               case XFER_MW_DMA_2:
-                       set_2regs(0x0e, 0x69);
-                       set_2regs(0x0f, 0x25);
-                       break;
-               case XFER_MW_DMA_1:
-                       set_2regs(0x0e, 0x6b);
-                       set_2regs(0x0f, 0x27);
-                       break;
-               case XFER_MW_DMA_0:
-                       set_2regs(0x0e, 0xdf);
-                       set_2regs(0x0f, 0x5f);
-                       break;
-#else
-       switch (speed) {
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-               case XFER_PIO_4:
-                       set_2regs(0x0c, 0x23);
-                       set_2regs(0x0d, 0x09);
-                       set_2regs(0x13, 0x25);
-                       break;
-               case XFER_PIO_3:
-                       set_2regs(0x0c, 0x27);
-                       set_2regs(0x0d, 0x0d);
-                       set_2regs(0x13, 0x35);
-                       break;
-               case XFER_PIO_2:
-                       set_2regs(0x0c, 0x23);
-                       set_2regs(0x0d, 0x26);
-                       set_2regs(0x13, 0x64);
-                       break;
-               case XFER_PIO_1:
-                       set_2regs(0x0c, 0x46);
-                       set_2regs(0x0d, 0x29);
-                       set_2regs(0x13, 0xa4);
-                       break;
-               case XFER_PIO_0:
-                       set_2regs(0x0c, 0xfb);
-                       set_2regs(0x0d, 0x2b);
-                       set_2regs(0x13, 0xac);
-                       break;
-               default:
-                       ;
+#endif
+
+       for (i = 0 ; i < 2 ; i++)
+               if (hwif->drives[i].present)
+                       drives[i+j] = &hwif->drives[i];
+
+       err = ide_config_drive_speed(drive, speed);
+
+       /* For modes < UDMA mode 6 we need only to SET_FEATURE */
+       if (speed < XFER_UDMA_6)
+               return err;
+
+       /* We need to adjust timings to ATA133 clock if ATA133 drives exist */
+       for (i = 0 ; i < 4 ; i++) {
+               if (!drives[i])
+                       continue;
+
+               /* Primary = 0x01, Secondary = 0x09 */
+               indexreg = high_16 + ((i > 1) ? 0x09 : 0x01);
+               datareg = indexreg + 2;
+
+               /* Master = 0x00, Slave = 0x08 */
+               adj = (i % 2) ? 0x08 : 0x00;
+
+               switch (drives[i]->current_speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA
+                       case XFER_UDMA_6:
+                               set_2regs(0x10, 0x1a);
+                               set_2regs(0x11, 0x01);
+                               set_2regs(0x12, 0xcb);
+                               break;
+                       case XFER_UDMA_5:
+                               set_2regs(0x10, 0x1a);
+                               set_2regs(0x11, 0x02);
+                               set_2regs(0x12, 0xcb);
+                               break;
+                       case XFER_UDMA_4:
+                               set_2regs(0x10, 0x1a);
+                               set_2regs(0x11, 0x03);
+                               set_2regs(0x12, 0xcd);
+                               break;
+                       case XFER_UDMA_3:
+                               set_2regs(0x10, 0x1a);
+                               set_2regs(0x11, 0x05);
+                               set_2regs(0x12, 0xcd);
+                               break;
+                       case XFER_UDMA_2:
+                               set_2regs(0x10, 0x2a);
+                               set_2regs(0x11, 0x07);
+                               set_2regs(0x12, 0xcd);
+                               break;
+                       case XFER_UDMA_1:
+                               set_2regs(0x10, 0x3a);
+                               set_2regs(0x11, 0x0a);
+                               set_2regs(0x12, 0xd0);
+                               break;
+                       case XFER_UDMA_0:
+                               set_2regs(0x10, 0x4a);
+                               set_2regs(0x11, 0x0f);
+                               set_2regs(0x12, 0xd5);
+                               break;
+                       case XFER_MW_DMA_2:
+                               set_2regs(0x0e, 0x69);
+                               set_2regs(0x0f, 0x25);
+                               break;
+                       case XFER_MW_DMA_1:
+                               set_2regs(0x0e, 0x6b);
+                               set_2regs(0x0f, 0x27);
+                               break;
+                       case XFER_MW_DMA_0:
+                               set_2regs(0x0e, 0xdf);
+                               set_2regs(0x0f, 0x5f);
+                               break;
+#endif
+                       case XFER_PIO_4:
+                               set_2regs(0x0c, 0x23);
+                               set_2regs(0x0d, 0x09);
+                               set_2regs(0x13, 0x25);
+                               break;
+                       case XFER_PIO_3:
+                               set_2regs(0x0c, 0x27);
+                               set_2regs(0x0d, 0x0d);
+                               set_2regs(0x13, 0x35);
+                               break;
+                       case XFER_PIO_2:
+                               set_2regs(0x0c, 0x23);
+                               set_2regs(0x0d, 0x26);
+                               set_2regs(0x13, 0x64);
+                               break;
+                       case XFER_PIO_1:
+                               set_2regs(0x0c, 0x46);
+                               set_2regs(0x0d, 0x29);
+                               set_2regs(0x13, 0xa4);
+                               break;
+                       case XFER_PIO_0:
+                               set_2regs(0x0c, 0xfb);
+                               set_2regs(0x0d, 0x2b);
+                               set_2regs(0x13, 0xac);
+                               break;
+                       default:
+                               ;
+               }
        }
 
-       return ide_config_drive_speed(drive, speed);
+       return err;
 }
 
 /*   0    1    2    3    4    5    6   7   8
@@ -475,16 +511,19 @@ static void pdc202xx_udma_start(struct ata_device *drive, struct request *rq)
 {
        struct ata_channel *ch = drive->channel;
        u32 high_16 = pci_resource_start(ch->pci_dev, 4);
-       unsigned long atapi_reg = high_16 + (ch->unit ? 0x24 : 0x00);
+       unsigned long atapi_port = high_16 + (ch->unit ? 0x24 : 0x20);
 
+       /* Enable ATAPI UDMA port for 48bit data on PDC20265/PDC20267 */
        if (drive->addressing) {
-               unsigned long word_count = 0;
-               u8 clock = IN_BYTE(high_16 + PDC_CLK);
+               unsigned long word_count = 0, hankval;
+               u32 clockreg = high_16 + PDC_CLK;
+               u8 clock = IN_BYTE(clockreg);
 
-               outb(clock|(ch->unit ? 0x08 : 0x02), high_16 + PDC_CLK);
+               OUT_BYTE(clock | (ch->unit ? 0x08 : 0x02), clockreg);
                word_count = (rq->nr_sectors << 8);
-               word_count = (rq_data_dir(rq) == READ) ? word_count | 0x05000000 : word_count | 0x06000000;
-               outl(word_count, atapi_reg);
+               hankval = (rq_data_dir(rq) == READ) ? 0x05 << 24 : 0x06 << 24;
+               hankval |= word_count;
+               outl(hankval, atapi_port);
        }
 
        /* Note that this is done *after* the cmd has been issued to the drive,
@@ -499,14 +538,18 @@ static int pdc202xx_udma_stop(struct ata_device *drive)
 {
        struct ata_channel *ch = drive->channel;
        u32 high_16 = pci_resource_start(ch->pci_dev, 4);
-       unsigned long atapi_reg = high_16 + (ch->unit ? 0x24 : 0x00);
+       unsigned long atapi_port = high_16 + (ch->unit ? 0x24 : 0x20);
        unsigned long dma_base = ch->dma_base;
-       u8 dma_stat, clock;
+       u8 dma_stat;
 
+       /* Disable ATAPI UDMA port for 48bit data on PDC20265/PDC20267 */
        if (drive->addressing) {
-               outl(0, atapi_reg);     /* zero out extra */
-               clock = IN_BYTE(high_16 + PDC_CLK);
-               OUT_BYTE(clock & ~(ch->unit ? 0x08:0x02), high_16 + PDC_CLK);
+               u32 clockreg = high_16 + PDC_CLK;
+               u8 clock;
+
+               outl(0, atapi_port);            /* zero out extra */
+               clock = IN_BYTE(clockreg);
+               OUT_BYTE(clock & ~(ch->unit ? 0x08 : 0x02), clockreg);
        }
 
        outb(inb(dma_base)&~1, dma_base);       /* stop DMA */
@@ -527,21 +570,21 @@ static void pdc202xx_bug(struct ata_device *drive)
 
 #endif
 
-static void pdc202xx_new_reset(struct ata_device *drive)
+/* FIXME: use generic ata_reset()  --bzolnier */
+static void pdc202xx_reset(struct ata_device *drive)
 {
-       ata_reset(drive->channel);
-       mdelay(1000);
-       ata_irq_enable(drive, 1);
-       mdelay(1000);
+       outb(0x04, drive->channel->io_ports[IDE_CONTROL_OFFSET]);
+       udelay(10);
+       outb(0x00, drive->channel->io_ports[IDE_CONTROL_OFFSET]);
        printk(KERN_INFO "PDC202XX: %s channel reset.\n",
-               drive->channel->unit ? "Secondary" : "Primary");
+                        drive->channel->unit ? "Secondary" : "Primary");
 }
 
 /*
  * software host reset
  *
  * BIOS will set UDMA timing on if the drive supports it.
- * The user may then want to turn it off. A bug is that
+ * The user may then want to turn it off. A bug is
  * that device cannot handle a downgrade in timing from
  * UDMA to DMA. Disk accesses after issuing a set
  * feature command will result in errors.
@@ -549,6 +592,7 @@ static void pdc202xx_new_reset(struct ata_device *drive)
  * A software reset leaves the timing registers intact,
  * but resets the drives on both channels.
  */
+#if 0
 static void pdc202xx_reset_host(struct pci_dev *dev)
 {
        u32 high_16 = pci_resource_start(dev, 4);
@@ -566,17 +610,24 @@ void pdc202xx_reset(struct ata_device *drive)
        printk(KERN_INFO "%s: channel needs reset.\n", ch->name);
        pdc202xx_reset_host(ch->pci_dev);
 }
+#endif
 
 static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
 {
        u32 high_16 = pci_resource_start(dev, 4);
-       u8 burst = IN_BYTE(high_16 + PDC_UDMA);
+       u32 burstreg = high_16 + PDC_UDMA;
+       u8 burst = IN_BYTE(burstreg);
+
+       set_reg_and_wait(burst | 0x10, burstreg, 100);
+       /* FIXME: 2 seconds ?! */
+       set_reg_and_wait(burst & ~0x10, burstreg, 2000);
 
        if (dev->resource[PCI_ROM_RESOURCE].start) {
                pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
                printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", dev->name, dev->resource[PCI_ROM_RESOURCE].start);
        }
 
+#if 0
        switch (dev->device) {
                case PCI_DEVICE_ID_PROMISE_20267:
                case PCI_DEVICE_ID_PROMISE_20265:
@@ -584,8 +635,6 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
                        pdc202xx_reset_host(dev);
                        break;
                default:
-               /* FIXME: only checked for 20246 - is this right?,
-                         if it is needed it should go to ide-pci --bkz */
                        if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
                                byte irq = 0, irq2 = 0;
                                pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
@@ -597,11 +646,13 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
                        }
                        break;
        }
+#endif
 
 #ifdef CONFIG_PDC202XX_BURST
        if (!(burst & 1)) {
                printk(KERN_INFO "%s: forcing (U)DMA BURST.\n", dev->name);
-               OUT_BYTE(burst | 1, high_16 + PDC_UDMA);
+               OUT_BYTE(burst | 1, burstreg);
+               burst = IN_BYTE(burstreg);
        }
 #endif
        printk(KERN_INFO "%s: (U)DMA BURST %sabled, "
@@ -613,6 +664,7 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
        return dev->irq;
 }
 
+#if 0
 /* chipsets newer then 20267 */
 static unsigned int __init pdc202xx_tx_init_chipset(struct pci_dev *dev)
 {
@@ -622,6 +674,7 @@ static unsigned int __init pdc202xx_tx_init_chipset(struct pci_dev *dev)
        }
        return dev->irq;
 }
+#endif
 
 static unsigned int __init pdc202xx_ata66_check(struct ata_channel *ch)
 {
@@ -642,17 +695,18 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif)
 {
        hwif->tuneproc  = &pdc202xx_tune_drive;
        hwif->quirkproc = &check_in_drive_lists;
+       hwif->resetproc = &pdc202xx_reset;
 
         switch(hwif->pci_dev->device) {
-               case PCI_DEVICE_ID_PROMISE_20275:
                case PCI_DEVICE_ID_PROMISE_20276:
+               case PCI_DEVICE_ID_PROMISE_20275:
+               case PCI_DEVICE_ID_PROMISE_20271:
                case PCI_DEVICE_ID_PROMISE_20269:
                case PCI_DEVICE_ID_PROMISE_20268:
                case PCI_DEVICE_ID_PROMISE_20268R:
                        hwif->udma_four = pdc202xx_tx_ata66_check(hwif);
 
                        hwif->speedproc = &pdc202xx_new_tune_chipset;
-                       hwif->resetproc = &pdc202xx_new_reset;
 #ifdef CONFIG_BLK_DEV_IDEDMA
                        if (hwif->dma_base)
                                hwif->udma_setup = pdc202xx_tx_udma_setup;
@@ -660,10 +714,6 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif)
                        break;
                case PCI_DEVICE_ID_PROMISE_20267:
                case PCI_DEVICE_ID_PROMISE_20265:
-               case PCI_DEVICE_ID_PROMISE_20262:
-                       hwif->udma_four = pdc202xx_ata66_check(hwif);
-
-                       hwif->resetproc = &pdc202xx_reset;
 #ifdef CONFIG_BLK_DEV_IDEDMA
                        /* we need special functions for lba48 */
                        if (hwif->dma_base) {
@@ -671,7 +721,10 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif)
                                hwif->udma_stop = pdc202xx_udma_stop;
                        }
 #endif
-               /* FIXME: check whether 20246 works with lba48 --bkz */
+               /* PDC20262 doesn't support LBA48 */
+               case PCI_DEVICE_ID_PROMISE_20262:
+                       hwif->udma_four = pdc202xx_ata66_check(hwif);
+
                case PCI_DEVICE_ID_PROMISE_20246:
 #ifdef CONFIG_BLK_DEV_IDEDMA
                        if (hwif->dma_base)
@@ -752,7 +805,7 @@ static struct ata_pci_device chipsets[] __initdata = {
        {
                vendor: PCI_VENDOR_ID_PROMISE,
                device: PCI_DEVICE_ID_PROMISE_20268,
-               init_chipset: pdc202xx_tx_init_chipset,
+               init_chipset: pdc202xx_init_chipset,
                init_channel: ide_init_pdc202xx,
                bootable: OFF_BOARD,
                flags: ATA_F_IRQ | ATA_F_DMA
@@ -764,7 +817,7 @@ static struct ata_pci_device chipsets[] __initdata = {
        {
                vendor: PCI_VENDOR_ID_PROMISE,
                device: PCI_DEVICE_ID_PROMISE_20268R,
-               init_chipset: pdc202xx_tx_init_chipset,
+               init_chipset: pdc202xx_init_chipset,
                init_channel: ide_init_pdc202xx,
                bootable: OFF_BOARD,
                flags: ATA_F_IRQ  | ATA_F_DMA
@@ -772,7 +825,15 @@ static struct ata_pci_device chipsets[] __initdata = {
        {
                vendor: PCI_VENDOR_ID_PROMISE,
                device: PCI_DEVICE_ID_PROMISE_20269,
-               init_chipset: pdc202xx_tx_init_chipset,
+               init_chipset: pdc202xx_init_chipset,
+               init_channel: ide_init_pdc202xx,
+               bootable: OFF_BOARD,
+               flags: ATA_F_IRQ | ATA_F_DMA
+       },
+       {
+               vendor: PCI_VENDOR_ID_PROMISE,
+               device: PCI_DEVICE_ID_PROMISE_20271,
+               init_chipset: pdc202xx_init_chipset,
                init_channel: ide_init_pdc202xx,
                bootable: OFF_BOARD,
                flags: ATA_F_IRQ | ATA_F_DMA
@@ -780,7 +841,7 @@ static struct ata_pci_device chipsets[] __initdata = {
        {
                vendor: PCI_VENDOR_ID_PROMISE,
                device: PCI_DEVICE_ID_PROMISE_20275,
-               init_chipset: pdc202xx_tx_init_chipset,
+               init_chipset: pdc202xx_init_chipset,
                init_channel: ide_init_pdc202xx,
                bootable: OFF_BOARD,
                flags: ATA_F_IRQ | ATA_F_DMA
@@ -788,7 +849,7 @@ static struct ata_pci_device chipsets[] __initdata = {
        {
                vendor: PCI_VENDOR_ID_PROMISE,
                device: PCI_DEVICE_ID_PROMISE_20276,
-               init_chipset: pdc202xx_tx_init_chipset,
+               init_chipset: pdc202xx_init_chipset,
                init_channel: ide_init_pdc202xx,
                bootable: OFF_BOARD,
                flags: ATA_F_IRQ | ATA_F_DMA
index 6a4153e15cee9980aa4f1f786cb07a4799ea645a..5fff033d2891137f72d7d88c5238f30cd9720ba0 100644 (file)
@@ -415,7 +415,7 @@ read_next:
        rq->nr_sectors -= nsect;
        total_remaining = rq->nr_sectors;
        if ((rq->current_nr_sectors -= nsect) <= 0)
-               __ata_end_request(drive, rq, 1, 0);
+               ata_end_request(drive, rq, 1, 0);
 
        /*
         * Now the data has been read in, do the following:
@@ -477,7 +477,7 @@ static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struc
 #ifdef DEBUG_WRITE
        printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
 #endif
-       __ata_end_request(drive, rq, 1, rq->nr_sectors);
+       ata_end_request(drive, rq, 1, rq->nr_sectors);
 
        return ATA_OP_FINISHED;
 }
@@ -629,7 +629,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
        /* Check that it's a regular command. If not, bomb out early. */
        if (!(rq->flags & REQ_CMD)) {
                blk_dump_rq_flags(rq, "pdc4030 bad flags");
-               __ata_end_request(drive, rq, 0, 0);
+               ata_end_request(drive, rq, 0, 0);
 
                return ATA_OP_FINISHED;
        }
@@ -709,7 +709,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
        default:
                printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n");
 
-               __ata_end_request(drive, rq, 0, 0);
+               ata_end_request(drive, rq, 0, 0);
                return ATA_OP_FINISHED;
        }
 }
index ac31d2f2c39837cd3a1b24354077e931a799acea..c10d825150016c231bbe3c7cbeba6cfd3a3c9ab9 100644 (file)
@@ -12,7 +12,7 @@
    
    Authors:    Arjan van de Ven <arjanv@redhat.com>
                
-   Based on work done by Søren Schmidt for FreeBSD  
+   Based on work done by Søren Schmidt for FreeBSD  
 
 */
 
index e9a62b5d03b4f0ac87d7ad2df9e8dd927a23a6a2..da683c0783f5575c87588f38e1d3f8a83a3b8ed5 100644 (file)
@@ -97,11 +97,15 @@ int ide_xlate_1024(kdev_t i_rdev, int xparm, int ptheads, const char *msg)
                }
        }
 
-       /* There used to be code here that assigned drive->id->CHS
-          to drive->CHS and that to drive->bios_CHS. However, some disks have
-          id->C/H/S = 4092/16/63 but are larger than 2.1 GB.  In such cases
-          that code was wrong.  Moreover, there seems to be no reason to do
-          any of these things. */
+       /* There used to be code here that assigned drive->id->CHS to
+        * drive->CHS and that to drive->bios_CHS. However, some disks have
+        * id->C/H/S = 4092/16/63 but are larger than 2.1 GB.  In such cases
+        * that code was wrong.  Moreover, there seems to be no reason to do
+        * any of these things.
+        *
+        * Please note that recent RedHat changes to the disk utils are bogous
+        * and will report spurious errors.
+        */
 
        /* translate? */
        if (drive->forced_geom)
@@ -169,8 +173,8 @@ int ide_xlate_1024(kdev_t i_rdev, int xparm, int ptheads, const char *msg)
 }
 
 /*
- * hd_driveid data come as little endian, it needs to be converted on big
- * endian machines.
+ * Drive ID data come as little endian, it needs to be converted on big endian
+ * machines.
  */
 void ata_fix_driveid(struct hd_driveid *id)
 {
@@ -319,11 +323,8 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed)
        outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2);
 #endif
 
-       /* Don't use ide_wait_cmd here - it will attempt to set_geometry and
-        * recalibrate, but for some reason these don't work at this point
-        * (lost interrupt).
-         *
-         * Select the drive, and issue the SETFEATURES command
+       /*
+         * Select the drive, and issue the SETFEATURES command.
          */
        disable_irq(ch->irq);   /* disable_irq_nosync ?? */
        udelay(1);
@@ -339,7 +340,6 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed)
        udelay(1);
        ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_CMD, NULL);
        ata_mask(drive);
-
        enable_irq(ch->irq);
 
        if (ret != ATA_OP_READY) {
@@ -1127,6 +1127,7 @@ static void channel_init(struct ata_channel *ch)
        gd->sizes = kmalloc(ATA_MINORS * sizeof(int), GFP_KERNEL);
        if (!gd->sizes)
                goto err_kmalloc_gd_sizes;
+       memset(gd->sizes, 0, ATA_MINORS*sizeof(gd->sizes[0]));
 
        gd->part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
        if (!gd->part)
index 3f64394baf0914b19f087aace99791965faf83fb..2d05fd15fb49460c31b2cb23f13cfc32ec317878 100644 (file)
@@ -134,7 +134,6 @@ static void tcq_invalidate_queue(struct ata_device *drive)
        ar->XXX_handler = tcq_nop_handler;
        ar->command_type = IDE_DRIVE_TASK_NO_DATA;
 
-       rq->rq_dev = mk_kdev(drive->channel->major, (drive->select.b.unit)<<PARTN_BITS);
        _elv_add_request(q, rq, 0, 0);
 
 out:
@@ -359,7 +358,7 @@ static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *r
 
        TCQ_PRINTK("%s: ending %p, tag %d\n", __FUNCTION__, rq, rq->tag);
 
-       __ata_end_request(drive, rq, !dma_stat, rq->nr_sectors);
+       ata_end_request(drive, rq, !dma_stat, rq->nr_sectors);
 
        /*
         * we completed this command, check if we can service a new command
index 8598b5d017029197b4d2c84cc02dcabeda757cf1..2769442f4e332d45a7dcfc0e38842aa014f81bbe 100644 (file)
@@ -129,7 +129,7 @@ void __init init_umc8672(void)      /* called from ide.c */
 
        __save_flags(flags);    /* local CPU only */
        __cli();                /* local CPU only */
-       if (check_region(0x108, 2)) {
+       if (!request_region(0x108, 2, "umc8672")) {
                __restore_flags(flags);
                printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n");
                return;
@@ -138,6 +138,7 @@ void __init init_umc8672(void)      /* called from ide.c */
        if (in_umc (0xd5) != 0xa0)
        {
                __restore_flags(flags); /* local CPU only */
+               release_region(0x108, 2); 
                printk ("umc8672: not found\n");
                return;
        }
@@ -146,7 +147,6 @@ void __init init_umc8672(void)      /* called from ide.c */
        umc_set_speeds (current_speeds);
        __restore_flags(flags); /* local CPU only */
 
-       request_region(0x108, 2, "umc8672");
        ide_hwifs[0].chipset = ide_umc8672;
        ide_hwifs[1].chipset = ide_umc8672;
        ide_hwifs[0].tuneproc = &tune_umc;
index 8598f13d0ee3dd5d57f36e0b7dadd99f0157a7f7..1f001b4172cc8e71b6967c6a81cdfcef9b3d7686 100644 (file)
@@ -244,7 +244,7 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int
        u8 *scsi_buf;
 
        if (!(rq->flags & REQ_PC)) {
-               __ata_end_request(drive, rq, uptodate, 0);
+               ata_end_request(drive, rq, uptodate, 0);
                return 0;
        }
 
@@ -491,14 +491,13 @@ static void idescsi_release(struct inode *inode, struct file *filp, struct ata_d
        MOD_DEC_USE_COUNT;
 }
 
+static Scsi_Host_Template template;
 static int idescsi_cleanup (struct ata_device *drive)
 {
-       struct Scsi_Host *host = drive->driver_data;
-
        if (ide_unregister_subdriver (drive)) {
                return 1;
        }
-       scsi_unregister(host);
+       scsi_unregister_host(&template);
 
        return 0;
 }
@@ -801,7 +800,6 @@ static int __init init_idescsi_module(void)
 static void __exit exit_idescsi_module(void)
 {
        unregister_ata_driver(&ata_ops);
-       scsi_unregister_host(&template);
 }
 
 module_init(init_idescsi_module);
index 0ac305922e3a8704b9e43f0dc772bad2796a3638..806aa4e491469591d87ed055a72f83e81f90d8e6 100644 (file)
@@ -74,15 +74,6 @@ struct atapi_packet_command {
        } s;
 };
 
-extern void atapi_init_pc(struct atapi_packet_command *pc);
-
-extern void atapi_discard_data(struct ata_device *, unsigned int);
-extern void atapi_write_zeros(struct ata_device *, unsigned int);
-
-extern void atapi_read(struct ata_device *, u8 *, unsigned int);
-extern void atapi_write(struct ata_device *, u8 *, unsigned int);
-
-
 /*
  *     ATAPI Status Register.
  */
@@ -360,3 +351,20 @@ typedef struct atapi_request_sense {
        u8      sk_specific[2];         /* Sense Key Specific */
        u8      pad[2];                 /* Padding to 20 bytes */
 } atapi_request_sense_result_t;
+
+
+extern void atapi_init_pc(struct atapi_packet_command *pc);
+
+extern void atapi_discard_data(struct ata_device *, unsigned int);
+extern void atapi_write_zeros(struct ata_device *, unsigned int);
+
+extern void atapi_read(struct ata_device *, u8 *, unsigned int);
+extern void atapi_write(struct ata_device *, u8 *, unsigned int);
+
+typedef enum {
+       ide_wait,       /* insert rq at end of list, and wait for it */
+       ide_preempt,    /* insert rq in front of current request */
+       ide_end         /* insert rq at end of list, but don't wait for it */
+} ide_action_t;
+
+extern int ide_do_drive_cmd(struct ata_device *, struct request *, ide_action_t);
index 4076310675f83a1e4be3160168e315c5340d9425..7b9c5cce01cf8d6ca6efd6391ce165ae63cfde5b 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef _IDE_H
 #define _IDE_H
+
 /*
  *  Copyright (C) 1994-2002  Linus Torvalds & authors
  */
@@ -57,15 +58,14 @@ typedef unsigned char       byte;   /* used everywhere */
  */
 #define ERROR_MAX      8       /* Max read/write errors per sector */
 #define ERROR_RESET    3       /* Reset controller every 4th retry */
-#define ERROR_RECAL    1       /* Recalibrate every 2nd retry */
 
 /*
- * state flags
+ * State flags.
  */
 #define DMA_PIO_RETRY  1       /* retrying in PIO */
 
 /*
- * Definitions for accessing IDE controller registers
+ * Definitions for accessing IDE controller registers.
  */
 
 enum {
@@ -192,23 +192,21 @@ typedef enum {
  * Structure to hold all information about the location of this port
  */
 typedef struct hw_regs_s {
-       ide_ioreg_t     io_ports[IDE_NR_PORTS]; /* task file registers */
-       int             irq;                    /* our irq number */
-       int             dma;                    /* our dma entry */
-       ide_ack_intr_t  *ack_intr;              /* acknowledge interrupt */
+       ide_ioreg_t     io_ports[IDE_NR_PORTS];             /* task file registers */
+       int             irq;                                /* our irq number */
+       int             dma;                                /* our dma entry */
+       int             (*ack_intr)(struct ata_channel *);  /* acknowledge interrupt */
        hwif_chipset_t  chipset;
 } hw_regs_t;
 
 /*
  * Set up hw_regs_t structure before calling ide_register_hw (optional)
  */
-void ide_setup_ports(hw_regs_t *hw,
-                       ide_ioreg_t base,
-                       int *offsets,
-                       ide_ioreg_t ctrl,
-                       ide_ioreg_t intr,
-                       ide_ack_intr_t *ack_intr,
-                       int irq);
+extern void ide_setup_ports(hw_regs_t *hw,
+       ide_ioreg_t base, int *offsets,
+       ide_ioreg_t ctrl, ide_ioreg_t intr,
+       int (*ack_intr)(struct ata_channel *),
+       int irq);
 
 #include <asm/ide.h>
 
@@ -282,14 +280,10 @@ struct ata_device {
        unsigned int usage;             /* current "open()" count for drive */
        char type; /* distingiush different devices: disk, cdrom, tape, floppy, ... */
 
-       /* NOTE: If we had proper separation between channel and host chip, we
-        * could move this to the channel and many sync problems would
-        * magically just go away.
-        */
-       request_queue_t queue;  /* per device request queue */
+       request_queue_t queue;          /* per device request queue */
        struct request *rq;             /* current request */
 
-       unsigned long sleep;    /* sleep until this time */
+       unsigned long sleep;            /* sleep until this time */
 
        byte     retry_pio;             /* retrying dma capable host in pio */
        byte     state;                 /* retry state */
@@ -341,6 +335,7 @@ struct ata_device {
 
        void            *driver_data;   /* extra driver data */
        devfs_handle_t  de;             /* directory for device */
+
        char            driver_req[10]; /* requests specific driver */
 
        int             last_lun;       /* last logical unit */
@@ -392,6 +387,7 @@ enum {
 enum {
        IDE_BUSY,       /* awaiting an interrupt */
        IDE_SLEEP,
+       IDE_PIO,        /* PIO in progress */
        IDE_DMA         /* DMA in progress */
 };
 
@@ -404,11 +400,15 @@ struct ata_channel {
         */
        spinlock_t *lock;
        unsigned long *active;          /* active processing request */
-
        ide_startstop_t (*handler)(struct ata_device *, struct request *);      /* irq handler, if active */
+
+       /* FIXME: Only still used in PDC4030.  Localize this code there by
+        * replacing with busy waits.
+        */
        struct timer_list timer;                                /* failsafe timer */
        ide_startstop_t (*expiry)(struct ata_device *, struct request *, unsigned long *);      /* irq handler, if active */
        unsigned long poll_timeout;                             /* timeout value during polled operations */
+
        struct ata_device *drive;                               /* last serviced drive */
 
 
@@ -508,8 +508,6 @@ struct ata_channel {
 extern int ide_register_hw(hw_regs_t *hw);
 extern void ide_unregister(struct ata_channel *);
 
-struct ata_taskfile;
-
 #define IDE_MAX_TAG    32
 
 #ifdef CONFIG_BLK_DEV_IDE_TCQ
@@ -605,8 +603,7 @@ extern int noautodma;
 #define DEVICE_NR(device)      (minor(device) >> PARTN_BITS)
 #include <linux/blk.h>
 
-extern int __ata_end_request(struct ata_device *, struct request *, int, unsigned int);
-
+extern int ata_end_request(struct ata_device *, struct request *, int, unsigned int);
 extern void ata_set_handler(struct ata_device *drive, ata_handler_t handler,
                unsigned long timeout, ata_expiry_t expiry);
 
@@ -626,22 +623,11 @@ int ide_xlate_1024(kdev_t, int, int, const char *);
  */
 struct ata_device *get_info_ptr(kdev_t i_rdev);
 
-/*
- * "action" parameter type for ide_do_drive_cmd() below.
- */
-typedef enum {
-       ide_wait,       /* insert rq at end of list, and wait for it */
-       ide_preempt,    /* insert rq in front of current request */
-       ide_end         /* insert rq at end of list, but don't wait for it */
-} ide_action_t;
-
 /*
  * temporarily mapping a (possible) highmem bio for PIO transfer
  */
 #define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9)
 
-extern int ide_do_drive_cmd(struct ata_device *, struct request *, ide_action_t);
-
 struct ata_taskfile {
        struct hd_drive_task_hdr taskfile;
        struct hd_drive_task_hdr  hobfile;
@@ -654,7 +640,6 @@ extern void ata_read(struct ata_device *, void *, unsigned int);
 extern void ata_write(struct ata_device *, void *, unsigned int);
 
 extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *, char *);
-extern void ide_fix_driveid(struct hd_driveid *id);
 extern int ide_config_drive_speed(struct ata_device *, byte);
 extern byte eighty_ninty_three(struct ata_device *);
 
@@ -803,13 +788,12 @@ extern spinlock_t ide_lock;
 
 #define DRIVE_LOCK(drive)      ((drive)->queue.queue_lock)
 
-extern int drive_is_ready(struct ata_device *drive);
-
 /* Low level device access functions. */
 
 extern void ata_select(struct ata_device *, unsigned long);
 extern void ata_mask(struct ata_device *);
 extern int ata_status(struct ata_device *, u8, u8);
+extern int ata_status_irq(struct ata_device *drive);
 extern int ata_status_poll( struct ata_device *, u8, u8,
                unsigned long, struct request *rq);
 
index 6758bf742e0c1d90ef38eb6e401b3ade08b408d1..c1f391bf8f62a15cba3db2b89bfa40e0f0213464 100644 (file)
 #define PCI_DEVICE_ID_PROMISE_20268    0x4d68
 #define PCI_DEVICE_ID_PROMISE_20268R   0x6268
 #define PCI_DEVICE_ID_PROMISE_20269    0x4d69
+#define PCI_DEVICE_ID_PROMISE_20271    0x6269
 #define PCI_DEVICE_ID_PROMISE_20275    0x1275
 #define PCI_DEVICE_ID_PROMISE_20276    0x5275
 #define PCI_DEVICE_ID_PROMISE_5300     0x5300