Commit 4cf319d5 authored by Martin Dalecki's avatar Martin Dalecki Committed by Russell King

[PATCH] 2.5.13 IDE 50

 - Fix wrong usage of time_after in ide.c. This should cure the drive seek
   timeout problems some people where expierencing. This was clarified to me by
   Bartek, who apparently checked whatever the actual code is consistent with
   the comments in front of it. Thank you Bartlomiej Zolnierkiewicz.

   I think now that we should have time_past(xxx) in <linux/timer.h>.

 - Fix hpt34x.c compilation.

 - Minor improvements in ide-pci and some cleanups in ide-probe.c

 - Nuke some vastly outdated comments.
parent 6fe18669
...@@ -249,14 +249,14 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) ...@@ -249,14 +249,14 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
ide_dma_off_quietly); ide_dma_off_quietly);
} }
static int config_drive_xfer_rate (ide_drive_t *drive) static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
ide_dma_action_t dma_func = ide_dma_on; ide_dma_action_t dma_func = ide_dma_on;
if (id && (id->capability & 1) && drive->channel->autodma) { if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive)) { if (ide_dmaproc(ide_dma_bad_drive, drive, rq)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
} }
...@@ -278,7 +278,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -278,7 +278,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on) if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if (ide_dmaproc(ide_dma_good_drive, drive)) { } else if (ide_dmaproc(ide_dma_good_drive, drive, rq)) {
if (id->eide_dma_time > 150) { if (id->eide_dma_time > 150) {
goto no_dma_set; goto no_dma_set;
} }
...@@ -301,7 +301,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -301,7 +301,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
dma_func = ide_dma_off; dma_func = ide_dma_off;
#endif /* CONFIG_HPT34X_AUTODMA */ #endif /* CONFIG_HPT34X_AUTODMA */
return drive->channel->dmaproc(dma_func, drive); return drive->channel->udma(dma_func, drive, rq);
} }
/* /*
...@@ -312,7 +312,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -312,7 +312,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
* by HighPoint|Triones Technologies, Inc. * by HighPoint|Triones Technologies, Inc.
*/ */
int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) int hpt34x_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
unsigned long dma_base = hwif->dma_base; unsigned long dma_base = hwif->dma_base;
...@@ -321,7 +321,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) ...@@ -321,7 +321,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
switch (func) { switch (func) {
case ide_dma_check: case ide_dma_check:
return config_drive_xfer_rate(drive); return config_drive_xfer_rate(drive, rq);
case ide_dma_read: case ide_dma_read:
reading = 1 << 3; reading = 1 << 3;
case ide_dma_write: case ide_dma_write:
...@@ -347,7 +347,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) ...@@ -347,7 +347,7 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
default: default:
break; break;
} }
return ide_dmaproc(func, drive); /* use standard DMA stuff */ return ide_dmaproc(func, drive, rq); /* use standard DMA stuff */
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif /* CONFIG_BLK_DEV_IDEDMA */
...@@ -423,7 +423,7 @@ void __init ide_init_hpt34x(struct ata_channel *hwif) ...@@ -423,7 +423,7 @@ void __init ide_init_hpt34x(struct ata_channel *hwif)
else else
hwif->autodma = 0; hwif->autodma = 0;
hwif->dmaproc = &hpt34x_dmaproc; hwif->udma = &hpt34x_dmaproc;
hwif->highmem = 1; hwif->highmem = 1;
} else { } else {
hwif->drives[0].autotune = 1; hwif->drives[0].autotune = 1;
......
/* /***** vi:set ts=8 sts=8 sw=8:************************************************
* Copyright (C) 1994-1998 Linus Torvalds and authors: *
* Copyright (C) 1994-1998,2002 Linus Torvalds and authors:
* *
* Mark Lord <mlord@pobox.com> * Mark Lord <mlord@pobox.com>
* Gadi Oxman <gadio@netvision.net.il> * Gadi Oxman <gadio@netvision.net.il>
* Andre Hedrick <andre@linux-ide.org> * Andre Hedrick <andre@linux-ide.org>
* Jens Axboe <axboe@suse.de> * Jens Axboe <axboe@suse.de>
* Marcin Dalecki <dalecki@evision.ag> * Marcin Dalecki <martin@dalecki.de>
* *
* This is the ATA disk device driver, as evolved from hd.c and ide.c. * This is the ATA disk device driver, as evolved from hd.c and ide.c.
*/ */
......
/* /**** vi:set ts=8 sts=8 sw=8:************************************************
* Copyright (c) 1998-2000 Andre Hedrick <andre@linux-ide.org> *
* Copyright (c) 1995-1998 Mark Lord * Copyright (C) 2002 Marcin Dalecki <martin@dalecki.de>
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 1995-1998 Mark Lord
* *
* May be copied or modified under the terms of the GNU General Public License * May be copied or modified under the terms of the GNU General Public License
*/ */
...@@ -81,17 +83,10 @@ extern void ide_init_hpt34x(struct ata_channel *); ...@@ -81,17 +83,10 @@ extern void ide_init_hpt34x(struct ata_channel *);
#endif #endif
#ifdef CONFIG_BLK_DEV_HPT366 #ifdef CONFIG_BLK_DEV_HPT366
extern byte hpt363_shared_irq;
extern byte hpt363_shared_pin;
extern unsigned int pci_init_hpt366(struct pci_dev *); extern unsigned int pci_init_hpt366(struct pci_dev *);
extern unsigned int ata66_hpt366(struct ata_channel *); extern unsigned int ata66_hpt366(struct ata_channel *);
extern void ide_init_hpt366(struct ata_channel *); extern void ide_init_hpt366(struct ata_channel *);
extern void ide_dmacapable_hpt366(struct ata_channel *, unsigned long); extern void ide_dmacapable_hpt366(struct ata_channel *, unsigned long);
#else
/* FIXME: those have to be killed */
static byte hpt363_shared_irq;
static byte hpt363_shared_pin;
#endif #endif
#ifdef CONFIG_BLK_DEV_NS87415 #ifdef CONFIG_BLK_DEV_NS87415
...@@ -177,7 +172,7 @@ typedef struct ide_pci_enablebit_s { ...@@ -177,7 +172,7 @@ typedef struct ide_pci_enablebit_s {
#define ATA_F_PHACK 0x40 /* apply PROMISE hacks */ #define ATA_F_PHACK 0x40 /* apply PROMISE hacks */
#define ATA_F_HPTHACK 0x80 /* apply HPT366 hacks */ #define ATA_F_HPTHACK 0x80 /* apply HPT366 hacks */
typedef struct ide_pci_device_s { struct ata_pci_device {
unsigned short vendor; unsigned short vendor;
unsigned short device; unsigned short device;
unsigned int (*init_chipset)(struct pci_dev *dev); unsigned int (*init_chipset)(struct pci_dev *dev);
...@@ -188,9 +183,9 @@ typedef struct ide_pci_device_s { ...@@ -188,9 +183,9 @@ typedef struct ide_pci_device_s {
unsigned int bootable; unsigned int bootable;
unsigned int extra; unsigned int extra;
unsigned int flags; unsigned int flags;
} ide_pci_device_t; };
static ide_pci_device_t pci_chipsets[] __initdata = { static struct ata_pci_device pci_chipsets[] __initdata = {
#ifdef CONFIG_BLK_DEV_PIIX #ifdef CONFIG_BLK_DEV_PIIX
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, pci_init_piix, ata66_piix, ide_init_piix, ide_dmacapable_piix, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 },
...@@ -319,7 +314,7 @@ static ide_pci_device_t pci_chipsets[] __initdata = { ...@@ -319,7 +314,7 @@ static ide_pci_device_t pci_chipsets[] __initdata = {
* settings of split-mirror pci-config space, place chipset into init-mode, * settings of split-mirror pci-config space, place chipset into init-mode,
* and/or preserve an interrupt if the card is not native ide support. * and/or preserve an interrupt if the card is not native ide support.
*/ */
static unsigned int __init trust_pci_irq(ide_pci_device_t *d, struct pci_dev *dev) static unsigned int __init trust_pci_irq(struct ata_pci_device *d, struct pci_dev *dev)
{ {
if (d->flags & ATA_F_IRQ) if (d->flags & ATA_F_IRQ)
return dev->irq; return dev->irq;
...@@ -484,7 +479,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co ...@@ -484,7 +479,7 @@ static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, co
* Setup DMA transfers on a channel. * Setup DMA transfers on a channel.
*/ */
static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *dev, static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *dev,
ide_pci_device_t *d, struct ata_pci_device *d,
int port, int port,
u8 class_rev, u8 class_rev,
int pciirq, int pciirq,
...@@ -534,7 +529,7 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d ...@@ -534,7 +529,7 @@ static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *d
* This gets called once for the master and for the slave interface. * This gets called once for the master and for the slave interface.
*/ */
static int __init setup_host_channel(struct pci_dev *dev, static int __init setup_host_channel(struct pci_dev *dev,
ide_pci_device_t *d, struct ata_pci_device *d,
int port, int port,
u8 class_rev, u8 class_rev,
int pciirq, int pciirq,
...@@ -648,17 +643,16 @@ static int __init setup_host_channel(struct pci_dev *dev, ...@@ -648,17 +643,16 @@ static int __init setup_host_channel(struct pci_dev *dev,
} }
/* /*
* Looks at the primary/secondary channels on a PCI IDE device and, if they * Looks at the primary/secondary channels on a PCI IDE device and, if they are
* are enabled, prepares the IDE driver for use with them. This generic code * enabled, prepares the IDE driver for use with them. This generic code works
* works for most PCI chipsets. * for most PCI chipsets.
* *
* One thing that is not standardized is the location of the primary/secondary * One thing that is not standardized is the location of the primary/secondary
* interface "enable/disable" bits. For chipsets that we "know" about, this * interface "enable/disable" bits. For chipsets that we "know" about, this
* information is in the ide_pci_device_t struct; for all other chipsets, we * information is in the struct ata_pci_device struct; for all other chipsets,
* just assume both interfaces are enabled. * we just assume both interfaces are enabled.
*/ */
static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device *d)
static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
{ {
int autodma = 0; int autodma = 0;
int pciirq = 0; int pciirq = 0;
...@@ -775,10 +769,11 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) ...@@ -775,10 +769,11 @@ static void __init setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
setup_host_channel(dev, d, ATA_SECONDARY, class_rev, pciirq, autodma, &pcicmd); setup_host_channel(dev, d, ATA_SECONDARY, class_rev, pciirq, autodma, &pcicmd);
} }
static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) static void __init pdc20270_device_order_fixup (struct pci_dev *dev, struct ata_pci_device *d)
{ {
struct pci_dev *dev2 = NULL, *findev; struct pci_dev *dev2 = NULL;
ide_pci_device_t *d2; struct pci_dev *findev;
struct ata_pci_device *d2;
if (dev->bus->self && if (dev->bus->self &&
dev->bus->self->vendor == PCI_VENDOR_ID_DEC && dev->bus->self->vendor == PCI_VENDOR_ID_DEC &&
...@@ -814,10 +809,10 @@ static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_dev ...@@ -814,10 +809,10 @@ static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_dev
setup_pci_device(dev2, d2); setup_pci_device(dev2, d2);
} }
static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) static void __init hpt366_device_order_fixup (struct pci_dev *dev, struct ata_pci_device *d)
{ {
struct pci_dev *dev2 = NULL, *findev; struct pci_dev *dev2 = NULL, *findev;
ide_pci_device_t *d2; struct ata_pci_device *d2;
unsigned char pin1 = 0, pin2 = 0; unsigned char pin1 = 0, pin2 = 0;
unsigned int class_rev; unsigned int class_rev;
...@@ -843,9 +838,7 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic ...@@ -843,9 +838,7 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic
(PCI_FUNC(findev->devfn) & 1)) { (PCI_FUNC(findev->devfn) & 1)) {
dev2 = findev; dev2 = findev;
pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
hpt363_shared_pin = (pin1 != pin2) ? 1 : 0; if ((pin1 != pin2) && (dev->irq == dev2->irq)) {
hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0;
if (hpt363_shared_pin && hpt363_shared_irq) {
d->bootable = ON_BOARD; d->bootable = ON_BOARD;
printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", dev->name, pin1, pin2); printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", dev->name, pin1, pin2);
} }
...@@ -869,7 +862,7 @@ static void __init scan_pcidev(struct pci_dev *dev) ...@@ -869,7 +862,7 @@ static void __init scan_pcidev(struct pci_dev *dev)
{ {
unsigned short vendor; unsigned short vendor;
unsigned short device; unsigned short device;
ide_pci_device_t *d; struct ata_pci_device *d;
vendor = dev->vendor; vendor = dev->vendor;
device = dev->device; device = dev->device;
...@@ -881,7 +874,7 @@ static void __init scan_pcidev(struct pci_dev *dev) ...@@ -881,7 +874,7 @@ static void __init scan_pcidev(struct pci_dev *dev)
++d; ++d;
if (d->init_channel == ATA_PCI_IGNORE) if (d->init_channel == ATA_PCI_IGNORE)
printk("%s: has been ignored by PCI bus scan\n", dev->name); printk(KERN_INFO "ATA: %s: ignored by PCI bus scan\n", dev->name);
else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1)) else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1))
return; return;
else if ((d->vendor == PCI_VENDOR_ID_CONTAQ && d->device == PCI_DEVICE_ID_CONTAQ_82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) else if ((d->vendor == PCI_VENDOR_ID_CONTAQ && d->device == PCI_DEVICE_ID_CONTAQ_82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
...@@ -896,10 +889,10 @@ static void __init scan_pcidev(struct pci_dev *dev) ...@@ -896,10 +889,10 @@ static void __init scan_pcidev(struct pci_dev *dev)
pdc20270_device_order_fixup(dev, d); pdc20270_device_order_fixup(dev, d);
else if (!(d->vendor == 0 && d->device == 0) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { else if (!(d->vendor == 0 && d->device == 0) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
if (d->vendor == 0 && d->device == 0) if (d->vendor == 0 && d->device == 0)
printk("%s: unknown IDE controller on PCI slot %s, vendor=%04x, device=%04x\n", printk(KERN_INFO "ATA: unknown ATA interface %s (%04x:%04x) on PCI slot %s\n",
dev->name, dev->slot_name, vendor, device); dev->name, vendor, device, dev->slot_name);
else else
printk("%s: IDE controller on PCI slot %s\n", dev->name, dev->slot_name); printk(KERN_INFO "ATA: interface %s on PCI slot %s\n", dev->name, dev->slot_name);
setup_pci_device(dev, d); setup_pci_device(dev, d);
} }
} }
......
/* /**** vi:set ts=8 sts=8 sw=8:************************************************
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below) * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
* *
* Mostly written by Mark Lord <mlord@pobox.com> * Mostly written by Mark Lord <mlord@pobox.com>
...@@ -47,7 +48,7 @@ ...@@ -47,7 +48,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
static inline void do_identify (ide_drive_t *drive, byte cmd) static inline void do_identify(struct ata_device *drive, u8 cmd)
{ {
int bswap = 1; int bswap = 1;
struct hd_driveid *id; struct hd_driveid *id;
...@@ -121,7 +122,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -121,7 +122,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
drive->present = 1; drive->present = 1;
/* /*
* Check for an ATAPI device * Check for an ATAPI device:
*/ */
if (cmd == WIN_PIDENTIFY) { if (cmd == WIN_PIDENTIFY) {
byte type = (id->config >> 8) & 0x1f; byte type = (id->config >> 8) & 0x1f;
...@@ -172,7 +173,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -172,7 +173,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
} }
/* /*
* Not an ATAPI device: looks like a "regular" hard disk * Not an ATAPI device: looks like a "regular" hard disk:
*/ */
if (id->config & (1<<7)) if (id->config & (1<<7))
drive->removable = 1; drive->removable = 1;
...@@ -185,7 +186,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -185,7 +186,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
*/ */
if (drive_is_flashcard(drive)) { if (drive_is_flashcard(drive)) {
ide_drive_t *mate = &drive->channel->drives[1 ^ drive->select.b.unit]; struct ata_device *mate = &drive->channel->drives[1 ^ drive->select.b.unit];
if (!mate->ata_flash) { if (!mate->ata_flash) {
mate->present = 0; mate->present = 0;
mate->noprobe = 1; mate->noprobe = 1;
...@@ -204,26 +205,37 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -204,26 +205,37 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
kfree(id); kfree(id);
err_kmalloc: err_kmalloc:
drive->present = 0; drive->present = 0;
return; return;
} }
/* /*
* try_to_identify() sends an ATA(PI) IDENTIFY request to a drive * Sends an ATA(PI) IDENTIFY request to a drive and wait for a response. It
* and waits for a response. It also monitors irqs while this is * also monitor irqs while this is happening, in hope of automatically
* happening, in hope of automatically determining which one is * determining which one is being used by the interface.
* being used by the interface.
* *
* Returns: 0 device was identified * Returns: 0 device was identified
* 1 device timed-out (no response to identify request) * 1 device timed-out (no response to identify request)
* 2 device aborted the command (refused to identify itself) * 2 device aborted the command (refused to identify itself)
*/ */
static int actual_try_to_identify (ide_drive_t *drive, byte cmd) static int identify(struct ata_device *drive, u8 cmd)
{ {
int rc; int rc;
int autoprobe = 0;
unsigned long cookie = 0;
ide_ioreg_t hd_status; ide_ioreg_t hd_status;
unsigned long timeout; unsigned long timeout;
byte s, a; u8 s;
u8 a;
if (IDE_CONTROL_REG && !drive->channel->irq) {
autoprobe = 1;
cookie = probe_irq_on();
OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */
}
rc = 1;
if (IDE_CONTROL_REG) { if (IDE_CONTROL_REG) {
/* take a deep breath */ /* take a deep breath */
ide_delay_50ms(); ide_delay_50ms();
...@@ -247,19 +259,18 @@ static int actual_try_to_identify (ide_drive_t *drive, byte cmd) ...@@ -247,19 +259,18 @@ static int actual_try_to_identify (ide_drive_t *drive, byte cmd)
#if CONFIG_BLK_DEV_PDC4030 #if CONFIG_BLK_DEV_PDC4030
if (drive->channel->chipset == ide_pdc4030) { if (drive->channel->chipset == ide_pdc4030) {
/* DC4030 hosted drives need their own identify... */ /* DC4030 hosted drives need their own identify... */
extern int pdc4030_identify(ide_drive_t *); extern int pdc4030_identify(struct ata_device *);
if (pdc4030_identify(drive)) {
return 1; if (pdc4030_identify(drive))
} goto out;
} else } else
#endif /* CONFIG_BLK_DEV_PDC4030 */ #endif
OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */ OUT_BYTE(cmd,IDE_COMMAND_REG); /* ask drive for ID */
timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
timeout += jiffies; timeout += jiffies;
do { do {
if (0 < (signed long)(jiffies - timeout)) { if (time_after(jiffies, timeout))
return 1; /* drive timed-out */ goto out; /* drive timed-out */
}
ide_delay_50ms(); /* give drive a breather */ ide_delay_50ms(); /* give drive a breather */
} while (IN_BYTE(hd_status) & BUSY_STAT); } while (IN_BYTE(hd_status) & BUSY_STAT);
...@@ -274,23 +285,8 @@ static int actual_try_to_identify (ide_drive_t *drive, byte cmd) ...@@ -274,23 +285,8 @@ static int actual_try_to_identify (ide_drive_t *drive, byte cmd)
__restore_flags(flags); /* local CPU only */ __restore_flags(flags); /* local CPU only */
} else } else
rc = 2; /* drive refused ID */ rc = 2; /* drive refused ID */
return rc;
}
static int try_to_identify (ide_drive_t *drive, byte cmd)
{
int retval;
int autoprobe = 0;
unsigned long cookie = 0;
if (IDE_CONTROL_REG && !drive->channel->irq) {
autoprobe = 1;
cookie = probe_irq_on();
OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */
}
retval = actual_try_to_identify(drive, cmd);
out:
if (autoprobe) { if (autoprobe) {
int irq; int irq;
OUT_BYTE(drive->ctl | 0x02, IDE_CONTROL_REG); /* mask device irq */ OUT_BYTE(drive->ctl | 0x02, IDE_CONTROL_REG); /* mask device irq */
...@@ -304,7 +300,8 @@ static int try_to_identify (ide_drive_t *drive, byte cmd) ...@@ -304,7 +300,8 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie); printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie);
} }
} }
return retval;
return rc;
} }
...@@ -324,10 +321,11 @@ static int try_to_identify (ide_drive_t *drive, byte cmd) ...@@ -324,10 +321,11 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
* 3 bad status from device (possible for ATAPI drives) * 3 bad status from device (possible for ATAPI drives)
* 4 probe was not attempted because failure was obvious * 4 probe was not attempted because failure was obvious
*/ */
static int do_probe (ide_drive_t *drive, byte cmd) static int do_probe(struct ata_device *drive, byte cmd)
{ {
int rc; int rc;
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
if (drive->present) { /* avoid waiting for inappropriate probes */ if (drive->present) { /* avoid waiting for inappropriate probes */
if ((drive->type != ATA_DISK) && (cmd == WIN_IDENTIFY)) if ((drive->type != ATA_DISK) && (cmd == WIN_IDENTIFY))
return 4; return 4;
...@@ -348,11 +346,10 @@ static int do_probe (ide_drive_t *drive, byte cmd) ...@@ -348,11 +346,10 @@ static int do_probe (ide_drive_t *drive, byte cmd)
return 3; /* no i/f present: mmm.. this should be a 4 -ml */ return 3; /* no i/f present: mmm.. this should be a 4 -ml */
} }
if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT) if (OK_STAT(GET_STAT(),READY_STAT,BUSY_STAT) || drive->present || cmd == WIN_PIDENTIFY)
|| drive->present || cmd == WIN_PIDENTIFY)
{ {
if ((rc = try_to_identify(drive,cmd))) /* send cmd and wait */ if ((rc = identify(drive,cmd))) /* send cmd and wait */
rc = try_to_identify(drive,cmd); /* failed: try again */ rc = identify(drive,cmd); /* failed: try again */
if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) { if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) {
unsigned long timeout; 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, GET_STAT());
...@@ -363,14 +360,14 @@ static int do_probe (ide_drive_t *drive, byte cmd) ...@@ -363,14 +360,14 @@ static int do_probe (ide_drive_t *drive, byte cmd)
timeout = jiffies; timeout = jiffies;
while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE)) while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE))
ide_delay_50ms(); ide_delay_50ms();
rc = try_to_identify(drive, cmd); rc = identify(drive, cmd);
} }
if (rc == 1) if (rc == 1)
printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT()); printk("%s: no response (status = 0x%02x)\n", drive->name, GET_STAT());
(void) GET_STAT(); /* ensure drive irq is clear */ (void) GET_STAT(); /* ensure drive irq is clear */
} else { } else
rc = 3; /* not present or maybe ATAPI */ rc = 3; /* not present or maybe ATAPI */
}
if (drive->select.b.unit != 0) { if (drive->select.b.unit != 0) {
SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */ SELECT_DRIVE(hwif,&hwif->drives[0]); /* exit with drive0 selected */
ide_delay_50ms(); ide_delay_50ms();
...@@ -379,10 +376,7 @@ static int do_probe (ide_drive_t *drive, byte cmd) ...@@ -379,10 +376,7 @@ static int do_probe (ide_drive_t *drive, byte cmd)
return rc; return rc;
} }
/* static void enable_nest(struct ata_device *drive)
*
*/
static void enable_nest(ide_drive_t *drive)
{ {
unsigned long timeout; unsigned long timeout;
...@@ -392,7 +386,7 @@ static void enable_nest(ide_drive_t *drive) ...@@ -392,7 +386,7 @@ static void enable_nest(ide_drive_t *drive)
OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
timeout = jiffies + WAIT_WORSTCASE; timeout = jiffies + WAIT_WORSTCASE;
do { do {
if (jiffies > timeout) { if (time_after(jiffies, timeout)) {
printk("failed (timeout)\n"); printk("failed (timeout)\n");
return; return;
} }
...@@ -411,17 +405,21 @@ static void enable_nest(ide_drive_t *drive) ...@@ -411,17 +405,21 @@ static void enable_nest(ide_drive_t *drive)
/* /*
* Tests for existence of a given drive using do_probe(). * Tests for existence of a given drive using do_probe().
*/ */
static inline void probe_for_drive (ide_drive_t *drive) static inline void probe_for_drive(struct ata_device *drive)
{ {
if (drive->noprobe) /* skip probing? */ if (drive->noprobe) /* skip probing? */
return; return;
if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */
do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ 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")) if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T"))
enable_nest(drive); enable_nest(drive);
if (!drive->present) if (!drive->present)
return; /* drive not found */ return; /* drive not found */
if (drive->id == NULL) { /* identification failed? */ if (drive->id == NULL) { /* identification failed? */
if (drive->type == ATA_DISK) { if (drive->type == ATA_DISK) {
printk ("%s: non-IDE drive, CHS=%d/%d/%d\n", printk ("%s: non-IDE drive, CHS=%d/%d/%d\n",
...@@ -545,7 +543,7 @@ static void channel_probe(struct ata_channel *ch) ...@@ -545,7 +543,7 @@ static void channel_probe(struct ata_channel *ch)
do { do {
ide_delay_50ms(); ide_delay_50ms();
stat = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]); stat = IN_BYTE(ch->io_ports[IDE_STATUS_OFFSET]);
} while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies)); } while ((stat & BUSY_STAT) && time_before(jiffies, timeout));
} }
__restore_flags(flags); /* local CPU only */ __restore_flags(flags); /* local CPU only */
...@@ -568,34 +566,7 @@ static void channel_probe(struct ata_channel *ch) ...@@ -568,34 +566,7 @@ static void channel_probe(struct ata_channel *ch)
__restore_flags(flags); __restore_flags(flags);
} }
/*
* init request queue
*/
static void init_device_queue(struct ata_device *drive)
{
request_queue_t *q = &drive->queue;
int max_sectors = 255;
q->queuedata = drive->channel;
blk_init_queue(q, do_ide_request, &ide_lock);
blk_queue_segment_boundary(q, 0xffff);
/* IDE can do up to 128K per request, pdc4030 needs smaller limit */
#ifdef CONFIG_BLK_DEV_PDC4030
if (drive->channel->chipset == ide_pdc4030)
max_sectors = 127;
#endif
blk_queue_max_sectors(q, max_sectors);
/* IDE DMA can do PRD_ENTRIES number of segments. */
blk_queue_max_hw_segments(q, PRD_SEGMENTS);
/* This is a driver limit and could be eliminated. */
blk_queue_max_phys_segments(q, PRD_SEGMENTS);
}
#if MAX_HWIFS > 1 #if MAX_HWIFS > 1
/* /*
* This is used to simplify logic in init_irq() below. * This is used to simplify logic in init_irq() below.
* *
...@@ -607,18 +578,19 @@ static void init_device_queue(struct ata_device *drive) ...@@ -607,18 +578,19 @@ static void init_device_queue(struct ata_device *drive)
* *
* This routine detects and reports such situations, but does not fix them. * This routine detects and reports such situations, but does not fix them.
*/ */
static void save_match(struct ata_channel *hwif, struct ata_channel *new, static struct ata_channel *save_match(struct ata_channel *ch, struct ata_channel *h,
struct ata_channel **match) struct ata_channel *match)
{ {
struct ata_channel *m = *match; if (match && match->hwgroup && match->hwgroup != h->hwgroup) {
if (!h->hwgroup)
return match;
if (m && m->hwgroup && m->hwgroup != new->hwgroup) { printk("%s: potential irq problem with %s and %s\n", ch->name,h->name, match->name);
if (!new->hwgroup)
return;
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 */ if (!match || match->irq != ch->irq) /* don't undo a prior perfect match */
*match = new; match = h;
return match;
} }
#endif #endif
...@@ -643,10 +615,8 @@ static int init_irq(struct ata_channel *ch) ...@@ -643,10 +615,8 @@ static int init_irq(struct ata_channel *ch)
ide_hwgroup_t *new_hwgroup; ide_hwgroup_t *new_hwgroup;
struct ata_channel *match = NULL; struct ata_channel *match = NULL;
/* Spare allocation before sleep. */
/* Allocate the buffer and potentially sleep first */ new_hwgroup = kmalloc(sizeof(*hwgroup), GFP_KERNEL);
new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
spin_lock_irqsave(&ide_lock, flags); spin_lock_irqsave(&ide_lock, flags);
ch->hwgroup = NULL; ch->hwgroup = NULL;
...@@ -658,19 +628,22 @@ static int init_irq(struct ata_channel *ch) ...@@ -658,19 +628,22 @@ static int init_irq(struct ata_channel *ch)
for (i = 0; i < MAX_HWIFS; ++i) { for (i = 0; i < MAX_HWIFS; ++i) {
struct ata_channel *h = &ide_hwifs[i]; struct ata_channel *h = &ide_hwifs[i];
if (h->hwgroup) { /* scan only initialized channels */ /* scan only initialized channels */
if (ch->irq == h->irq) { if (!h->hwgroup)
ch->sharing_irq = h->sharing_irq = 1; continue;
if (ch->chipset != ide_pci || h->chipset != ide_pci)
save_match(ch, h, &match);
/* FIXME: This is still confusing. What would if (ch->irq != h->irq)
* happen if we match-ed two times? continue;
*/
if (ch->serialized || h->serialized) ch->sharing_irq = h->sharing_irq = 1;
save_match(ch, h, &match);
} if (ch->chipset != ide_pci || h->chipset != ide_pci ||
ch->serialized || h->serialized) {
if (match && match->hwgroup && match->hwgroup != h->hwgroup)
printk("%s: potential irq problem with %s and %s\n", ch->name, h->name, match->name);
/* don't undo a prior perfect match */
if (!match || match->irq != ch->irq)
match = h;
} }
} }
#endif #endif
...@@ -721,6 +694,8 @@ static int init_irq(struct ata_channel *ch) ...@@ -721,6 +694,8 @@ static int init_irq(struct ata_channel *ch)
ch->hwgroup = hwgroup; ch->hwgroup = hwgroup;
for (i = 0; i < MAX_DRIVES; ++i) { for (i = 0; i < MAX_DRIVES; ++i) {
struct ata_device *drive = &ch->drives[i]; struct ata_device *drive = &ch->drives[i];
request_queue_t *q;
int max_sectors = 255;
if (!drive->present) if (!drive->present)
continue; continue;
...@@ -728,7 +703,27 @@ static int init_irq(struct ata_channel *ch) ...@@ -728,7 +703,27 @@ static int init_irq(struct ata_channel *ch)
if (!hwgroup->XXX_drive) if (!hwgroup->XXX_drive)
hwgroup->XXX_drive = drive; hwgroup->XXX_drive = drive;
init_device_queue(drive); /*
* Init the per device request queue
*/
q = &drive->queue;
q->queuedata = drive->channel;
blk_init_queue(q, do_ide_request, &ide_lock);
blk_queue_segment_boundary(q, 0xffff);
/* ATA can do up to 128K per request, pdc4030 needs smaller limit */
#ifdef CONFIG_BLK_DEV_PDC4030
if (drive->channel->chipset == ide_pdc4030)
max_sectors = 127;
#endif
blk_queue_max_sectors(q, max_sectors);
/* IDE DMA can do PRD_ENTRIES number of segments. */
blk_queue_max_hw_segments(q, PRD_ENTRIES);
/* FIXME: This is a driver limit and could be eliminated. */
blk_queue_max_phys_segments(q, PRD_ENTRIES);
} }
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
...@@ -754,81 +749,11 @@ static int init_irq(struct ata_channel *ch) ...@@ -754,81 +749,11 @@ static int init_irq(struct ata_channel *ch)
return 0; return 0;
} }
/*
* init_gendisk() (as opposed to ide_geninit) is called for each major device,
* after probing for drives, to allocate partition tables and other data
* structures needed for the routines in genhd.c. ide_geninit() gets called
* somewhat later, during the partition check.
*/
static void init_gendisk(struct ata_channel *hwif)
{
struct gendisk *gd;
unsigned int unit, minors, i;
extern devfs_handle_t ide_devfs_handle;
minors = MAX_DRIVES * (1 << PARTN_BITS);
gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
if (!gd)
goto err_kmalloc_gd;
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);
if (!gd->part)
goto err_kmalloc_gd_part;
memset(gd->part, 0, minors * sizeof(struct hd_struct));
for (unit = 0; unit < MAX_DRIVES; ++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->nr_real = MAX_DRIVES; /* current num real drives */
gd->next = NULL; /* linked list of major devs */
gd->fops = ide_fops; /* file operations */
gd->de_arr = kmalloc(sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL);
gd->flags = kmalloc(sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL);
if (gd->de_arr)
memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES);
if (gd->flags)
memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES);
hwif->gd = gd;
add_gendisk(gd);
for (unit = 0; unit < MAX_DRIVES; ++unit) {
char name[80];
ide_add_generic_settings(hwif->drives + unit);
hwif->drives[unit].dn = ((hwif->unit ? 2 : 0) + unit);
sprintf (name, "host%d/bus%d/target%d/lun%d",
hwif->index, hwif->unit, unit, hwif->drives[unit].lun);
if (hwif->drives[unit].present)
hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
}
return;
err_kmalloc_bs:
kfree(gd->part);
err_kmalloc_gd_part:
kfree(gd->sizes);
err_kmalloc_gd_sizes:
kfree(gd);
err_kmalloc_gd:
printk(KERN_CRIT "(ide::init_gendisk) Out of memory\n");
return;
}
/* /*
* Returns the queue which corresponds to a given device. * Returns the queue which corresponds to a given device.
* *
* FIXME: this should take struct block_device * as argument in future. * FIXME: this should take struct block_device * as argument in future.
*/ */
static request_queue_t *ata_get_queue(kdev_t dev) static request_queue_t *ata_get_queue(kdev_t dev)
{ {
struct ata_channel *ch = (struct ata_channel *)blk_dev[major(dev)].data; struct ata_channel *ch = (struct ata_channel *)blk_dev[major(dev)].data;
...@@ -837,8 +762,15 @@ static request_queue_t *ata_get_queue(kdev_t dev) ...@@ -837,8 +762,15 @@ static request_queue_t *ata_get_queue(kdev_t dev)
return &ch->drives[DEVICE_NR(dev) & 1].queue; return &ch->drives[DEVICE_NR(dev) & 1].queue;
} }
/* Number of minor numbers we consume par channel. */
#define ATA_MINORS (MAX_DRIVES * (1 << PARTN_BITS))
static void channel_init(struct ata_channel *ch) static void channel_init(struct ata_channel *ch)
{ {
struct gendisk *gd;
unsigned int unit;
extern devfs_handle_t ide_devfs_handle;
if (!ch->present) if (!ch->present)
return; return;
...@@ -888,33 +820,96 @@ static void channel_init(struct ata_channel *ch) ...@@ -888,33 +820,96 @@ static void channel_init(struct ata_channel *ch)
printk(KERN_INFO "%s: probed IRQ %d failed, using default.\n", ch->name, ch->irq); printk(KERN_INFO "%s: probed IRQ %d failed, using default.\n", ch->name, ch->irq);
} }
init_gendisk(ch); /* Initialize partition and global device data. ide_geninit() gets
* called somewhat later, during the partition check.
*/
gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
if (!gd)
goto err_kmalloc_gd;
gd->sizes = kmalloc(ATA_MINORS * sizeof(int), GFP_KERNEL);
if (!gd->sizes)
goto err_kmalloc_gd_sizes;
gd->part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
if (!gd->part)
goto err_kmalloc_gd_part;
memset(gd->part, 0, ATA_MINORS * sizeof(struct hd_struct));
for (unit = 0; unit < MAX_DRIVES; ++unit)
ch->drives[unit].part = &gd->part[unit << PARTN_BITS];
gd->major = ch->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->nr_real = MAX_DRIVES; /* current num real drives */
gd->next = NULL; /* linked list of major devs */
gd->fops = ide_fops; /* file operations */
gd->de_arr = kmalloc(sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL);
if (gd->de_arr)
memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES);
else
goto err_kmalloc_gd_de_arr;
gd->flags = kmalloc(sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL);
if (gd->flags)
memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES);
else
goto err_kmalloc_gd_flags;
ch->gd = gd;
add_gendisk(gd);
for (unit = 0; unit < MAX_DRIVES; ++unit) {
char name[80];
ide_add_generic_settings(ch->drives + unit);
ch->drives[unit].dn = ((ch->unit ? 2 : 0) + unit);
sprintf(name, "host%d/bus%d/target%d/lun%d",
ch->index, ch->unit, unit, ch->drives[unit].lun);
if (ch->drives[unit].present)
ch->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
}
blk_dev[ch->major].data = ch; blk_dev[ch->major].data = ch;
blk_dev[ch->major].queue = ata_get_queue; blk_dev[ch->major].queue = ata_get_queue;
/* all went well, flag this channel entry as valid */ /* All went well, flag this channel entry as valid again. */
ch->present = 1; ch->present = 1;
return; return;
err_kmalloc_gd_flags:
kfree(gd->de_arr);
err_kmalloc_gd_de_arr:
kfree(gd->part);
err_kmalloc_gd_part:
kfree(gd->sizes);
err_kmalloc_gd_sizes:
kfree(gd);
err_kmalloc_gd:
printk(KERN_CRIT "(%s) Out of memory\n", __FUNCTION__);
} }
int ideprobe_init (void) int ideprobe_init (void)
{ {
unsigned int index; unsigned int i;
int probe[MAX_HWIFS]; int probe[MAX_HWIFS];
memset(probe, 0, MAX_HWIFS * sizeof(int)); for (i = 0; i < MAX_HWIFS; ++i)
for (index = 0; index < MAX_HWIFS; ++index) probe[i] = !ide_hwifs[i].present;
probe[index] = !ide_hwifs[index].present;
/* /*
* Probe for drives in the usual way.. CMOS/BIOS, then poke at ports * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports
*/ */
for (index = 0; index < MAX_HWIFS; ++index) for (i = 0; i < MAX_HWIFS; ++i)
if (probe[index]) if (probe[i])
channel_probe(&ide_hwifs[index]); channel_probe(&ide_hwifs[i]);
for (index = 0; index < MAX_HWIFS; ++index) for (i = 0; i < MAX_HWIFS; ++i)
if (probe[index]) if (probe[i])
channel_init(&ide_hwifs[index]); channel_init(&ide_hwifs[i]);
return 0; return 0;
} }
/* /**** vi:set ts=8 sts=8 sw=8:************************************************
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below) *
* Copyright (C) 1994-1998,2002 Linus Torvalds and authors:
* *
* Mostly written by Mark Lord <mlord@pobox.com> * Mark Lord <mlord@pobox.com>
* and Gadi Oxman <gadio@netvision.net.il> * Gadi Oxman <gadio@netvision.net.il>
* and Andre Hedrick <andre@linux-ide.org> * Andre Hedrick <andre@linux-ide.org>
* Jens Axboe <axboe@suse.de>
* Marcin Dalecki <martin@dalecki.de>
* *
* See linux/MAINTAINERS for address of current maintainer. * See linux/MAINTAINERS for address of current maintainer.
* *
* This is the multiple IDE interface driver, as evolved from hd.c. * This is the basic common code of the ATA interface drivers.
* It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs (usually 14 & 15). *
* There can be up to two drives per interface, as per the ATA-2 spec. * It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs (usually 14
* & 15). There can be up to two drives per interface, as per the ATA-7 spec.
* *
* Primary: ide0, port 0x1f0; major=3; hda is minor=0; hdb is minor=64 * Primary: ide0, port 0x1f0; major=3; hda is minor=0; hdb is minor=64
* Secondary: ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64 * Secondary: ide1, port 0x170; major=22; hdc is minor=0; hdd is minor=64
...@@ -17,102 +21,15 @@ ...@@ -17,102 +21,15 @@
* Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64 * Quaternary: ide3, port 0x???; major=34; hdg is minor=0; hdh is minor=64
* ... * ...
* *
* From hd.c: * Contributors:
* |
* | It traverses the request-list, using interrupts to jump between functions.
* | As nearly all functions can be called within interrupts, we may not sleep.
* | Special care is recommended. Have Fun!
* |
* | modified by Drew Eckhardt to check nr of hd's from the CMOS.
* |
* | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
* | in the early extended-partition checks and added DM partitions.
* |
* | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI).
* |
* | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
* | and general streamlining by Mark Lord (mlord@pobox.com).
*
* October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by:
* *
* Mark Lord (mlord@pobox.com) (IDE Perf.Pkg) * Drew Eckhardt
* Delman Lee (delman@ieee.org) ("Mr. atdisk2") * Branko Lankester <lankeste@fwi.uva.nl>
* Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom) * Mika Liljeberg
* Delman Lee <delman@ieee.org>
* Scott Snyder <snyder@fnald0.fnal.gov>
* *
* This was a rewrite of just about everything from hd.c, though some original * Some additional driver compile-time options are in <linux/ide.h>
* code is still sprinkled about. Think of it as a major evolution, with
* inspiration from lots of linux users, esp. hamish@zot.apana.org.au
*
* Version 1.0 ALPHA initial code, primary i/f working okay
* Version 1.3 BETA dual i/f on shared irq tested & working!
* Version 1.4 BETA added auto probing for irq(s)
* Version 1.5 BETA added ALPHA (untested) support for IDE cd-roms,
* ...
* Version 5.50 allow values as small as 20 for idebus=
* Version 5.51 force non io_32bit in drive_cmd_intr()
* change delay_10ms() to delay_50ms() to fix problems
* Version 5.52 fix incorrect invalidation of removable devices
* add "hdx=slow" command line option
* Version 5.60 start to modularize the driver; the disk and ATAPI
* drivers can be compiled as loadable modules.
* move IDE probe code to ide-probe.c
* move IDE disk code to ide-disk.c
* add support for generic IDE device subdrivers
* add m68k code from Geert Uytterhoeven
* probe all interfaces by default
* add ioctl to (re)probe an interface
* Version 6.00 use per device request queues
* attempt to optimize shared hwgroup performance
* add ioctl to manually adjust bandwidth algorithms
* add kerneld support for the probe module
* fix bug in ide_error()
* fix bug in the first ide_get_lock() call for Atari
* don't flush leftover data for ATAPI devices
* Version 6.01 clear hwgroup->active while the hwgroup sleeps
* support HDIO_GETGEO for floppies
* Version 6.02 fix ide_ack_intr() call
* check partition table on floppies
* Version 6.03 handle bad status bit sequencing in ide_wait_stat()
* Version 6.10 deleted old entries from this list of updates
* replaced triton.c with ide-dma.c generic PCI DMA
* added support for BIOS-enabled UltraDMA
* rename all "promise" things to "pdc4030"
* fix EZ-DRIVE handling on small disks
* Version 6.11 fix probe error in ide_scan_devices()
* fix ancient "jiffies" polling bugs
* mask all hwgroup interrupts on each irq entry
* Version 6.12 integrate ioctl and proc interfaces
* fix parsing of "idex=" command line parameter
* Version 6.13 add support for ide4/ide5 courtesy rjones@orchestream.com
* Version 6.14 fixed IRQ sharing among PCI devices
* Version 6.15 added SMP awareness to IDE drivers
* Version 6.16 fixed various bugs; even more SMP friendly
* Version 6.17 fix for newest EZ-Drive problem
* Version 6.18 default unpartitioned-disk translation now "BIOS LBA"
* Version 6.19 Re-design for a UNIFORM driver for all platforms,
* model based on suggestions from Russell King and
* Geert Uytterhoeven
* Promise DC4030VL now supported.
* add support for ide6/ide7
* delay_50ms() changed to ide_delay_50ms() and exported.
* Version 6.20 Added/Fixed Generic ATA-66 support and hwif detection.
* Added hdx=flash to allow for second flash disk
* detection w/o the hang loop.
* Added support for ide8/ide9
* Added idex=ata66 for the quirky chipsets that are
* ATA-66 compliant, but have yet to determine a method
* of verification of the 80c cable presence.
* Specifically Promise's PDC20262 chipset.
* Version 6.21 Fixing/Fixed SMP spinlock issue with insight from an old
* hat that clarified original low level driver design.
* Version 6.30 Added SMP support; fixed multmode issues. -ml
* Version 6.31 Debug Share INTR's and request queue streaming
* Native ATA-100 support
* Prep for Cascades Project
* Version 6.32 4GB highmem support for DMA, and mapping of those for
* PIO transfer (Jens Axboe)
*
* Some additional driver compile-time options are in ./include/linux/ide.h
*/ */
#define VERSION "7.0.0" #define VERSION "7.0.0"
...@@ -253,10 +170,7 @@ static inline void set_recovery_timer(struct ata_channel *channel) ...@@ -253,10 +170,7 @@ static inline void set_recovery_timer(struct ata_channel *channel)
#endif #endif
} }
/* static void init_hwif_data(struct ata_channel *ch, unsigned int index)
* Do not even *think* about calling this!
*/
static void init_hwif_data(struct ata_channel *hwif, unsigned int index)
{ {
static const byte ide_major[] = { static const byte ide_major[] = {
IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR,
...@@ -266,30 +180,30 @@ static void init_hwif_data(struct ata_channel *hwif, unsigned int index) ...@@ -266,30 +180,30 @@ static void init_hwif_data(struct ata_channel *hwif, unsigned int index)
unsigned int unit; unsigned int unit;
hw_regs_t hw; hw_regs_t hw;
/* bulk initialize hwif & drive info with zeros */ /* bulk initialize channel & drive info with zeros */
memset(hwif, 0, sizeof(struct ata_channel)); memset(ch, 0, sizeof(struct ata_channel));
memset(&hw, 0, sizeof(hw_regs_t)); memset(&hw, 0, sizeof(hw_regs_t));
/* fill in any non-zero initial values */ /* fill in any non-zero initial values */
hwif->index = index; ch->index = index;
ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &ch->irq);
memcpy(&hwif->hw, &hw, sizeof(hw)); memcpy(&ch->hw, &hw, sizeof(hw));
memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports)); memcpy(ch->io_ports, hw.io_ports, sizeof(hw.io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET];
#ifdef CONFIG_BLK_DEV_HD #ifdef CONFIG_BLK_DEV_HD
if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) if (ch->io_ports[IDE_DATA_OFFSET] == HD_DATA)
hwif->noprobe = 1; /* may be overridden by ide_setup() */ ch->noprobe = 1; /* may be overridden by ide_setup() */
#endif /* CONFIG_BLK_DEV_HD */ #endif /* CONFIG_BLK_DEV_HD */
hwif->major = ide_major[index]; ch->major = ide_major[index];
sprintf(hwif->name, "ide%d", index); sprintf(ch->name, "ide%d", index);
hwif->bus_state = BUSSTATE_ON; ch->bus_state = BUSSTATE_ON;
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (unit = 0; unit < MAX_DRIVES; ++unit) {
struct ata_device *drive = &hwif->drives[unit]; struct ata_device *drive = &ch->drives[unit];
drive->type = ATA_DISK; drive->type = ATA_DISK;
drive->select.all = (unit<<4)|0xa0; drive->select.all = (unit<<4)|0xa0;
drive->channel = hwif; drive->channel = ch;
drive->ctl = 0x08; drive->ctl = 0x08;
drive->ready_stat = READY_STAT; drive->ready_stat = READY_STAT;
drive->bad_wstat = BAD_W_STAT; drive->bad_wstat = BAD_W_STAT;
...@@ -1258,7 +1172,7 @@ static struct ata_device *choose_urgent_device(struct ata_channel *channel) ...@@ -1258,7 +1172,7 @@ static struct ata_device *choose_urgent_device(struct ata_channel *channel)
/* This device still wants to remain idle. /* This device still wants to remain idle.
*/ */
if (drive->sleep && time_after(jiffies, drive->sleep)) if (drive->sleep && time_after(drive->sleep, jiffies))
continue; continue;
/* Take this device, if there is no device choosen thus far or /* Take this device, if there is no device choosen thus far or
...@@ -1285,7 +1199,7 @@ static struct ata_device *choose_urgent_device(struct ata_channel *channel) ...@@ -1285,7 +1199,7 @@ static struct ata_device *choose_urgent_device(struct ata_channel *channel)
* want to hog the cpu too much. * want to hog the cpu too much.
*/ */
if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
sleep = jiffies + WAIT_MIN_SLEEP; sleep = jiffies + WAIT_MIN_SLEEP;
#if 1 #if 1
if (timer_pending(&channel->hwgroup->timer)) if (timer_pending(&channel->hwgroup->timer))
...@@ -2861,7 +2775,7 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m ...@@ -2861,7 +2775,7 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
* "hdx=flash" : allows for more than one ata_flash disk to be * "hdx=flash" : allows for more than one ata_flash disk to be
* registered. In most cases, only one device * registered. In most cases, only one device
* will be present. * will be present.
* "hdx=scsi" : the return of the ide-scsi flag, this is useful for * "hdx=ide-scsi" : the return of the ide-scsi flag, this is useful for
* allowwing ide-floppy, ide-tape, and ide-cdrom|writers * allowwing ide-floppy, ide-tape, and ide-cdrom|writers
* to use ide-scsi emulation on a device specific option. * to use ide-scsi emulation on a device specific option.
* "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz, * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz,
...@@ -2928,14 +2842,14 @@ int __init ide_setup (char *s) ...@@ -2928,14 +2842,14 @@ int __init ide_setup (char *s)
strncmp(s,"hd",2)) /* hdx= & hdxlun= */ strncmp(s,"hd",2)) /* hdx= & hdxlun= */
return 0; return 0;
printk("ide_setup: %s", s); printk(KERN_INFO "ide_setup: %s", s);
init_ide_data (); init_ide_data ();
#ifdef CONFIG_BLK_DEV_IDEDOUBLER #ifdef CONFIG_BLK_DEV_IDEDOUBLER
if (!strcmp(s, "ide=doubler")) { if (!strcmp(s, "ide=doubler")) {
extern int ide_doubler; extern int ide_doubler;
printk(" : Enabled support for IDE doublers\n"); printk(KERN_INFO" : Enabled support for IDE doublers\n");
ide_doubler = 1; ide_doubler = 1;
return 1; return 1;
...@@ -2943,7 +2857,7 @@ int __init ide_setup (char *s) ...@@ -2943,7 +2857,7 @@ int __init ide_setup (char *s)
#endif #endif
if (!strcmp(s, "ide=nodma")) { if (!strcmp(s, "ide=nodma")) {
printk("IDE: Prevented DMA\n"); printk(KERN_INFO "ATA: Prevented DMA\n");
noautodma = 1; noautodma = 1;
return 1; return 1;
...@@ -3497,7 +3411,7 @@ static int __init ata_module_init(void) ...@@ -3497,7 +3411,7 @@ static int __init ata_module_init(void)
{ {
int h; int h;
printk(KERN_INFO "Uniform Multi-Platform E-IDE driver ver.:" VERSION "\n"); printk(KERN_INFO "ATA/ATAPI driver v" VERSION "\n");
ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL); ide_devfs_handle = devfs_mk_dir (NULL, "ide", NULL);
...@@ -3519,7 +3433,7 @@ static int __init ata_module_init(void) ...@@ -3519,7 +3433,7 @@ static int __init ata_module_init(void)
system_bus_speed = 33; system_bus_speed = 33;
#endif #endif
printk("ide: system bus speed %dMHz\n", system_bus_speed); printk(KERN_INFO "ATA: system bus speed %dMHz\n", system_bus_speed);
init_ide_data (); init_ide_data ();
...@@ -3640,27 +3554,23 @@ static char *options = NULL; ...@@ -3640,27 +3554,23 @@ static char *options = NULL;
MODULE_PARM(options,"s"); MODULE_PARM(options,"s");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static void __init parse_options (char *line) static int __init init_ata(void)
{ {
char *next = line;
if (line == NULL || !*line) if (options != NULL && *options) {
return; char *next = options;
while ((line = next) != NULL) {
if ((next = strchr(line,' ')) != NULL) while ((options = next) != NULL) {
if ((next = strchr(options,' ')) != NULL)
*next++ = 0; *next++ = 0;
if (!ide_setup(line)) if (!ide_setup(options))
printk ("Unknown option '%s'\n", line); printk(KERN_ERR "Unknown option '%s'\n", options);
}
} }
}
static int __init init_ata (void)
{
parse_options(options);
return ata_module_init(); return ata_module_init();
} }
static void __exit cleanup_ata (void) static void __exit cleanup_ata(void)
{ {
int h; int h;
......
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