patch-2.1.15 linux/drivers/block/ide.c
Next file: linux/drivers/block/ide.h
Previous file: linux/drivers/block/ide-tape.c
Back to the patch index
Back to the overall index
- Lines: 729
- Date:
Wed Dec 11 16:45:55 1996
- Orig file:
v2.1.14/linux/drivers/block/ide.c
- Orig date:
Sun Nov 10 20:12:09 1996
diff -u --recursive --new-file v2.1.14/linux/drivers/block/ide.c linux/drivers/block/ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide.c Version 5.60 Nov 5, 1996
+ * linux/drivers/block/ide.c Version 6.00 Dec 4, 1996
*
* Copyright (C) 1994-1996 Linus Torvalds & authors (see below)
*/
@@ -269,6 +269,13 @@
* 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
*
* Some additional driver compile-time options are in ide.h
*
@@ -294,6 +301,8 @@
#include <linux/hdreg.h>
#include <linux/genhd.h>
#include <linux/malloc.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
@@ -301,11 +310,6 @@
#include <asm/io.h>
#include <asm/bitops.h>
-#ifdef CONFIG_PCI
-#include <linux/bios32.h>
-#include <linux/pci.h>
-#endif /* CONFIG_PCI */
-
#include "ide.h"
#include "ide_modes.h"
@@ -354,18 +358,14 @@
restore_flags(flags);
return (t - i);
}
+#endif /* DISK_RECOVERY_TIME */
-static void set_recovery_timer (ide_hwif_t *hwif)
+static inline void set_recovery_timer (ide_hwif_t *hwif)
{
+#if (DISK_RECOVERY_TIME > 0)
hwif->last_time = read_timer();
-}
-#define SET_RECOVERY_TIMER(drive) set_recovery_timer (drive)
-
-#else
-
-#define SET_RECOVERY_TIMER(drive)
-
#endif /* DISK_RECOVERY_TIME */
+}
/*
* Do not even *think* about calling this!
@@ -820,7 +820,8 @@
}
save_flags(flags);
cli();
- blk_dev[MAJOR(rq->rq_dev)].current_request = rq->next;
+ drive->queue = rq->next;
+ blk_dev[MAJOR(rq->rq_dev)].current_request = NULL;
HWGROUP(drive)->rq = NULL;
rq->rq_status = RQ_INACTIVE;
if (rq->sem != NULL)
@@ -840,21 +841,19 @@
ide_sti();
printk("%s: %s: status=0x%02x", drive->name, msg, stat);
#if FANCY_STATUS_DUMPS
- if (drive->media == ide_disk) {
- printk(" { ");
- if (stat & BUSY_STAT)
- printk("Busy ");
- else {
- if (stat & READY_STAT) printk("DriveReady ");
- if (stat & WRERR_STAT) printk("DeviceFault ");
- if (stat & SEEK_STAT) printk("SeekComplete ");
- if (stat & DRQ_STAT) printk("DataRequest ");
- if (stat & ECC_STAT) printk("CorrectedError ");
- if (stat & INDEX_STAT) printk("Index ");
- if (stat & ERR_STAT) printk("Error ");
- }
- printk("}");
+ printk(" { ");
+ if (stat & BUSY_STAT)
+ printk("Busy ");
+ else {
+ if (stat & READY_STAT) printk("DriveReady ");
+ if (stat & WRERR_STAT) printk("DeviceFault ");
+ if (stat & SEEK_STAT) printk("SeekComplete ");
+ if (stat & DRQ_STAT) printk("DataRequest ");
+ if (stat & ECC_STAT) printk("CorrectedError ");
+ if (stat & INDEX_STAT) printk("Index ");
+ if (stat & ERR_STAT) printk("Error ");
}
+ printk("}");
#endif /* FANCY_STATUS_DUMPS */
printk("\n");
if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
@@ -907,6 +906,8 @@
{
int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS;
+ if (drive->media != ide_disk)
+ return;
while (i > 0) {
unsigned long buffer[16];
unsigned int wcount = (i > 16) ? 16 : i;
@@ -951,7 +952,8 @@
if (rq->errors >= ERROR_MAX) {
if (drive->driver != NULL)
DRIVER(drive)->end_request(0, HWGROUP(drive));
- ide_end_request(0, HWGROUP(drive));
+ else
+ ide_end_request(0, HWGROUP(drive));
} else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
@@ -1093,24 +1095,20 @@
/*
* do_request() initiates handling of a new I/O request
*/
-static inline void do_request (ide_hwif_t *hwif, struct request *rq)
+static inline void do_request (ide_hwgroup_t *hwgroup, ide_hwif_t *hwif, ide_drive_t *drive)
{
- unsigned int minor, unit;
unsigned long block, blockend;
- ide_drive_t *drive = NULL;
+ struct request *rq = drive->queue;
+ unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS;
ide_sti();
#ifdef DEBUG
printk("%s: do_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
#endif
- minor = MINOR(rq->rq_dev);
- unit = minor >> PARTN_BITS;
- if (MAJOR(rq->rq_dev) != hwif->major || unit >= MAX_DRIVES) {
- printk("%s: bad device number: %s\n",
- hwif->name, kdevname(rq->rq_dev));
+ if (unit >= MAX_DRIVES) {
+ printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
goto kill_rq;
}
- drive = &hwif->drives[unit];
#ifdef DEBUG
if (rq->bh && !buffer_locked(rq->bh)) {
printk("%s: block not locked\n", drive->name);
@@ -1129,17 +1127,18 @@
if (block == 0 && drive->remap_0_to_1)
block = 1; /* redirect MBR access to EZ-Drive partn table */
#endif /* FAKE_FDISK_FOR_EZDRIVE */
- ((ide_hwgroup_t *)hwif->hwgroup)->drive = drive;
#if (DISK_RECOVERY_TIME > 0)
while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
#endif
- SELECT_DRIVE(hwif,drive);
+ hwgroup->hwif = hwif;
+ hwgroup->drive = drive;
+ SELECT_DRIVE(hwif, drive);
if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
printk("%s: drive not ready for command\n", drive->name);
return;
}
-
+
if (!drive->special.all) {
if (rq->cmd == IDE_DRIVE_CMD) {
execute_drive_cmd(drive, rq);
@@ -1155,10 +1154,96 @@
do_special(drive);
return;
kill_rq:
- if (drive != NULL && drive->driver != NULL)
+ if (drive->driver != NULL)
DRIVER(drive)->end_request(0, HWGROUP(drive));
else
- ide_end_request(0, hwif->hwgroup);
+ ide_end_request(0, hwgroup);
+}
+
+/*
+ * ide_stall_queue() can be used by a drive to give excess bandwidth back
+ * to the hwgroup by sleeping for timeout jiffies.
+ */
+void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
+{
+ if (timeout > WAIT_WORSTCASE)
+ timeout = WAIT_WORSTCASE;
+ drive->sleep = timeout + jiffies;
+}
+
+#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time)
+
+/*
+ * choose_drive() selects the next drive which will be serviced.
+ */
+static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
+{
+ ide_drive_t *drive, *best;
+
+repeat:
+ best = NULL;
+ drive = hwgroup->drive;
+ do {
+ if (!drive->queue)
+ continue;
+ if (drive->sleep && drive->sleep > jiffies)
+ continue;
+ if (!best) {
+ best = drive;
+ continue;
+ }
+ if (drive->sleep && (!best->sleep || drive->sleep < best->sleep))
+ best = drive;
+ if (!best->sleep && WAKEUP(drive) < WAKEUP(best))
+ best = drive;
+ } while ((drive = drive->next) != hwgroup->drive);
+ if (best != hwgroup->drive && best && best->service_time > WAIT_MIN_SLEEP && !best->sleep && best->nice1) {
+ long t = (signed) (WAKEUP(best) - jiffies);
+ if (t >= WAIT_MIN_SLEEP) {
+ /*
+ * We *may* have some time to spare, but first let's see if
+ * someone can potentially benefit from our nice mood today..
+ */
+ drive = best->next;
+ do {
+ if (drive->sleep) /* this drive tried to be nice to us */
+ continue;
+ if (WAKEUP(drive) > jiffies - best->service_time && WAKEUP(drive) < jiffies + t) {
+ ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP));
+ goto repeat;
+ }
+ } while ((drive = drive->next) != best);
+ }
+ }
+ return best;
+}
+
+static inline void ide_leave_hwgroup (ide_hwgroup_t *hwgroup)
+{
+ ide_drive_t *drive = hwgroup->drive;
+ unsigned long sleep = 0;
+
+ hwgroup->rq = NULL;
+ do {
+ blk_dev[HWIF(drive)->major].current_request = NULL;
+ if (!drive->sleep)
+ continue;
+ if (!sleep) {
+ sleep = drive->sleep;
+ continue;
+ }
+ if (drive->sleep < sleep)
+ sleep = drive->sleep;
+ } while ((drive = drive->next) != hwgroup->drive);
+ if (sleep) {
+ if (sleep < jiffies + WAIT_MIN_SLEEP)
+ sleep = jiffies + WAIT_MIN_SLEEP;
+ hwgroup->timer.expires = sleep;
+ add_timer(&hwgroup->timer);
+ } else { /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
+ ide_release_lock(&ide_lock);
+ hwgroup->active = 0;
+ }
}
/*
@@ -1184,32 +1269,35 @@
return;
}
do {
- ide_hwif_t *hwif = hwgroup->hwif;
- struct request *rq;
- if ((rq = hwgroup->rq) == NULL) {
- if (hwif->sharing_irq && hwgroup->drive) /* set nIEN */
- OUT_BYTE(hwgroup->drive->ctl|2,hwif->io_ports[IDE_CONTROL_OFFSET]);
- /*
- * hwgroup->next_hwif is different from hwgroup->hwif
- * only when a request is inserted using "ide_next".
- * This saves wear and tear on IDE tapes.
- */
- hwif = hwgroup->next_hwif;
- do {
- rq = blk_dev[hwif->major].current_request;
- if (rq != NULL && rq->rq_status != RQ_INACTIVE)
- goto got_rq;
- } while ((hwif = hwif->next) != hwgroup->next_hwif);
- ide_release_lock(&ide_lock);
- return; /* no work left for this hwgroup */
+ ide_drive_t *drive = choose_drive(hwgroup);
+ if (drive != NULL) {
+ ide_hwif_t *hwif = HWIF(drive);
+ if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif)
+ OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
+ drive->sleep = 0;
+ blk_dev[hwif->major].current_request = hwgroup->rq = drive->queue;
+ drive->service_start = jiffies;
+ do_request(hwgroup, hwif, drive);
+ cli();
+ } else {
+ ide_leave_hwgroup(hwgroup); /* no work left for this hwgroup */
+ return;
}
- got_rq:
- do_request(hwgroup->hwif = hwgroup->next_hwif = hwif, hwgroup->rq = rq);
- cli();
} while (hwgroup->handler == NULL);
}
/*
+ * ide_get_queue() returns the queue which corresponds to a given device.
+ */
+struct request **ide_get_queue (kdev_t dev)
+{
+ struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
+ ide_hwif_t *hwif = bdev->data;
+
+ return &hwif->drives[DEVICE_NR(dev) & 1].queue;
+}
+
+/*
* do_hwgroup_request() invokes ide_do_request() after first masking
* all possible interrupts for the current hwgroup. This prevents race
* conditions in the event that an unexpected interrupt occurs while
@@ -1226,7 +1314,9 @@
ide_hwif_t *hgif = hwgroup->hwif;
ide_hwif_t *hwif = hgif;
+ del_timer(&hwgroup->timer);
ide_get_lock(&ide_lock, ide_intr, hwgroup);
+ hwgroup->active = 1;
do {
disable_irq(hwif->irq);
} while ((hwif = hwif->next) != hgif);
@@ -1267,25 +1357,28 @@
{
ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
ide_drive_t *drive = hwgroup->drive;
+ ide_handler_t *handler;
unsigned long flags;
save_flags(flags);
cli();
- if (hwgroup->poll_timeout != 0) { /* polling in progress? */
- ide_handler_t *handler = hwgroup->handler;
+ if ((handler = hwgroup->handler) != NULL) {
hwgroup->handler = NULL;
- handler(drive);
- } else if (hwgroup->handler == NULL) { /* not waiting for anything? */
- ide_sti(); /* drive must have responded just as the timer expired */
- printk("%s: marginal timeout\n", drive->name);
- } else {
- hwgroup->handler = NULL; /* abort the operation */
- if (hwgroup->hwif->dmaproc)
- (void) hwgroup->hwif->dmaproc (ide_dma_abort, drive);
- ide_error(drive, "irq timeout", GET_STAT());
- }
- if (hwgroup->handler == NULL)
+ if (hwgroup->poll_timeout != 0) /* polling in progress? */
+ handler(drive);
+ else { /* abort the operation */
+ if (hwgroup->hwif->dmaproc)
+ (void) hwgroup->hwif->dmaproc (ide_dma_abort, drive);
+ ide_error(drive, "irq timeout", GET_STAT());
+ }
+ cli();
+ if (hwgroup->handler == NULL) {
+ set_recovery_timer(HWIF(drive));
+ drive->service_time = jiffies - drive->service_start;
+ do_hwgroup_request (hwgroup);
+ }
+ } else
do_hwgroup_request (hwgroup);
restore_flags(flags);
}
@@ -1368,7 +1461,8 @@
handler(drive);
cli(); /* this is necessary, as next rq may be different irq */
if (hwgroup->handler == NULL) {
- SET_RECOVERY_TIMER(HWIF(drive));
+ set_recovery_timer(HWIF(drive));
+ drive->service_time = jiffies - drive->service_start;
ide_do_request(hwgroup);
}
} else {
@@ -1394,9 +1488,6 @@
ide_drive_t *drive = &hwif->drives[unit];
if (drive->present)
return drive;
- } else if (major == IDE0_MAJOR && unit < 4) {
- printk("ide: probable bad entry for /dev/hd%c\n", 'a'+unit);
- printk("ide: to fix it, run: /usr/src/linux/scripts/MAKEDEV.ide\n");
}
break;
}
@@ -1443,15 +1534,14 @@
* If action is ide_end, then the rq is queued at the end of the
* request queue, and the function returns immediately without waiting
* for the new rq to be completed. This is again intended for careful
- * use by the ATAPI tape/cdrom driver code. (Currently used by ide-tape.c,
- * when operating in the pipelined operation mode).
+ * use by the ATAPI tape/cdrom driver code.
*/
int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action)
{
unsigned long flags;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned int major = HWIF(drive)->major;
struct request *cur_rq;
- struct blk_dev_struct *bdev = &blk_dev[major];
struct semaphore sem = MUTEX_LOCKED;
if (IS_PROMISE_DRIVE && rq->buffer != NULL)
@@ -1461,24 +1551,16 @@
rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS);
if (action == ide_wait)
rq->sem = &sem;
- unplug_device(bdev);
save_flags(flags);
cli();
- if (action == ide_next)
- HWGROUP(drive)->next_hwif = HWIF(drive);
- cur_rq = bdev->current_request;
+ cur_rq = drive->queue;
if (cur_rq == NULL || action == ide_preempt) {
rq->next = cur_rq;
- bdev->current_request = rq;
- if (action == ide_preempt) {
- HWGROUP(drive)->rq = NULL;
- } else
- if (HWGROUP(drive)->rq == NULL) { /* is this necessary (?) */
- bdev->request_fn();
- cli();
- }
+ drive->queue = rq;
+ if (action == ide_preempt)
+ hwgroup->rq = NULL;
} else {
if (action == ide_wait || action == ide_end) {
while (cur_rq->next != NULL) /* find end of list */
@@ -1487,6 +1569,10 @@
rq->next = cur_rq->next;
cur_rq->next = rq;
}
+ if (!hwgroup->active) {
+ do_hwgroup_request(hwgroup);
+ cli();
+ }
if (action == ide_wait && rq->rq_status != RQ_INACTIVE)
down(&sem); /* wait for it to be serviced */
restore_flags(flags);
@@ -1564,14 +1650,21 @@
static void ide_init_module (int type)
{
+ int found = 0;
ide_module_t *module = ide_modules;
while (module) {
- if (module->type == type)
+ if (module->type == type) {
+ found = 1;
(void) module->init();
+ }
module = module->next;
}
revalidate_drives();
+#ifdef CONFIG_KERNELD
+ if (!found && type == IDE_PROBE_MODULE)
+ (void) request_module("ide-probe");
+#endif /* CONFIG_KERNELD */
}
static int ide_open(struct inode * inode, struct file * filp)
@@ -1630,7 +1723,7 @@
void ide_unregister (unsigned int index)
{
struct gendisk *gd, **gdp;
- ide_drive_t *drive;
+ ide_drive_t *drive, *d;
ide_hwif_t *hwif, *g;
ide_hwgroup_t *hwgroup;
int irq_count = 0, unit;
@@ -1651,11 +1744,6 @@
goto abort;
if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
goto abort;
- if (drive->id != NULL) {
- kfree(drive->id);
- drive->id = NULL;
- }
- drive->present = 0;
}
hwif->present = 0;
hwgroup = hwif->hwgroup;
@@ -1684,15 +1772,31 @@
* Remove us from the hwgroup, and free
* the hwgroup if we were the only member
*/
+ d = hwgroup->drive;
+ for (index = 0; index < MAX_DRIVES; ++index) {
+ drive = &hwif->drives[index];
+ if (!drive->present)
+ continue;
+ while (hwgroup->drive->next != drive)
+ hwgroup->drive = hwgroup->drive->next;
+ hwgroup->drive->next = drive->next;
+ if (hwgroup->drive == drive)
+ hwgroup->drive = NULL;
+ if (drive->id != NULL) {
+ kfree(drive->id);
+ drive->id = NULL;
+ }
+ drive->present = 0;
+ }
+ if (d->present)
+ hwgroup->drive = d;
while (hwgroup->hwif->next != hwif)
hwgroup->hwif = hwgroup->hwif->next;
hwgroup->hwif->next = hwif->next;
if (hwgroup->hwif == hwif)
- hwgroup->hwif = hwif->next;
- if (hwgroup->next_hwif == hwif)
- hwgroup->next_hwif = hwif->next;
- if (hwgroup->hwif == hwif)
kfree(hwgroup);
+ else
+ hwgroup->hwif = HWIF(hwgroup->drive);
/*
* Remove us from the kernel's knowledge
@@ -1700,6 +1804,8 @@
unregister_blkdev(hwif->major, hwif->name);
kfree(blksize_size[hwif->major]);
blk_dev[hwif->major].request_fn = NULL;
+ blk_dev[hwif->major].data = NULL;
+ blk_dev[hwif->major].queue = NULL;
blksize_size[hwif->major] = NULL;
for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
if (*gdp == hwif->gd)
@@ -1731,13 +1837,8 @@
}
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
- if (!hwif->present) {
- ide_init_hwif_ports(hwif->io_ports, data_port, &hwif->irq);
- if (ctl_port)
- hwif->io_ports[IDE_CONTROL_OFFSET] = ctl_port;
- hwif->irq = irq;
+ if (!hwif->present)
goto found;
- }
}
for (index = 0; index < MAX_HWIFS; index++)
ide_unregister(index);
@@ -1748,6 +1849,10 @@
ide_unregister(index);
if (hwif->present)
return -1;
+ ide_init_hwif_ports(hwif->io_ports, data_port, &hwif->irq);
+ if (ctl_port)
+ hwif->io_ports[IDE_CONTROL_OFFSET] = ctl_port;
+ hwif->irq = irq;
hwif->noprobe = 0;
ide_init_module(IDE_PROBE_MODULE);
ide_init_module(IDE_DRIVER_MODULE);
@@ -1828,6 +1933,18 @@
case HDIO_GET_NOWERR:
return put_user(drive->bad_wstat == BAD_R_STAT, (long *) arg);
+ case HDIO_GET_NICE:
+ {
+ long nice = 0;
+
+ nice |= drive->dsc_overlap << IDE_NICE_DSC_OVERLAP;
+ nice |= drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP;
+ nice |= drive->nice0 << IDE_NICE_0;
+ nice |= drive->nice1 << IDE_NICE_1;
+ nice |= drive->nice2 << IDE_NICE_2;
+ return put_user(nice, (long *) arg);
+ }
+
case HDIO_SET_DMA:
if (!suser()) return -EACCES;
if (drive->driver != NULL && !DRIVER(drive)->supports_dma)
@@ -1955,6 +2072,19 @@
return -EIO;
return 0;
}
+ case HDIO_SET_NICE:
+ if (!suser()) return -EACCES;
+ if (drive->driver == NULL)
+ return -EPERM;
+ if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
+ return -EPERM;
+ drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
+ if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) {
+ drive->dsc_overlap = 0;
+ return -EPERM;
+ }
+ drive->nice1 = (arg >> IDE_NICE_1) & 1;
+ return 0;
RO_IOCTLS(inode->i_rdev, arg);
@@ -2058,7 +2188,7 @@
}
if (++n == max_vals)
break;
- if (*s == ',')
+ if (*s == ',' || *s == ';')
++s;
}
if (!*s)
@@ -2439,10 +2569,10 @@
#endif /* CONFIG_PCI */
/*
- * ide_init_pci() finds/initializes "known" PCI IDE interfaces
+ * probe_for_hwifs() finds/initializes "known" IDE interfaces
*
- * This routine should ideally be using pcibios_find_class() to find
- * all IDE interfaces, but that function causes some systems to "go weird".
+ * This routine should ideally be using pcibios_find_class() to find all
+ * PCI IDE interfaces, but that function causes some systems to "go weird".
*/
static void probe_for_hwifs (void)
{
@@ -2489,10 +2619,13 @@
*/
probe_for_hwifs ();
+ /*
+ * Probe for devices
+ */
#ifdef CONFIG_BLK_DEV_IDE
#ifdef __mc68000__
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
- ide_get_lock(&ide_lock, ide_intr, NULL);
+ ide_get_lock(&ide_lock, NULL, NULL);
disable_irq(ide_hwifs[0].irq);
}
#endif /* __mc68000__ */
@@ -2507,6 +2640,9 @@
#endif /* __mc68000__ */
#endif /* CONFIG_BLK_DEV_IDE */
+ /*
+ * Attempt to match drivers for the available drives
+ */
#ifdef CONFIG_BLK_DEV_IDEDISK
(void) idedisk_init();
#endif /* CONFIG_BLK_DEV_IDEDISK */
@@ -2519,6 +2655,9 @@
#ifdef CONFIG_BLK_DEV_IDEFLOPPY
(void) idefloppy_init();
#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+#ifdef CONFIG_BLK_DEV_IDESCSI
+ (void) idescsi_init();
+#endif /* CONFIG_BLK_DEV_IDESCSI */
}
static int default_cleanup (ide_drive_t *drive)
@@ -2595,6 +2734,10 @@
unsigned int unit, index, i;
ide_drive_t *drive;
+ for (index = 0; index < MAX_HWIFS; ++index)
+ if (ide_hwifs[index].present) goto search;
+ ide_init_module(IDE_PROBE_MODULE);
+search:
for (index = 0, i = 0; index < MAX_HWIFS; ++index) {
for (unit = 0; unit < MAX_DRIVES; ++unit) {
drive = &ide_hwifs[index].drives[unit];
@@ -2613,15 +2756,19 @@
save_flags(flags);
cli();
if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL ||
- drive->busy || drive->usage || drive->media != driver->media) {
+ drive->busy || drive->usage) {
restore_flags(flags);
return 1;
}
drive->driver = driver;
setup_driver_defaults(drive);
restore_flags(flags);
- if (driver->supports_dma && !drive->using_dma && drive->autotune != 2 && HWIF(drive)->dmaproc != NULL)
- (void) (HWIF(drive)->dmaproc(ide_dma_check, drive));
+ if (drive->autotune != 2) {
+ if (driver->supports_dma && HWIF(drive)->dmaproc != NULL)
+ (void) (HWIF(drive)->dmaproc(ide_dma_check, drive));
+ drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap);
+ drive->nice1 = 1;
+ }
drive->revalidate = 1;
return 0;
}
@@ -2691,6 +2838,7 @@
*/
X(ide_timer_expiry), X(ide_intr),
X(ide_geninit), X(ide_fops),
+ X(ide_get_queue),
X(do_ide0_request),
#if MAX_HWIFS > 1
X(do_ide1_request),
@@ -2714,7 +2862,7 @@
X(ide_do_reset), X(ide_init_drive_cmd),
X(ide_do_drive_cmd), X(ide_end_drive_cmd),
X(ide_end_request), X(ide_revalidate_disk),
- X(ide_cmd),
+ X(ide_cmd), X(ide_stall_queue),
X(ide_register), X(ide_unregister),
#include <linux/symtab_end.h>
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov