ide: fix probing for hosts with serialized or IRQ sharing interfaces
[pandora-kernel.git] / drivers / ide / ide-probe.c
index 6a6f2e0..817564f 100644 (file)
  *
  * This is the IDE probe module, as evolved from hd.c and ide.c.
  *
- * Version 1.00                move drive probing code from ide.c to ide-probe.c
- * Version 1.01                fix compilation problem for m68k
- * Version 1.02                increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot
- *                      by Andrea Arcangeli
- * Version 1.03                fix for (hwif->chipset == ide_4drives)
- * Version 1.04                fixed buggy treatments of known flash memory cards
- *
- * Version 1.05                fix for (hwif->chipset == ide_pdc4030)
- *                     added ide6/7/8/9
- *                     allowed for secondary flash card to be detectable
- *                      with new flag : drive->ata_flash : 1;
- * Version 1.06                stream line request queue and prep for cascade project.
- * Version 1.07                max_sect <= 255; slower disks would get behind and
- *                     then fall over when they get to 256.    Paul G.
- * Version 1.10                Update set for new IDE. drive->id is now always
- *                     valid after probe time even with noprobe
+ * -- increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot
+ *      by Andrea Arcangeli
  */
 
 #include <linux/module.h>
@@ -109,10 +95,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
 #ifdef CONFIG_IDEDISK_MULTI_MODE
                id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
                id->multsect_valid = id->multsect ? 1 : 0;
-               drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
+               drive->mult_req = id->multsect_valid ? id->max_multsect : 0;
                drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
 #else  /* original, pre IDE-NFG, per request of AC */
-               drive->mult_req = INITIAL_MULT_COUNT;
+               drive->mult_req = 0;
                if (drive->mult_req > id->max_multsect)
                        drive->mult_req = id->max_multsect;
                if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
@@ -172,11 +158,12 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
        ide_fixstring(id->fw_rev,    sizeof(id->fw_rev),    bswap);
        ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap);
 
+       /* we depend on this a lot! */
+       id->model[sizeof(id->model)-1] = '\0';
+
        if (strstr(id->model, "E X A B Y T E N E S T"))
                goto err_misc;
 
-       /* we depend on this a lot! */
-       id->model[sizeof(id->model)-1] = '\0';
        printk("%s: %s, ", drive->name, id->model);
        drive->present = 1;
        drive->dead = 0;
@@ -247,7 +234,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
 
        drive->media = ide_disk;
        printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
-       QUIRK_LIST(drive);
+
        return;
 
 err_misc:
@@ -643,7 +630,7 @@ static void hwif_register (ide_hwif_t *hwif)
 
 static int wait_hwif_ready(ide_hwif_t *hwif)
 {
-       int rc;
+       int unit, rc;
 
        printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name);
 
@@ -660,38 +647,44 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
                return rc;
 
        /* Now make sure both master & slave are ready */
-       SELECT_DRIVE(&hwif->drives[0]);
-       hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
-       mdelay(2);
-       rc = ide_wait_not_busy(hwif, 35000);
-       if (rc)
-               return rc;
-       SELECT_DRIVE(&hwif->drives[1]);
-       hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
-       mdelay(2);
-       rc = ide_wait_not_busy(hwif, 35000);
+       for (unit = 0; unit < MAX_DRIVES; unit++) {
+               ide_drive_t *drive = &hwif->drives[unit];
 
+               /* Ignore disks that we will not probe for later. */
+               if (!drive->noprobe || drive->present) {
+                       SELECT_DRIVE(drive);
+                       if (IDE_CONTROL_REG)
+                               hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+                       mdelay(2);
+                       rc = ide_wait_not_busy(hwif, 35000);
+                       if (rc)
+                               goto out;
+               } else
+                       printk(KERN_DEBUG "%s: ide_wait_not_busy() skipped\n",
+                                         drive->name);
+       }
+out:
        /* Exit function with master reselected (let's be sane) */
-       SELECT_DRIVE(&hwif->drives[0]);
-       
+       if (unit)
+               SELECT_DRIVE(&hwif->drives[0]);
+
        return rc;
 }
 
 /**
  *     ide_undecoded_slave     -       look for bad CF adapters
- *     @hwif: interface
+ *     @drive1: drive
  *
  *     Analyse the drives on the interface and attempt to decide if we
  *     have the same drive viewed twice. This occurs with crap CF adapters
  *     and PCMCIA sometimes.
  */
 
-void ide_undecoded_slave(ide_hwif_t *hwif)
+void ide_undecoded_slave(ide_drive_t *drive1)
 {
-       ide_drive_t *drive0 = &hwif->drives[0];
-       ide_drive_t *drive1 = &hwif->drives[1];
+       ide_drive_t *drive0 = &drive1->hwif->drives[0];
 
-       if (drive0->present == 0 || drive1->present == 0)
+       if ((drive1->dn & 1) == 0 || drive0->present == 0)
                return;
 
        /* If the models don't match they are not the same product */
@@ -820,8 +813,12 @@ static void probe_hwif(ide_hwif_t *hwif)
                return;
        }
 
-       if (hwif->fixup)
-               hwif->fixup(hwif);
+       for (unit = 0; unit < MAX_DRIVES; unit++) {
+               ide_drive_t *drive = &hwif->drives[unit];
+
+               if (drive->present && hwif->quirkproc)
+                       hwif->quirkproc(drive);
+       }
 
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
                ide_drive_t *drive = &hwif->drives[unit];
@@ -836,16 +833,8 @@ static void probe_hwif(ide_hwif_t *hwif)
 
                        drive->nice1 = 1;
 
-                       if (hwif->ide_dma_on) {
-                               /*
-                                * Force DMAing for the beginning of the check.
-                                * Some chipsets appear to do interesting
-                                * things, if not checked and cleared.
-                                *   PARANOIA!!!
-                                */
-                               hwif->dma_off_quietly(drive);
+                       if (hwif->dma_host_set)
                                ide_set_dma(drive);
-                       }
                }
        }
 
@@ -859,25 +848,6 @@ static void probe_hwif(ide_hwif_t *hwif)
        }
 }
 
-static int hwif_init(ide_hwif_t *hwif);
-static void hwif_register_devices(ide_hwif_t *hwif);
-
-static int probe_hwif_init(ide_hwif_t *hwif)
-{
-       probe_hwif(hwif);
-
-       if (!hwif_init(hwif)) {
-               printk(KERN_INFO "%s: failed to initialize IDE interface\n",
-                                hwif->name);
-               return -1;
-       }
-
-       if (hwif->present)
-               hwif_register_devices(hwif);
-
-       return 0;
-}
-
 #if MAX_HWIFS > 1
 /*
  * save_match() is used to simplify logic in init_irq() below.
@@ -974,11 +944,6 @@ static int ide_init_queue(ide_drive_t *drive)
  * Much of the code is for correctly detecting/handling irq sharing
  * and irq serialization situations.  This is somewhat complex because
  * it handles static as well as dynamic (PCMCIA) IDE interfaces.
- *
- * The IRQF_DISABLED in sa_flags means ide_intr() is always entered with
- * interrupts completely disabled.  This can be bad for interrupt latency,
- * but anything else has led to problems on some machines.  We re-enable
- * interrupts as much as we can safely do in most places.
  */
 static int init_irq (ide_hwif_t *hwif)
 {
@@ -1061,17 +1026,13 @@ static int init_irq (ide_hwif_t *hwif)
         * Allocate the irq, if not already obtained for another hwif
         */
        if (!match || match->irq != hwif->irq) {
-               int sa = IRQF_DISABLED;
+               int sa = 0;
 #if defined(__mc68000__) || defined(CONFIG_APUS)
                sa = IRQF_SHARED;
 #endif /* __mc68000__ || CONFIG_APUS */
 
-               if (IDE_CHIPSET_IS_PCI(hwif->chipset)) {
+               if (IDE_CHIPSET_IS_PCI(hwif->chipset))
                        sa = IRQF_SHARED;
-#ifndef CONFIG_IDEPCI_SHARE_IRQ
-                       sa |= IRQF_DISABLED;
-#endif /* CONFIG_IDEPCI_SHARE_IRQ */
-               }
 
                if (hwif->io_ports[IDE_CONTROL_OFFSET])
                        /* clear nIEN */
@@ -1179,7 +1140,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data)
 {
        struct gendisk *p = data;
        *part &= (1 << PARTN_BITS) - 1;
-       return &p->kobj;
+       return &p->dev.kobj;
 }
 
 static int exact_lock(dev_t dev, void *data)
@@ -1414,11 +1375,38 @@ EXPORT_SYMBOL_GPL(ideprobe_init);
 
 int ide_device_add(u8 idx[4])
 {
+       ide_hwif_t *hwif;
        int i, rc = 0;
 
        for (i = 0; i < 4; i++) {
-               if (idx[i] != 0xff)
-                       rc |= probe_hwif_init(&ide_hwifs[idx[i]]);
+               if (idx[i] == 0xff)
+                       continue;
+
+               probe_hwif(&ide_hwifs[idx[i]]);
+       }
+
+       for (i = 0; i < 4; i++) {
+               if (idx[i] == 0xff)
+                       continue;
+
+               hwif = &ide_hwifs[idx[i]];
+
+               if (hwif_init(hwif) == 0) {
+                       printk(KERN_INFO "%s: failed to initialize IDE "
+                                        "interface\n", hwif->name);
+                       rc = -1;
+                       continue;
+               }
+       }
+
+       for (i = 0; i < 4; i++) {
+               if (idx[i] == 0xff)
+                       continue;
+
+               hwif = &ide_hwifs[idx[i]];
+
+               if (hwif->present)
+                       hwif_register_devices(hwif);
        }
 
        for (i = 0; i < 4; i++) {