PATCH: amd7409.c

From: Bartlomiej Zolnierkiewicz (dake@staszic.waw.pl)
Date: Tue May 30 2000 - 17:07:02 EST


Hi
        following patch:

* adds support for single-word DMA modes for chipset revisions >= C4
* prints nice :) info when chipset revision is < C4
* adds info about available AMD's datasheets
* moves 'pio_timing |= (0x03 << drive->dn);' outside switch(speed) {}
  in function amd7409_tune_chipset ()
* removes two unused externs

This patch is against kernel 2.4.0-test1-ac4 but also applies cleanly to
vanilla 2.4.0-test1 and ac1/ac2/ac5.

It hasn't been tested because I don't have AMD7409. Please test it.

diff -u linux.240t1ac4/drivers/ide/amd7409.c linux/drivers/ide/amd7409.c
--- linux.240t1ac4/drivers/ide/amd7409.c Sat May 27 02:54:22 2000
+++ linux/drivers/ide/amd7409.c Tue May 30 22:27:08 2000
@@ -4,6 +4,11 @@
  * Copyright (C) 2000 Andre Hedrick <andre@suse.com>
  * May be copied or modified under the terms of the GNU General Public License
  *
+ * "AMD-756(TM) Peripheral Bus Controller Data Sheet" is available at:
+ * http://www.amd.com/products/cpg/athlon/techdocs/pdf/22548.pdf
+ * and "AMD-756(TM) Peripheral Bus Controller Revision Guide" at:
+ * http://www.amd.com/products/cpg/athlon/techdocs/pdf/22591.pdf
+ *
  */
 
 #include <linux/config.h>
@@ -26,6 +31,10 @@
 
 #include "ide_modes.h"
 
+#ifdef CONFIG_BLK_DEV_IDEDMA
+byte 1word_dma_ok = 0;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
 #define DISPLAY_VIPER_TIMINGS
 
 #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
@@ -34,7 +43,6 @@
 
 static int amd7409_get_info(char *, char **, off_t, int);
 extern int (*amd7409_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-extern char *ide_media_verbose(ide_drive_t *);
 static struct pci_dev *bmide_dev;
 
 static int amd7409_get_info (char *buffer, char **addr, off_t offset, int count)
@@ -69,11 +77,8 @@
 
 byte amd7409_proc = 0;
 
-extern char *ide_xfer_verbose (byte xfer_rate);
-
 /*
  * Here is where all the hard work goes to program the chipset.
- *
  */
 static int amd7409_tune_chipset (ide_drive_t *drive, byte speed)
 {
@@ -122,63 +127,60 @@
                 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:
+ dma_pio_timing |= 0x42;
+ break;
+ case XFER_SW_DMA_1:
+ dma_pio_timing |= 0x65;
+ break;
+ case XFER_SW_DMA_0:
+ 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;
@@ -289,6 +291,12 @@
                 speed = XFER_MW_DMA_1;
         } else if (id->dma_mword & 0x0001) {
                 speed = XFER_MW_DMA_0;
+ } else if ((id->dma_1word & 0x0004) && 1word_dma_ok) {
+ speed = XFER_SW_DMA_2;
+ } else if ((id->dma_1word & 0x0002) && 1word_dma_ok) {
+ speed = XFER_SW_DMA_1;
+ } else if ((id->dma_1word & 0x0001) && 1word_dma_ok) {
+ speed = XFER_SW_DMA_0;
         } else {
                 return ((int) ide_dma_off_quietly);
         }
@@ -327,7 +335,8 @@
                         }
                 } else if (id->field_valid & 2) {
 try_dma_modes:
- if (id->dma_mword & 0x0007) {
+ if ((id->dma_mword & 0x0007) ||
+ (id>dma_1word & 0x007)) {
                                 /* Force if Capable regular DMA modes */
                                 dma_func = config_chipset_for_dma(drive);
                                 if (dma_func != ide_dma_on)
@@ -357,7 +366,6 @@
 /*
  * amd7409_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
  */
-
 int amd7409_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
         switch (func) {
@@ -373,6 +381,20 @@
 unsigned int __init pci_init_amd7409 (struct pci_dev *dev, const char *name)
 {
         unsigned long fixdma_base = dev->resource[4].start;
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ byte amd7409_rev;
+
+ /*
+ * single-word DMA is broken on silicon revisions < C4
+ */
+ pci_read_config_byte(dev, PCI_REVISION_ID, &amd7409_rev);
+
+ if (amd7409_rev >= 7)
+ 1word_dma_ok = 1;
+
+ if (!1word_dma_ok)
+ printk("AMD7409: disabling single-word DMA support (revision < C4)\n");
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 
         if (!fixdma_base || fixdma_base == PCI_BASE_ADDRESS_IO_MASK) {
                 /*
@@ -387,6 +409,7 @@
                 if (inb(fixdma_base+2) & 0x80)
                         printk("%s: simplex device: DMA will fail!!\n", name);
         }
+
 #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
         if (!amd7409_proc) {
                 amd7409_proc = 1;

--
Bartlomiej Zolnierkiewicz <bkz>

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed May 31 2000 - 21:00:25 EST