summaryrefslogtreecommitdiffstats
path: root/drivers/block/ide.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/ide.c')
-rw-r--r--drivers/block/ide.c118
1 files changed, 80 insertions, 38 deletions
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 5bdb1d477..873f57cc9 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide.c Version 6.21 November 9, 1999
+ * linux/drivers/block/ide.c Version 6.30 Dec 28, 1999
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
@@ -108,6 +108,7 @@
* 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
*
* Some additional driver compile-time options are in ./include/linux/ide.h
*
@@ -116,8 +117,8 @@
*
*/
-#define REVISION "Revision: 6.21"
-#define VERSION "Id: ide.c 6.21 1999/11/10"
+#define REVISION "Revision: 6.30"
+#define VERSION "Id: ide.c 6.30 1999/12/28"
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -169,6 +170,10 @@ static int idebus_parameter; /* holds the "idebus=" parameter */
static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
static int initializing; /* set while initializing built-in drivers */
+#ifdef CONFIG_BLK_DEV_IDEPCI
+static int ide_scan_direction = 0; /* HELLO, comment me!! */
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+
#if defined(__mc68000__) || defined(CONFIG_APUS)
/*
* ide_lock is used by the Atari code to obtain access to the IDE interrupt,
@@ -542,22 +547,28 @@ unsigned long current_capacity (ide_drive_t *drive)
return 0;
}
+extern struct block_device_operations ide_fops[];
/*
- * ide_geninit() is called exactly *once* for each major, from genhd.c,
- * at the beginning of the initial partition check for the drives.
+ * ide_geninit() is called exactly *once* for each interface.
*/
-void ide_geninit (struct gendisk *gd)
+void ide_geninit (ide_hwif_t *hwif)
{
unsigned int unit;
- ide_hwif_t *hwif = gd->real_devices;
+ struct gendisk *gd = hwif->gd;
- for (unit = 0; unit < gd->nr_real; ++unit) {
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- drive->part[0].nr_sects = current_capacity(drive);
- if (!drive->present || (drive->media != ide_disk && drive->media != ide_floppy) ||
- drive->driver == NULL || !drive->part[0].nr_sects)
- drive->part[0].start_sect = -1; /* skip partition check */
+ if (!drive->present)
+ continue;
+ if (drive->media!=ide_disk && drive->media!=ide_floppy)
+ continue;
+ register_disk(gd,MKDEV(hwif->major,unit<<PARTN_BITS),
+#ifdef CONFIG_BLK_DEV_ISAPNP
+ (drive->forced_geom && drive->noprobe) ? 1 :
+#endif /* CONFIG_BLK_DEV_ISAPNP */
+ 1<<PARTN_BITS, ide_fops,
+ current_capacity(drive));
}
}
@@ -669,7 +680,7 @@ static void pre_reset (ide_drive_t *drive)
* (up to 30 seconds worstcase). So, instead of busy-waiting here for it,
* we set a timer to poll at 50ms intervals.
*/
-static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
{
unsigned int unit;
unsigned long flags;
@@ -1213,7 +1224,7 @@ repeat:
* the driver. This makes the driver much more friendlier to shared IRQs
* than previous designs, while remaining 100% (?) SMP safe and capable.
*/
-static void ide_do_request (ide_hwgroup_t *hwgroup)
+static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
{
struct blk_dev_struct *bdev;
ide_drive_t *drive;
@@ -1272,14 +1283,25 @@ static void ide_do_request (ide_hwgroup_t *hwgroup)
drive->service_start = jiffies;
bdev = &blk_dev[hwif->major];
- if( bdev->request_queue.plugged ) /* FIXME: paranoia */
+ if ( bdev->request_queue.plugged ) /* FIXME: paranoia */
printk("%s: Huh? nuking plugged queue\n", drive->name);
bdev->request_queue.current_request = hwgroup->rq = drive->queue.current_request;
+ /*
+ * Some systems have trouble with IDE IRQs arriving while
+ * the driver is still setting things up. So, here we disable
+ * the IRQ used by this interface while the request is being started.
+ * This may look bad at first, but pretty much the same thing
+ * happens anyway when any interrupt comes in, IDE or otherwise
+ * -- the kernel masks the IRQ while it is being handled.
+ */
+ if (hwif->irq != masked_irq)
+ disable_irq_nosync(hwif->irq);
spin_unlock(&io_request_lock);
- if (!hwif->serialized) /* play it safe with buggy hardware */
- ide__sti();
+ ide__sti(); /* allow other IRQs while we start this request */
startstop = start_request(drive);
spin_lock_irq(&io_request_lock);
+ if (hwif->irq != masked_irq)
+ enable_irq(hwif->irq);
if (startstop == ide_stopped)
hwgroup->busy = 0;
}
@@ -1297,69 +1319,69 @@ request_queue_t *ide_get_queue (kdev_t dev)
void do_ide0_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[0].hwgroup);
+ ide_do_request (ide_hwifs[0].hwgroup, 0);
}
#if MAX_HWIFS > 1
void do_ide1_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[1].hwgroup);
+ ide_do_request (ide_hwifs[1].hwgroup, 0);
}
#endif /* MAX_HWIFS > 1 */
#if MAX_HWIFS > 2
void do_ide2_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[2].hwgroup);
+ ide_do_request (ide_hwifs[2].hwgroup, 0);
}
#endif /* MAX_HWIFS > 2 */
#if MAX_HWIFS > 3
void do_ide3_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[3].hwgroup);
+ ide_do_request (ide_hwifs[3].hwgroup, 0);
}
#endif /* MAX_HWIFS > 3 */
#if MAX_HWIFS > 4
void do_ide4_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[4].hwgroup);
+ ide_do_request (ide_hwifs[4].hwgroup, 0);
}
#endif /* MAX_HWIFS > 4 */
#if MAX_HWIFS > 5
void do_ide5_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[5].hwgroup);
+ ide_do_request (ide_hwifs[5].hwgroup, 0);
}
#endif /* MAX_HWIFS > 5 */
#if MAX_HWIFS > 6
void do_ide6_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[6].hwgroup);
+ ide_do_request (ide_hwifs[6].hwgroup, 0);
}
#endif /* MAX_HWIFS > 6 */
#if MAX_HWIFS > 7
void do_ide7_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[7].hwgroup);
+ ide_do_request (ide_hwifs[7].hwgroup, 0);
}
#endif /* MAX_HWIFS > 7 */
#if MAX_HWIFS > 8
void do_ide8_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[8].hwgroup);
+ ide_do_request (ide_hwifs[8].hwgroup, 0);
}
#endif /* MAX_HWIFS > 8 */
#if MAX_HWIFS > 9
void do_ide9_request (request_queue_t *q)
{
- ide_do_request (ide_hwifs[9].hwgroup);
+ ide_do_request (ide_hwifs[9].hwgroup, 0);
}
#endif /* MAX_HWIFS > 9 */
@@ -1445,7 +1467,7 @@ void ide_timer_expiry (unsigned long data)
hwgroup->busy = 0;
}
}
- ide_do_request(hwgroup);
+ ide_do_request(hwgroup, 0);
spin_unlock_irqrestore(&io_request_lock, flags);
}
@@ -1593,7 +1615,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
if (startstop == ide_stopped) {
if (hwgroup->handler == NULL) { /* paranoia */
hwgroup->busy = 0;
- ide_do_request(hwgroup);
+ ide_do_request(hwgroup, hwif->irq);
} else {
printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name);
}
@@ -1608,6 +1630,9 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
ide_drive_t *get_info_ptr (kdev_t i_rdev)
{
int major = MAJOR(i_rdev);
+#if 0
+ int minor = MINOR(i_rdev) & PARTN_MASK;
+#endif
unsigned int h;
for (h = 0; h < MAX_HWIFS; ++h) {
@@ -1616,7 +1641,11 @@ ide_drive_t *get_info_ptr (kdev_t i_rdev)
unsigned unit = DEVICE_NR(i_rdev);
if (unit < MAX_DRIVES) {
ide_drive_t *drive = &hwif->drives[unit];
+#if 0
+ if ((drive->present) && (drive->part[minor].nr_sects))
+#else
if (drive->present)
+#endif
return drive;
}
break;
@@ -1698,7 +1727,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
rq->next = cur_rq->next;
cur_rq->next = rq;
}
- ide_do_request(hwgroup);
+ ide_do_request(hwgroup, 0);
spin_unlock_irqrestore(&io_request_lock, flags);
if (action == ide_wait) {
down(&sem); /* wait for it to be serviced */
@@ -1751,11 +1780,10 @@ int ide_revalidate_disk (kdev_t i_rdev)
drive->part[p].nr_sects = 0;
};
- drive->part[0].nr_sects = current_capacity(drive);
- if ((drive->media != ide_disk && drive->media != ide_floppy) ||
- drive->driver == NULL || !drive->part[0].nr_sects)
- drive->part[0].start_sect = -1;
- resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
+ grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
+ (drive->media != ide_disk &&
+ drive->media != ide_floppy) ? 1 : 1<<PARTN_BITS,
+ current_capacity(drive));
drive->busy = 0;
wake_up(&drive->wqueue);
@@ -1846,7 +1874,6 @@ static int ide_release (struct inode * inode, struct file * file)
ide_drive_t *drive;
if ((drive = get_info_ptr(inode->i_rdev)) != NULL) {
- fsync_dev(inode->i_rdev);
drive->usage--;
if (drive->driver != NULL)
DRIVER(drive)->release(inode, file, drive);
@@ -2678,6 +2705,7 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
* for chipsets that are ATA-66 capable, but
* the ablity to bit test for detection is
* currently unknown.
+ * "ide=reverse" : Formerly called to pci sub-system, but now local.
*
* "splitfifo=betweenChan"
* : FIFO Configuration of VIA 82c586(<nothing>,"A"or"B").
@@ -2728,6 +2756,14 @@ int __init ide_setup (char *s)
}
#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+#ifdef CONFIG_BLK_DEV_IDEPCI
+ if (!strcmp(s, "ide=reverse")) {
+ ide_scan_direction = 1;
+ printk("ide: Enabled support for IDE inverse scan order.\n");
+ return 0;
+ }
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+
init_ide_data ();
/*
@@ -3061,7 +3097,7 @@ static void __init probe_for_hwifs (void)
if (pci_present())
{
#ifdef CONFIG_BLK_DEV_IDEPCI
- ide_scan_pcibus();
+ ide_scan_pcibus(ide_scan_direction);
#else
#ifdef CONFIG_BLK_DEV_RZ1000
{
@@ -3367,7 +3403,6 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup);
EXPORT_SYMBOL(drive_is_flashcard);
EXPORT_SYMBOL(ide_timer_expiry);
EXPORT_SYMBOL(ide_intr);
-EXPORT_SYMBOL(ide_geninit);
EXPORT_SYMBOL(ide_fops);
EXPORT_SYMBOL(ide_get_queue);
EXPORT_SYMBOL(do_ide0_request);
@@ -3449,6 +3484,7 @@ EXPORT_SYMBOL(current_capacity);
int __init ide_init (void)
{
static char banner_printed = 0;
+ int i;
if (!banner_printed) {
printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
@@ -3461,6 +3497,12 @@ int __init ide_init (void)
ide_init_builtin_drivers();
initializing = 0;
+ for (i = 0; i < MAX_HWIFS; ++i) {
+ ide_hwif_t *hwif = &ide_hwifs[i];
+ if (hwif->present)
+ ide_geninit(hwif);
+ }
+
return 0;
}