patch-2.4.21 linux-2.4.21/drivers/ide/ide-probe.c
Next file: linux-2.4.21/drivers/ide/ide-proc.c
Previous file: linux-2.4.21/drivers/ide/ide-pnp.c
Back to the patch index
Back to the overall index
- Lines: 1507
- Date:
2003-06-13 07:51:33.000000000 -0700
- Orig file:
linux-2.4.20/drivers/ide/ide-probe.c
- Orig date:
2002-11-28 15:53:13.000000000 -0800
diff -urN linux-2.4.20/drivers/ide/ide-probe.c linux-2.4.21/drivers/ide/ide-probe.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/ide-probe.c Version 1.07 March 18, 2001
+ * linux/drivers/ide/ide-probe.c Version 1.11 Mar 05, 2003
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
@@ -27,6 +27,8 @@
* 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
*/
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -46,40 +48,106 @@
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/spinlock.h>
+#include <linux/pci.h>
+#include <linux/kmod.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-static inline void do_identify (ide_drive_t *drive, byte cmd)
+/**
+ * generic_id - add a generic drive id
+ * @drive: drive to make an ID block for
+ *
+ * Add a fake id field to the drive we are passed. This allows
+ * use to skip a ton of NULL checks (which people always miss)
+ * and make drive properties unconditional outside of this file
+ */
+
+static void generic_id(ide_drive_t *drive)
{
- int bswap = 1;
- struct hd_driveid *id;
+ drive->id->cyls = drive->cyl;
+ drive->id->heads = drive->head;
+ drive->id->sectors = drive->sect;
+ drive->id->cur_cyls = drive->cyl;
+ drive->id->cur_heads = drive->head;
+ drive->id->cur_sectors = drive->sect;
+}
+
+/**
+ * drive_is_flashcard - check for compact flash
+ * @drive: drive to check
+ *
+ * CompactFlash cards and their brethern pretend to be removable
+ * hard disks, except:
+ * (1) they never have a slave unit, and
+ * (2) they don't have doorlock mechanisms.
+ * This test catches them, and is invoked elsewhere when setting
+ * appropriate config bits.
+ *
+ * FIXME: This treatment is probably applicable for *all* PCMCIA (PC CARD)
+ * devices, so in linux 2.3.x we should change this to just treat all
+ * PCMCIA drives this way, and get rid of the model-name tests below
+ * (too big of an interface change for 2.4.x).
+ * At that time, we might also consider parameterizing the timeouts and
+ * retries, since these are MUCH faster than mechanical drives. -M.Lord
+ */
+
+static inline int drive_is_flashcard (ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
- id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC); /* called with interrupts disabled! */
- if (!id) {
- printk(KERN_WARNING "(ide-probe::do_identify) Out of memory.\n");
- goto err_kmalloc;
+ if (drive->removable && id != NULL) {
+ if (id->config == 0x848a) return 1; /* CompactFlash */
+ if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */
+ || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
+ || !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */
+ || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */
+ || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */
+ || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */
+ {
+ return 1; /* yes, it is a flash memory card */
+ }
}
+ return 0; /* no, it is not a flash memory card */
+}
- ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */
- ide__sti(); /* local CPU only */
- ide_fix_driveid(id);
+/**
+ * do_identify - identify a drive
+ * @drive: drive to identify
+ * @cmd: command used
+ *
+ * Called when we have issued a drive identify command to
+ * read and parse the results. This function is run with
+ * interrupts disabled.
+ */
+
+static inline void do_identify (ide_drive_t *drive, u8 cmd)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ int bswap = 1;
+ struct hd_driveid *id;
- if (id->word156 == 0x4d42) {
- printk("%s: drive->id->word156 == 0x%04x \n", drive->name, drive->id->word156);
- }
+ /* called with interrupts disabled! */
+ id = drive->id;
+ /* read 512 bytes of id info */
+ hwif->ata_input_data(drive, id, SECTOR_WORDS);
+ drive->id_read = 1;
+ local_irq_enable();
+
+ ide_fix_driveid(id);
if (!drive->forced_lun)
drive->last_lun = id->last_lun & 0x7;
+
#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
/*
* EATA SCSI controllers do a hardware ATA emulation:
* Ignore them if there is a driver for them available.
*/
- if ((id->model[0] == 'P' && id->model[1] == 'M')
- || (id->model[0] == 'S' && id->model[1] == 'K')) {
+ if ((id->model[0] == 'P' && id->model[1] == 'M') ||
+ (id->model[0] == 'S' && id->model[1] == 'K')) {
printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
goto err_misc;
}
@@ -93,27 +161,30 @@
if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */
|| (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */
|| (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
- bswap ^= 1; /* Vertos drives may still be weird */
+ /* Vertos drives may still be weird */
+ bswap ^= 1;
}
- ide_fixstring (id->model, sizeof(id->model), bswap);
- ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap);
- ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap);
+ ide_fixstring(id->model, sizeof(id->model), bswap);
+ ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap);
+ ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap);
if (strstr(id->model, "E X A B Y T E N E S T"))
goto err_misc;
- id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */
+ /* 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;
/*
* Check for an ATAPI device
*/
if (cmd == WIN_PIDENTIFY) {
- byte type = (id->config >> 8) & 0x1f;
+ u8 type = (id->config >> 8) & 0x1f;
printk("ATAPI ");
#ifdef CONFIG_BLK_DEV_PDC4030
- if (HWIF(drive)->channel == 1 && HWIF(drive)->chipset == ide_pdc4030) {
+ if (hwif->channel == 1 && hwif->chipset == ide_pdc4030) {
printk(" -- not supported on 2nd Promise port\n");
goto err_misc;
}
@@ -121,19 +192,24 @@
switch (type) {
case ide_floppy:
if (!strstr(id->model, "CD-ROM")) {
- if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP"))
+ if (!strstr(id->model, "oppy") &&
+ !strstr(id->model, "poyp") &&
+ !strstr(id->model, "ZIP"))
printk("cdrom or floppy?, assuming ");
if (drive->media != ide_cdrom) {
printk ("FLOPPY");
+ drive->removable = 1;
break;
}
}
- type = ide_cdrom; /* Early cdrom models used zero */
+ /* Early cdrom models used zero */
+ type = ide_cdrom;
case ide_cdrom:
drive->removable = 1;
#ifdef CONFIG_PPC
/* kludge for Apple PowerBook internal zip */
- if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) {
+ if (!strstr(id->model, "CD-ROM") &&
+ strstr(id->model, "ZIP")) {
printk ("FLOPPY");
type = ide_floppy;
break;
@@ -162,128 +238,173 @@
*/
if (id->config & (1<<7))
drive->removable = 1;
+
/*
* Prevent long system lockup probing later for non-existant
- * slave drive if the hwif is actually a flash memory card of some variety:
+ * slave drive if the hwif is actually a flash memory card of
+ * some variety:
*/
+ drive->is_flash = 0;
if (drive_is_flashcard(drive)) {
- ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit];
+#if 0
+ /* The new IDE adapter widgets don't follow this heuristic
+ so we must nowdays just bite the bullet and take the
+ probe hit */
+ ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit];
if (!mate->ata_flash) {
mate->present = 0;
mate->noprobe = 1;
}
+#endif
+ drive->is_flash = 1;
}
drive->media = ide_disk;
- printk("ATA DISK drive\n");
- QUIRK_LIST(HWIF(drive),drive);
+ printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" );
+ QUIRK_LIST(drive);
return;
err_misc:
kfree(id);
-err_kmalloc:
drive->present = 0;
return;
}
-/*
- * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive
- * and waits for a response. It also monitors irqs while this is
- * happening, in hope of automatically determining which one is
- * being used by the interface.
+/**
+ * actual_try_to_identify - send ata/atapi identify
+ * @drive: drive to identify
+ * @cmd: comamnd to use
*
- * Returns: 0 device was identified
- * 1 device timed-out (no response to identify request)
- * 2 device aborted the command (refused to identify itself)
+ * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive
+ * and waits for a response. It also monitors irqs while this is
+ * happening, in hope of automatically determining which one is
+ * being used by the interface.
+ *
+ * Returns: 0 device was identified
+ * 1 device timed-out (no response to identify request)
+ * 2 device aborted the command (refused to identify itself)
*/
-static int actual_try_to_identify (ide_drive_t *drive, byte cmd)
+
+static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
{
+ ide_hwif_t *hwif = HWIF(drive);
int rc;
ide_ioreg_t hd_status;
unsigned long timeout;
- byte s, a;
+ u8 s = 0, a = 0;
if (IDE_CONTROL_REG) {
/* take a deep breath */
ide_delay_50ms();
- a = IN_BYTE(IDE_ALTSTATUS_REG);
- s = IN_BYTE(IDE_STATUS_REG);
+ a = hwif->INB(IDE_ALTSTATUS_REG);
+ s = hwif->INB(IDE_STATUS_REG);
if ((a ^ s) & ~INDEX_STAT) {
- printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a);
- hd_status = IDE_STATUS_REG; /* ancient Seagate drives, broken interfaces */
+ printk(KERN_INFO "%s: probing with STATUS(0x%02x) instead of "
+ "ALTSTATUS(0x%02x)\n", drive->name, s, a);
+ /* ancient Seagate drives, broken interfaces */
+ hd_status = IDE_STATUS_REG;
} else {
- hd_status = IDE_ALTSTATUS_REG; /* use non-intrusive polling */
+ /* use non-intrusive polling */
+ hd_status = IDE_ALTSTATUS_REG;
}
} else {
ide_delay_50ms();
hd_status = IDE_STATUS_REG;
}
- /* set features register for atapi identify command to be sure of reply */
+ /* set features register for atapi
+ * identify command to be sure of reply
+ */
if ((cmd == WIN_PIDENTIFY))
- OUT_BYTE(0,IDE_FEATURE_REG); /* disable dma & overlap */
+ /* disable dma & overlap */
+ hwif->OUTB(0, IDE_FEATURE_REG);
-#if CONFIG_BLK_DEV_PDC4030
- if (HWIF(drive)->chipset == ide_pdc4030) {
- /* DC4030 hosted drives need their own identify... */
- extern int pdc4030_identify(ide_drive_t *);
- if (pdc4030_identify(drive)) {
+ if (hwif->identify != NULL) {
+ if (hwif->identify(drive))
return 1;
- }
- } else
-#endif /* CONFIG_BLK_DEV_PDC4030 */
- OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */
+ } else {
+ /* ask drive for ID */
+ hwif->OUTB(cmd, IDE_COMMAND_REG);
+ }
timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
timeout += jiffies;
do {
- if (0 < (signed long)(jiffies - timeout)) {
- return 1; /* drive timed-out */
+ if (time_after(jiffies, timeout)) {
+ /* drive timed-out */
+ return 1;
}
- ide_delay_50ms(); /* give drive a breather */
- } while (IN_BYTE(hd_status) & BUSY_STAT);
+ /* give drive a breather */
+ ide_delay_50ms();
+ } while ((hwif->INB(hd_status)) & BUSY_STAT);
- ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */
- if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
+ /* wait for IRQ and DRQ_STAT */
+ ide_delay_50ms();
+ if (OK_STAT((hwif->INB(IDE_STATUS_REG)), DRQ_STAT, BAD_R_STAT)) {
unsigned long flags;
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only; some systems need this */
- do_identify(drive, cmd); /* drive returned ID */
- rc = 0; /* drive responded with ID */
- (void) GET_STAT(); /* clear drive IRQ */
- __restore_flags(flags); /* local CPU only */
- } else
- rc = 2; /* drive refused ID */
+
+ /* local CPU only; some systems need this */
+ local_irq_save(flags);
+ /* drive returned ID */
+ do_identify(drive, cmd);
+ /* drive responded with ID */
+ rc = 0;
+ /* clear drive IRQ */
+ (void) hwif->INB(IDE_STATUS_REG);
+ local_irq_restore(flags);
+ } else {
+ /* drive refused ID */
+ rc = 2;
+ }
return rc;
}
-static int try_to_identify (ide_drive_t *drive, byte cmd)
+/**
+ * try_to_identify - try to identify a drive
+ * @drive: drive to probe
+ * @cmd: comamnd to use
+ *
+ * Issue the identify command and then do IRQ probing to
+ * complete the identification when needed by finding the
+ * IRQ the drive is attached to
+ */
+
+static int try_to_identify (ide_drive_t *drive, u8 cmd)
{
+ ide_hwif_t *hwif = HWIF(drive);
int retval;
int autoprobe = 0;
unsigned long cookie = 0;
- if (IDE_CONTROL_REG && !HWIF(drive)->irq) {
+ if (IDE_CONTROL_REG && !hwif->irq) {
autoprobe = 1;
cookie = probe_irq_on();
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */
+ /* enable device irq */
+ hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
}
retval = actual_try_to_identify(drive, cmd);
if (autoprobe) {
int irq;
- OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
- (void) GET_STAT(); /* clear drive IRQ */
+ /* mask device irq */
+ hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);
+ /* clear drive IRQ */
+ (void) hwif->INB(IDE_STATUS_REG);
udelay(5);
irq = probe_irq_off(cookie);
- if (!HWIF(drive)->irq) {
+ if (!hwif->irq) {
if (irq > 0) {
- HWIF(drive)->irq = irq;
- } else { /* Mmmm.. multiple IRQs.. don't know which was ours */
- printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie);
+ hwif->irq = irq;
+ } else {
+ /* Mmmm.. multiple IRQs..
+ * don't know which was ours
+ */
+ printk("%s: IRQ probe failed (0x%lx)\n",
+ drive->name, cookie);
#ifdef CONFIG_BLK_DEV_CMD640
#ifdef CMD640_DUMP_REGS
- if (HWIF(drive)->chipset == ide_cmd640) {
- printk("%s: Hmmm.. probably a driver problem.\n", drive->name);
+ if (hwif->chipset == ide_cmd640) {
+ printk("%s: Hmmm.. probably a driver "
+ "problem.\n", drive->name);
CMD640_DUMP_REGS;
}
#endif /* CMD640_DUMP_REGS */
@@ -295,15 +416,19 @@
}
-/*
- * do_probe() has the difficult job of finding a drive if it exists,
- * without getting hung up if it doesn't exist, without trampling on
- * ethernet cards, and without leaving any IRQs dangling to haunt us later.
- *
- * If a drive is "known" to exist (from CMOS or kernel parameters),
- * but does not respond right away, the probe will "hang in there"
- * for the maximum wait time (about 30 seconds), otherwise it will
- * exit much more quickly.
+/**
+ * do_probe - probe an IDE device
+ * @drive: drive to probe
+ * @cmd: command to use
+ *
+ * do_probe() has the difficult job of finding a drive if it exists,
+ * without getting hung up if it doesn't exist, without trampling on
+ * ethernet cards, and without leaving any IRQs dangling to haunt us later.
+ *
+ * If a drive is "known" to exist (from CMOS or kernel parameters),
+ * but does not respond right away, the probe will "hang in there"
+ * for the maximum wait time (about 30 seconds), otherwise it will
+ * exit much more quickly.
*
* Returns: 0 device was identified
* 1 device timed-out (no response to identify request)
@@ -311,11 +436,14 @@
* 3 bad status from device (possible for ATAPI drives)
* 4 probe was not attempted because failure was obvious
*/
-static int do_probe (ide_drive_t *drive, byte cmd)
+
+static int do_probe (ide_drive_t *drive, u8 cmd)
{
int rc;
ide_hwif_t *hwif = HWIF(drive);
- if (drive->present) { /* avoid waiting for inappropriate probes */
+
+ if (drive->present) {
+ /* avoid waiting for inappropriate probes */
if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY))
return 4;
}
@@ -324,44 +452,66 @@
drive->name, drive->present, drive->media,
(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
#endif
- ide_delay_50ms(); /* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */
- SELECT_DRIVE(hwif,drive);
+
+ /* needed for some systems
+ * (e.g. crw9624 as drive0 with disk as slave)
+ */
ide_delay_50ms();
- if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {
+ SELECT_DRIVE(drive);
+ ide_delay_50ms();
+ if (hwif->INB(IDE_SELECT_REG) != drive->select.all && !drive->present) {
if (drive->select.b.unit != 0) {
- SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */
- ide_delay_50ms(); /* allow BUSY_STAT to assert & clear */
+ /* exit with drive0 selected */
+ SELECT_DRIVE(&hwif->drives[0]);
+ /* allow BUSY_STAT to assert & clear */
+ ide_delay_50ms();
}
- return 3; /* no i/f present: mmm.. this should be a 4 -ml */
+ /* no i/f present: mmm.. this should be a 4 -ml */
+ return 3;
}
- if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT)
- || drive->present || cmd == WIN_PIDENTIFY)
- {
- if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */
- rc = try_to_identify(drive,cmd); /* failed: try again */
- if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) {
+ if (OK_STAT((hwif->INB(IDE_STATUS_REG)), READY_STAT, BUSY_STAT) ||
+ drive->present || cmd == WIN_PIDENTIFY) {
+ /* send cmd and wait */
+ if ((rc = try_to_identify(drive, cmd))) {
+ /* failed: try again */
+ rc = try_to_identify(drive,cmd);
+ }
+ if (hwif->INB(IDE_STATUS_REG) == (BUSY_STAT|READY_STAT))
+ return 4;
+
+ if ((rc == 1 && cmd == WIN_PIDENTIFY) &&
+ ((drive->autotune == IDE_TUNE_DEFAULT) ||
+ (drive->autotune == IDE_TUNE_AUTO))) {
unsigned long timeout;
- printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT());
+ printk("%s: no response (status = 0x%02x), "
+ "resetting drive\n", drive->name,
+ hwif->INB(IDE_STATUS_REG));
ide_delay_50ms();
- OUT_BYTE (drive->select.all, IDE_SELECT_REG);
+ hwif->OUTB(drive->select.all, IDE_SELECT_REG);
ide_delay_50ms();
- OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
+ hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
timeout = jiffies;
- while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE))
+ while (((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) &&
+ time_before(jiffies, timeout + WAIT_WORSTCASE))
ide_delay_50ms();
rc = try_to_identify(drive, cmd);
}
if (rc == 1)
- printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT());
- (void) GET_STAT(); /* ensure drive irq is clear */
+ printk("%s: no response (status = 0x%02x)\n",
+ drive->name, hwif->INB(IDE_STATUS_REG));
+ /* ensure drive irq is clear */
+ (void) hwif->INB(IDE_STATUS_REG);
} else {
- rc = 3; /* not present or maybe ATAPI */
+ /* not present or maybe ATAPI */
+ rc = 3;
}
if (drive->select.b.unit != 0) {
- SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */
+ /* exit with drive0 selected */
+ SELECT_DRIVE(&hwif->drives[0]);
ide_delay_50ms();
- (void) GET_STAT(); /* ensure drive irq is clear */
+ /* ensure drive irq is clear */
+ (void) hwif->INB(IDE_STATUS_REG);
}
return rc;
}
@@ -371,12 +521,13 @@
*/
static void enable_nest (ide_drive_t *drive)
{
+ ide_hwif_t *hwif = HWIF(drive);
unsigned long timeout;
- printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model);
- SELECT_DRIVE(HWIF(drive), drive);
+ printk("%s: enabling %s -- ", hwif->name, drive->id->model);
+ SELECT_DRIVE(drive);
ide_delay_50ms();
- OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
+ hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
timeout = jiffies + WAIT_WORSTCASE;
do {
if (time_after(jiffies, timeout)) {
@@ -384,193 +535,405 @@
return;
}
ide_delay_50ms();
- } while (GET_STAT() & BUSY_STAT);
+ } while ((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT);
+
ide_delay_50ms();
- if (!OK_STAT(GET_STAT(), 0, BAD_STAT))
- printk("failed (status = 0x%02x)\n", GET_STAT());
- else
+
+ if (!OK_STAT((hwif->INB(IDE_STATUS_REG)), 0, BAD_STAT)) {
+ printk("failed (status = 0x%02x)\n", hwif->INB(IDE_STATUS_REG));
+ } else {
printk("success\n");
- if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */
- (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */
+ }
+
+ /* if !(success||timed-out) */
+ if (do_probe(drive, WIN_IDENTIFY) >= 2) {
+ /* look for ATAPI device */
+ (void) do_probe(drive, WIN_PIDENTIFY);
}
}
-/*
- * probe_for_drive() tests for existence of a given drive using do_probe().
+/**
+ * probe_for_drives - upper level drive probe
+ * @drive: drive to probe for
*
- * Returns: 0 no device was found
- * 1 device was found (note: drive->present might still be 0)
+ * probe_for_drive() tests for existence of a given drive using do_probe()
+ * and presents things to the user as needed.
+ *
+ * Returns: 0 no device was found
+ * 1 device was found (note: drive->present might
+ * still be 0)
*/
-static inline byte probe_for_drive (ide_drive_t *drive)
+
+static inline u8 probe_for_drive (ide_drive_t *drive)
{
- if (drive->noprobe) /* skip probing? */
- return drive->present;
- if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */
- (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */
- }
- if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T"))
- enable_nest(drive);
- if (!drive->present)
- return 0; /* drive not found */
- if (drive->id == NULL) { /* identification failed? */
- if (drive->media == ide_disk) {
- printk ("%s: non-IDE drive, CHS=%d/%d/%d\n",
- drive->name, drive->cyl, drive->head, drive->sect);
- } else if (drive->media == ide_cdrom) {
- printk("%s: ATAPI cdrom (?)\n", drive->name);
- } else {
- drive->present = 0; /* nuke it */
+ /*
+ * In order to keep things simple we have an id
+ * block for all drives at all times. If the device
+ * is pre ATA or refuses ATA/ATAPI identify we
+ * will add faked data to this.
+ *
+ * Also note that 0 everywhere means "can't do X"
+ */
+
+ drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL);
+ drive->id_read = 0;
+ if(drive->id == NULL)
+ {
+ printk(KERN_ERR "ide: out of memory for id data.\n");
+ return 0;
+ }
+ memset(drive->id, 0, SECTOR_WORDS * 4);
+ strcpy(drive->id->model, "UNKNOWN");
+
+ /* skip probing? */
+ if (!drive->noprobe)
+ {
+ /* if !(success||timed-out) */
+ if (do_probe(drive, WIN_IDENTIFY) >= 2) {
+ /* look for ATAPI device */
+ (void) do_probe(drive, WIN_PIDENTIFY);
+ }
+ if (strstr(drive->id->model, "E X A B Y T E N E S T"))
+ enable_nest(drive);
+ if (!drive->present)
+ /* drive not found */
+ return 0;
+
+ /* identification failed? */
+ if (!drive->id_read) {
+ if (drive->media == ide_disk) {
+ printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n",
+ drive->name, drive->cyl,
+ drive->head, drive->sect);
+ } else if (drive->media == ide_cdrom) {
+ printk(KERN_INFO "%s: ATAPI cdrom (?)\n", drive->name);
+ } else {
+ /* nuke it */
+ printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
+ drive->present = 0;
+ }
}
+ /* drive was found */
}
- return 1; /* drive was found */
+ if(!drive->present)
+ return 0;
+ /* The drive wasn't being helpful. Add generic info only */
+ if(!drive->id_read)
+ generic_id(drive);
+ return drive->present;
}
-/*
- * Calculate the region that this interface occupies,
- * handling interfaces where the registers may not be
- * ordered sanely. We deal with the CONTROL register
- * separately.
+#define hwif_check_region(addr, num) \
+ ((hwif->mmio) ? check_mem_region((addr),(num)) : check_region((addr),(num)))
+
+/**
+ * hwif_check_regions - check resources for IDE
+ * @hwif: interface to use
+ *
+ * Checks if all the needed resources for an interface are free
+ * providing the interface is PIO. Right now core IDE code does
+ * this work which is deeply wrong. MMIO leaves it to the controller
+ * driver, PIO will migrate this way over time
*/
+
static int hwif_check_regions (ide_hwif_t *hwif)
{
- int region_errors = 0;
-
- hwif->straight8 = 0;
- region_errors = ide_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_ERROR_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_LCYL_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_HCYL_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);
- region_errors += ide_check_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);
+ u32 i = 0;
+ int addr_errs = 0;
+ if (hwif->mmio == 2)
+ return 0;
+ addr_errs = hwif_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
+ for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+ addr_errs += hwif_check_region(hwif->io_ports[i], 1);
if (hwif->io_ports[IDE_CONTROL_OFFSET])
- region_errors += ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
+ addr_errs += hwif_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
if (hwif->io_ports[IDE_IRQ_OFFSET])
- region_errors += ide_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);
+ addr_errs += hwif_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);
#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
- /*
- * If any errors are return, we drop the hwif interface.
- */
- return(region_errors);
+ /* If any errors are return, we drop the hwif interface. */
+ hwif->straight8 = 0;
+ return(addr_errs);
}
+//EXPORT_SYMBOL(hwif_check_regions);
+
+#define hwif_request_region(addr, num, name) \
+ ((hwif->mmio) ? request_mem_region((addr),(num),(name)) : request_region((addr),(num),(name)))
+
static void hwif_register (ide_hwif_t *hwif)
{
+ u32 i = 0;
+
+ if (hwif->mmio == 2)
+ return;
+ if (hwif->io_ports[IDE_CONTROL_OFFSET])
+ hwif_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name);
+#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
+ if (hwif->io_ports[IDE_IRQ_OFFSET])
+ hwif_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name);
+#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) ==
((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) {
- ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name);
+ hwif_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name);
hwif->straight8 = 1;
- goto jump_straight8;
+ return;
}
- if (hwif->io_ports[IDE_DATA_OFFSET])
- ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_ERROR_OFFSET])
- ide_request_region(hwif->io_ports[IDE_ERROR_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_NSECTOR_OFFSET])
- ide_request_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_SECTOR_OFFSET])
- ide_request_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_LCYL_OFFSET])
- ide_request_region(hwif->io_ports[IDE_LCYL_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_HCYL_OFFSET])
- ide_request_region(hwif->io_ports[IDE_HCYL_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_SELECT_OFFSET])
- ide_request_region(hwif->io_ports[IDE_SELECT_OFFSET], 1, hwif->name);
- if (hwif->io_ports[IDE_STATUS_OFFSET])
- ide_request_region(hwif->io_ports[IDE_STATUS_OFFSET], 1, hwif->name);
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+ hwif_request_region(hwif->io_ports[i], 1, hwif->name);
+}
-jump_straight8:
- if (hwif->io_ports[IDE_CONTROL_OFFSET])
- ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name);
-#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
- if (hwif->io_ports[IDE_IRQ_OFFSET])
- ide_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name);
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
+//EXPORT_SYMBOL(hwif_register);
+
+/* Enable code below on all archs later, for now, I want it on PPC
+ */
+#ifdef CONFIG_PPC
+/*
+ * This function waits for the hwif to report a non-busy status
+ * see comments in probe_hwif()
+ */
+static int wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
+{
+ u8 stat = 0;
+
+ while(timeout--) {
+ /* Turn this into a schedule() sleep once I'm sure
+ * about locking issues (2.5 work ?)
+ */
+ mdelay(1);
+ stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+ if ((stat & BUSY_STAT) == 0)
+ break;
+ /* Assume a value of 0xff means nothing is connected to
+ * the interface and it doesn't implement the pull-down
+ * resistor on D7
+ */
+ if (stat == 0xff)
+ break;
+ }
+ return ((stat & BUSY_STAT) == 0) ? 0 : -EBUSY;
+}
+
+static int wait_hwif_ready(ide_hwif_t *hwif)
+{
+ int rc;
+
+ printk(KERN_INFO "Probing IDE interface %s...\n", hwif->name);
+
+ /* Let HW settle down a bit from whatever init state we
+ * come from */
+ mdelay(2);
+
+ /* Wait for BSY bit to go away, spec timeout is 30 seconds,
+ * I know of at least one disk who takes 31 seconds, I use 35
+ * here to be safe
+ */
+ rc = wait_not_busy(hwif, 35000);
+ if (rc)
+ 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 = wait_not_busy(hwif, 10000);
+ if (rc)
+ return rc;
+ SELECT_DRIVE(&hwif->drives[1]);
+ hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ mdelay(2);
+ rc = wait_not_busy(hwif, 10000);
+
+ /* Exit function with master reselected (let's be sane) */
+ SELECT_DRIVE(&hwif->drives[0]);
+
+ return rc;
}
+#endif /* CONFIG_PPC */
/*
* 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.
*/
-static void probe_hwif (ide_hwif_t *hwif)
+void probe_hwif (ide_hwif_t *hwif)
{
unsigned int unit;
unsigned long flags;
+ unsigned int irqd;
if (hwif->noprobe)
return;
#ifdef CONFIG_BLK_DEV_IDE
if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) {
extern void probe_cmos_for_drives(ide_hwif_t *);
-
- probe_cmos_for_drives (hwif);
+ probe_cmos_for_drives(hwif);
}
#endif
-
- if ((hwif->chipset != ide_4drives || !hwif->mate->present) &&
+ if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) &&
#if CONFIG_BLK_DEV_PDC4030
(hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
#endif /* CONFIG_BLK_DEV_PDC4030 */
(hwif_check_regions(hwif))) {
- int msgout = 0;
+ u16 msgout = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
if (drive->present) {
drive->present = 0;
- printk("%s: ERROR, PORTS ALREADY IN USE\n", drive->name);
+ printk(KERN_ERR "%s: ERROR, PORTS ALREADY IN USE\n",
+ drive->name);
msgout = 1;
}
}
if (!msgout)
- printk("%s: ports already in use, skipping probe\n", hwif->name);
+ printk(KERN_ERR "%s: ports already in use, skipping probe\n",
+ hwif->name);
return;
}
- __save_flags(flags); /* local CPU only */
- __sti(); /* local CPU only; needed for jiffies and irq probing */
+ /*
+ * We must always disable IRQ, as probe_for_drive will assert IRQ, but
+ * we'll install our IRQ driver much later...
+ */
+ irqd = hwif->irq;
+ if (irqd)
+ disable_irq(hwif->irq);
+
+ local_irq_set(flags);
+
+#ifdef CONFIG_PPC
+ /* This is needed on some PPCs and a bunch of BIOS-less embedded
+ * platforms. Typical cases are:
+ *
+ * - The firmware hard reset the disk before booting the kernel,
+ * the drive is still doing it's poweron-reset sequence, that
+ * can take up to 30 seconds
+ * - The firmware does nothing (or no firmware), the device is
+ * still in POST state (same as above actually).
+ * - Some CD/DVD/Writer combo drives tend to drive the bus during
+ * their reset sequence even when they are non-selected slave
+ * devices, thus preventing discovery of the main HD
+ *
+ * Doing this wait-for-busy should not harm any existing configuration
+ * (at least things won't be worse than what current code does, that
+ * is blindly go & talk to the drive) and fix some issues like the
+ * above.
+ *
+ * BenH.
+ */
+ if (wait_hwif_ready(hwif))
+ printk(KERN_WARNING "%s: Wait for ready failed before probe !\n", hwif->name);
+#endif /* CONFIG_PPC */
+
/*
* Second drive should only exist if first drive was found,
* but a lot of cdrom drives are configured as single slaves.
*/
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- (void) probe_for_drive (drive);
+ drive->dn = ((hwif->channel ? 2 : 0) + unit);
+ hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
+ (void) probe_for_drive(drive);
if (drive->present && !hwif->present) {
hwif->present = 1;
- if (hwif->chipset != ide_4drives || !hwif->mate->present) {
+ if (hwif->chipset != ide_4drives ||
+ !hwif->mate ||
+ !hwif->mate->present) {
hwif_register(hwif);
}
}
}
if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) {
unsigned long timeout = jiffies + WAIT_WORSTCASE;
- byte stat;
+ u8 stat;
- printk("%s: reset\n", hwif->name);
- OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ printk(KERN_WARNING "%s: reset\n", hwif->name);
+ hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
udelay(10);
- OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
do {
ide_delay_50ms();
- stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
- } while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies));
+ stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+ } while ((stat & BUSY_STAT) && time_after(timeout, jiffies));
}
- __restore_flags(flags); /* local CPU only */
+ local_irq_restore(flags);
+ /*
+ * Use cached IRQ number. It might be (and is...) changed by probe
+ * code above
+ */
+ if (irqd)
+ enable_irq(irqd);
+
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
+ int enable_dma = 1;
+
if (drive->present) {
- ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
- if (tuneproc != NULL && drive->autotune == 1)
- tuneproc(drive, 255); /* auto-tune PIO mode */
+ if (hwif->tuneproc != NULL &&
+ drive->autotune == IDE_TUNE_AUTO)
+ /* auto-tune PIO mode */
+ hwif->tuneproc(drive, 255);
+
+#ifdef CONFIG_IDEDMA_ONLYDISK
+ if (drive->media != ide_disk)
+ enable_dma = 0;
+#endif
+ /*
+ * MAJOR HACK BARF :-/
+ *
+ * FIXME: chipsets own this cruft!
+ */
+ /*
+ * Move here to prevent module loading clashing.
+ */
+ // drive->autodma = hwif->autodma;
+ if ((hwif->ide_dma_check) &&
+ ((drive->autotune == IDE_TUNE_DEFAULT) ||
+ (drive->autotune == IDE_TUNE_AUTO))) {
+ /*
+ * Force DMAing for the beginning of the check.
+ * Some chipsets appear to do interesting
+ * things, if not checked and cleared.
+ * PARANOIA!!!
+ */
+ hwif->ide_dma_off_quietly(drive);
+ if (enable_dma)
+ hwif->ide_dma_check(drive);
+ }
+ }
+ }
+}
+
+EXPORT_SYMBOL(probe_hwif);
+
+#if 0
+int hwif_init (ide_hwif_t *hwif);
+int probe_hwif_init (ide_hwif_t *hwif)
+{
+ hwif->initializing = 1;
+ probe_hwif(hwif);
+ hwif_init(hwif);
+
+#if 1
+ if (hwif->present) {
+ u16 unit = 0;
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ ide_drive_t *drive = &hwif->drives[unit];
+ if (drive->present) {
+ ata_attach(drive);
+ }
}
}
+#endif
+ hwif->initializing = 0;
+ return 0;
}
+EXPORT_SYMBOL(probe_hwif_init);
+#endif
+
#if MAX_HWIFS > 1
/*
* save_match() is used to simplify logic in init_irq() below.
@@ -583,18 +946,20 @@
*
* This routine detects and reports such situations, but does not fix them.
*/
-static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
+void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
{
ide_hwif_t *m = *match;
if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
if (!new->hwgroup)
return;
- printk("%s: potential irq problem with %s and %s\n", hwif->name, new->name, m->name);
+ printk("%s: potential irq problem with %s and %s\n",
+ hwif->name, new->name, m->name);
}
if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
*match = new;
}
+EXPORT_SYMBOL(save_match);
#endif /* MAX_HWIFS > 1 */
/*
@@ -606,14 +971,9 @@
q->queuedata = HWGROUP(drive);
blk_init_queue(q, do_ide_request);
-
- if (drive->media == ide_disk) {
-#ifdef CONFIG_BLK_DEV_ELEVATOR_NOOP
- elevator_init(&q->elevator, ELEVATOR_NOOP);
-#endif
- }
}
+#undef __IRQ_HELL_SPIN
/*
* This routine sets up the irq for an ide interface, and creates a new
* hwgroup for the irq/hwif if none was previously assigned.
@@ -627,20 +987,26 @@
* 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)
+int init_irq (ide_hwif_t *hwif)
{
unsigned long flags;
unsigned int index;
ide_hwgroup_t *hwgroup, *new_hwgroup;
ide_hwif_t *match = NULL;
-
+#if 0
+ /* Allocate the buffer and no sleep allowed */
+ new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_ATOMIC);
+#else
/* Allocate the buffer and potentially sleep first */
-
new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
+#endif
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
+#ifndef __IRQ_HELL_SPIN
+ save_and_cli(flags);
+#else
+ spin_lock_irqsave(&io_request_lock, flags);
+#endif
hwif->hwgroup = NULL;
#if MAX_HWIFS > 1
@@ -652,7 +1018,8 @@
if (h->hwgroup) { /* scan only initialized hwif's */
if (hwif->irq == h->irq) {
hwif->sharing_irq = h->sharing_irq = 1;
- if (hwif->chipset != ide_pci || h->chipset != ide_pci) {
+ if (hwif->chipset != ide_pci ||
+ h->chipset != ide_pci) {
save_match(hwif, h, &match);
}
}
@@ -677,7 +1044,11 @@
} else {
hwgroup = new_hwgroup;
if (!hwgroup) {
- restore_flags(flags); /* all CPUs */
+#ifndef __IRQ_HELL_SPIN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
return 1;
}
memset(hwgroup, 0, sizeof(ide_hwgroup_t));
@@ -695,19 +1066,30 @@
* Allocate the irq, if not already obtained for another hwif
*/
if (!match || match->irq != hwif->irq) {
-#ifdef CONFIG_IDEPCI_SHARE_IRQ
- int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_SHIRQ : SA_INTERRUPT;
-#else /* !CONFIG_IDEPCI_SHARE_IRQ */
- int sa = IDE_CHIPSET_IS_PCI(hwif->chipset) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
+ int sa = SA_INTERRUPT;
+#if defined(__mc68000__) || defined(CONFIG_APUS)
+ sa = SA_SHIRQ;
+#endif /* __mc68000__ || CONFIG_APUS */
+
+ if (IDE_CHIPSET_IS_PCI(hwif->chipset)) {
+ sa = SA_SHIRQ;
+#ifndef CONFIG_IDEPCI_SHARE_IRQ
+ sa |= SA_INTERRUPT;
#endif /* CONFIG_IDEPCI_SHARE_IRQ */
+ }
if (hwif->io_ports[IDE_CONTROL_OFFSET])
- OUT_BYTE(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]); /* clear nIEN */
+ /* clear nIEN */
+ hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]);
- if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) {
+ if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) {
if (!match)
kfree(hwgroup);
- restore_flags(flags); /* all CPUs */
+#ifndef __IRQ_HELL_SPIN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
return 1;
}
}
@@ -735,10 +1117,16 @@
printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);
#endif
}
- restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */
+
+ /* all CPUs; safe now that hwif->hwgroup is set up */
+#ifndef __IRQ_HELL_SPIN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
- printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name,
+ printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
hwif->io_ports[IDE_DATA_OFFSET],
hwif->io_ports[IDE_DATA_OFFSET]+7,
hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
@@ -748,7 +1136,7 @@
hwif->io_ports[IDE_DATA_OFFSET]+7,
hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq));
#else
- printk("%s at %p on irq 0x%08x", hwif->name,
+ printk("%s at 0x%08lx on irq %d", hwif->name,
hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
#endif /* __mc68000__ && CONFIG_APUS */
if (match)
@@ -758,6 +1146,8 @@
return 0;
}
+EXPORT_SYMBOL(init_irq);
+
/*
* init_gendisk() (as opposed to ide_geninit) is called for each major device,
* after probing for drives, to allocate partition tables and other data
@@ -771,34 +1161,27 @@
int *bs, *max_sect, *max_ra;
extern devfs_handle_t ide_devfs_handle;
-#if 1
units = MAX_DRIVES;
-#else
- /* figure out maximum drive number on the interface */
- for (units = MAX_DRIVES; units > 0; --units) {
- if (hwif->drives[units-1].present)
- break;
- }
-#endif
minors = units * (1<<PARTN_BITS);
- gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
+ gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
if (!gd)
goto err_kmalloc_gd;
- memset (gd, 0, sizeof(struct gendisk));
- gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
+ memset(gd, 0, sizeof(struct gendisk));
+
+ gd->sizes = kmalloc(minors * sizeof(int), GFP_KERNEL);
if (!gd->sizes)
goto err_kmalloc_gd_sizes;
- gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
+ gd->part = kmalloc(minors * sizeof(struct hd_struct), GFP_KERNEL);
if (!gd->part)
goto err_kmalloc_gd_part;
- bs = kmalloc (minors*sizeof(int), GFP_KERNEL);
+ bs = kmalloc(minors*sizeof(int), GFP_KERNEL);
if (!bs)
goto err_kmalloc_bs;
- max_sect = kmalloc (minors*sizeof(int), GFP_KERNEL);
+ max_sect = kmalloc(minors*sizeof(int), GFP_KERNEL);
if (!max_sect)
goto err_kmalloc_max_sect;
- max_ra = kmalloc (minors*sizeof(int), GFP_KERNEL);
+ max_ra = kmalloc(minors*sizeof(int), GFP_KERNEL);
if (!max_ra)
goto err_kmalloc_max_ra;
@@ -813,55 +1196,49 @@
/*
* IDE can do up to 128K per request == 256
*/
- *max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : 128);
+ *max_sect++ = ((hwif->rqsize) ? hwif->rqsize : 128);
*max_ra++ = vm_max_readahead;
}
for (unit = 0; unit < units; ++unit)
hwif->drives[unit].part = &gd->part[unit << PARTN_BITS];
- gd->major = hwif->major; /* our major device number */
- gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */
- gd->minor_shift = PARTN_BITS; /* num bits for partitions */
- gd->max_p = 1<<PARTN_BITS; /* 1 + max partitions / drive */
- gd->nr_real = units; /* current num real drives */
- gd->real_devices= hwif; /* ptr to internal data */
- gd->next = NULL; /* linked list of major devs */
- gd->fops = ide_fops; /* file operations */
- gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
- gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
+ /* our major device number */
+ gd->major = hwif->major;
+ /* treated special in genhd.c */
+ gd->major_name = IDE_MAJOR_NAME;
+ /* num bits for partitions */
+ gd->minor_shift = PARTN_BITS;
+ /* 1 + max partitions / drive */
+ gd->max_p = 1<<PARTN_BITS;
+ /* current num real drives */
+ gd->nr_real = units;
+ /* ptr to internal data */
+ gd->real_devices= hwif;
+ /* linked list of major devs */
+ gd->next = NULL;
+ /* file operations */
+ gd->fops = ide_fops;
+ gd->de_arr = kmalloc(sizeof *gd->de_arr * units, GFP_KERNEL);
+ gd->flags = kmalloc(sizeof *gd->flags * units, GFP_KERNEL);
if (gd->de_arr)
- memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
+ memset(gd->de_arr, 0, sizeof *gd->de_arr * units);
if (gd->flags)
- memset (gd->flags, 0, sizeof *gd->flags * units);
+ memset(gd->flags, 0, sizeof *gd->flags * units);
hwif->gd = gd;
add_gendisk(gd);
for (unit = 0; unit < units; ++unit) {
-#if 1
char name[64];
ide_add_generic_settings(hwif->drives + unit);
- hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
+// hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
sprintf (name, "host%d/bus%d/target%d/lun%d",
(hwif->channel && hwif->mate) ?
hwif->mate->index : hwif->index,
hwif->channel, unit, hwif->drives[unit].lun);
if (hwif->drives[unit].present)
hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
-#else
- if (hwif->drives[unit].present) {
- char name[64];
-
- ide_add_generic_settings(hwif->drives + unit);
- hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
- sprintf (name, "host%d/bus%d/target%d/lun%d",
- (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index,
- hwif->channel, unit, hwif->drives[unit].lun);
- hwif->drives[unit].de =
- devfs_mk_dir (ide_devfs_handle, name, NULL);
- }
-#endif
}
return;
@@ -880,7 +1257,9 @@
return;
}
-static int hwif_init (ide_hwif_t *hwif)
+EXPORT_SYMBOL(init_gendisk);
+
+int hwif_init (ide_hwif_t *hwif)
{
if (!hwif->present)
return 0;
@@ -893,15 +1272,18 @@
}
#ifdef CONFIG_BLK_DEV_HD
if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
- printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name);
+ printk("%s: CANNOT SHARE IRQ WITH OLD "
+ "HARDDISK DRIVER (hd.c)\n", hwif->name);
return (hwif->present = 0);
}
#endif /* CONFIG_BLK_DEV_HD */
-
- hwif->present = 0; /* we set it back to 1 if all is ok below */
+
+ /* we set it back to 1 if all is ok below */
+ hwif->present = 0;
if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) {
- printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major);
+ printk("%s: UNABLE TO GET MAJOR NUMBER %d\n",
+ hwif->name, hwif->major);
return (hwif->present = 0);
}
@@ -912,14 +1294,15 @@
* this port and try that.
*/
if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
- printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i);
- (void) unregister_blkdev (hwif->major, hwif->name);
+ printk("%s: Disabled unable to get IRQ %d.\n",
+ hwif->name, i);
+ (void) unregister_blkdev(hwif->major, hwif->name);
return (hwif->present = 0);
}
if (init_irq(hwif)) {
printk("%s: probed IRQ %d and default IRQ %d failed.\n",
hwif->name, i, hwif->irq);
- (void) unregister_blkdev (hwif->major, hwif->name);
+ (void) unregister_blkdev(hwif->major, hwif->name);
return (hwif->present = 0);
}
printk("%s: probed IRQ %d failed, using default.\n",
@@ -942,19 +1325,51 @@
return hwif->present;
}
+EXPORT_SYMBOL(hwif_init);
+
void export_ide_init_queue (ide_drive_t *drive)
{
ide_init_queue(drive);
}
-byte export_probe_for_drive (ide_drive_t *drive)
+EXPORT_SYMBOL(export_ide_init_queue);
+
+u8 export_probe_for_drive (ide_drive_t *drive)
{
return probe_for_drive(drive);
}
-EXPORT_SYMBOL(export_ide_init_queue);
EXPORT_SYMBOL(export_probe_for_drive);
+#ifndef HWIF_PROBE_CLASSIC_METHOD
+int probe_hwif_init (ide_hwif_t *hwif)
+{
+ hwif->initializing = 1;
+ probe_hwif(hwif);
+ hwif_init(hwif);
+
+#ifndef CLASSIC_BUILTINS_METHOD
+# ifndef FAKE_CLASSIC_ATTACH_METHOD
+# ifdef DIRECT_HWIF_PROBE_ATTACH_METHOD
+ if (hwif->present) {
+ u16 unit = 0;
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ ide_drive_t *drive = &hwif->drives[unit];
+ if (drive->present)
+ ide_attach_drive(drive);
+ }
+ }
+# endif /* DIRECT_HWIF_PROBE_ATTACH_METHOD */
+# endif /* FAKE_CLASSIC_ATTACH_METHOD */
+#endif /* CLASSIC_BUILTINS_METHOD */
+ hwif->initializing = 0;
+ return 0;
+}
+
+EXPORT_SYMBOL(probe_hwif_init);
+
+#endif /* HWIF_PROBE_CLASSIC_METHOD */
+
int ideprobe_init (void);
static ide_module_t ideprobe_module = {
IDE_PROBE_MODULE,
@@ -975,12 +1390,20 @@
/*
* Probe for drives in the usual way.. CMOS/BIOS, then poke at ports
*/
+#ifdef HWIF_PROBE_CLASSIC_METHOD
for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index])
probe_hwif(&ide_hwifs[index]);
+
for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index])
hwif_init(&ide_hwifs[index]);
+#else /* HWIF_PROBE_CLASSIC_METHOD */
+ for (index = 0; index < MAX_HWIFS; ++index)
+ if (probe[index])
+ probe_hwif_init(&ide_hwifs[index]);
+#endif /* HWIF_PROBE_CLASSIC_METHOD */
+
if (!ide_probe)
ide_probe = &ideprobe_module;
MOD_DEC_USE_COUNT;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)