patch-1.3.45 linux/drivers/block/ide.c

Next file: linux/drivers/block/ide.h
Previous file: linux/drivers/block/genhd.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.44/linux/drivers/block/ide.c linux/drivers/block/ide.c
@@ -1,11 +1,11 @@
 /*
- *  linux/drivers/block/ide.c	Version 5.17  Nov 3, 1995
+ *  linux/drivers/block/ide.c	Version 5.18  Nov 16, 1995
  *
  *  Copyright (C) 1994, 1995  Linus Torvalds & authors (see below)
  */
 
 /*
- * This is the multiple IDE interface driver, as evolved from hd.c.  
+ * This is the multiple IDE interface driver, as evolved from hd.c.
  * It supports up to four 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.
  *
@@ -13,17 +13,17 @@
  * Secondary i/f:  ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
  * Tertiary i/f:   ide2: major=33; (hde)         minor=0; (hdf)         minor=64
  * Quaternary i/f: ide3: major=34; (hdg)         minor=0; (hdh)         minor=64
- * 
+ *
  * It is easy to extend ide.c to handle more than four interfaces:
  *
  *	Change the MAX_HWIFS constant in ide.h.
- * 
+ *
  *	Define some new major numbers (in major.h), and insert them into
  *	the ide_hwif_to_major table in ide.c.
- * 
+ *
  *	Fill in the extra values for the new interfaces into the two tables
  *	inside ide.c:  default_io_base[]  and  default_irqs[].
- * 
+ *
  *	Create the new request handlers by cloning "do_ide3_request()"
  *	for each new interface, and add them to the switch statement
  *	in the ide_init() function in ide.c.
@@ -56,7 +56,7 @@
  *  Maintained by Mark Lord (mlord@bnr.ca):  ide.c, ide.h, triton.c, hd.c, ..
  *
  *  This was a rewrite of just about everything from hd.c, though some original
- *  code is still sprinkled about.  Think of it as a major evolution, with 
+ *  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
@@ -167,15 +167,18 @@
  *			remove "Huh?" from cmd640 code
  *			added qd6580 interface speed select from Colten Edwards
  *  Version 5.17	kludge around bug in BIOS32 on Intel triton motherboards
+ *  Version 5.18	new CMD640 code, moved to cmd640.c, #include'd for now
+ *			new UMC8672 code, moved to umc8672.c, #include'd for now
+ *			disallow turning on DMA when h/w not capable of DMA
  *
  *  Driver compile-time options are in ide.h
  *
  *  To do, in likely order of completion:
+ *	- make cmd640.c and umc8672.c compile separately from ide.c
  *	- add ALI M1443/1445 chipset support from derekn@vw.ece.cmu.edu
- *	- add Promise Caching controller support from peterd@pnd-pc.demon.co.uk
  *	- add ioctls to get/set interface timings on various interfaces
+ *	- add Promise Caching controller support from peterd@pnd-pc.demon.co.uk
  *	- modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
- *	- improved CMD support:  handed this off to someone else
  *	- find someone to work on IDE *tape drive* support
  */
 
@@ -209,9 +212,14 @@
 
 #include "ide.h"
 
+#ifdef SUPPORT_CMD640
+void cmd640_tune_drive(ide_drive_t *);
+static int cmd640_vlb = 0;
+#endif
+
        ide_hwif_t	ide_hwifs[MAX_HWIFS];		/* hwif info */
 static ide_hwgroup_t	*irq_to_hwgroup [16];
-static const byte	ide_hwif_to_major[MAX_HWIFS]   = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
+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};
@@ -999,7 +1007,7 @@
 
 /*
  * multwrite() transfers a block of one or more sectors of data to a drive
- * as part of a disk multwrite operation.  
+ * as part of a disk multwrite operation.
  */
 static void multwrite (ide_drive_t *drive)
 {
@@ -1232,7 +1240,7 @@
 	if (drive->select.b.lba) {
 #ifdef DEBUG
 		printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",
-			drive->name, (rq->cmd==READ)?"read":"writ", 
+			drive->name, (rq->cmd==READ)?"read":"writ",
 			block, rq->nr_sectors, (unsigned long) rq->buffer);
 #endif
 		OUT_BYTE(block,io_base+IDE_SECTOR_OFFSET);
@@ -1333,7 +1341,7 @@
 	}
 	drive = &hwif->drives[unit];
 #ifdef DEBUG
-	if (rq->bh && !rq->bh->b_lock) {
+	if (rq->bh && !buffer_locked(rq->bh)) {
 		printk("%s: block not locked\n", drive->name);
 		goto kill_rq;
 	}
@@ -1495,7 +1503,7 @@
 		printk("%s: marginal timeout\n", drive->name);
 	} else {				 /* drive not responding */
 		hwgroup->handler = NULL;
-		if (hwgroup->hwif->dmaproc) 
+		if (hwgroup->hwif->dmaproc)
 			(void) hwgroup->hwif->dmaproc (ide_dma_abort, drive);
 		if (!ide_error(drive, "irq timeout", GET_STAT()))
 			do_hwgroup_request (hwgroup);
@@ -1522,7 +1530,7 @@
  * In reality, this is a non-issue.  The new command is not sent unless the
  * drive is ready to accept one, in which case we know the drive is not
  * trying to interrupt us.  And ide_set_handler() is always invoked before
- * completing the issuance of any new drive command, so we will not be 
+ * completing the issuance of any new drive command, so we will not be
  * accidently invoked as a result of any valid command completion interrupt.
  *
  */
@@ -1806,24 +1814,24 @@
 		case BLKRAGET:
 			return write_fs_long(arg, read_ahead[MAJOR(inode->i_rdev)]);
 
-         	case BLKGETSIZE:   /* Return device size */
+	 	case BLKGETSIZE:   /* Return device size */
 			return write_fs_long(arg, drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects);
 		case BLKRRPART: /* Re-read partition tables */
 			return revalidate_disk(inode->i_rdev);
 
-                case HDIO_GET_KEEPSETTINGS:
+		case HDIO_GET_KEEPSETTINGS:
 			return write_fs_long(arg, drive->keep_settings);
 
-                case HDIO_GET_UNMASKINTR:
+		case HDIO_GET_UNMASKINTR:
 			return write_fs_long(arg, drive->unmask);
 
-                case HDIO_GET_DMA:
+		case HDIO_GET_DMA:
 			return write_fs_long(arg, drive->using_dma);
 
-                case HDIO_GET_CHIPSET:
+		case HDIO_GET_CHIPSET:
 			return write_fs_long(arg, drive->chipset);
 
-                case HDIO_GET_MULTCOUNT:
+		case HDIO_GET_MULTCOUNT:
 			return write_fs_long(arg, drive->mult_count);
 
 		case HDIO_GET_IDENTITY:
@@ -1858,6 +1866,10 @@
 			cli();
 			switch (cmd) {
 				case HDIO_SET_DMA:
+					if (!(HWIF(drive)->dmaproc)) {
+						restore_flags(flags);
+						return -EPERM;
+					}
 					drive->using_dma = arg;
 					break;
 				case HDIO_SET_KEEPSETTINGS:
@@ -2046,7 +2058,7 @@
 		drive->present = 1;
 		drive->cyl     = drive->bios_cyl  = id->cyls;
 		drive->head    = drive->bios_head = id->heads;
-		drive->sect    = drive->bios_sect = id->sectors; 
+		drive->sect    = drive->bios_sect = id->sectors;
 	}
 	/* Handle logical geometry translation by the drive */
 	if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads
@@ -2055,7 +2067,7 @@
 		/*
 		 * Extract the physical drive geometry for our use.
 		 * Note that we purposely do *not* update the bios info.
-		 * This way, programs that use it (like fdisk) will 
+		 * This way, programs that use it (like fdisk) will
 		 * still have the same logical view as the BIOS does,
 		 * which keeps the partition table from being screwed.
 		 *
@@ -2079,7 +2091,7 @@
 	if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) {
 		drive->cyl  = id->cyls;
 		drive->head = id->heads;
-		drive->sect = id->sectors; 
+		drive->sect = id->sectors;
 	}
 	/* Correct the number of cyls if the bios value is too small */
 	if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) {
@@ -2107,6 +2119,9 @@
 			printk(", DMA");
 	}
 	printk("\n");
+#ifdef SUPPORT_CMD640
+	cmd640_tune_drive(drive);	/* but can we tune a fish? */
+#endif
 }
 
 /*
@@ -2336,8 +2351,8 @@
  * The code enables the secondary IDE controller and the PIO4 (3?) timings on
  * the primary (EIDE). You may probably have to enable the 32-bit support to
  * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
- * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my 
- * filesystem  corrupted with -u1, but under heavy disk load only :-)  
+ * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
+ * filesystem  corrupted with -u1, but under heavy disk load only :-)
  *
  * From: mlord@bnr.ca -- this chipset is now forced to use the "serialize" feature,
  * which hopefully will make it more reliable to use.. maybe it has the same bugs
@@ -2417,59 +2432,13 @@
 }
 #endif /* SUPPORT_QD6580 */
 
-#if SUPPORT_CMD640
-/*
- * ??? fixme: 
- */
-byte read_cmd640_vlb (byte port, byte reg)
-{
-	byte val;
-
-	unsigned long flags;
-	save_flags(flags);
-	cli();
-	outw(reg, port);
-	val = inb(port+4);
-	restore_flags(flags);
-	return val;
-}
-
-void write_cmd640_vlb (byte port, byte reg, byte val)
-{
-	unsigned long flags;
-	save_flags(flags);
-	cli();
-	outw(reg, port);
-	outw(val, port+4);
-	restore_flags(flags);
-}
-
-void init_cmd640_vlb (void)
-{
-	byte reg;
-	unsigned short port = 0x178;
-
-	serialized = 1;
- 	printk("ide: buggy CMD640 interface: serialized, ");
-	reg = read_cmd640_vlb(port, 0x50);
-	if (reg == 0xff || (reg & 0x90) != 0x90) {
-#if TRY_CMD640_VLB_AT_0x78
-		port = 0x78;
-		reg = read_cmd640_vlb(port, 0x50);
-		if (reg == 0xff || (reg & 0x90) != 0x90)
+#ifdef SUPPORT_UMC8672
+#include "umc8672.c"	/* until we tidy up the interface some more */
 #endif
-		{
-			disallow_unmask = 1;
-			printk("(probe failed) disabled unmasking\n");
-			return;
-		}
-	}
-	write_cmd640_vlb(port, 0x51, read_cmd640_vlb(port, 0x51)|0xc8);
-	write_cmd640_vlb(port, 0x57, read_cmd640_vlb(port, 0x57)|0x0c);
-	printk("disabled read-ahead, enabled secondary\n");
 
-}
-#endif /* SUPPORT_CMD640 */
+#ifdef SUPPORT_CMD640
+#include "cmd640.c"	/* until we tidy up the interface some more */
+#endif
 
 /*
  * stridx() returns the offset of c within s,
@@ -2488,7 +2457,7 @@
  * 2. if the remainder matches one of the supplied keywords,
  *     the index (1 based) of the keyword is negated and returned.
  * 3. if the remainder is a series of no more than max_vals numbers
- *     separated by commas, the numbers are saved in vals[] and a 
+ *     separated by commas, the numbers are saved in vals[] and a
  *     count of how many were saved is returned.  Base10 is assumed,
  *     and base16 is allowed when prefixed with "0x".
  * 4. otherwise, zero is returned.
@@ -2511,7 +2480,7 @@
 		/*
 		 * Look for a series of no more than "max_vals"
 		 * numeric values separated by commas, in base10,
-		 * or base16 when prefixed with "0x".  
+		 * or base16 when prefixed with "0x".
 		 * Return a count of how many were found.
 		 */
 		for (n = 0; (i = stridx(decimal, *s)) >= 0;) {
@@ -2621,11 +2590,18 @@
 	 * Look for interface options:  "idex="
 	 */
 	if (s[0] == 'i' && s[1] == 'd' && s[2] == 'e' && s[3] >= '0' && s[3] <= max_hwif) {
-		const char *ide_words[] = {"noprobe", "serialize", "dtc2278", "ht6560b", "cmd640_vlb", "qd6580", NULL};
+		const char *ide_words[] = {"noprobe", "serialize", "dtc2278", "ht6560b",
+					"cmd640_vlb", "qd6580", "umc8672", NULL};
 		hw = s[3] - '0';
 		hwif = &ide_hwifs[hw];
 
 		switch (match_parm(&s[4], ide_words, vals, 3)) {
+#if SUPPORT_UMC8672
+			case -7: /* "umc8672" */
+				if (hw != 0) goto bad_hwif;
+				init_umc8672();
+				goto done;
+#endif /* SUPPORT_UMC8672 */
 #if SUPPORT_QD6580
 			case -6: /* "qd6580" */
 				if (hw != 0) goto bad_hwif;
@@ -2635,8 +2611,7 @@
 #if SUPPORT_CMD640
 			case -5: /* "cmd640_vlb" */
 				if (hw > 1) goto bad_hwif;
-				init_cmd640_vlb();
-				goto do_serialize; /* not necessary once we implement the above */
+				cmd640_vlb = 1;
 				break;
 #endif /* SUPPORT_CMD640 */
 #if SUPPORT_HT6560B
@@ -2709,7 +2684,7 @@
 
 	drive->cyl  = drive->bios_cyl  = drive->id->cyls;
 	drive->head = drive->bios_head = drive->id->heads;
-	drive->sect = drive->bios_sect = drive->id->sectors; 
+	drive->sect = drive->bios_sect = drive->id->sectors;
 	drive->special.b.set_geometry = 1;
 
 	tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
@@ -2745,7 +2720,7 @@
  * drives in the system -- the ones reflected as drive 1 or 2.  The first
  * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
  * nibble.  This will be either a 4 bit drive type or 0xf indicating use byte
- * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value 
+ * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value
  * means we have an AT controller hard disk for that drive.
  *
  * Of course, there is no guarantee that either drive is actually on the
@@ -2905,45 +2880,6 @@
 }
 #endif /* SUPPORT_RZ1000 */
 
-#if SUPPORT_CMD640
-void init_cmd640 (byte bus, byte fn)
-{
-	int rc;
-	unsigned char reg;
-
-	serialized = 1;
-	printk("ide: buggy CMD640 interface: ");
-
-#if 0	/* funny.. the cmd640b I tried this on claimed to not be enabled.. */
-	unsigned short sreg;
-	if ((rc = pcibios_read_config_word (bus, fn, PCI_COMMAND, &sreg))) {
-		ide_pci_access_error (rc);
-	} else if (!(sreg & 1)) {
-		printk("not enabled\n");
-	} else {
-
-	/*
-	 * The first part is undocumented magic from the DOS driver.
-	 * According to the datasheet, there is no port 0x5b on the cmd640.
-	 */
-	(void) pcibios_write_config_byte(bus, fn, 0x5b, 0xbd);
-	if (pcibios_write_config_byte(bus, fn, 0x5b, 0xbd) != 0xbd)
-		printk("init_cmd640: huh? 0x5b read back wrong\n");
-	(void) pcibios_write_config_byte(bus, fn, 0x5b, 0);
-#endif /* 0 */
-	/*
-	 * The rest is from the cmd640b datasheet.
-	 */
-	if ((rc = pcibios_read_config_byte(bus, fn, 0x51, &reg))
-	 || (rc =  pcibios_write_config_byte(bus, fn, 0x51, reg | 0xc0)) /* 0xc8 to enable 2nd i/f */
-	 || (rc =  pcibios_read_config_byte(bus, fn, 0x57, &reg))
-	 || (rc =  pcibios_write_config_byte(bus, fn, 0x57, reg | 0x0c)))
-		buggy_interface_fallback (rc);
-	else
-		printk("serialized, disabled read-ahead\n");
-}
-#endif /* SUPPORT_CMD640 */
-
 typedef void (ide_pci_init_proc_t)(byte, byte);
 
 /*
@@ -2966,7 +2902,7 @@
 
 /*
  * ide_init_pci() finds/initializes "known" PCI 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".
  */
@@ -2975,9 +2911,6 @@
 #if SUPPORT_RZ1000
 	ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, &init_rz1000, 0);
 #endif
-#if SUPPORT_CMD640
-	ide_probe_pci (PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, &init_cmd640, 0);
-#endif
 #ifdef CONFIG_BLK_DEV_TRITON
 	/*
 	 * Apparently the BIOS32 services on Intel motherboards are buggy,
@@ -3008,6 +2941,9 @@
 	if (pcibios_present())
 		ide_init_pci ();
 #endif /* CONFIG_PCI */
+#ifdef SUPPORT_CMD640
+	ide_probe_for_cmd640x();
+#endif
 
 	/*
 	 * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports

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