patch-2.4.0-test2 linux/drivers/ide/amd7409.c

Next file: linux/drivers/ide/cmd64x.c
Previous file: linux/drivers/ide/alim15x3.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test1/linux/drivers/ide/amd7409.c linux/drivers/ide/amd7409.c
@@ -1,7 +1,7 @@
 /*
- * linux/drivers/ide/amd7409.c		Version 0.04	Mar. 18, 2000
+ * linux/drivers/ide/amd7409.c		Version 0.05	June 9, 2000
  *
- * Copyright (C) 2000			Andre Hedrick <andre@suse.com>
+ * Copyright (C) 1999-2000		Andre Hedrick <andre@linux-ide.org>
  * May be copied or modified under the terms of the GNU General Public License
  *
  */
@@ -40,7 +40,7 @@
 static int amd7409_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	u32 bibma = bmide_dev->resource[4].start;
+	u32 bibma = pci_resource_start(bmide_dev, 4);
 	u8 c0 = 0, c1 = 0;
 
 	/*
@@ -71,6 +71,20 @@
 
 extern char *ide_xfer_verbose (byte xfer_rate);
 
+static unsigned int amd7409_swdma_check (struct pci_dev *dev)
+{
+	unsigned int class_rev;
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+	return ((int) (class_rev >= 7) ? 1 : 0);
+}
+
+static int amd7409_swdma_error(ide_drive_t *drive)
+{
+	printk("%s: single-word DMA not support (revision < C4)\n", drive->name);
+	return 0;
+}
+
 /*
  * Here is where all the hard work goes to program the chipset.
  *
@@ -122,64 +136,68 @@
 		case XFER_UDMA_4:
 			ultra_timing |= 0x45;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_UDMA_3:
 			ultra_timing |= 0x44;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_UDMA_2:
 			ultra_timing |= 0x40;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_UDMA_1:
 			ultra_timing |= 0x41;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_UDMA_0:
 			ultra_timing |= 0x42;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_MW_DMA_2:
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_MW_DMA_1:
 			dma_pio_timing |= 0x21;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_MW_DMA_0:
 			dma_pio_timing |= 0x77;
-			pio_timing |= (0x03 << drive->dn);
+			break;
+		case XFER_SW_DMA_2:
+			if (!amd7409_swdma_check(dev))
+				return amd7409_swdma_error(drive);
+			dma_pio_timing |= 0x42;
+			break;
+		case XFER_SW_DMA_1:
+			if (!amd7409_swdma_check(dev))
+				return amd7409_swdma_error(drive);
+			dma_pio_timing |= 0x65;
+			break;
+		case XFER_SW_DMA_0:
+			if (!amd7409_swdma_check(dev))
+				return amd7409_swdma_error(drive);
+			dma_pio_timing |= 0xA8;
 			break;
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_PIO_3:
 			dma_pio_timing |= 0x22;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_PIO_2:
 			dma_pio_timing |= 0x42;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_PIO_1:
 			dma_pio_timing |= 0x65;
-			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_PIO_0:
 		default:
 			dma_pio_timing |= 0xA8;
-			pio_timing |= (0x03 << drive->dn);
 			break;
         }
 
+	pio_timing |= (0x03 << drive->dn);
+
 	if (!drive->init_speed)
 		drive->init_speed = speed;
 
@@ -268,12 +286,14 @@
 static int config_chipset_for_dma (ide_drive_t *drive)
 {
 	struct hd_driveid *id	= drive->id;
-	byte udma_66		= ((id->hw_config & 0x2000) &&
-				   (HWIF(drive)->udma_four)) ? 1 : 0;
+	byte udma_66		= eighty_ninty_three(drive);
+	byte udma_100		= 0;
 	byte speed		= 0x00;
 	int  rval;
 
-	if ((id->dma_ultra & 0x0010) && (udma_66)) {
+	if ((id->dma_ultra & 0x0020) && (udma_66)&& (udma_100)) {
+		speed = XFER_UDMA_5;
+	} else if ((id->dma_ultra & 0x0010) && (udma_66)) {
 		speed = XFER_UDMA_4;
 	} else if ((id->dma_ultra & 0x0008) && (udma_66)) {
 		speed = XFER_UDMA_3;
@@ -318,7 +338,7 @@
 		}
 		dma_func = ide_dma_off_quietly;
 		if (id->field_valid & 4) {
-			if (id->dma_ultra & 0x001F) {
+			if (id->dma_ultra & 0x002F) {
 				/* Force if Capable UltraDMA */
 				dma_func = config_chipset_for_dma(drive);
 				if ((id->field_valid & 2) &&
@@ -327,12 +347,15 @@
 			}
 		} else if (id->field_valid & 2) {
 try_dma_modes:
-			if (id->dma_mword & 0x0007) {
+			if ((id->dma_mword & 0x0007) ||
+			    ((id->dma_1word & 0x007) &&
+			     (amd7409_swdma_check(HWIF(drive)->pci_dev)))) {
 				/* Force if Capable regular DMA modes */
 				dma_func = config_chipset_for_dma(drive);
 				if (dma_func != ide_dma_on)
 					goto no_dma_set;
 			}
+			
 		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
 			if (id->eide_dma_time > 150) {
 				goto no_dma_set;
@@ -372,9 +395,14 @@
 
 unsigned int __init pci_init_amd7409 (struct pci_dev *dev, const char *name)
 {
-	unsigned long fixdma_base = dev->resource[4].start;
+	unsigned long fixdma_base = pci_resource_start(dev, 4);
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	if (!amd7409_swdma_check(dev))
+		printk("%s: disabling single-word DMA support (revision < C4)\n", name);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 
-	if (!fixdma_base || fixdma_base == PCI_BASE_ADDRESS_IO_MASK) {
+	if (!fixdma_base) {
 		/*
 		 *
 		 */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)