vserver 1.9.5.x5
[linux-2.6.git] / drivers / ide / pci / hpt366.c
index 77bc208..c8ee0b8 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * linux/drivers/ide/pci/hpt366.c              Version 0.34    Sept 17, 2002
+ * linux/drivers/ide/pci/hpt366.c              Version 0.36    April 25, 2003
  *
  * Copyright (C) 1999-2003             Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001         Sun Microsystems, Inc.
+ * Portions Copyright (C) 2003         Red Hat Inc
  *
  * Thanks to HighPoint Technologies for their assistance, and hardware.
  * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
  * Reset the hpt366 on error, reset on dma
  * Fix disabling Fast Interrupt hpt366.
  *     Mike Waychison <crlf@sun.com>
+ *
+ * Added support for 372N clocking and clock switching. The 372N needs
+ * different clocks on read/write. This requires overloading rw_disk and
+ * other deeply crazy things. Thanks to <http://www.hoerstreich.de> for
+ * keeping me sane. 
+ *             Alan Cox <alan@redhat.com>
+ *
  */
 
 
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "hpt366.h"
+/* various tuning parameters */
+#define HPT_RESET_STATE_ENGINE
+#undef HPT_DELAY_INTERRUPT
+#undef HPT_SERIALIZE_IO
+
+static const char *quirk_drives[] = {
+       "QUANTUM FIREBALLlct08 08",
+       "QUANTUM FIREBALLP KA6.4",
+       "QUANTUM FIREBALLP LM20.4",
+       "QUANTUM FIREBALLP LM20.5",
+       NULL
+};
 
-#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
+static const char *bad_ata100_5[] = {
+       "IBM-DTLA-307075",
+       "IBM-DTLA-307060",
+       "IBM-DTLA-307045",
+       "IBM-DTLA-307030",
+       "IBM-DTLA-307020",
+       "IBM-DTLA-307015",
+       "IBM-DTLA-305040",
+       "IBM-DTLA-305030",
+       "IBM-DTLA-305020",
+       "IC35L010AVER07-0",
+       "IC35L020AVER07-0",
+       "IC35L030AVER07-0",
+       "IC35L040AVER07-0",
+       "IC35L060AVER07-0",
+       "WDC AC310200R",
+       NULL
+};
 
-static unsigned int hpt_revision(struct pci_dev *dev);
-static unsigned int hpt_minimum_revision(struct pci_dev *dev, int revision);
+static const char *bad_ata66_4[] = {
+       "IBM-DTLA-307075",
+       "IBM-DTLA-307060",
+       "IBM-DTLA-307045",
+       "IBM-DTLA-307030",
+       "IBM-DTLA-307020",
+       "IBM-DTLA-307015",
+       "IBM-DTLA-305040",
+       "IBM-DTLA-305030",
+       "IBM-DTLA-305020",
+       "IC35L010AVER07-0",
+       "IC35L020AVER07-0",
+       "IC35L030AVER07-0",
+       "IC35L040AVER07-0",
+       "IC35L060AVER07-0",
+       "WDC AC310200R",
+       NULL
+};
 
-#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
+static const char *bad_ata66_3[] = {
+       "WDC AC310200R",
+       NULL
+};
 
-static u8 hpt366_proc = 0;
-static struct pci_dev *hpt_devs[HPT366_MAX_DEVS];
-static int n_hpt_devs;
+static const char *bad_ata33[] = {
+       "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
+       "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
+       "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
+       "Maxtor 90510D4",
+       "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
+       "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
+       "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
+       NULL
+};
 
-static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-       char *p = buffer;
-       char *chipset_nums[] = {"366", "366",  "368",
-                               "370", "370A", "372",
-                               "302", "371",  "374" };
-       int i, len;
-
-       p += sprintf(p, "\n                             "
-               "HighPoint HPT366/368/370/372/374\n");
-       for (i = 0; i < n_hpt_devs; i++) {
-               struct pci_dev *dev = hpt_devs[i];
-               unsigned long iobase = dev->resource[4].start;
-               u32 class_rev = hpt_revision(dev);
-               u8 c0, c1;
-
-               p += sprintf(p, "\nController: %d\n", i);
-               p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]);
-               p += sprintf(p, "--------------- Primary Channel "
-                               "--------------- Secondary Channel "
-                               "--------------\n");
-
-               /* get the bus master status registers */
-               c0 = inb(iobase + 0x2);
-               c1 = inb(iobase + 0xa);
-               p += sprintf(p, "Enabled:        %s"
-                               "                             %s\n",
-                       (c0 & 0x80) ? "no" : "yes",
-                       (c1 & 0x80) ? "no" : "yes");
+struct chipset_bus_clock_list_entry {
+       u8              xfer_speed;
+       unsigned int    chipset_settings;
+};
+
+/* key for bus clock timings
+ * bit
+ * 0:3    data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW
+ *        DMA. cycles = value + 1
+ * 4:8    data_low_time. active time of DIOW_/DIOR_ for PIO and MW
+ *        DMA. cycles = value + 1
+ * 9:12   cmd_high_time. inactive time of DIOW_/DIOR_ during task file
+ *        register access.
+ * 13:17  cmd_low_time. active time of DIOW_/DIOR_ during task file
+ *        register access.
+ * 18:21  udma_cycle_time. clock freq and clock cycles for UDMA xfer.
+ *        during task file register access.
+ * 22:24  pre_high_time. time to initialize 1st cycle for PIO and MW DMA
+ *        xfer.
+ * 25:27  cmd_pre_high_time. time to initialize 1st PIO cycle for task
+ *        register access.
+ * 28     UDMA enable
+ * 29     DMA enable
+ * 30     PIO_MST enable. if set, the chip is in bus master mode during
+ *        PIO.
+ * 31     FIFO enable.
+ */
+static struct chipset_bus_clock_list_entry forty_base_hpt366[] = {
+       {       XFER_UDMA_4,    0x900fd943      },
+       {       XFER_UDMA_3,    0x900ad943      },
+       {       XFER_UDMA_2,    0x900bd943      },
+       {       XFER_UDMA_1,    0x9008d943      },
+       {       XFER_UDMA_0,    0x9008d943      },
+
+       {       XFER_MW_DMA_2,  0xa008d943      },
+       {       XFER_MW_DMA_1,  0xa010d955      },
+       {       XFER_MW_DMA_0,  0xa010d9fc      },
+
+       {       XFER_PIO_4,     0xc008d963      },
+       {       XFER_PIO_3,     0xc010d974      },
+       {       XFER_PIO_2,     0xc010d997      },
+       {       XFER_PIO_1,     0xc010d9c7      },
+       {       XFER_PIO_0,     0xc018d9d9      },
+       {       0,              0x0120d9d9      }
+};
+
+static struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = {
+       {       XFER_UDMA_4,    0x90c9a731      },
+       {       XFER_UDMA_3,    0x90cfa731      },
+       {       XFER_UDMA_2,    0x90caa731      },
+       {       XFER_UDMA_1,    0x90cba731      },
+       {       XFER_UDMA_0,    0x90c8a731      },
+
+       {       XFER_MW_DMA_2,  0xa0c8a731      },
+       {       XFER_MW_DMA_1,  0xa0c8a732      },      /* 0xa0c8a733 */
+       {       XFER_MW_DMA_0,  0xa0c8a797      },
+
+       {       XFER_PIO_4,     0xc0c8a731      },
+       {       XFER_PIO_3,     0xc0c8a742      },
+       {       XFER_PIO_2,     0xc0d0a753      },
+       {       XFER_PIO_1,     0xc0d0a7a3      },      /* 0xc0d0a793 */
+       {       XFER_PIO_0,     0xc0d0a7aa      },      /* 0xc0d0a7a7 */
+       {       0,              0x0120a7a7      }
+};
+
+static struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = {
+       {       XFER_UDMA_4,    0x90c98521      },
+       {       XFER_UDMA_3,    0x90cf8521      },
+       {       XFER_UDMA_2,    0x90cf8521      },
+       {       XFER_UDMA_1,    0x90cb8521      },
+       {       XFER_UDMA_0,    0x90cb8521      },
+
+       {       XFER_MW_DMA_2,  0xa0ca8521      },
+       {       XFER_MW_DMA_1,  0xa0ca8532      },
+       {       XFER_MW_DMA_0,  0xa0ca8575      },
+
+       {       XFER_PIO_4,     0xc0ca8521      },
+       {       XFER_PIO_3,     0xc0ca8532      },
+       {       XFER_PIO_2,     0xc0ca8542      },
+       {       XFER_PIO_1,     0xc0d08572      },
+       {       XFER_PIO_0,     0xc0d08585      },
+       {       0,              0x01208585      }
+};
+
+/* from highpoint documentation. these are old values */
+static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = {
+/*     {       XFER_UDMA_5,    0x1A85F442,     0x16454e31      }, */
+       {       XFER_UDMA_5,    0x16454e31      },
+       {       XFER_UDMA_4,    0x16454e31      },
+       {       XFER_UDMA_3,    0x166d4e31      },
+       {       XFER_UDMA_2,    0x16494e31      },
+       {       XFER_UDMA_1,    0x164d4e31      },
+       {       XFER_UDMA_0,    0x16514e31      },
+
+       {       XFER_MW_DMA_2,  0x26514e21      },
+       {       XFER_MW_DMA_1,  0x26514e33      },
+       {       XFER_MW_DMA_0,  0x26514e97      },
+
+       {       XFER_PIO_4,     0x06514e21      },
+       {       XFER_PIO_3,     0x06514e22      },
+       {       XFER_PIO_2,     0x06514e33      },
+       {       XFER_PIO_1,     0x06914e43      },
+       {       XFER_PIO_0,     0x06914e57      },
+       {       0,              0x06514e57      }
+};
+
+static struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = {
+       {       XFER_UDMA_5,    0x14846231      },
+       {       XFER_UDMA_4,    0x14886231      },
+       {       XFER_UDMA_3,    0x148c6231      },
+       {       XFER_UDMA_2,    0x148c6231      },
+       {       XFER_UDMA_1,    0x14906231      },
+       {       XFER_UDMA_0,    0x14986231      },
+
+       {       XFER_MW_DMA_2,  0x26514e21      },
+       {       XFER_MW_DMA_1,  0x26514e33      },
+       {       XFER_MW_DMA_0,  0x26514e97      },
+
+       {       XFER_PIO_4,     0x06514e21      },
+       {       XFER_PIO_3,     0x06514e22      },
+       {       XFER_PIO_2,     0x06514e33      },
+       {       XFER_PIO_1,     0x06914e43      },
+       {       XFER_PIO_0,     0x06914e57      },
+       {       0,              0x06514e57      }
+};
+
+/* these are the current (4 sep 2001) timings from highpoint */
+static struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = {
+       {       XFER_UDMA_5,    0x12446231      },
+       {       XFER_UDMA_4,    0x12446231      },
+       {       XFER_UDMA_3,    0x126c6231      },
+       {       XFER_UDMA_2,    0x12486231      },
+       {       XFER_UDMA_1,    0x124c6233      },
+       {       XFER_UDMA_0,    0x12506297      },
+
+       {       XFER_MW_DMA_2,  0x22406c31      },
+       {       XFER_MW_DMA_1,  0x22406c33      },
+       {       XFER_MW_DMA_0,  0x22406c97      },
+
+       {       XFER_PIO_4,     0x06414e31      },
+       {       XFER_PIO_3,     0x06414e42      },
+       {       XFER_PIO_2,     0x06414e53      },
+       {       XFER_PIO_1,     0x06814e93      },
+       {       XFER_PIO_0,     0x06814ea7      },
+       {       0,              0x06814ea7      }
+};
+
+/* 2x 33MHz timings */
+static struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = {
+       {       XFER_UDMA_5,    0x1488e673      },
+       {       XFER_UDMA_4,    0x1488e673      },
+       {       XFER_UDMA_3,    0x1498e673      },
+       {       XFER_UDMA_2,    0x1490e673      },
+       {       XFER_UDMA_1,    0x1498e677      },
+       {       XFER_UDMA_0,    0x14a0e73f      },
+
+       {       XFER_MW_DMA_2,  0x2480fa73      },
+       {       XFER_MW_DMA_1,  0x2480fa77      }, 
+       {       XFER_MW_DMA_0,  0x2480fb3f      },
+
+       {       XFER_PIO_4,     0x0c82be73      },
+       {       XFER_PIO_3,     0x0c82be95      },
+       {       XFER_PIO_2,     0x0c82beb7      },
+       {       XFER_PIO_1,     0x0d02bf37      },
+       {       XFER_PIO_0,     0x0d02bf5f      },
+       {       0,              0x0d02bf5f      }
+};
+
+static struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = {
+       {       XFER_UDMA_5,    0x12848242      },
+       {       XFER_UDMA_4,    0x12ac8242      },
+       {       XFER_UDMA_3,    0x128c8242      },
+       {       XFER_UDMA_2,    0x120c8242      },
+       {       XFER_UDMA_1,    0x12148254      },
+       {       XFER_UDMA_0,    0x121882ea      },
+
+       {       XFER_MW_DMA_2,  0x22808242      },
+       {       XFER_MW_DMA_1,  0x22808254      },
+       {       XFER_MW_DMA_0,  0x228082ea      },
+
+       {       XFER_PIO_4,     0x0a81f442      },
+       {       XFER_PIO_3,     0x0a81f443      },
+       {       XFER_PIO_2,     0x0a81f454      },
+       {       XFER_PIO_1,     0x0ac1f465      },
+       {       XFER_PIO_0,     0x0ac1f48a      },
+       {       0,              0x0ac1f48a      }
+};
+
+static struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = {
+       {       XFER_UDMA_6,    0x1c81dc62      },
+       {       XFER_UDMA_5,    0x1c6ddc62      },
+       {       XFER_UDMA_4,    0x1c8ddc62      },
+       {       XFER_UDMA_3,    0x1c8edc62      },      /* checkme */
+       {       XFER_UDMA_2,    0x1c91dc62      },
+       {       XFER_UDMA_1,    0x1c9adc62      },      /* checkme */
+       {       XFER_UDMA_0,    0x1c82dc62      },      /* checkme */
+
+       {       XFER_MW_DMA_2,  0x2c829262      },
+       {       XFER_MW_DMA_1,  0x2c829266      },      /* checkme */
+       {       XFER_MW_DMA_0,  0x2c82922e      },      /* checkme */
+
+       {       XFER_PIO_4,     0x0c829c62      },
+       {       XFER_PIO_3,     0x0c829c84      },
+       {       XFER_PIO_2,     0x0c829ca6      },
+       {       XFER_PIO_1,     0x0d029d26      },
+       {       XFER_PIO_0,     0x0d029d5e      },
+       {       0,              0x0d029d5e      }
+};
+
+static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = {
+       {       XFER_UDMA_5,    0x12848242      },
+       {       XFER_UDMA_4,    0x12ac8242      },
+       {       XFER_UDMA_3,    0x128c8242      },
+       {       XFER_UDMA_2,    0x120c8242      },
+       {       XFER_UDMA_1,    0x12148254      },
+       {       XFER_UDMA_0,    0x121882ea      },
+
+       {       XFER_MW_DMA_2,  0x22808242      },
+       {       XFER_MW_DMA_1,  0x22808254      },
+       {       XFER_MW_DMA_0,  0x228082ea      },
+
+       {       XFER_PIO_4,     0x0a81f442      },
+       {       XFER_PIO_3,     0x0a81f443      },
+       {       XFER_PIO_2,     0x0a81f454      },
+       {       XFER_PIO_1,     0x0ac1f465      },
+       {       XFER_PIO_0,     0x0ac1f48a      },
+       {       0,              0x0a81f443      }
+};
+
+static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = {
+       {       XFER_UDMA_6,    0x1c869c62      },
+       {       XFER_UDMA_5,    0x1cae9c62      },
+       {       XFER_UDMA_4,    0x1c8a9c62      },
+       {       XFER_UDMA_3,    0x1c8e9c62      },
+       {       XFER_UDMA_2,    0x1c929c62      },
+       {       XFER_UDMA_1,    0x1c9a9c62      },
+       {       XFER_UDMA_0,    0x1c829c62      },
+
+       {       XFER_MW_DMA_2,  0x2c829c62      },
+       {       XFER_MW_DMA_1,  0x2c829c66      },
+       {       XFER_MW_DMA_0,  0x2c829d2e      },
+
+       {       XFER_PIO_4,     0x0c829c62      },
+       {       XFER_PIO_3,     0x0c829c84      },
+       {       XFER_PIO_2,     0x0c829ca6      },
+       {       XFER_PIO_1,     0x0d029d26      },
+       {       XFER_PIO_0,     0x0d029d5e      },
+       {       0,              0x0d029d26      }
+};
+
+static struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = {
+       {       XFER_UDMA_6,    0x12808242      },
+       {       XFER_UDMA_5,    0x12848242      },
+       {       XFER_UDMA_4,    0x12ac8242      },
+       {       XFER_UDMA_3,    0x128c8242      },
+       {       XFER_UDMA_2,    0x120c8242      },
+       {       XFER_UDMA_1,    0x12148254      },
+       {       XFER_UDMA_0,    0x121882ea      },
+
+       {       XFER_MW_DMA_2,  0x22808242      },
+       {       XFER_MW_DMA_1,  0x22808254      },
+       {       XFER_MW_DMA_0,  0x228082ea      },
+
+       {       XFER_PIO_4,     0x0a81f442      },
+       {       XFER_PIO_3,     0x0a81f443      },
+       {       XFER_PIO_2,     0x0a81f454      },
+       {       XFER_PIO_1,     0x0ac1f465      },
+       {       XFER_PIO_0,     0x0ac1f48a      },
+       {       0,              0x06814e93      }
+};
+
+/* FIXME: 50MHz timings for HPT374 */
+
+#if 0
+static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = {
+       {       XFER_UDMA_6,    0x12406231      },      /* checkme */
+       {       XFER_UDMA_5,    0x12446231      },      /* 0x14846231 */
+       {       XFER_UDMA_4,    0x16814ea7      },      /* 0x14886231 */
+       {       XFER_UDMA_3,    0x16814ea7      },      /* 0x148c6231 */
+       {       XFER_UDMA_2,    0x16814ea7      },      /* 0x148c6231 */
+       {       XFER_UDMA_1,    0x16814ea7      },      /* 0x14906231 */
+       {       XFER_UDMA_0,    0x16814ea7      },      /* 0x14986231 */
+       {       XFER_MW_DMA_2,  0x16814ea7      },      /* 0x26514e21 */
+       {       XFER_MW_DMA_1,  0x16814ea7      },      /* 0x26514e97 */
+       {       XFER_MW_DMA_0,  0x16814ea7      },      /* 0x26514e97 */
+       {       XFER_PIO_4,     0x06814ea7      },      /* 0x06514e21 */
+       {       XFER_PIO_3,     0x06814ea7      },      /* 0x06514e22 */
+       {       XFER_PIO_2,     0x06814ea7      },      /* 0x06514e33 */
+       {       XFER_PIO_1,     0x06814ea7      },      /* 0x06914e43 */
+       {       XFER_PIO_0,     0x06814ea7      },      /* 0x06914e57 */
+       {       0,              0x06814ea7      }
+};
+#endif
+
+#define HPT366_DEBUG_DRIVE_INFO                0
+#define HPT374_ALLOW_ATA133_6          0
+#define HPT371_ALLOW_ATA133_6          0
+#define HPT302_ALLOW_ATA133_6          0
+#define HPT372_ALLOW_ATA133_6          1
+#define HPT370_ALLOW_ATA100_5          1
+#define HPT366_ALLOW_ATA66_4           1
+#define HPT366_ALLOW_ATA66_3           1
+#define HPT366_MAX_DEVS                        8
+
+#define F_LOW_PCI_33   0x23
+#define F_LOW_PCI_40   0x29
+#define F_LOW_PCI_50   0x2d
+#define F_LOW_PCI_66   0x42
+
+/* FIXME: compare with driver's code before removing */
 #if 0
                if (hpt_minimum_revision(dev, 3)) {
                        u8 cbl;
@@ -120,16 +460,6 @@ static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count)
                                (cbl & 0x01) ? 33 : 66);
                        p += sprintf(p, "\n");
                }
-#endif
-               p += sprintf(p, "--------------- drive0 --------- drive1 "
-                               "------- drive0 ---------- drive1 -------\n");
-               p += sprintf(p, "DMA capable:    %s              %s" 
-                               "            %s               %s\n",
-                       (c0 & 0x20) ? "yes" : "no ", 
-                       (c0 & 0x40) ? "yes" : "no ",
-                       (c1 & 0x20) ? "yes" : "no ", 
-                       (c1 & 0x40) ? "yes" : "no ");
-
                {
                        u8 c2, c3;
                        /* older revs don't have these registers mapped 
@@ -151,15 +481,7 @@ static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count)
                                        (c3 & 0x80) ? "PIO " : "off ");
                }
        }
-       p += sprintf(p, "\n");
-
-       /* p - buffer must be less than 4k! */
-       len = (p - buffer) - offset;
-       *addr = buffer + offset;
-       
-       return len > count ? count : len;
-}
-#endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
+#endif
 
 static u32 hpt_revision (struct pci_dev *dev)
 {
@@ -168,6 +490,9 @@ static u32 hpt_revision (struct pci_dev *dev)
        class_rev &= 0xff;
 
        switch(dev->device) {
+               /* Remap new 372N onto 372 */
+               case PCI_DEVICE_ID_TTI_HPT372N:
+                       class_rev = PCI_DEVICE_ID_TTI_HPT372; break;
                case PCI_DEVICE_ID_TTI_HPT374:
                        class_rev = PCI_DEVICE_ID_TTI_HPT374; break;
                case PCI_DEVICE_ID_TTI_HPT371:
@@ -217,6 +542,11 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive)
        return mode;
 }
 
+/*
+ *     Note for the future; the SATA hpt37x we must set
+ *     either PIO or UDMA modes 0,4,5
+ */
 static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
 {
        struct pci_dev *dev     = HWIF(drive)->pci_dev;
@@ -292,7 +622,7 @@ static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_
        return chipset_table->chipset_settings;
 }
 
-static void hpt366_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 {
        struct pci_dev *dev     = HWIF(drive)->pci_dev;
        u8 speed                = hpt3xx_ratefilter(drive, xferspeed);
@@ -329,14 +659,11 @@ static void hpt366_tune_chipset (ide_drive_t *drive, u8 xferspeed)
        reg2 &= ~0x80000000;
 
        pci_write_config_dword(dev, regtime, reg2);
-}
 
-static void hpt368_tune_chipset (ide_drive_t *drive, u8 speed)
-{
-       hpt366_tune_chipset(drive, speed);
+       return ide_config_drive_speed(drive, speed);
 }
 
-static void hpt370_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 {
        struct pci_dev *dev = HWIF(drive)->pci_dev;
        u8 speed        = hpt3xx_ratefilter(drive, xferspeed);
@@ -378,9 +705,11 @@ static void hpt370_tune_chipset (ide_drive_t *drive, u8 xferspeed)
        }
 
        pci_write_config_dword(dev, drive_pci, list_conf);
+
+       return ide_config_drive_speed(drive, speed);
 }
 
-static void hpt372_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 {
        struct pci_dev *dev     = HWIF(drive)->pci_dev;
        u8 speed        = hpt3xx_ratefilter(drive, xferspeed);
@@ -406,11 +735,8 @@ static void hpt372_tune_chipset (ide_drive_t *drive, u8 xferspeed)
        if (speed < XFER_MW_DMA_0)
                list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
        pci_write_config_dword(dev, drive_pci, list_conf);
-}
 
-static void hpt374_tune_chipset (ide_drive_t *drive, u8 speed)
-{
-       hpt372_tune_chipset(drive, speed);
+       return ide_config_drive_speed(drive, speed);
 }
 
 static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed)
@@ -418,7 +744,7 @@ static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed)
        struct pci_dev *dev     = HWIF(drive)->pci_dev;
 
        if (hpt_minimum_revision(dev, 8))
-               hpt374_tune_chipset(drive, speed);
+               return hpt372_tune_chipset(drive, speed); /* not a typo */
 #if 0
        else if (hpt_minimum_revision(dev, 7))
                hpt371_tune_chipset(drive, speed);
@@ -426,15 +752,11 @@ static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed)
                hpt302_tune_chipset(drive, speed);
 #endif
        else if (hpt_minimum_revision(dev, 5))
-               hpt372_tune_chipset(drive, speed);
+               return hpt372_tune_chipset(drive, speed);
        else if (hpt_minimum_revision(dev, 3))
-               hpt370_tune_chipset(drive, speed);
-       else if (hpt_minimum_revision(dev, 2))
-               hpt368_tune_chipset(drive, speed);
-       else
-                hpt366_tune_chipset(drive, speed);
-
-       return ((int) ide_config_drive_speed(drive, speed));
+               return hpt370_tune_chipset(drive, speed);
+       else    /* hpt368: hpt_minimum_revision(dev, 2) */
+               return hpt36x_tune_chipset(drive, speed);
 }
 
 static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio)
@@ -513,35 +835,16 @@ static int hpt366_config_drive_xfer_rate (ide_drive_t *drive)
        drive->init_speed = 0;
 
        if (id && (id->capability & 1) && drive->autodma) {
-               /* Consult the list of known "bad" drives */
-               if (__ide_dma_bad_drive(drive))
-                       goto fast_ata_pio;
-               if (id->field_valid & 4) {
-                       if (id->dma_ultra & hwif->ultra_mask) {
-                               /* Force if Capable UltraDMA */
-                               int dma = config_chipset_for_dma(drive);
-                               if ((id->field_valid & 2) && !dma)
-                                       goto try_dma_modes;
-                       }
-               } else if (id->field_valid & 2) {
-try_dma_modes:
-                       if (id->dma_mword & hwif->mwdma_mask) {
-                               /* Force if Capable regular DMA modes */
-                               if (!config_chipset_for_dma(drive))
-                                       goto no_dma_set;
-                       }
-               } else if (__ide_dma_good_drive(drive) &&
-                          (id->eide_dma_time < 150)) {
-                       /* Consult the list of known "good" drives */
-                       if (!config_chipset_for_dma(drive))
-                               goto no_dma_set;
-               } else {
-                       goto fast_ata_pio;
+
+               if (ide_use_dma(drive)) {
+                       if (config_chipset_for_dma(drive))
+                               return hwif->ide_dma_on(drive);
                }
-               return hwif->ide_dma_on(drive);
+
+               goto fast_ata_pio;
+
        } else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
                hpt3xx_tune_drive(drive, 5);
                return hwif->ide_dma_off_quietly(drive);
        }
@@ -569,7 +872,7 @@ static int hpt366_ide_dma_lostirq (ide_drive_t *drive)
        /* how about we flush and reset, mmmkay? */
        pci_write_config_byte(dev, 0x51, 0x1F);
        /* fall through to a reset */
-       case ide_dma_begin:
+       case dma_start:
        case ide_dma_end:
        /* reset the chips state over and over.. */
        pci_write_config_byte(dev, 0x51, 0x13);
@@ -584,12 +887,12 @@ static void hpt370_clear_engine (ide_drive_t *drive)
        udelay(10);
 }
 
-static int hpt370_ide_dma_begin (ide_drive_t *drive)
+static void hpt370_ide_dma_start(ide_drive_t *drive)
 {
 #ifdef HPT_RESET_STATE_ENGINE
        hpt370_clear_engine(drive);
 #endif
-       return __ide_dma_begin(drive);
+       ide_dma_start(drive);
 }
 
 static int hpt370_ide_dma_end (ide_drive_t *drive)
@@ -680,6 +983,62 @@ static int hpt374_ide_dma_end (ide_drive_t *drive)
        return __ide_dma_end(drive);
 }
 
+/**
+ *     hpt372n_set_clock       -       perform clock switching dance
+ *     @drive: Drive to switch
+ *     @mode: Switching mode (0x21 for write, 0x23 otherwise)
+ *
+ *     Switch the DPLL clock on the HPT372N devices. This is a
+ *     right mess.
+ */
+static void hpt372n_set_clock(ide_drive_t *drive, int mode)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       
+       /* FIXME: should we check for DMA active and BUG() */
+       /* Tristate the bus */
+       outb(0x80, hwif->dma_base+0x73);
+       outb(0x80, hwif->dma_base+0x77);
+       
+       /* Switch clock and reset channels */
+       outb(mode, hwif->dma_base+0x7B);
+       outb(0xC0, hwif->dma_base+0x79);
+       
+       /* Reset state machines */
+       outb(0x37, hwif->dma_base+0x70);
+       outb(0x37, hwif->dma_base+0x74);
+       
+       /* Complete reset */
+       outb(0x00, hwif->dma_base+0x79);
+       
+       /* Reconnect channels to bus */
+       outb(0x00, hwif->dma_base+0x73);
+       outb(0x00, hwif->dma_base+0x77);
+}
+
+/**
+ *     hpt372n_rw_disk         -       prepare for I/O
+ *     @drive: drive for command
+ *     @rq: block request structure
+ *
+ *     This is called when a disk I/O is issued to the 372N.
+ *     We need it because of the clock switching.
+ */
+
+static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       int wantclock;
+
+       wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
+
+       if (hwif->config_data != wantclock) {
+               hpt372n_set_clock(drive, wantclock);
+               hwif->config_data = wantclock;
+       }
+}
+
 /*
  * Since SUN Cobalt is attempting to do this operation, I should disclose
  * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
@@ -706,9 +1065,6 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state)
        u8 reg59h = 0, reset    = (hwif->channel) ? 0x80 : 0x40;
        u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;
 
-       if (!hwif)
-               return -EINVAL;
-
 //     hwif->bus_state = state;
 
        pci_read_config_byte(dev, 0x59, &reg59h);
@@ -742,9 +1098,6 @@ static int hpt370_busproc(ide_drive_t * drive, int state)
        u8 tristate = 0, resetmask = 0, bus_reg = 0;
        u16 tri_reg;
 
-       if (!hwif)
-               return -EINVAL;
-
        hwif->bus_state = state;
 
        if (hwif->channel) { 
@@ -801,13 +1154,23 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
        u16 freq;
        u32 pll;
        u8 reg5bh;
-
-#if 1
        u8 reg5ah = 0;
+       unsigned long dmabase = pci_resource_start(dev, 4);
+       u8 did, rid;    
+       int is_372n = 0;
+       
        pci_read_config_byte(dev, 0x5a, &reg5ah);
        /* interrupt force enable */
        pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));
-#endif
+
+       if(dmabase)
+       {
+               did = inb(dmabase + 0x22);
+               rid = inb(dmabase + 0x28);
+       
+               if((did == 4 && rid == 6) || (did == 5 && rid > 1))
+                       is_372n = 1;
+       }
 
        /*
         * default to pci clock. make sure MA15/16 are set to output
@@ -818,47 +1181,86 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
        /*
         * set up the PLL. we need to adjust it so that it's stable. 
         * freq = Tpll * 192 / Tpci
+        *
+        * Todo. For non x86 should probably check the dword is
+        * set to 0xABCDExxx indicating the BIOS saved f_CNT
         */
        pci_read_config_word(dev, 0x78, &freq);
        freq &= 0x1FF;
-       if (freq < 0xa0) {
-               pll = F_LOW_PCI_33;
-               if (hpt_minimum_revision(dev,8))
-                       pci_set_drvdata(dev, (void *) thirty_three_base_hpt374);
-               else if (hpt_minimum_revision(dev,5))
-                       pci_set_drvdata(dev, (void *) thirty_three_base_hpt372);
-               else if (hpt_minimum_revision(dev,4))
-                       pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a);
+       
+       /*
+        * The 372N uses different PCI clock information and has
+        * some other complications
+        *      On PCI33 timing we must clock switch
+        *      On PCI66 timing we must NOT use the PCI clock
+        *
+        * Currently we always set up the PLL for the 372N
+        */
+        
+       pci_set_drvdata(dev, NULL);
+       
+       if(is_372n)
+       {
+               printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n");
+               if(freq < 0x55)
+                       pll = F_LOW_PCI_33;
+               else if(freq < 0x70)
+                       pll = F_LOW_PCI_40;
+               else if(freq < 0x7F)
+                       pll = F_LOW_PCI_50;
                else
-                       pci_set_drvdata(dev, (void *) thirty_three_base_hpt370);
-               printk("HPT37X: using 33MHz PCI clock\n");
-       } else if (freq < 0xb0) {
-               pll = F_LOW_PCI_40;
-       } else if (freq < 0xc8) {
-               pll = F_LOW_PCI_50;
-               if (hpt_minimum_revision(dev,8))
-                       pci_set_drvdata(dev, NULL);
-               else if (hpt_minimum_revision(dev,5))
-                       pci_set_drvdata(dev, (void *) fifty_base_hpt372);
-               else if (hpt_minimum_revision(dev,4))
-                       pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+                       pll = F_LOW_PCI_66;
+                       
+               printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll);
+                       
+               /* We always use the pll not the PCI clock on 372N */
+       }
+       else
+       {
+               if(freq < 0x9C)
+                       pll = F_LOW_PCI_33;
+               else if(freq < 0xb0)
+                       pll = F_LOW_PCI_40;
+               else if(freq <0xc8)
+                       pll = F_LOW_PCI_50;
                else
-                       pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
-               printk("HPT37X: using 50MHz PCI clock\n");
-       } else {
-               pll = F_LOW_PCI_66;
-               if (hpt_minimum_revision(dev,8))
-               {
-                       printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
-                       pci_set_drvdata(dev, NULL);
+                       pll = F_LOW_PCI_66;
+       
+               if (pll == F_LOW_PCI_33) {
+                       if (hpt_minimum_revision(dev,8))
+                               pci_set_drvdata(dev, (void *) thirty_three_base_hpt374);
+                       else if (hpt_minimum_revision(dev,5))
+                               pci_set_drvdata(dev, (void *) thirty_three_base_hpt372);
+                       else if (hpt_minimum_revision(dev,4))
+                               pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a);
+                       else
+                               pci_set_drvdata(dev, (void *) thirty_three_base_hpt370);
+                       printk("HPT37X: using 33MHz PCI clock\n");
+               } else if (pll == F_LOW_PCI_40) {
+                       /* Unsupported */
+               } else if (pll == F_LOW_PCI_50) {
+                       if (hpt_minimum_revision(dev,8))
+                               pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+                       else if (hpt_minimum_revision(dev,5))
+                               pci_set_drvdata(dev, (void *) fifty_base_hpt372);
+                       else if (hpt_minimum_revision(dev,4))
+                               pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+                       else
+                               pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+                       printk("HPT37X: using 50MHz PCI clock\n");
+               } else {
+                       if (hpt_minimum_revision(dev,8))
+                       {
+                               printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
+                       }
+                       else if (hpt_minimum_revision(dev,5))
+                               pci_set_drvdata(dev, (void *) sixty_six_base_hpt372);
+                       else if (hpt_minimum_revision(dev,4))
+                               pci_set_drvdata(dev, (void *) sixty_six_base_hpt370a);
+                       else
+                               pci_set_drvdata(dev, (void *) sixty_six_base_hpt370);
+                       printk("HPT37X: using 66MHz PCI clock\n");
                }
-               else if (hpt_minimum_revision(dev,5))
-                       pci_set_drvdata(dev, (void *) sixty_six_base_hpt372);
-               else if (hpt_minimum_revision(dev,4))
-                       pci_set_drvdata(dev, (void *) sixty_six_base_hpt370a);
-               else
-                       pci_set_drvdata(dev, (void *) sixty_six_base_hpt370);
-               printk("HPT37X: using 66MHz PCI clock\n");
        }
        
        /*
@@ -991,15 +1393,6 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
        }
        if (ret)
                return ret;
-       
-#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
-       hpt_devs[n_hpt_devs++] = dev;
-
-       if (!hpt366_proc) {
-               hpt366_proc = 1;
-               ide_pci_create_host_proc("hpt366", hpt366_get_info);
-       }
-#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */
 
        return dev->irq;
 }
@@ -1008,12 +1401,27 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
 {
        struct pci_dev *dev             = hwif->pci_dev;
        u8 ata66 = 0, regmask           = (hwif->channel) ? 0x01 : 0x02;
-
+       u8 did, rid;
+       unsigned long dmabase           = hwif->dma_base;
+       int is_372n = 0;
+       
+       if(dmabase)
+       {
+               did = inb(dmabase + 0x22);
+               rid = inb(dmabase + 0x28);
+       
+               if((did == 4 && rid == 6) || (did == 5 && rid > 1))
+                       is_372n = 1;
+       }
+               
        hwif->tuneproc                  = &hpt3xx_tune_drive;
        hwif->speedproc                 = &hpt3xx_tune_chipset;
        hwif->quirkproc                 = &hpt3xx_quirkproc;
        hwif->intrproc                  = &hpt3xx_intrproc;
        hwif->maskproc                  = &hpt3xx_maskproc;
+       
+       if(is_372n)
+               hwif->rw_disk = &hpt372n_rw_disk;
 
        /*
         * The HPT37x uses the CBLID pins as outputs for MA15/MA16
@@ -1101,7 +1509,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
                hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
                hwif->ide_dma_end = &hpt374_ide_dma_end;
        } else if (hpt_minimum_revision(dev,3)) {
-               hwif->ide_dma_begin = &hpt370_ide_dma_begin;
+               hwif->dma_start = &hpt370_ide_dma_start;
                hwif->ide_dma_end = &hpt370_ide_dma_end;
                hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
                hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq;
@@ -1151,12 +1559,12 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
        ide_setup_dma(hwif, dmabase, 8);
 }
 
-static void __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
+static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
 {
        struct pci_dev *findev = NULL;
 
        if (PCI_FUNC(dev->devfn) & 1)
-               return;
+               return -ENODEV;
 
        while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
                if ((findev->vendor == dev->vendor) &&
@@ -1169,40 +1577,46 @@ static void __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d
                                printk(KERN_WARNING "%s: pci-config space interrupt "
                                        "fixed.\n", d->name);
                        }
-                       ide_setup_pci_devices(dev, findev, d);
-                       return;
+                       return ide_setup_pci_devices(dev, findev, d);
                }
        }
-       ide_setup_pci_device(dev, d);
+       return ide_setup_pci_device(dev, d);
 }
 
-static void __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d)
+static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d)
 {
-       ide_setup_pci_device(dev, d);
+       return ide_setup_pci_device(dev, d);
 }
 
-static void __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
+static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
 {
        struct pci_dev *findev = NULL;
        u8 pin1 = 0, pin2 = 0;
        unsigned int class_rev;
        char *chipset_names[] = {"HPT366", "HPT366",  "HPT368",
-                                "HPT370", "HPT370A", "HPT372"};
+                                "HPT370", "HPT370A", "HPT372",
+                                "HPT372N" };
 
        if (PCI_FUNC(dev->devfn) & 1)
-               return;
+               return -ENODEV;
 
        pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
        class_rev &= 0xff;
 
-       strcpy(d->name, chipset_names[class_rev]);
+       if(dev->device == PCI_DEVICE_ID_TTI_HPT372N)
+               class_rev = 6;
+               
+       if(class_rev <= 6)
+               d->name = chipset_names[class_rev];
 
        switch(class_rev) {
+               case 6:
                case 5:
                case 4:
-               case 3: ide_setup_pci_device(dev, d);
-                       return;
-               default:        break;
+               case 3:
+                       goto init_single;
+               default:
+                       break;
        }
 
        d->channels = 1;
@@ -1220,13 +1634,71 @@ static void __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d
                                        "pin1=%d pin2=%d\n", d->name,
                                        pin1, pin2);
                        }
-                       ide_setup_pci_devices(dev, findev, d);
-                       return;
+                       return ide_setup_pci_devices(dev, findev, d);
                }
        }
-       ide_setup_pci_device(dev, d);
+init_single:
+       return ide_setup_pci_device(dev, d);
 }
 
+static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
+       {       /* 0 */
+               .name           = "HPT366",
+               .init_setup     = init_setup_hpt366,
+               .init_chipset   = init_chipset_hpt366,
+               .init_hwif      = init_hwif_hpt366,
+               .init_dma       = init_dma_hpt366,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+               .extra          = 240
+       },{     /* 1 */
+               .name           = "HPT372A",
+               .init_setup     = init_setup_hpt37x,
+               .init_chipset   = init_chipset_hpt366,
+               .init_hwif      = init_hwif_hpt366,
+               .init_dma       = init_dma_hpt366,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+       },{     /* 2 */
+               .name           = "HPT302",
+               .init_setup     = init_setup_hpt37x,
+               .init_chipset   = init_chipset_hpt366,
+               .init_hwif      = init_hwif_hpt366,
+               .init_dma       = init_dma_hpt366,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+       },{     /* 3 */
+               .name           = "HPT371",
+               .init_setup     = init_setup_hpt37x,
+               .init_chipset   = init_chipset_hpt366,
+               .init_hwif      = init_hwif_hpt366,
+               .init_dma       = init_dma_hpt366,
+               .channels       = 2,
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+       },{     /* 4 */
+               .name           = "HPT374",
+               .init_setup     = init_setup_hpt374,
+               .init_chipset   = init_chipset_hpt366,
+               .init_hwif      = init_hwif_hpt366,
+               .init_dma       = init_dma_hpt366,
+               .channels       = 2,    /* 4 */
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+       },{     /* 5 */
+               .name           = "HPT372N",
+               .init_setup     = init_setup_hpt37x,
+               .init_chipset   = init_chipset_hpt366,
+               .init_hwif      = init_hwif_hpt366,
+               .init_dma       = init_dma_hpt366,
+               .channels       = 2,    /* 4 */
+               .autodma        = AUTODMA,
+               .bootable       = OFF_BOARD,
+       }
+};
 
 /**
  *     hpt366_init_one -       called when an HPT366 is found
@@ -1241,8 +1713,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
 {
        ide_pci_device_t *d = &hpt366_chipsets[id->driver_data];
 
-       d->init_setup(dev, d);
-       return 0;
+       return d->init_setup(dev, d);
 }
 
 static struct pci_device_id hpt366_pci_tbl[] = {
@@ -1251,12 +1722,13 @@ static struct pci_device_id hpt366_pci_tbl[] = {
        { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
        { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
        { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+       { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
 
 static struct pci_driver driver = {
-       .name           = "HPT366 IDE",
+       .name           = "HPT366_IDE",
        .id_table       = hpt366_pci_tbl,
        .probe          = hpt366_init_one,
 };