patch-2.0.11 linux/drivers/block/ide.c
Next file: linux/drivers/block/ide.h
Previous file: linux/drivers/block/ide-cd.c
Back to the patch index
Back to the overall index
- Lines: 355
- Date:
Mon Aug 5 08:19:52 1996
- Orig file:
v2.0.10/linux/drivers/block/ide.c
- Orig date:
Thu Aug 1 15:53:34 1996
diff -u --recursive --new-file v2.0.10/linux/drivers/block/ide.c linux/drivers/block/ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide.c Version 5.46 Jul 23, 1996
+ * linux/drivers/block/ide.c Version 5.49 Aug 4, 1996
*
* Copyright (C) 1994-1996 Linus Torvalds & authors (see below)
*/
@@ -246,6 +246,16 @@
* include mc68000 patches from Geert Uytterhoeven
* add Gadi's fix for PCMCIA cdroms
* Version 5.46 remove the mc68000 #ifdefs for 2.0.x
+ * Version 5.47 fix set_tune race condition
+ * fix bug in earlier PCMCIA cdrom update
+ * Version 5.48 if def'd, invoke CMD640_DUMP_REGS when irq probe fails
+ * lengthen the do_reset1() pulse, for laptops
+ * add idebus=xx parameter for cmd640 and ali chipsets
+ * no_unmask flag now per-drive instead of per-hwif
+ * fix tune_req so that it gets done immediately
+ * fix missing restore_flags() in ide_ioctl
+ * prevent use of io_32bit on cmd640 with no prefetch
+ * Version 5.49 fix minor quirks in probing routines
*
* Some additional driver compile-time options are in ide.h
*
@@ -294,6 +304,13 @@
static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10};
+static int idebus_parameter; /* holds the "idebus=" parameter */
+static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
+
+/*
+ * This is declared extern in ide.h, for access by other IDE modules:
+ */
+ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
#if (DISK_RECOVERY_TIME > 0)
/*
@@ -402,6 +419,32 @@
for (index = 0; index < MAX_HWIFS; ++index)
init_hwif_data(index);
+
+ idebus_parameter = 0;
+ system_bus_speed = 0;
+}
+
+/*
+ * ide_system_bus_speed() returns what we think is the system VESA/PCI
+ * bus speed (in Mhz). This is used for calculating interface PIO timings.
+ * The default is 40 for known PCI systems, 50 otherwise.
+ * The "idebus=xx" parameter can be used to override this value.
+ * The actual value to be used is computed/displayed the first time through.
+ */
+int ide_system_bus_speed (void)
+{
+ if (!system_bus_speed) {
+ if (idebus_parameter)
+ system_bus_speed = idebus_parameter; /* user supplied value */
+#ifdef CONFIG_PCI
+ else if (pcibios_present())
+ system_bus_speed = 40; /* safe default value for PCI */
+#endif /* CONFIG_PCI */
+ else
+ system_bus_speed = 50; /* safe default value for VESA and PCI */
+ printk("ide: Assuming %dMhz system bus speed for PIO modes; override with idebus=xx\n", system_bus_speed);
+ }
+ return system_bus_speed;
}
#if SUPPORT_VLB_SYNC
@@ -770,9 +813,9 @@
* recover from reset very quickly, saving us the first 50ms wait time.
*/
OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG); /* set SRST and nIEN */
- udelay(5); /* more than enough time */
+ udelay(10); /* more than enough time */
OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */
- udelay(5); /* more than enough time */
+ udelay(10); /* more than enough time */
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler (drive, &reset_pollfunc, HZ/20);
#endif /* OK_TO_RESET_CONTROLLER */
@@ -1183,7 +1226,7 @@
static inline void do_special (ide_drive_t *drive)
{
special_t *s = &drive->special;
-next:
+
#ifdef DEBUG
printk("%s: do_special: 0x%02x\n", drive->name, s->all);
#endif
@@ -1201,12 +1244,11 @@
s->b.recalibrate = 0;
if (drive->media == ide_disk && !IS_PROMISE_DRIVE)
ide_cmd(drive, WIN_RESTORE, drive->sect, &recal_intr);
- } else if (s->b.set_pio) {
+ } else if (s->b.set_tune) {
ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
- s->b.set_pio = 0;
+ s->b.set_tune = 0;
if (tuneproc != NULL)
- tuneproc(drive, drive->pio_req);
- goto next;
+ tuneproc(drive, drive->tune_req);
} else if (s->b.set_multmode) {
s->b.set_multmode = 0;
if (drive->media == ide_disk) {
@@ -1639,6 +1681,7 @@
if (!drive->present)
continue;
SELECT_DRIVE(hwif,drive);
+ udelay(100); /* Ugly, but wait_stat() may not be safe here */
if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT)) {
/* Try to not flood the console with msgs */
static unsigned long last_msgtime = 0;
@@ -1653,6 +1696,7 @@
}
} while ((hwif = hwif->next) != hwgroup->hwif);
SELECT_DRIVE(hwif,hwgroup->drive); /* Ugh.. probably interrupts current I/O */
+ udelay(100); /* Ugly, but wait_stat() may not be safe here */
}
/*
@@ -1917,10 +1961,6 @@
if (drive->media != ide_disk)
drive->part[0].start_sect = -1;
resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
-#ifdef CONFIG_BLK_DEV_IDECD
- if (drive->media == ide_cdrom)
- ide_cdrom_setup(drive);
-#endif /* CONFIG_BLK_DEV_IDECD */
drive->busy = 0;
wake_up(&drive->wqueue);
@@ -2046,7 +2086,7 @@
drive->keep_settings = arg;
break;
case HDIO_SET_UNMASKINTR:
- if (arg && HWIF(drive)->no_unmask) {
+ if (arg && drive->no_unmask) {
restore_flags(flags);
return -EPERM;
}
@@ -2056,8 +2096,14 @@
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
break;
case HDIO_SET_32BIT:
- if (arg > (1 + (SUPPORT_VLB_SYNC<<1)))
+ if (arg > (1 + (SUPPORT_VLB_SYNC<<1))) {
+ restore_flags(flags);
return -EINVAL;
+ }
+ if (arg && drive->no_io_32bit) {
+ restore_flags(flags);
+ return -EPERM;
+ }
drive->io_32bit = arg;
#ifdef CONFIG_BLK_DEV_DTC2278
if (HWIF(drive)->chipset == ide_dtc2278)
@@ -2123,9 +2169,14 @@
return -ENOSYS;
save_flags(flags);
cli();
- drive->pio_req = (int) arg;
- drive->special.b.set_pio = 1;
+ if (drive->special.b.set_tune) {
+ restore_flags(flags);
+ return -EBUSY;
+ }
+ drive->tune_req = (byte) arg;
+ drive->special.b.set_tune = 1;
restore_flags(flags);
+ (void) ide_do_drive_cmd (drive, &rq, ide_wait);
return 0;
RO_IOCTLS(inode->i_rdev, arg);
@@ -2431,11 +2482,6 @@
save_flags(flags);
cli(); /* some systems need this */
do_identify(drive, cmd); /* drive returned ID */
- if (drive->present && drive->media != ide_tape) {
- ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
- if (tuneproc != NULL && drive->autotune == 1)
- tuneproc(drive, 255); /* auto-tune PIO mode */
- }
rc = 0; /* drive responded with ID */
(void) GET_STAT(); /* clear drive IRQ */
restore_flags(flags);
@@ -2455,12 +2501,12 @@
} else { /* Mmmm.. multiple IRQs.. don't know which was ours */
printk("%s: IRQ probe failed (%d)\n", drive->name, irqs);
#ifdef CONFIG_BLK_DEV_CMD640
+#ifdef CMD640_DUMP_REGS
if (HWIF(drive)->chipset == ide_cmd640) {
- extern byte (*get_cmd640_reg)(int);
printk("%s: Hmmm.. probably a driver problem.\n", drive->name);
- printk("%s: cmd640 reg 09h == 0x%02x\n", drive->name, get_cmd640_reg(9));
- printk("%s: cmd640 reg 51h == 0x%02x\n", drive->name, get_cmd640_reg(0x51));
+ CMD640_DUMP_REGS;
}
+#endif /* CMD640_DUMP_REGS */
#endif /* CONFIG_BLK_DEV_CMD640 */
}
}
@@ -2486,7 +2532,7 @@
static int do_probe (ide_drive_t *drive, byte cmd)
{
int rc;
- ide_hwif_t *hwif;
+ ide_hwif_t *hwif = HWIF(drive);
#ifdef CONFIG_BLK_DEV_IDEATAPI
if (drive->present) { /* avoid waiting for inappropriate probes */
if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY))
@@ -2498,12 +2544,12 @@
drive->name, drive->present, drive->media,
(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
#endif
- hwif = HWIF(drive);
SELECT_DRIVE(hwif,drive);
- OUT_BYTE(drive->select.all,IDE_SELECT_REG); /* select target drive */
- delay_10ms(); /* wait for BUSY_STAT */
+ delay_10ms(); /* allow BUSY_STAT to assert & clear */
+ delay_10ms();
if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {
OUT_BYTE(0xa0,IDE_SELECT_REG); /* exit with drive0 selected */
+ delay_10ms(); /* allow BUSY_STAT to assert & clear */
return 3; /* no i/f present: avoid killing ethernet cards */
}
@@ -2665,6 +2711,14 @@
}
}
restore_flags(flags);
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ ide_drive_t *drive = &hwif->drives[unit];
+ if (drive->present && drive->media != ide_tape) {
+ ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
+ if (tuneproc != NULL && drive->autotune == 1)
+ tuneproc(drive, 255); /* auto-tune PIO mode */
+ }
+ }
}
}
@@ -2701,9 +2755,11 @@
* Try matching against the supplied keywords,
* and return -(index+1) if we match one
*/
- for (i = 0; *keywords != NULL; ++i) {
- if (!strcmp(s, *keywords++))
- return -(i+1);
+ if (keywords != NULL) {
+ for (i = 0; *keywords != NULL; ++i) {
+ if (!strcmp(s, *keywords++))
+ return -(i+1);
+ }
}
/*
* Look for a series of no more than "max_vals"
@@ -2750,6 +2806,15 @@
* and quite likely to cause trouble with
* older/odd IDE drives.
*
+ * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in Mhz,
+ * where "xx" is between 25 and 66 inclusive,
+ * used when tuning chipset PIO modes.
+ * For PCI bus, 25 is correct for a P75 system,
+ * 30 is correct for P90,P120,P180 systems,
+ * and 33 is used for P100,P133,P166 systems.
+ * If in doubt, use idebus=33 for PCI.
+ * As for VLB, it is safest to not specify it.
+ *
* "idex=noprobe" : do not attempt to access/use this interface
* "idex=base" : probe for an interface at the addr specified,
* where "base" is usually 0x1f0 or 0x170
@@ -2838,10 +2903,25 @@
goto bad_option;
}
}
+
+ if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e')
+ goto bad_option;
+ /*
+ * Look for bus speed option: "idebus="
+ */
+ if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') {
+ if (match_parm(&s[6], NULL, vals, 1) != 1)
+ goto bad_option;
+ if (vals[0] >= 25 && vals[0] <= 66)
+ idebus_parameter = vals[0];
+ else
+ printk(" -- BAD BUS SPEED! Expected value from 25 to 66");
+ goto done;
+ }
/*
* Look for interface options: "idex="
*/
- if (s[0] == 'i' && s[1] == 'd' && s[2] == 'e' && s[3] >= '0' && s[3] <= max_hwif) {
+ if (s[3] >= '0' && s[3] <= max_hwif) {
/*
* Be VERY CAREFUL changing this: note hardcoded indexes below
*/
@@ -2854,17 +2934,19 @@
/*
* Cryptic check to ensure chipset not already set for hwif:
*/
- if (i >= 0 || i <= -5) {
+ if (i > 0 || i <= -5) {
if (hwif->chipset != ide_unknown)
goto bad_option;
- if (i < 0 && ide_hwifs[1].chipset != ide_unknown)
- goto bad_option;
+ if (i <= -5) {
+ if (ide_hwifs[1].chipset != ide_unknown)
+ goto bad_option;
+ /*
+ * Interface keywords work only for ide0:
+ */
+ if (hw != 0)
+ goto bad_hwif;
+ }
}
- /*
- * Interface keywords work only for ide0:
- */
- if (i <= -5 && hw != 0)
- goto bad_hwif;
switch (i) {
#ifdef CONFIG_BLK_DEV_PROMISE
@@ -3329,6 +3411,7 @@
{
int index, i, rc = -1;
ide_hwif_t *hwif;
+ ide_drive_t *drive;
unsigned long flags;
save_flags(flags);
@@ -3346,8 +3429,14 @@
probe_hwif(hwif);
if (!hwif_init(index))
break;
- for (i = 0; i < hwif->gd->nr_real; i++)
+ for (i = 0; i < hwif->gd->nr_real; i++) {
+ drive = &hwif->drives[i];
revalidate_disk(MKDEV(hwif->major, i<<PARTN_BITS));
+#ifdef CONFIG_BLK_DEV_IDECD
+ if (drive->present && drive->media == ide_cdrom)
+ ide_cdrom_setup(drive);
+#endif /* CONFIG_BLK_DEV_IDECD */
+ }
rc = index;
break;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov