patch-2.1.71 linux/drivers/block/ide-dma.c

Next file: linux/drivers/block/ide-probe.c
Previous file: linux/drivers/block/ide-disk.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.70/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide-dma.c	Version 4.01  November 30, 1997
+ *  linux/drivers/block/ide-dma.c	Version 4.06  December 3, 1997
  *
  *  Copyright (c) 1995-1998  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -64,6 +64,7 @@
  *
  * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports.
  */
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
@@ -75,7 +76,6 @@
 #include <linux/pci.h>
 #include <linux/bios32.h>
 #include <linux/init.h>
-#include <linux/config.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -141,14 +141,20 @@
 }
 
 /*
- * build_dmatable() prepares a dma request.
+ * ide_build_dmatable() prepares a dma request.
  * Returns 0 if all went okay, returns 1 otherwise.
+ * May also be invoked from trm290.c
  */
-static int build_dmatable (ide_drive_t *drive)
+int ide_build_dmatable (ide_drive_t *drive)
 {
 	struct request *rq = HWGROUP(drive)->rq;
 	struct buffer_head *bh = rq->bh;
 	unsigned long size, addr, *table = HWIF(drive)->dmatable;
+#ifdef CONFIG_BLK_DEV_TRM290
+	unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290);
+#else
+	const int is_trm290_chipset = 0;
+#endif
 	unsigned int count = 0;
 
 	do {
@@ -172,32 +178,40 @@
 				size += bh->b_size;
 			}
 		}
-
 		/*
 		 * Fill in the dma table, without crossing any 64kB boundaries.
-		 * We assume 16-bit alignment of all blocks.
+		 * The hardware requires 16-bit alignment of all blocks
+		 * (trm290 requires 32-bit alignment).
 		 */
+		if ((addr & 3)) {
+			printk("%s: misaligned DMA buffer\n", drive->name);
+			return 0;
+		}
 		while (size) {
 			if (++count >= PRD_ENTRIES) {
 				printk("%s: DMA table too small\n", drive->name);
-				return 1; /* revert to PIO for this request */
+				return 0; /* revert to PIO for this request */
 			} else {
-				unsigned long bcount = 0x10000 - (addr & 0xffff);
+				unsigned long xcount, bcount = 0x10000 - (addr & 0xffff);
 				if (bcount > size)
 					bcount = size;
 				*table++ = addr;
-				*table++ = bcount & 0xffff;
+				xcount = bcount & 0xffff;
+				if (is_trm290_chipset)
+					xcount = ((xcount >> 2) - 1) << 16;
+				*table++ = xcount;
 				addr += bcount;
 				size -= bcount;
 			}
 		}
 	} while (bh != NULL);
 	if (count) {
-		*--table |= 0x80000000;	/* set End-Of-Table (EOT) bit */
-		return 0;
+		if (!is_trm290_chipset)
+			*--table |= 0x80000000;	/* set End-Of-Table (EOT) bit */
+		return count;
 	}
 	printk("%s: empty DMA table?\n", drive->name);
-	return 1;	/* let the PIO routines handle this weirdness */
+	return 0;
 }
 
 /*
@@ -214,11 +228,13 @@
  * Returns 0 if all went well.
  * Returns 1 if DMA read/write could not be started, in which case
  * the caller should revert to PIO for the current request.
+ * May also be invoked from trm290.c
  */
-static int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	unsigned long dma_base = HWIF(drive)->dma_base;
-	unsigned int reading = 0;
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long dma_base = hwif->dma_base;
+	unsigned int count, reading = 0;
 
 	switch (func) {
 		case ide_dma_off:
@@ -243,11 +259,11 @@
 			printk("ide_dmaproc: unsupported func: %d\n", func);
 			return 1;
 		case ide_dma_read:
-			reading = (1 << 3);
+			reading = 1 << 3;
 		case ide_dma_write:
-			if (build_dmatable (drive))
-				return 1;
-			outl(virt_to_bus (HWIF(drive)->dmatable), dma_base + 4); /* PRD table */
+			if (!(count = ide_build_dmatable(drive)))
+				return 1;	/* try PIO instead of DMA */
+			outl(virt_to_bus(hwif->dmatable), dma_base + 4); /* PRD table */
 			outb(reading, dma_base);			/* specify r/w */
 			outb(inb(dma_base+2)|0x06, dma_base+2);		/* clear status bits */
 			if (drive->media != ide_disk)
@@ -262,32 +278,85 @@
 static int config_drive_for_dma (ide_drive_t *drive)
 {
 	const char **list;
-
 	struct hd_driveid *id = drive->id;
+	ide_hwif_t *hwif = HWIF(drive);
+
 	if (id && (id->capability & 1)) {
 		/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
 		if (id->field_valid & 4)	/* UltraDMA */
 			if  ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
-				return ide_dmaproc(ide_dma_on, drive);
+				return hwif->dmaproc(ide_dma_on, drive);
 		/* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */
 		if (id->field_valid & 2)	/* regular DMA */
 			if  ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)
-				return ide_dmaproc(ide_dma_on, drive);
+				return hwif->dmaproc(ide_dma_on, drive);
 		/* Consult the list of known "good" drives */
 		list = good_dma_drives;
 		while (*list) {
 			if (!strcmp(*list++,id->model))
-				return ide_dmaproc(ide_dma_on, drive);
+				return hwif->dmaproc(ide_dma_on, drive);
 		}
 	}
-	return ide_dmaproc(ide_dma_off_quietly, drive);
+	return hwif->dmaproc(ide_dma_off_quietly, drive);
 }
 
+void ide_setup_dma (ide_hwif_t *hwif, unsigned short dmabase, unsigned int num_ports)
+{
+	static unsigned long dmatable = 0;
+	static unsigned leftover = 0;
+
+	printk("    %s: BM-DMA at 0x%04x-0x%04x", hwif->name, dmabase, dmabase + num_ports - 1);
+	if (check_region(dmabase, num_ports)) {
+		printk(" -- ERROR, PORT ADDRESSES ALREADY IN USE\n");
+		return;
+	}
+	request_region(dmabase, num_ports, hwif->name);
+	hwif->dma_base = dmabase;
+	if (leftover < (PRD_ENTRIES * PRD_BYTES)) {
+		/*
+		 * The BM-DMA uses full 32bit addr, so we can
+		 * safely use __get_free_page() here instead
+		 * of __get_dma_pages() -- no ISA limitations.
+		 */
+		dmatable = __get_free_pages(GFP_KERNEL,1,0);
+		leftover = dmatable ? PAGE_SIZE : 0;
+	}
+	if (!dmatable) {
+		printk(" -- ERROR, UNABLE TO ALLOCATE PRD TABLE\n");
+	} else {
+		hwif->dmatable = (unsigned long *) dmatable;
+		dmatable += (PRD_ENTRIES * PRD_BYTES);
+		leftover -= (PRD_ENTRIES * PRD_BYTES);
+		hwif->dmaproc = &ide_dmaproc;
+		if (hwif->chipset != ide_trm290) {
+			byte dma_stat = inb(dmabase+2);
+			printk(", BIOS DMA settings: %s:%s %s:%s",
+		 	 hwif->drives[0].name, (dma_stat & 0x20) ? "yes" : "no ",
+		 	 hwif->drives[1].name, (dma_stat & 0x40) ? "yes" : "no");
+		}
+		printk("\n");
+	}
+}
+
+#ifdef CONFIG_BLK_DEV_TRM290
+extern void ide_init_trm290(byte, byte, ide_hwif_t *);
+#define INIT_TRM290 (&ide_init_trm290)
+#else
+#define INIT_TRM290 (NULL)
+#endif	/* CONFIG_BLK_DEV_TRM290 */
+
+#ifdef CONFIG_BLK_DEV_OPTI621
+extern void ide_init_opti621(byte, byte, ide_hwif_t *);
+#define INIT_OPTI (&ide_init_opti621)
+#else
+#define INIT_OPTI (NULL)
+#endif	/* CONFIG_BLK_DEV_OPTI621 */
+
 #define DEVID_PIIX	(PCI_VENDOR_ID_INTEL  |(PCI_DEVICE_ID_INTEL_82371_1   <<16))
 #define DEVID_PIIX3	(PCI_VENDOR_ID_INTEL  |(PCI_DEVICE_ID_INTEL_82371SB_1 <<16))
 #define DEVID_PIIX4	(PCI_VENDOR_ID_INTEL  |(PCI_DEVICE_ID_INTEL_82371AB   <<16))
 #define DEVID_VP_IDE 	(PCI_VENDOR_ID_VIA    |(PCI_DEVICE_ID_VIA_82C586_1    <<16))
-#define DEVID_PDC2046	(PCI_VENDOR_ID_PROMISE|(PCI_DEVICE_ID_PROMISE_20246   <<16))
+#define DEVID_PDC20246	(PCI_VENDOR_ID_PROMISE|(PCI_DEVICE_ID_PROMISE_20246   <<16))
 #define DEVID_RZ1000	(PCI_VENDOR_ID_PCTECH |(PCI_DEVICE_ID_PCTECH_RZ1000   <<16))
 #define DEVID_RZ1001	(PCI_VENDOR_ID_PCTECH |(PCI_DEVICE_ID_PCTECH_RZ1001   <<16))
 #define DEVID_CMD640	(PCI_VENDOR_ID_CMD    |(PCI_DEVICE_ID_CMD_640         <<16))
@@ -295,13 +364,9 @@
 #define DEVID_SIS5513	(PCI_VENDOR_ID_SI     |(PCI_DEVICE_ID_SI_5513         <<16))
 #define DEVID_OPTI	(PCI_VENDOR_ID_OPTI   |(PCI_DEVICE_ID_OPTI_82C621     <<16))
 #define DEVID_OPTI2	(PCI_VENDOR_ID_OPTI   |(0xd568 /* from datasheets */  <<16))
-
-#ifdef CONFIG_BLK_DEV_OPTI621
-extern void ide_init_opti621(byte, byte, ide_hwif_t *);
-#define INIT_OPTI (&ide_init_opti621)
-#else
-#define INIT_OPTI (NULL)
-#endif
+#define DEVID_TRM290	(PCI_VENDOR_ID_TEKRAM |(PCI_DEVICE_ID_TEKRAM_DC290    <<16))
+#define DEVID_NS87410	(PCI_VENDOR_ID_NS     |(PCI_DEVICE_ID_NS_87410        <<16))
+#define DEVID_HT6565	(PCI_VENDOR_ID_HOLTEK |(PCI_DEVICE_ID_HOLTEK_6565     <<16))
 
 typedef struct ide_pci_enablebit_s {
 	byte	reg;	/* byte pci reg holding the enable-bit */
@@ -321,14 +386,17 @@
 	{DEVID_PIIX3,	"PIIX3",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}} },
 	{DEVID_PIIX4,	"PIIX4",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}} },
 	{DEVID_VP_IDE,	"VP_IDE",	NULL,		{{0x40,0x02,0x02}, {0x40,0x01,0x01}} },
-	{DEVID_PDC2046,	"PDC2046",	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}} },
+	{DEVID_PDC20246,"PDC20246",	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}} },
 	{DEVID_RZ1000,	NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
 	{DEVID_RZ1001,	NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
 	{DEVID_CMD640,	NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
 	{DEVID_OPTI,	"OPTI",		INIT_OPTI,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}} },
 	{DEVID_OPTI2,	"OPTI2",	INIT_OPTI,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}} },
-	{DEVID_SIS5513,	"SIS5513",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
+	{DEVID_SIS5513,	"SIS5513",	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}} },
 	{DEVID_CMD646,	"CMD646",	NULL,		{{0x00,0x00,0x00}, {0x51,0x80,0x80}} },
+	{DEVID_TRM290,	"TRM290",	INIT_TRM290,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
+	{DEVID_NS87410,	"NS87410",	NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}} },
+	{DEVID_HT6565,	"HT6565",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
 	{0,		"PCI_IDE",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}} }};
 
 __initfunc(static ide_pci_device_t *lookup_devid(unsigned int devid))
@@ -339,38 +407,6 @@
 	return d;
 }
 
-__initfunc(static void ide_setup_dma (ide_hwif_t *hwif, unsigned short dmabase))
-{
-	static unsigned long dmatable = 0;
-	static unsigned leftover = 0;
-
-	printk("    %s: BM-DMA at 0x%04x-0x%04x", hwif->name, dmabase, dmabase+7);
-	if (check_region(dmabase, 8)) {
-		printk(" -- ERROR, PORTS ALREADY IN USE");
-	} else {
-		request_region(dmabase, 8, hwif->name);
-		hwif->dma_base = dmabase;
-		if (leftover < (PRD_ENTRIES * PRD_BYTES)) {
-			/*
-			 * The BM-DMA uses full 32bit addr, so we can
-			 * safely use __get_free_page() here instead
-			 * of __get_dma_pages() -- no ISA limitations.
-			 */
-			dmatable = __get_free_pages(GFP_KERNEL,1,0);
-			leftover = dmatable ? PAGE_SIZE : 0;
-		}
-		if (dmatable) {
-			printk(", PRD table at %08lx", dmatable);
-			hwif->dmatable = (unsigned long *) dmatable;
-			dmatable += (PRD_ENTRIES * PRD_BYTES);
-			leftover -= (PRD_ENTRIES * PRD_BYTES);
-			outl(virt_to_bus(hwif->dmatable), dmabase + 4);
-			hwif->dmaproc = &ide_dmaproc;
-		}
-	}
-	printk("\n");
-}
-
 /* The next two functions were stolen from cmd640.c, with
    a few modifications  */
 
@@ -501,7 +537,7 @@
 	}
 	return NULL;
 }
-
+				
 /*
  * ide_setup_pci_device() looks at the primary/secondary interfaces
  * on a PCI IDE device and, if they are enabled, prepares the IDE driver
@@ -516,11 +552,9 @@
 {
 	unsigned int port, at_least_one_hwif_enabled = 0;
 	unsigned short base = 0, ctl = 0;
-	byte tmp = 0, pciirq = 0;
-	ide_hwif_t *hwif;
+	byte tmp = 0;
+	ide_hwif_t *hwif, *mate = NULL;
 
-	if (pcibios_read_config_byte(bus, fn, 0x3c, &pciirq))
-		pciirq = 0;	/* probe later if not set */
 	for (port = 0; port <= 1; ++port) {
 		ide_pci_enablebit_t *e = &(d->enablebits[port]);
 		if (e->reg) {
@@ -542,25 +576,33 @@
 			continue;
 		}
 		hwif->chipset = ide_pci;
+		hwif->pci_port = port;
+		if (mate) {
+			hwif->mate = mate;
+			mate->mate = hwif;
+		}
+		mate = hwif;	/* for next iteration */
 		if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
 			ide_init_hwif_ports(hwif->io_ports, base, NULL);
 			hwif->io_ports[IDE_CONTROL_OFFSET] = ctl + 2;
 		}
-		if (!hwif->irq)
-			hwif->irq = port ? 0 : pciirq;	/* always probe for secondary irq */
 		if (bmiba) {
 			if ((inb(bmiba+2) & 0x80)) {	/* simplex DMA only? */
 				printk("%s: simplex device:  DMA disabled\n", d->name);
 			} else {	/* supports simultaneous DMA on both channels */
-				ide_setup_dma(hwif, bmiba + (8 * port));
+				ide_setup_dma(hwif, bmiba + (8 * port), 8);
 			}
 		}
+		if (d->id) {  /* For "known" chipsets, allow other irqs during i/o */
+			hwif->drives[0].unmask = 1;
+			hwif->drives[1].unmask = 1;
+		}
 		if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
 			d->init_hwif(bus, fn, hwif);
 		at_least_one_hwif_enabled = 1;
 	}
 	if (!at_least_one_hwif_enabled)
-		printk("%s: neither IDE port is enabled\n", d->name);
+		printk("%s: neither IDE port enabled (BIOS)\n", d->name);
 }
 
 /*
@@ -570,9 +612,9 @@
 __initfunc(static inline void ide_scan_pci_device (unsigned int bus, unsigned int fn))
 {
 	unsigned int devid, ccode;
-	unsigned short pcicmd;
+	unsigned short pcicmd, class;
 	ide_pci_device_t *d;
-	byte hedt;
+	byte hedt, progif;
 
 	if (pcibios_read_config_byte(bus, fn, 0x0e, &hedt))
 		hedt = 0;
@@ -582,26 +624,36 @@
 		 || pcibios_read_config_dword(bus, fn, 0x08, &ccode))
 			return;
 		d = lookup_devid(devid);
-		if (d->name == NULL)	/* some chips (cmd640 & rz1000) are handled elsewhere */
+		if (d->name == NULL)	/* some chips (cmd640, rz1000) are handled elsewhere */
 			continue;
-		if (d->id || (ccode >> 16) == PCI_CLASS_STORAGE_IDE) {
-			printk("%s: %sIDE device on PCI bus %d function %d\n", d->name, d->id ? "" : "unknown ", bus, fn);
+		progif = (ccode >> 8) & 0xff;
+		class = ccode >> 16;
+		if (d->id || class == PCI_CLASS_STORAGE_IDE) {
+			if (d->id)
+				printk("%s: IDE device on PCI bus %d function %d\n", d->name, bus, fn);
+			else
+				printk("%s: unknown IDE device on PCI bus %d function %d, VID=%04x, DID=%04x\n",
+					d->name, bus, fn, devid & 0xffff, devid >> 16);
 			/*
-	 		* See if IDE ports are enabled
-	 		*/
+	 		 * See if IDE ports are enabled
+	 		 */
 			if (pcibios_read_config_word(bus, fn, 0x04, &pcicmd)) {
 				printk("%s: error accessing PCICMD\n", d->name);
 			} else if ((pcicmd & 1) == 0) {
-				printk("%s: device is disabled (BIOS)\n", d->name);
+				printk("%s: device disabled (BIOS)\n", d->name);
 			} else {
 				unsigned int bmiba = 0;
 				/*
-		 		 * Check for Bus-Master DMA capability
-		 		 */
-				if (!(pcicmd & 4) || !(bmiba = ide_get_or_set_bmiba(bus, fn, d->name))) {
-					if ((ccode >> 16) == PCI_CLASS_STORAGE_RAID || (ccode && 0x8000))
-						printk("%s: Bus-Master DMA is disabled (BIOS)\n", d->name);
+			 	 * Check for Bus-Master DMA capability
+			 	 */
+				if (d->id == DEVID_PDC20246 || (class == PCI_CLASS_STORAGE_IDE && (progif & 0x80))) {
+					if ((!(pcicmd & 4) || !(bmiba = ide_get_or_set_bmiba(bus, fn, d->name)))) {
+						printk("%s: Bus-Master DMA disabled (BIOS), pcicmd=0x%04x, progif=0x%02x, bmiba=0x%04x\n", d->name, pcicmd, progif, bmiba);
+					}
 				}
+				/*
+				 * Setup the IDE ports
+				 */
 				ide_setup_pci_device(bus, fn, bmiba, d);
 			}
 		}

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