summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@trik.(none)>2004-11-06 02:31:02 +0100
committerBartlomiej Zolnierkiewicz <bzolnier@trik.(none)>2004-11-06 02:31:02 +0100
commitdc3f1bf75e1d7c37b1e7ed49294fc6753f81e2ab (patch)
treea15925d727c27bf83e40e35474e8ec0dd58db41e
parent4d81fe20ebfef6a993dda2f496c3141442f96142 (diff)
[ide] apply undecoded slave fixup only for ide-cs
From: Alan Cox <alan@lxorguk.ukuu.org.uk> (some changes by me - bart) We add probe_hwif_init_with_fixup (seperate naming as requested by Bartlomiej). This runs a fixup on present interfaces before attaching the drives. In order to be useful we need also an _with_fixup version of ide_register_hw function. The sometimes troublesome undecoded slave detector is moved to its own function and exported so that ide-cs and the upcoming delkin_cb can both use it (along with any arch specific cf/pcmcia drivers I don't know about). The non-relevant checks for this scenario are removed. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r--drivers/ide/ide-probe.c63
-rw-r--r--drivers/ide/ide.c14
-rw-r--r--drivers/ide/legacy/ide-cs.c2
-rw-r--r--include/linux/ide.h4
4 files changed, 64 insertions, 19 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index ca53e05a88ed..7b6d9c991ca2 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -652,6 +652,43 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
return rc;
}
+/**
+ * ide_undecoded_slave - look for bad CF adapters
+ * @hwif: interface
+ *
+ * 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)
+{
+ ide_drive_t *drive0 = &hwif->drives[0];
+ ide_drive_t *drive1 = &hwif->drives[1];
+
+ if (drive0->present == 0 || drive1->present == 0)
+ return;
+
+ /* If the models don't match they are not the same product */
+ if (strcmp(drive0->id->model, drive1->id->model))
+ return;
+
+ /* Serial numbers do not match */
+ if (strncmp(drive0->id->serial_no, drive1->id->serial_no, 20))
+ return;
+
+ /* No serial number, thankfully very rare for CF */
+ if (drive0->id->serial_no[0] == 0)
+ return;
+
+ /* Appears to be an IDE flash adapter with decode bugs */
+ printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
+
+ drive1->present = 0;
+}
+
+EXPORT_SYMBOL_GPL(ide_undecoded_slave);
+
/*
* This routine only knows how to look for drive units 0 and 1
* on an interface, so any setting of MAX_DRIVES > 2 won't work here.
@@ -723,20 +760,6 @@ static void probe_hwif(ide_hwif_t *hwif)
ide_drive_t *drive = &hwif->drives[unit];
drive->dn = (hwif->channel ? 2 : 0) + unit;
(void) probe_for_drive(drive);
- if (drive->present && hwif->present && unit == 1) {
- if (strcmp(hwif->drives[0].id->model, drive->id->model) == 0 &&
- /* Don't do this for noprobe or non ATA */
- strcmp(drive->id->model, "UNKNOWN") &&
- /* And beware of confused Maxtor drives that go "M0000000000"
- "The SN# is garbage in the ID block..." [Eric] */
- strncmp(drive->id->serial_no, "M0000000000000000000", 20) &&
- /* Same goes for another set of Maxtor drives that say "D3000000" */
- strncmp(drive->id->serial_no, "D3000000", 8) &&
- strncmp(hwif->drives[0].id->serial_no, drive->id->serial_no, 20) == 0) {
- printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
- drive->present = 0;
- }
- }
if (drive->present && !hwif->present) {
hwif->present = 1;
if (hwif->chipset != ide_4drives ||
@@ -810,9 +833,14 @@ static void probe_hwif(ide_hwif_t *hwif)
}
static int hwif_init(ide_hwif_t *hwif);
-int probe_hwif_init (ide_hwif_t *hwif)
+
+int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
{
probe_hwif(hwif);
+
+ if (fixup)
+ fixup(hwif);
+
hwif_init(hwif);
if (hwif->present) {
@@ -830,6 +858,11 @@ int probe_hwif_init (ide_hwif_t *hwif)
return 0;
}
+int probe_hwif_init(ide_hwif_t *hwif)
+{
+ return probe_hwif_init_with_fixup(hwif, NULL);
+}
+
EXPORT_SYMBOL(probe_hwif_init);
#if MAX_HWIFS > 1
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 427f633dc441..1dd413ae439b 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -985,9 +985,10 @@ void ide_setup_ports ( hw_regs_t *hw,
}
/**
- * ide_register_hw - register IDE interface
+ * ide_register_hw_with_fixup - register IDE interface
* @hw: hardware registers
* @hwifp: pointer to returned hwif
+ * @fixup: fixup function
*
* Register an IDE interface, specifying exactly the registers etc.
* Set init=1 iff calling before probes have taken place.
@@ -995,7 +996,7 @@ void ide_setup_ports ( hw_regs_t *hw,
* Returns -1 on error.
*/
-int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
+int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif))
{
int index, retry = 1;
ide_hwif_t *hwif;
@@ -1034,7 +1035,7 @@ found:
hwif->chipset = hw->chipset;
if (!initializing) {
- probe_hwif_init(hwif);
+ probe_hwif_init_with_fixup(hwif, fixup);
create_proc_ide_interfaces();
}
@@ -1044,6 +1045,13 @@ found:
return (initializing || hwif->present) ? index : -1;
}
+EXPORT_SYMBOL(ide_register_hw_with_fixup);
+
+int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp)
+{
+ return ide_register_hw_with_fixup(hw, hwifp, NULL);
+}
+
EXPORT_SYMBOL(ide_register_hw);
/*
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index dda2a17e0c6e..36426f72cb3f 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -206,7 +206,7 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq
ide_init_hwif_ports(&hw, io, ctl, NULL);
hw.irq = irq;
hw.chipset = ide_pci;
- return ide_register_hw(&hw, NULL);
+ return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
}
/*======================================================================
diff --git a/include/linux/ide.h b/include/linux/ide.h
index e619f8247483..b7bfa3f233ea 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -240,6 +240,7 @@ typedef struct hw_regs_s {
* Register new hardware with ide
*/
int ide_register_hw(hw_regs_t *hw, struct hwif_s **hwifp);
+int ide_register_hw_with_fixup(hw_regs_t *, struct hwif_s **, void (*)(struct hwif_s *));
/*
* Set up hw_regs_t structure before calling ide_register_hw (optional)
@@ -1487,6 +1488,9 @@ extern int ide_hwif_request_regions(ide_hwif_t *hwif);
extern void ide_hwif_release_regions(ide_hwif_t* hwif);
extern void ide_unregister (unsigned int index);
+void ide_undecoded_slave(ide_hwif_t *);
+
+int probe_hwif_init_with_fixup(ide_hwif_t *, void (*)(ide_hwif_t *));
extern int probe_hwif_init(ide_hwif_t *);
static inline void *ide_get_hwifdata (ide_hwif_t * hwif)