patch-2.0.37 linux/drivers/block/triton.c

Next file: linux/drivers/cdrom/sbpcd.c
Previous file: linux/drivers/block/proc_array.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.36/linux/drivers/block/triton.c linux/drivers/block/triton.c
@@ -1,107 +1,18 @@
 /*
  *  linux/drivers/block/triton.c	Version 1.13  Aug 12, 1996
+ *					Version 1.13a June 1998 - new chipsets
+ *					Version 1.13b July 1998 - DMA blacklist
  *
  *  Copyright (c) 1995-1996  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
  */
 
 /*
- * This module provides support for the Bus Master IDE DMA function
- * of the Intel PCI Triton I/II chipsets (i82371FB or i82371SB).
- *
- * Pretty much the same code will work for the OPTi "Viper" chipset.
- * Look for DMA support for this in linux kernel 2.1.xx, when it appears.
- *
- * DMA is currently supported only for hard disk drives (not cdroms).
- *
- * Support for cdroms will likely be added at a later date,
- * after broader experience has been obtained with hard disks.
- *
- * Up to four drives may be enabled for DMA, and the Triton chipset will
- * (hopefully) arbitrate the PCI bus among them.  Note that the i82371 chip
- * provides a single "line buffer" for the BM IDE function, so performance of
- * multiple (two) drives doing DMA simultaneously will suffer somewhat,
- * as they contest for that resource bottleneck.  This is handled transparently
- * inside the i82371 chip.
- *
- * By default, DMA support is prepared for use, but is currently enabled only
- * for drives which support multi-word DMA mode2 (mword2), or which are
- * recognized as "good" (see table below).  Drives with only mode0 or mode1
- * (single or multi) DMA should also work with this chipset/driver (eg. MC2112A)
- * but are not enabled by default.  Use "hdparm -i" to view modes supported
- * by a given drive.
- *
- * The hdparm-2.4 (or later) utility can be used for manually enabling/disabling
- * DMA support, but must be (re-)compiled against this kernel version or later.
- *
- * To enable DMA, use "hdparm -d1 /dev/hd?" on a per-drive basis after booting.
- * If problems arise, ide.c will disable DMA operation after a few retries.
- * This error recovery mechanism works and has been extremely well exercised.
- *
- * IDE drives, depending on their vintage, may support several different modes
- * of DMA operation.  The boot-time modes are indicated with a "*" in
- * the "hdparm -i" listing, and can be changed with *knowledgeable* use of
- * the "hdparm -X" feature.  There is seldom a need to do this, as drives
- * normally power-up with their "best" PIO/DMA modes enabled.
- *
- * Testing was done with an ASUS P55TP4XE/100 system and the following drives:
- *
- *   Quantum Fireball 1080A (1Gig w/83kB buffer), DMA mode2, PIO mode4.
- *	- DMA mode2 works well (7.4MB/sec), despite the tiny on-drive buffer.
- *	- This drive also does PIO mode4, at about the same speed as DMA mode2.
- *	  An awesome drive for the price!
- *
- *   Fujitsu M1606TA (1Gig w/256kB buffer), DMA mode2, PIO mode4.
- *	- DMA mode2 gives horrible performance (1.6MB/sec), despite the good
- *	  size of the on-drive buffer and a boasted 10ms average access time.
- *	- PIO mode4 was better, but peaked at a mere 4.5MB/sec.
- *
- *   Micropolis MC2112A (1Gig w/508kB buffer), drive pre-dates EIDE and ATA2.
- *	- DMA works fine (2.2MB/sec), probably due to the large on-drive buffer.
- *	- This older drive can also be tweaked for fastPIO (3.7MB/sec) by using
- *	  maximum clock settings (5,4) and setting all flags except prefetch.
- *
- *   Western Digital AC31000H (1Gig w/128kB buffer), DMA mode1, PIO mode3.
- *	- DMA does not work reliably.  The drive appears to be somewhat tardy
- *	  in deasserting DMARQ at the end of a sector.  This is evident in
- *	  the observation that WRITEs work most of the time, depending on
- *	  cache-buffer occupancy, but multi-sector reads seldom work.
- *
- * Testing was done with a Gigabyte GA-586 ATE system and the following drive:
- * (Uwe Bonnes - bon@elektron.ikp.physik.th-darmstadt.de)
- *
- *   Western Digital AC31600H (1.6Gig w/128kB buffer), DMA mode2, PIO mode4.
- *	- much better than its 1Gig cousin, this drive is reported to work
- *	  very well with DMA (7.3MB/sec).
- *
- * Other drives:
- *
- *   Maxtor 7540AV (515Meg w/32kB buffer), DMA modes mword0/sword2, PIO mode3.
- *	- a budget drive, with budget performance, around 3MB/sec.
- *
- *   Western Digital AC2850F (814Meg w/64kB buffer), DMA mode1, PIO mode3.
- *	- another "caviar" drive, similar to the AC31000, except that this one
- *	  worked with DMA in at least one system.  Throughput is about 3.8MB/sec
- *	  for both DMA and PIO.
- *
- *   Conner CFS850A (812Meg w/64kB buffer), DMA mode2, PIO mode4.
- *	- like most Conner models, this drive proves that even a fast interface
- *	  cannot improve slow media.  Both DMA and PIO peak around 3.5MB/sec.
- *
- *   Maxtor 71260AT (1204Meg w/256kB buffer), DMA mword0/sword2, PIO mode3.
- *	- works with DMA, on some systems (but not always on others, eg. Dell),
- *	giving 3-4MB/sec performance, about the same as mode3.
- *
- * If you have any drive models to add, email your results to:  mlord@pobox.com
- * Keep an eye on /var/adm/messages for "DMA disabled" messages.
- *
- * Some people have reported trouble with Intel Zappa motherboards.
- * This can be fixed by upgrading the AMI BIOS to version 1.00.04.BS0,
- * available from ftp://ftp.intel.com/pub/bios/10004bs0.exe
- * (thanks to Glen Morrell <glen@spin.Stanford.edu> for researching this).
- *
- * And, yes, Intel Zappa boards really *do* use the Triton IDE ports.
+ * This module provides support for Bus Master IDE DMA functions in various
+ * motherboard chipsets and PCI controller cards.
+ * Please check /Documentation/ide.txt and /Documentation/udma.txt for details.
  */
+
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -120,6 +31,13 @@
 #include "ide.h"
 
 #undef DISPLAY_TRITON_TIMINGS	/* define this to display timings */
+#undef DISPLAY_APOLLO_TIMINGS	/* define this for extensive debugging information */
+
+#if defined(CONFIG_PROC_FS) && defined(DISPLAY_APOLLO_TIMINGS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#include <linux/via_ide_dma.h>
+#endif
 
 /*
  * good_dma_drives() lists the model names (from "hdparm -i")
@@ -132,6 +50,27 @@
 				 NULL};
 
 /*
+ * bad_dma_drives() lists the model names (from "hdparm -i")
+ * of drives which supposedly support (U)DMA but which are
+ * known to corrupt data with this interface under Linux.
+ *
+ * Note: the list was generated by statistical analysis of problem
+ * reports. It's not clear if there are problems with the drives,
+ * or with some combination of drive/controller or what. 
+ *
+ * You can forcibly override this if you wish. This is the kernel
+ * 'Tread carefully' list.
+ *
+ * Finally see http://www.wdc.com/quality/err-rec.html if you have
+ * one of the listed drives. 
+ */
+const char *bad_dma_drives[] = {"WDC AC11000H",
+				"WDC AC22100H",
+				"WDC AC32500H",
+				"WDC AC33100H",
+				 NULL};
+
+/*
  * Our Physical Region Descriptor (PRD) table should be large enough
  * to handle the biggest I/O request we are likely to see.  Since requests
  * can have no more than 256 sectors, and since the typical blocksize is
@@ -150,6 +89,7 @@
 #define PRD_BYTES	8
 #define PRD_ENTRIES	(PAGE_SIZE / (2 * PRD_BYTES))
 #define DEFAULT_BMIBA	0xe800	/* in case BIOS did not init it */
+#define DEFAULT_BMCRBA  0xcc00  /* VIA's default value */
 
 /*
  * dma_intr() is the handler for disk read/write DMA interrupts
@@ -161,8 +101,8 @@
 	struct request *rq = HWGROUP(drive)->rq;
 	unsigned short dma_base = HWIF(drive)->dma_base;
 
-	dma_stat = inb(dma_base+2);		/* get DMA status */
 	outb(inb(dma_base)&~1, dma_base);	/* stop DMA operation */
+	dma_stat = inb(dma_base+2);		/* get DMA status */
 	stat = GET_STAT();			/* get drive status */
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if ((dma_stat & 7) == 4) {	/* verify good DMA status */
@@ -244,23 +184,37 @@
 	return 1;	/* let the PIO routines handle this weirdness */
 }
 
+/*
+ * We will only enable drives with multi-word (mode2) (U)DMA capabilities,
+ * and ignore the very rare cases of drives that can only do single-word
+ * (modes 0 & 1) (U)DMA transfers. We also discard "blacklisted" hard disks.
+ */
 static int config_drive_for_dma (ide_drive_t *drive)
 {
 	const char **list;
 	struct hd_driveid *id = drive->id;
 
 	if (id && (id->capability & 1)) {
-		/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
+		/* Consult the list of known "bad" drives */
+		list = bad_dma_drives;
+		while (*list) {
+			if (!strcmp(*list++,id->model)) {
+				drive->using_dma = 0;   /* no DMA */
+				printk("ide: Disabling DMA modes on %s drive (%s).\n", drive->name, id->model);
+				return 1;	/* DMA disabled */
+			}
+		}
+		/* Enable DMA on any drive that has mode 2 UltraDMA enabled */
 		if (id->field_valid & 4)	/* UltraDMA */
-			if  ((id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
+			if  ((id->dma_ultra & 0x404) == 0x404) {
 				drive->using_dma = 1;
-				return 0;	/* dma enabled */
+				return 0;	/* DMA enabled */
 			}
-		/* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */
+		/* Enable DMA on any drive that has mode2 DMA enabled */
 		if (id->field_valid & 2)	/* regular DMA */
-			if  ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) {
+			if  ((id->dma_mword & 0x404) == 0x404) {
 				drive->using_dma = 1;
-				return 0;	/* dma enabled */
+				return 0;	/* DMA enabled */
 			}
 		/* Consult the list of known "good" drives */
 		list = good_dma_drives;
@@ -387,22 +341,135 @@
 }
 
 /*
+ *  Set VIA Chipset Timings for (U)DMA modes enabled.
+ */
+static int set_via_timings (byte bus, byte fn, byte post, byte flush)
+{
+	byte via_config = 0;
+	int rc = 0;
+
+	/* setting IDE read prefetch buffer and IDE post write buffer */
+	if ((rc = pcibios_read_config_byte(bus, fn, 0x41, &via_config)))
+		return (1);
+	if ((rc = pcibios_write_config_byte(bus, fn, 0x41, via_config | post)))
+		return (1);
+
+	/* setting Channel read and End-of-sector FIFO flush: */
+	if ((rc = pcibios_read_config_byte(bus, fn, 0x46, &via_config)))
+		return (1);
+	if ((rc = pcibios_write_config_byte(bus, fn, 0x46, via_config | flush)))
+		return (1);
+
+	return (0);
+}
+
+/*
  * ide_init_triton() prepares the IDE driver for DMA operation.
  * This routine is called once, from ide.c during driver initialization,
- * for each triton chipset which is found (unlikely to be more than one).
+ * for each BM-DMA chipset which is found (rarely more than one).
  */
 void ide_init_triton (byte bus, byte fn)
 {
 	int rc = 0, h;
 	int dma_enabled = 0;
-	unsigned short pcicmd;
-	unsigned int bmiba, timings;
+	unsigned short io[6], count = 0, step_count = 0;
+	unsigned short pcicmd, vendor, device, class;
+	unsigned int bmiba, timings, reg, tmp;
+	unsigned int addressbios = 0;
+
+#ifdef DISPLAY_APOLLO_TIMINGS
+	bmide_bus = bus;
+	bmide_fn = fn;
+#endif /* DISPLAY_APOLLO_TIMINGS */
+
+/*
+ *  We pick up the vendor, device, and class info for selecting the correct
+ *  controller that is supported.  Since we can access this routine more than
+ *  once with the use of onboard and off-board EIDE controllers, a method
+ *  of determining "who is who for what" is needed.
+ */
+
+	pcibios_read_config_word (bus, fn, PCI_VENDOR_ID, &vendor);
+	pcibios_read_config_word (bus, fn, PCI_DEVICE_ID, &device);
+	pcibios_read_config_word (bus, fn, PCI_CLASS_DEVICE, &class);
+
+	switch(vendor) {
+		case PCI_VENDOR_ID_INTEL:
+                   printk("ide: Intel 82371 (single FIFO) DMA Bus Mastering IDE ");
+                   break;
+		case PCI_VENDOR_ID_SI:
+			printk("ide: SiS 5513 (dual FIFO) DMA Bus Mastering IDE ");
+			break;
+                case PCI_VENDOR_ID_VIA:
+                   printk("ide: VIA VT82C586B (split FIFO) UDMA Bus Mastering IDE ");
+                   break;
+		case PCI_VENDOR_ID_PROMISE:
+			/*	PCI_CLASS_STORAGE_RAID == class	*/
+			/*
+			 *  I have been able to make my Promise Ultra33 UDMA card change class.
+			 *  It has reported as both PCI_CLASS_STORAGE_RAID and PCI_CLASS_STORAGE_IDE.
+			 *  Since the PCI_CLASS_STORAGE_RAID mode should automatically mirror the
+			 *  two halves of the PCI_CONFIG register data, but sometimes it forgets.
+			 *  Thus we guarantee that they are identical, with a quick check and
+			 *  correction if needed.
+			 *  PDC20246 (primary) PDC20247 (secondary) IDE hwif's.
+			 *
+			 *  Note that Promise "stories,fibs,..." about this device not being
+			 *  capable of ATAPI and AT devices.
+			 */
+			if (PCI_CLASS_STORAGE_RAID == class) {
+				unsigned char irq1 = 0, irq2 = 0;
+				pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &irq1);
+				pcibios_read_config_byte (bus, fn, (PCI_INTERRUPT_LINE)|0x80, &irq2);
+				if (irq1 != irq2) {
+					pcibios_write_config_byte(bus, fn, (PCI_INTERRUPT_LINE)|0x80, irq1);
+				}
+			}
+		case PCI_VENDOR_ID_ARTOP:
+			/*	PCI_CLASS_STORAGE_SCSI == class	*/
+			/*
+			 *  I have found that by stroking rom_enable_bit on both the AEC6210U/UF and
+			 *  PDC20246 controller cards, the features desired are almost guaranteed
+			 *  to be enabled and compatible.  This ROM may not be registered in the
+			 *  config data, but it can be turned on.  Registration failure has only
+			 *  been observed if and only if Linux sets up the pci_io_address in the
+			 *  0x6000 range.  If they are setup in the 0xef00 range it is reported.
+			 *  WHY??? got me.........
+			 */
+			printk("ide: %s UDMA Bus Mastering ",
+				(vendor == PCI_VENDOR_ID_ARTOP) ? "AEC6210" : "PDC20246");
+			pcibios_read_config_dword(bus, fn, PCI_ROM_ADDRESS, &addressbios);
+			if (addressbios) {
+				pcibios_write_config_byte(bus, fn, PCI_ROM_ADDRESS, addressbios | PCI_ROM_ADDRESS_ENABLE);
+				printk("with ROM enabled at 0x%08x", addressbios);
+			}
+			/*
+			 *  This was stripped out of 2.1.XXX kernel code and parts from a patch called
+			 *  promise_update.  This finds the PCI_BASE_ADDRESS spaces and makes them
+			 *  available for configuration later.
+			 *  PCI_BASE_ADDRESS_0  hwif0->io_base
+			 *  PCI_BASE_ADDRESS_1  hwif0->ctl_port
+			 *  PCI_BASE_ADDRESS_2  hwif1->io_base
+			 *  PCI_BASE_ADDRESS_3  hwif1->ctl_port
+			 *  PCI_BASE_ADDRESS_4  bmiba
+			 */
+			memset(io, 0, 6 * sizeof(unsigned short));
+			for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
+				pcibios_read_config_dword(bus, fn, reg, &tmp);
+				if (tmp & PCI_BASE_ADDRESS_SPACE_IO)
+					io[count++] = tmp & PCI_BASE_ADDRESS_IO_MASK;
+			}
+			break;
+		default:
+			return;
+	}
+
+	printk("\n    Controller on PCI bus %d function %d\n", bus, fn);
 
-	printk("ide: i82371 PIIX (Triton) on PCI bus %d function %d\n", bus, fn);
 	/*
 	 * See if IDE and BM-DMA features are enabled:
 	 */
-	if ((rc = pcibios_read_config_word(bus, fn, 0x04, &pcicmd)))
+	if ((rc = pcibios_read_config_word(bus, fn, PCI_COMMAND, &pcicmd)))
 		goto quit;
 	if ((pcicmd & 1) == 0)  {
 		printk("ide: ports are not enabled (BIOS)\n");
@@ -416,21 +483,21 @@
 		 */
 		int try_again = 1;
 		do {
-			if ((rc = pcibios_read_config_dword(bus, fn, 0x20, &bmiba)))
+			if ((rc = pcibios_read_config_dword(bus, fn, PCI_BASE_ADDRESS_4, &bmiba)))
 				goto quit;
 			bmiba &= 0xfff0;	/* extract port base address */
 			if (bmiba) {
 				dma_enabled = 1;
 				break;
 			} else {
-				printk("ide: BM-DMA base register is invalid (0x%04x, PnP BIOS problem)\n", bmiba);
-				if (inb(DEFAULT_BMIBA) != 0xff || !try_again)
+                                printk("ide: BM-DMA base register is invalid (0x%04x, PnP BIOS problem)\n", bmiba);
+                                if (inb(((vendor == PCI_VENDOR_ID_VIA) ? DEFAULT_BMCRBA : DEFAULT_BMIBA)) != 0xff || !try_again)
 					break;
-				printk("ide: setting BM-DMA base register to 0x%04x\n", DEFAULT_BMIBA);
-				if ((rc = pcibios_write_config_word(bus, fn, 0x04, pcicmd&~1)))
+				printk("ide: setting BM-DMA base register to 0x%04x\n", ((vendor == PCI_VENDOR_ID_VIA) ? DEFAULT_BMCRBA : DEFAULT_BMIBA));
+				if ((rc = pcibios_write_config_word(bus, fn, PCI_COMMAND, pcicmd&~1)))
 					goto quit;
-				rc = pcibios_write_config_dword(bus, fn, 0x20, DEFAULT_BMIBA|1);
-				if (pcibios_write_config_word(bus, fn, 0x04, pcicmd|5) || rc)
+				rc = pcibios_write_config_dword(bus, fn, 0x20, ((vendor == PCI_VENDOR_ID_VIA) ? DEFAULT_BMCRBA : DEFAULT_BMIBA)|1);
+				if (pcibios_write_config_word(bus, fn, PCI_COMMAND, pcicmd|5) || rc)
 					goto quit;
 			}
 		} while (try_again--);
@@ -439,89 +506,218 @@
 	/*
 	 * See if ide port(s) are enabled
 	 */
-	if ((rc = pcibios_read_config_dword(bus, fn, 0x40, &timings)))
-		goto quit;
-	if (!(timings & 0x80008000)) {
-		printk("ide: neither port is enabled\n");
+	if ((rc = pcibios_read_config_dword(bus, fn,
+		(vendor == PCI_VENDOR_ID_PROMISE) ? 0x50 : 
+		(vendor == PCI_VENDOR_ID_ARTOP) ? 0x54 :
+		0x40, &timings)))
 		goto quit;
-	}
+	/*
+	 * We do a vendor check since the Ultra33 and AEC6210
+	 * holds their timings in a different location.
+	 */
+	printk("ide: timings == %08x\n", timings);
+
+	/*
+	 *  The switch preserves some stuff that was original.
+	 */
+	switch(vendor) {
+		case PCI_VENDOR_ID_INTEL:
+			if (!(timings & 0x80008000)) {
+				printk("ide: INTEL: neither port is enabled\n");
+				goto quit;
+			}
+			break;
+		case PCI_VENDOR_ID_VIA:
+			if(!(timings & 0x03)) {
+				printk("ide: VIA: neither port is enabled\n");
+				goto quit;
+			}
+			break;
+		case PCI_VENDOR_ID_SI:
+		case PCI_VENDOR_ID_PROMISE:
+		case PCI_VENDOR_ID_ARTOP:
+                default:
+                        break;
+        }
 
 	/*
 	 * Save the dma_base port addr for each interface
 	 */
 	for (h = 0; h < MAX_HWIFS; ++h) {
+		ide_hwif_t *hwif = &ide_hwifs[h];
+
+		/*
+		 *  This prevents the first contoller from accidentally
+		 *  initalizing the hwif's that it does not use and block
+		 *  an off-board ide-pci from getting in the game.
+		 */
+		if (step_count >= 2) {
+			goto quit;
+		}
+#ifdef CONFIG_BLK_DEV_OFFBOARD
+		/*
+		 *  This is a forced override for the onboard ide controller
+		 *  to be enabled, if one chooses to have an offboard ide-pci
+		 *  card as the primary booting device.  This beasty is
+		 *  for offboard UDMA upgrades with hard disks, but saving
+		 *  the onboard DMA2 controllers for CDROMS, TAPES, ZIPS, etc...
+		 */
+		if ((vendor == PCI_VENDOR_ID_INTEL) ||
+		    (vendor == PCI_VENDOR_ID_SI) ||
+		    (vendor == PCI_VENDOR_ID_VIA)) {
+			if (h == 2) {
+				hwif->io_base = 0x1f0;
+				hwif->ctl_port = 0x3f6;
+				hwif->irq = 14;
+				hwif->noprobe = 0;
+			}
+			if (h == 3) {
+				hwif->io_base = 0x170;
+				hwif->ctl_port = 0x376;
+				hwif->irq = 15;
+				hwif->noprobe = 0;
+			}
+		}
+#endif /* CONFIG_BLK_DEV_OFFBOARD */
+		/*
+		 *  If the chipset is listed as "ide_unknown", lets get a
+		 *  hwif while they last.  This does the first check on
+		 *  the current availability of the ide_hwifs[h] in question.
+		 */
+		if (hwif->chipset != ide_unknown) {
+			continue;
+		} else if (vendor == PCI_VENDOR_ID_INTEL) {
+			unsigned short time;
 #ifdef DISPLAY_TRITON_TIMINGS
-		byte s_clks, r_clks;
-		unsigned short devid;
+			byte s_clks, r_clks;
+			unsigned short devid;
 #endif /* DISPLAY_TRITON_TIMINGS */
-		ide_hwif_t *hwif = &ide_hwifs[h];
-		unsigned short time;
-		if (hwif->io_base == 0x1f0) {
-			time = timings & 0xffff;
-			if ((time & 0x8000) == 0)	/* interface enabled? */
-				continue;
-			hwif->chipset = ide_triton;
-			if (dma_enabled)
-				init_triton_dma(hwif, bmiba);
-		} else if (hwif->io_base == 0x170) {
-			time = timings >> 16;
-			if ((time & 0x8000) == 0)	/* interface enabled? */
+			if (hwif->io_base == 0x1f0) {
+				time = timings & 0xffff;
+				if ((time & 0x8000) == 0)	/* interface enabled? */
+					continue;
+				hwif->chipset = ide_triton;
+				if (dma_enabled)
+					init_triton_dma(hwif, bmiba);
+				step_count++;
+			} else if (hwif->io_base == 0x170) {
+				time = timings >> 16;
+				if ((time & 0x8000) == 0)	/* interface enabled? */
+					continue;
+				hwif->chipset = ide_triton;
+				if (dma_enabled)
+					init_triton_dma(hwif, bmiba + 8);
+				step_count++;
+			} else {
 				continue;
-			hwif->chipset = ide_triton;
-			if (dma_enabled)
-				init_triton_dma(hwif, bmiba + 8);
-		} else
-			continue;
+			}
 #ifdef DISPLAY_TRITON_TIMINGS
-		s_clks = ((~time >> 12) & 3) + 2;
-		r_clks = ((~time >>  8) & 3) + 1;
-		printk("    %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d\n",
-		 hwif->name, time, s_clks, r_clks);
-		if ((time & 0x40) && !pcibios_read_config_word(bus, fn, 0x02, &devid)
-		 && devid == PCI_DEVICE_ID_INTEL_82371SB_1)
-		{
-			byte stime;
-			if (pcibios_read_config_byte(bus, fn, 0x44, &stime)) {
-				if (hwif->io_base == 0x1f0) {
-					s_clks = ~stime >> 6;
-					r_clks = ~stime >> 4;
+			s_clks = ((~time >> 12) & 3) + 2;
+			r_clks = ((~time >>  8) & 3) + 1;
+			printk("    %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d\n",
+				hwif->name, time, s_clks, r_clks);
+			if ((time & 0x40) && !pcibios_read_config_word(bus, fn, PCI_DEVICE_ID, &devid)
+				&& devid == PCI_DEVICE_ID_INTEL_82371SB_1) {
+				byte stime;
+				if (pcibios_read_config_byte(bus, fn, 0x44, &stime)) {
+					if (hwif->io_base == 0x1f0) {
+						s_clks = ~stime >> 6;
+						r_clks = ~stime >> 4;
+					} else {
+						s_clks = ~stime >> 2;
+						r_clks = ~stime;
+					}
+					s_clks = (s_clks & 3) + 2;
+					r_clks = (r_clks & 3) + 1;
+					printk("                   slave: sample_CLKs=%d, recovery_CLKs=%d\n",
+						s_clks, r_clks);
+				}
+			}
+			print_triton_drive_flags (0, time & 0xf);
+			print_triton_drive_flags (1, (time >> 4) & 0xf);
+#endif /* DISPLAY_TRITON_TIMINGS */
+		} else if (vendor == PCI_VENDOR_ID_SI) {
+			if (hwif->io_base == 0x1f0) {
+				hwif->chipset = ide_triton;
+				if (dma_enabled)
+					init_triton_dma(hwif, bmiba);
+				step_count++;
+			} else if (hwif->io_base == 0x170) {
+				hwif->chipset = ide_triton;
+				if (dma_enabled)
+					init_triton_dma(hwif, bmiba + 8);
+				step_count++;
+			} else {
+				continue;
+			}
+		} else if(vendor == PCI_VENDOR_ID_VIA) {
+			if (hwif->io_base == 0x1f0) {
+				if((timings & 0x02) == 0)
+					continue;
+				hwif->chipset = ide_triton;
+				if (dma_enabled)
+					init_triton_dma(hwif, bmiba);
+				if (set_via_timings(bus, fn, 0xc0, 0xa0))
+					goto quit;
+#ifdef DISPLAY_APOLLO_TIMINGS
+				proc_register_dynamic(&proc_root, &via_proc_entry);
+#endif /* DISPLAY_APOLLO_TIMINGS */
+				step_count++;
+			} else if (hwif->io_base == 0x170) {
+				if((timings & 0x01) == 0)
+					continue;
+				hwif->chipset = ide_triton;
+				if (dma_enabled)
+					init_triton_dma(hwif, bmiba + 8);
+				if (set_via_timings(bus, fn, 0x30, 0x50))
+					goto quit;
+				step_count++;
+			} else {
+				continue;
+			}
+		} else if ((vendor == PCI_VENDOR_ID_PROMISE) ||
+			   (vendor == PCI_VENDOR_ID_ARTOP)) {
+	/*
+	 *  This silly tmp = h routine allows an off-board ide-pci card to
+	 *  be booted as primary hwifgroup, provided that the onboard
+	 *  controllers are disabled.  If they are active, then we wait our
+	 *  turn for hwif assignment.
+	 */
+			unsigned char irq = 0;
+			pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &irq);
+			if ((h == 0) || (h == 1)) {
+				tmp = h * 2;
+			} else {
+				tmp = (h - 2) * 2;
+			}
+			hwif->io_base = io[tmp];
+			hwif->ctl_port = io[tmp + 1] + 2;
+			hwif->irq = irq;
+			hwif->noprobe = 0;
+
+			if (vendor == PCI_VENDOR_ID_ARTOP) {
+				hwif->serialized = 1;
+			}
+
+			if (dma_enabled) {
+				if (!check_region(bmiba, 8)) {
+					hwif->chipset = ide_udma;
+					init_triton_dma(hwif, bmiba);
+					step_count++;
+				} else if (!check_region((bmiba + 0x08), 8)) {
+					if ((vendor == PCI_VENDOR_ID_PROMISE) &&
+					    (!check_region(bmiba+16, 16))) {
+						request_region(bmiba+16, 16, "PDC20246");
+					}
+					hwif->chipset = ide_udma;
+					init_triton_dma(hwif, bmiba + 8);
+					step_count++;
 				} else {
-					s_clks = ~stime >> 2;
-					r_clks = ~stime;
+					continue;
 				}
-				s_clks = (s_clks & 3) + 2;
-				r_clks = (r_clks & 3) + 1;
-				printk("                   slave: sample_CLKs=%d, recovery_CLKs=%d\n",
-		 			s_clks, r_clks);
 			}
 		}
-		print_triton_drive_flags (0, time & 0xf);
-		print_triton_drive_flags (1, (time >> 4) & 0xf);
-#endif /* DISPLAY_TRITON_TIMINGS */
 	}
 
-quit: if (rc) printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
-}
-
-void ide_init_promise (byte bus, byte fn, ide_hwif_t *hwif0, ide_hwif_t *hwif1, unsigned short dma)
-{
-	int rc;
-	unsigned short pcicmd;
-	unsigned int bmiba = 0;
-
-	printk("ide: Enabling DMA for Promise Technology IDE Ultra-DMA 33 on PCI bus %d function %d, port 0x%04x\n", bus, fn, dma);
-	if ((rc = pcibios_read_config_word(bus, fn, 0x04, &pcicmd)) || (pcicmd & 1) == 0 || (pcicmd & 4) == 0)
-		goto abort;
-	if ((rc = pcibios_read_config_dword(bus, fn, 0x20, &bmiba)))
-		goto abort;
-	bmiba &= 0xfff0;	/* extract port base address */
-	if (bmiba != dma || !bmiba)
-		goto abort;
-	hwif0->chipset = ide_promise_udma;
-	hwif1->chipset = ide_promise_udma;
-	init_triton_dma(hwif0, bmiba);
-	init_triton_dma(hwif1, bmiba + 0x08);
-	return;
-abort:
-	printk(KERN_WARNING "ide: Promise/33 not configured correctly (BIOS)\n");
+	quit: if (rc) printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov