Commit 989e85fa authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] ide-probe updates

Fix crash with slave and no master
Fix crash with hdb=noprobe hdb=cdrom
Fix crash with pre ATA devices refusing IDENTIFY
Fix flash slave making master disappear
Add interfaces that the PPC uses to do disk spin up when the BIOS has not
Add framework to allow hdparm -d1 on a box built with IDE_DMA_ONLYDISK
Fix identify framework so we can fix the proc identify crash too
parent ef3739f1
/*
* linux/drivers/ide/ide-probe.c Version 1.07 March 18, 2001
* linux/drivers/ide/ide-probe.c Version 1.10 Feb 11, 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 */
......@@ -54,7 +56,38 @@
#include <asm/uaccess.h>
#include <asm/io.h>
/*
/**
* 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 int generic_id(ide_drive_t *drive)
{
drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL);
if(drive->id == NULL)
{
printk(KERN_ERR "ide: out of memory for id data.\n");
return -ENOMEM;
}
memset(drive->id, 0, SECTOR_WORDS * 4);
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;
strcpy(drive->id->model, "UNKNOWN");
return 0;
}
/**
* 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
......@@ -63,13 +96,14 @@
* 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.2.x).
* At that time, we might also consider parameterizing the timeouts and retries,
* since these are MUCH faster than mechanical drives. -M.Lord
* 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
*/
inline int drive_is_flashcard (ide_drive_t *drive)
static inline int drive_is_flashcard (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
......@@ -88,6 +122,16 @@ inline int drive_is_flashcard (ide_drive_t *drive)
return 0; /* no, it is not a flash memory card */
}
/**
* 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);
......@@ -207,6 +251,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
*/
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
......@@ -214,11 +259,17 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
*/
drive->is_flash = 0;
if (drive_is_flashcard(drive)) {
#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];
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;
......@@ -244,7 +295,11 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
return;
}
/*
/**
* actual_try_to_identify - send ata/atapi identify
* @drive: drive to identify
* @cmd: comamnd to use
*
* 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
......@@ -254,11 +309,12 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
* 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, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
int rc;
ide_ioreg_t hd_status;
unsigned long hd_status;
unsigned long timeout;
u8 s = 0, a = 0;
......@@ -268,7 +324,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
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 "
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;
......@@ -327,6 +383,16 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
return rc;
}
/**
* 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);
......@@ -376,7 +442,11 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
}
/*
/**
* 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.
......@@ -392,6 +462,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
* 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, u8 cmd)
{
int rc;
......@@ -507,18 +578,23 @@ static void enable_nest (ide_drive_t *drive)
}
}
/*
* 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
*
* 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)
* 1 device was found (note: drive->present might
* still be 0)
*/
static inline u8 probe_for_drive (ide_drive_t *drive)
{
/* skip probing? */
if (drive->noprobe)
return drive->present;
if (!drive->noprobe)
{
/* if !(success||timed-out) */
if (do_probe(drive, WIN_IDENTIFY) >= 2) {
/* look for ATAPI device */
......@@ -533,18 +609,24 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
/* identification failed? */
if (drive->id == NULL) {
if (drive->media == ide_disk) {
printk("%s: non-IDE drive, CHS=%d/%d/%d\n",
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("%s: ATAPI cdrom (?)\n", drive->name);
printk(KERN_INFO "%s: ATAPI cdrom (?)\n", drive->name);
} else {
/* nuke it */
drive->present = 0;
}
}
/* drive was found */
return 1;
}
if(!drive->present)
return 0;
if(drive->id == NULL)
if(generic_id(drive) < 0)
drive->present = 0;
return drive->present;
}
static int hwif_check_region(ide_hwif_t *hwif, unsigned long addr, int num)
......@@ -560,12 +642,21 @@ static int hwif_check_region(ide_hwif_t *hwif, unsigned long addr, int num)
{
printk("%s: %s resource 0x%lX-0x%lX not free.\n",
hwif->name, hwif->mmio?"MMIO":"I/O", addr, addr+num-1);
mdelay(2000);
}
return err;
}
/**
* 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)
{
u32 i = 0;
......@@ -627,6 +718,72 @@ static void hwif_register (ide_hwif_t *hwif)
//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.
......@@ -650,13 +807,13 @@ void probe_hwif (ide_hwif_t *hwif)
ide_drive_t *drive = &hwif->drives[unit];
if (drive->present) {
drive->present = 0;
printk("%s: ERROR, PORTS ALREADY IN USE\n",
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",
printk(KERN_ERR "%s: ports already in use, skipping probe\n",
hwif->name);
return;
}
......@@ -666,17 +823,35 @@ void probe_hwif (ide_hwif_t *hwif)
* we'll install our IRQ driver much later...
*/
irqd = hwif->irq;
if (irqd >= NR_IRQS)
{
printk(KERN_ERR "***WARNING***: Bogus interrupt reported. Probably a bug in the Linux ACPI\n");
printk(KERN_ERR "***WARNING***: Attempting to continue as best we can.\n");
irqd = 0;
}
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.
......@@ -689,6 +864,7 @@ void probe_hwif (ide_hwif_t *hwif)
if (drive->present && !hwif->present) {
hwif->present = 1;
if (hwif->chipset != ide_4drives ||
!hwif->mate ||
!hwif->mate->present) {
hwif_register(hwif);
}
......@@ -698,7 +874,7 @@ void probe_hwif (ide_hwif_t *hwif)
unsigned long timeout = jiffies + WAIT_WORSTCASE;
u8 stat;
printk("%s: reset\n", hwif->name);
printk(KERN_WARNING "%s: reset\n", hwif->name);
hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
udelay(10);
hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
......@@ -718,11 +894,18 @@ void probe_hwif (ide_hwif_t *hwif)
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
int enable_dma = 1;
if (drive->present) {
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 :-/
*
......@@ -742,6 +925,7 @@ void probe_hwif (ide_hwif_t *hwif)
* PARANOIA!!!
*/
hwif->ide_dma_off_quietly(drive);
if (enable_dma)
hwif->ide_dma_check(drive);
}
}
......@@ -757,7 +941,6 @@ int probe_hwif_init (ide_hwif_t *hwif)
probe_hwif(hwif);
hwif_init(hwif);
#if 1
if (hwif->present) {
u16 unit = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
......@@ -767,7 +950,6 @@ int probe_hwif_init (ide_hwif_t *hwif)
}
}
}
#endif
hwif->initializing = 0;
return 0;
}
......@@ -855,13 +1037,8 @@ static int init_irq (ide_hwif_t *hwif)
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
spin_lock_irqsave(&ide_lock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment