patch-1.3.9 linux/drivers/block/ide.c
Next file: linux/drivers/block/mcdx.c
Previous file: linux/drivers/block/genhd.c
Back to the patch index
Back to the overall index
- Lines: 380
- Date:
Mon Jul 10 17:08:05 1995
- Orig file:
v1.3.8/linux/drivers/block/ide.c
- Orig date:
Tue Jun 27 14:11:33 1995
diff -u --recursive --new-file v1.3.8/linux/drivers/block/ide.c linux/drivers/block/ide.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide.c Version 3.16 May 30, 1995
+ * linux/drivers/block/ide.c Version 4.00 Jul 10, 1995
*
* Copyright (C) 1994, 1995 Linus Torvalds & authors (see below)
*/
@@ -40,47 +40,10 @@
* 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.1 ALPHA fixes for dual i/f
- * Version 1.2 ALPHA first serious attempt at sharing irqs
* 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,
- * fixed hd.c coexistence bug, other minor stuff
- * Version 1.6 BETA fix link error when cd-rom not configured
- * Version 2.0 BETA lots of minor fixes; remove annoying messages; ...
- * Version 2.2 BETA fixed reset_drives; major overhaul of autoprobing
- * Version 2.3 BETA set DEFAULT_UNMASK_INTR to 0 again; cosmetic changes
- * Version 2.4 BETA added debounce on reading of drive status reg,
- * added config flags to remove unwanted features
- * Version 2.5 BETA fixed problem with leftover phantom IRQ after probe,
- * allow "set_geometry" even when in LBA (as per spec(?)),
- * assorted miscellaneous tweaks.
- * Version 2.6 BETA more config flag stuff, another probing tweak,
- * (not released) multmode now defaults to status quo from boot time,
- * moved >16heads check to init time, rearranged reset code
- * added HDIO_DRIVE_CMD, removed standby/xfermode stuff
- * hopefully fixed ATAPI probing code, added hdx=cdrom
- * Version 2.7 BETA fixed invocation of cdrom_setup()
- * Version 2.8 BETA fixed compile error for DISK_RECOVERY_TIME>0
- * fixed incorrect drive selection in DO_DRIVE_CMD (Bug!)
- * Version 2.9 BETA more work on ATAPI CDROM recognition
- * (not released) changed init order so partition checks go in sequence
- * Version 3.0 BETA included ide-cd.c update from Steve with Mitsumi fixes
- * attempt to fix byte-swap problem with Mitsumi id_info
- * ensure drives on second i/f get initialized on boot
- * preliminary compile-time support for 32bit IDE i/f chips
- * added check_region() and snarf_region() to probes
- * Version 3.1 BETA ensure drives on *both* i/f get initialized on boot
- * fix byte-swap problem with Mitsumi id_info
- * changed ide_timermask into ide_timerbit
- * get rid of unexpected interrupts after probing
- * don't wait for READY_STAT on cdrom drives
- * Version 3.2 BETA Ooops.. mistakenly left VLB_32BIT_IDE on by default
- * new ide-cd.c from Scott
- * Version 3.3 BETA fix compiling with PROBE_FOR_IRQS==0
- * (sent to Linus) tweak in do_probe() to fix Delman's DRDY problem
- * Version 3.4 BETA removed "444" debug message
- * (sent to Linus)
+ * ...
* Version 3.5 correct the bios_cyl field if it's too small
* (linux 1.1.76) (to help fdisk with brain-dead BIOSs)
* Version 3.6 cosmetic corrections to comments and stuff
@@ -120,12 +83,23 @@
* add boot flag to enable "dtc2278" probe
* add probe to avoid EATA (SCSI) interfaces,
* courtesy of neuffer@goofy.zdv.uni-mainz.de.
+ * Version 4.00 tidy up verify_area() calls - heiko@colossus.escape.de
+ * add flag to ignore WRERR_STAT for some drives
+ * courtesy of David.H.West@um.cc.umich.edu
+ * assembly syntax tweak to VLB_SYNC
+ * removeable drive support from scuba@cs.tu-berlin.de
+ * add transparent support for DiskManager-6.0x "Dynamic
+ * Disk Overlay" (DDO), most of this in in genhd.c
+ * eliminate "multiple mode turned off" message at boot
*
* To do:
- * - improved CMD support: tech info is supposedly "in the mail"
+ * - add support for alternative IDE port addresses
+ * - refine the DiskManager-6.0x overlay support (special cases)
+ * - improved CMD support: tech info is in my hands for 640B chip
* - special 32-bit controller-type detection & support
* - figure out how to support oddball "intelligent" caching cards
* - reverse-engineer 3/4 drive support on fancy "Promise" cards
+ * - find someone to work on IDE *tape drive* support
*/
#include <linux/config.h>
@@ -262,7 +236,7 @@
#if SUPPORT_VLB_32BIT
#if SUPPORT_VLB_SYNC
-#define VLB_SYNC __asm__ __volatile__ ("pusha\n movl $0x01f2,%edx\n inb (%dx),%al\n inb (%dx),%al\n inb (%dx),%al\n popa\n")
+#define VLB_SYNC __asm__ __volatile__ ("pusha\n movl $0x01f2,%edx\n inb %dx,%al\n inb %dx,%al\n inb %dx,%al\n popa\n")
#endif /* SUPPORT_VLB_SYNC */
#endif /* SUPPORT_VLB_32BIT */
@@ -274,7 +248,7 @@
#define GET_STAT(hwif) IN_BYTE(HD_STATUS,hwif)
#define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good))
#define BAD_R_STAT (BUSY_STAT | ERR_STAT)
-#define BAD_W_STAT (BUSY_STAT | ERR_STAT | WRERR_STAT)
+#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT)
#define BAD_STAT (BAD_R_STAT | DRQ_STAT)
#define DRIVE_READY (READY_STAT | SEEK_STAT)
#define DATA_READY (DRIVE_READY | DRQ_STAT)
@@ -333,15 +307,15 @@
byte unmask; /* pretty quick access to this also */
dev_type type : 1; /* disk or cdrom (or tape, floppy..) */
unsigned present : 1; /* drive is physically present */
- unsigned dont_probe : 1; /* from: hdx=noprobe */
+ unsigned noprobe : 1; /* from: hdx=noprobe */
unsigned keep_settings : 1; /* restore settings after drive reset */
unsigned busy : 1; /* mutex for ide_open, revalidate_.. */
unsigned vlb_32bit : 1; /* use 32bit in/out for data */
unsigned vlb_sync : 1; /* needed for some 32bit chip sets */
- unsigned reserved0 : 1; /* unused */
+ unsigned be_quiet : 1; /* supress "multiple mode" msg at boot */
special_t special; /* special action flags */
select_t select; /* basic drive/head select reg value */
- byte mult_count, chipset, reserved2;
+ byte mult_count, chipset, bad_wstat;
byte usage, mult_req, wpcom, ctl;
byte head, sect, bios_head, bios_sect;
unsigned short cyl, bios_cyl;
@@ -782,7 +756,7 @@
int i;
struct request *rq = ide_cur_rq[DEV_HWIF];
- if (OK_STAT(stat=GET_STAT(DEV_HWIF),DRIVE_READY,BAD_W_STAT)) {
+ if (OK_STAT(stat=GET_STAT(DEV_HWIF),DRIVE_READY,dev->bad_wstat)) {
#ifdef DEBUG
printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n",
dev->name, rq->sector, (unsigned long) rq->buffer,
@@ -849,7 +823,7 @@
int i;
struct request *rq = &ide_write_rq[DEV_HWIF];
- if (OK_STAT(stat=GET_STAT(DEV_HWIF),DRIVE_READY,BAD_W_STAT)) {
+ if (OK_STAT(stat=GET_STAT(DEV_HWIF),DRIVE_READY,dev->bad_wstat)) {
if (stat & DRQ_STAT) {
if (rq->nr_sectors) {
if (dev->mult_count)
@@ -896,13 +870,14 @@
dev->mult_req = dev->mult_count = 0;
dev->special.b.recalibrate = 1;
(void) dump_status(DEV_HWIF, "set_multmode", stat);
- } else {
+ } else if (!dev->be_quiet) {
if ((dev->mult_count = dev->mult_req))
printk (" %s: enabled %d-sector multiple mode\n",
dev->name, dev->mult_count);
else
printk (" %s: multiple mode turned off\n", dev->name);
}
+ dev->be_quiet = 0;
DO_REQUEST;
}
@@ -1078,7 +1053,7 @@
if (rq->cmd == WRITE) {
OUT_BYTE(dev->wpcom,HD_PRECOMP); /* for ancient drives */
OUT_BYTE(dev->mult_count ? WIN_MULTWRITE : WIN_WRITE, HD_COMMAND);
- WAIT_STAT(dev, DATA_READY, BAD_W_STAT, WAIT_DRQ, "DRQ", error);
+ WAIT_STAT(dev,DATA_READY,dev->bad_wstat,WAIT_DRQ,"DRQ",error);
if (!dev->unmask)
cli();
if (dev->mult_count) {
@@ -1383,6 +1358,8 @@
sleep_on(&dev->wqueue);
dev->usage++;
restore_flags(flags);
+ if (dev->id->config & (1<<7)) /* for removeable disks */
+ check_disk_change(inode->i_rdev);
#ifdef CONFIG_BLK_DEV_IDECD
if (dev->type == cdrom)
return cdrom_open (inode, filp, dev);
@@ -1416,7 +1393,7 @@
* usage == 1 (we need an open channel to use an ioctl :-), so this
* is our limit.
*/
-static int revalidate_disk(int i_rdev)
+static int revalidate_disk(dev_t i_rdev)
{
unsigned int i, major, start, drive = DEVICE_NR(i_rdev);
ide_dev_t *dev;
@@ -1584,29 +1561,34 @@
memcpy_tofs((char *)arg, (char *)dev->id, sizeof(*dev->id));
return 0;
+ case HDIO_GET_NOWERR:
+ return write_fs_long(arg, dev->bad_wstat == BAD_R_STAT);
+
case HDIO_SET_KEEPSETTINGS:
case HDIO_SET_UNMASKINTR:
- if (!suser()) return -EACCES;
- if ((arg > 1) || (MINOR(inode->i_rdev) & PARTN_MASK))
- return -EINVAL;
- save_flags(flags);
- cli();
- if (cmd == HDIO_SET_KEEPSETTINGS)
- dev->keep_settings = arg;
- else
- dev->unmask = arg;
- restore_flags(flags);
- return 0;
-
+ case HDIO_SET_NOWERR:
case HDIO_SET_CHIPSET:
if (!suser()) return -EACCES;
- if ((arg > 3) || (MINOR(inode->i_rdev) & PARTN_MASK))
+ if ((arg > 1) || (MINOR(inode->i_rdev) & PARTN_MASK))
return -EINVAL;
save_flags(flags);
cli();
- dev->chipset = arg;
- dev->vlb_sync = (arg & 2) >> 1;
- dev->vlb_32bit = (arg & 1);
+ switch (cmd) {
+ case HDIO_SET_KEEPSETTINGS:
+ dev->keep_settings = arg;
+ break;
+ case HDIO_SET_UNMASKINTR:
+ dev->unmask = arg;
+ break;
+ case HDIO_SET_NOWERR:
+ dev->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
+ break;
+ case HDIO_SET_CHIPSET:
+ dev->chipset = arg;
+ dev->vlb_sync = (arg & 2) >> 1;
+ dev->vlb_32bit = (arg & 1);
+ break;
+ }
restore_flags(flags);
return 0;
@@ -1625,14 +1607,12 @@
dev->mult_req = arg;
dev->special.b.set_multmode = 1;
restore_flags(flags);
-#ifdef IDE_DRIVE_CMD
+#ifndef IDE_DRIVE_CMD
+ return 0;
+#else
do_drive_cmd (inode->i_rdev, NULL);
return (dev->mult_count == arg) ? 0 : -EIO;
-#else
- return 0;
-#endif /* IDE_DRIVE_CMD */
-#ifdef IDE_DRIVE_CMD
case HDIO_DRIVE_CMD:
{
unsigned long args;
@@ -1640,11 +1620,13 @@
if (NULL == (long *) arg)
err = do_drive_cmd(inode->i_rdev,NULL);
else {
- if (!(err = verify_area(VERIFY_WRITE,(long *)arg,sizeof(long))))
+ if (!(err = verify_area(VERIFY_READ,(long *)arg,sizeof(long))))
{
args = get_user((long *)arg);
- err = do_drive_cmd(inode->i_rdev,(char *)&args);
- put_user(args,(long *)arg);
+ if (!(err = verify_area(VERIFY_WRITE,(long *)arg,sizeof(long)))) {
+ err = do_drive_cmd(inode->i_rdev,(char *)&args);
+ put_user(args,(long *)arg);
+ }
}
}
return err;
@@ -1662,18 +1644,20 @@
}
}
-#ifdef CONFIG_BLK_DEV_IDECD
static int ide_check_media_change (dev_t full_dev)
{
ide_dev_t *dev;
if ((dev = get_info_ptr(full_dev)) == NULL)
return -ENODEV;
- if (dev->type != cdrom)
- return 0;
- return cdrom_check_media_change (dev);
-}
+#ifdef CONFIG_BLK_DEV_IDECD
+ if (dev->type == cdrom)
+ return cdrom_check_media_change (dev);
#endif /* CONFIG_BLK_DEV_IDECD */
+ if (dev->id->config & (1<<7)) /* for removeable disks */
+ return 1; /* always assume it was changed */
+ return 0;
+}
static void fixstring (byte *s, int bytecount, int byteswap)
@@ -1850,8 +1834,10 @@
dev->mult_req = INITIAL_MULT_COUNT;
if (dev->mult_req > id->max_multsect)
dev->mult_req = id->max_multsect;
- if (dev->mult_req || ((id->multsect_valid & 1) && id->multsect))
+ if (dev->mult_req || ((id->multsect_valid & 1) && id->multsect)) {
dev->special.b.set_multmode = 1;
+ dev->be_quiet = 1;
+ }
printk(", MaxMult=%d", id->max_multsect);
}
printk("\n");
@@ -1998,7 +1984,7 @@
* 1 device was found (note: dev->present might still be 0)
*/
{
- if (dev->dont_probe) /* skip probing? */
+ if (dev->noprobe) /* skip probing? */
return dev->present;
if (do_probe(dev, WIN_IDENTIFY) >= 2) { /* if !(success || timed-out) */
#ifdef CONFIG_BLK_DEV_IDECD
@@ -2106,7 +2092,7 @@
}
#endif /* SUPPORT_DTC2278 */
#if SUPPORT_SERIALIZE
- if (!strcmp(str,"serialize") || !strcmp(str,"cmd")) {
+ if (!strcmp(str,"serialize")) {
printk("%s\n",str);
single_threaded = 1; /* serialize all drive access */
return;
@@ -2114,7 +2100,12 @@
#endif /* SUPPORT_SERIALIZE */
if (!strcmp(str,"noprobe")) {
printk("%s\n",str);
- dev->dont_probe = 1; /* don't probe for this drive */
+ dev->noprobe = 1; /* don't probe for this drive */
+ return;
+ }
+ if (!strcmp(str,"nowerr")) {
+ printk("%s\n",str);
+ dev->bad_wstat = BAD_R_STAT; /* ignore WRERR_STAT */
return;
}
#ifdef CONFIG_BLK_DEV_IDECD
@@ -2168,6 +2159,22 @@
ide_setup (str, ints);
}
+
+void ide_xlate_1024 (dev_t full_dev)
+{
+ ide_dev_t *dev;
+
+ if ((dev = get_info_ptr(full_dev)) != NULL) {
+ dev->bios_cyl -= 1; /* keeps fdisk sane */
+ while (dev->bios_cyl > 1024) {
+ if (dev->bios_head > 32)
+ return;
+ dev->bios_head *= 2;
+ dev->bios_cyl /= 2;
+ }
+ }
+}
+
#ifndef CONFIG_BLK_DEV_HD
/*
* We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
@@ -2238,6 +2245,8 @@
dev->keep_settings = 0;
ide_hd[hwif][drive<<PARTN_BITS].start_sect = 0;
dev->name = ide_devname[hwif][drive];
+ if (!dev->bad_wstat)
+ dev->bad_wstat = BAD_W_STAT;
}
}
@@ -2319,11 +2328,9 @@
ide_open, /* open */
ide_release, /* release */
block_fsync /* fsync */
-#ifdef CONFIG_BLK_DEV_IDECD
,NULL, /* fasync */
ide_check_media_change, /* check_media_change */
- NULL /* revalidate */
-#endif CONFIG_BLK_DEV_IDECD
+ revalidate_disk /* revalidate */
};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this