This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / ide / pci / hpt366.c
index a0463c7..520b8f2 100644 (file)
 
 #include "hpt366.h"
 
-/*
- *     Hold all the highpoint quirks and revision information in one
- *     place.
- */
-struct hpt_info
+#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 unsigned int hpt_revision(struct pci_dev *dev);
+static unsigned int hpt_minimum_revision(struct pci_dev *dev, int revision);
+
+#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
+
+static u8 hpt366_proc = 0;
+static struct pci_dev *hpt_devs[HPT366_MAX_DEVS];
+static int n_hpt_devs;
+
+static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count)
 {
-       u8 max_mode;            /* Speeds allowed */
-       int revision;           /* Chipset revision */
-       int flags;              /* Chipset properties */
-#define PLL_MODE       1
-#define IS_372N                2
-                               /* Speed table */
-       struct chipset_bus_clock_list_entry *speed;
-};
+       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);
+               if(class_rev < 9)
+                       p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]);
+               else
+                       p += sprintf(p, "Chipset: HPT revision %d\n", 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");
+#if 0
+               if (hpt_minimum_revision(dev, 3)) {
+                       u8 cbl;
+                       cbl = inb(iobase + 0x7b);
+                       outb(cbl | 1, iobase + 0x7b);
+                       outb(cbl & ~1, iobase + 0x7b);
+                       cbl = inb(iobase + 0x7a);
+                       p += sprintf(p, "Cable:          ATA-%d"
+                                       "                          ATA-%d\n",
+                               (cbl & 0x02) ? 33 : 66,
+                               (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 
+                        * into io space */
+                       pci_read_config_byte(dev, 0x43, &c0);
+                       pci_read_config_byte(dev, 0x47, &c1);
+                       pci_read_config_byte(dev, 0x4b, &c2);
+                       pci_read_config_byte(dev, 0x4f, &c3);
+
+                       p += sprintf(p, "Mode:           %s             %s"
+                                       "           %s              %s\n",
+                               (c0 & 0x10) ? "UDMA" : (c0 & 0x20) ? "DMA " : 
+                                       (c0 & 0x80) ? "PIO " : "off ",
+                               (c1 & 0x10) ? "UDMA" : (c1 & 0x20) ? "DMA " :
+                                       (c1 & 0x80) ? "PIO " : "off ",
+                               (c2 & 0x10) ? "UDMA" : (c2 & 0x20) ? "DMA " :
+                                       (c2 & 0x80) ? "PIO " : "off ",
+                               (c3 & 0x10) ? "UDMA" : (c3 & 0x20) ? "DMA " :
+                                       (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) */
 
 /*
  *     This wants fixing so that we do everything not by classrev
@@ -99,7 +183,7 @@ struct hpt_info
  *     enumeration of chip variants and using that
  */
  
-static __devinit u32 hpt_revision (struct pci_dev *dev)
+static u32 hpt_revision (struct pci_dev *dev)
 {
        u32 class_rev;
        pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
@@ -123,33 +207,37 @@ static __devinit u32 hpt_revision (struct pci_dev *dev)
        return class_rev;
 }
 
+static u32 hpt_minimum_revision (struct pci_dev *dev, int revision)
+{
+       unsigned int class_rev = hpt_revision(dev);
+       revision--;
+       return ((int) (class_rev > revision) ? 1 : 0);
+}
+
 static int check_in_drive_lists(ide_drive_t *drive, const char **list);
 
 static u8 hpt3xx_ratemask (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = drive->hwif;
-       struct hpt_info *info   = ide_get_hwifdata(hwif);
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
        u8 mode                 = 0;
 
-       /* FIXME: TODO - move this to set info->mode once at boot */
-       
-       if (info->revision >= 8) {              /* HPT374 */
+       if (hpt_minimum_revision(dev, 8)) {             /* HPT374 */
                mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3;
-       } else if (info->revision >= 7) {       /* HPT371 */
+       } else if (hpt_minimum_revision(dev, 7)) {      /* HPT371 */
                mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3;
-       } else if (info->revision >= 6) {       /* HPT302 */
+       } else if (hpt_minimum_revision(dev, 6)) {      /* HPT302 */
                mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3;
-       } else if (info->revision >= 5) {       /* HPT372 */
+       } else if (hpt_minimum_revision(dev, 5)) {      /* HPT372 */
                mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3;
-       } else if (info->revision >= 4) {       /* HPT370A */
+       } else if (hpt_minimum_revision(dev, 4)) {      /* HPT370A */
                mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
-       } else if (info->revision >= 3) {       /* HPT370 */
+       } else if (hpt_minimum_revision(dev, 3)) {      /* HPT370 */
                mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
                mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode;
        } else {                                /* HPT366 and HPT368 */
                mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2;
        }
-       if (!eighty_ninty_three(drive) && mode)
+       if (!eighty_ninty_three(drive) && (mode))
                mode = min(mode, (u8)1);
        return mode;
 }
@@ -161,8 +249,7 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive)
  
 static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
 {
-       ide_hwif_t *hwif        = drive->hwif;
-       struct hpt_info *info   = ide_get_hwifdata(hwif);
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
        u8 mode                 = hpt3xx_ratemask(drive);
 
        if (drive->media != ide_disk)
@@ -174,7 +261,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
                        break;
                case 0x03:
                        speed = min(speed, (u8)XFER_UDMA_5);
-                       if (info->revision >= 5)
+                       if (hpt_minimum_revision(dev, 5))
                                break;
                        if (check_in_drive_lists(drive, bad_ata100_5))
                                speed = min(speed, (u8)XFER_UDMA_4);
@@ -184,7 +271,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
        /*
         * CHECK ME, Does this need to be set to 5 ??
         */
-                       if (info->revision >= 3)
+                       if (hpt_minimum_revision(dev, 3))
                                break;
                        if ((check_in_drive_lists(drive, bad_ata66_4)) ||
                            (!(HPT366_ALLOW_ATA66_4)))
@@ -198,7 +285,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
        /*
         * CHECK ME, Does this need to be set to 5 ??
         */
-                       if (info->revision >= 3)
+                       if (hpt_minimum_revision(dev, 3))
                                break;
                        if (check_in_drive_lists(drive, bad_ata33))
                                speed = min(speed, (u8)XFER_MW_DMA_2);
@@ -237,12 +324,11 @@ static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_
 
 static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 {
-       ide_hwif_t *hwif        = drive->hwif;
-       struct pci_dev *dev     = hwif->pci_dev;
-       struct hpt_info *info   = ide_get_hwifdata(hwif);
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
        u8 speed                = hpt3xx_ratefilter(drive, xferspeed);
+//     u8 speed                = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
        u8 regtime              = (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
-       u8 regfast              = (hwif->channel) ? 0x55 : 0x51;
+       u8 regfast              = (HWIF(drive)->channel) ? 0x55 : 0x51;
        u8 drive_fast           = 0;
        u32 reg1 = 0, reg2      = 0;
 
@@ -250,11 +336,16 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
         * Disable the "fast interrupt" prediction.
         */
        pci_read_config_byte(dev, regfast, &drive_fast);
+#if 0
+       if (drive_fast & 0x02)
+               pci_write_config_byte(dev, regfast, drive_fast & ~0x20);
+#else
        if (drive_fast & 0x80)
                pci_write_config_byte(dev, regfast, drive_fast & ~0x80);
+#endif
 
-       reg2 = pci_bus_clock_list(speed, info->speed);
-
+       reg2 = pci_bus_clock_list(speed,
+               (struct chipset_bus_clock_list_entry *) pci_get_drvdata(dev));
        /*
         * Disable on-chip PIO FIFO/buffer
         *  (to avoid problems handling I/O errors later)
@@ -274,11 +365,10 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 
 static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 {
-       ide_hwif_t *hwif        = drive->hwif;
-       struct pci_dev *dev = hwif->pci_dev;
-       struct hpt_info *info   = ide_get_hwifdata(hwif);
+       struct pci_dev *dev = HWIF(drive)->pci_dev;
        u8 speed        = hpt3xx_ratefilter(drive, xferspeed);
-       u8 regfast      = (drive->hwif->channel) ? 0x55 : 0x51;
+//     u8 speed        = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
+       u8 regfast      = (HWIF(drive)->channel) ? 0x55 : 0x51;
        u8 drive_pci    = 0x40 + (drive->dn * 4);
        u8 new_fast     = 0, drive_fast = 0;
        u32 list_conf   = 0, drive_conf = 0;
@@ -303,13 +393,17 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
        if (new_fast != drive_fast)
                pci_write_config_byte(dev, regfast, new_fast);
 
-       list_conf = pci_bus_clock_list(speed, info->speed);
+       list_conf = pci_bus_clock_list(speed, 
+                                      (struct chipset_bus_clock_list_entry *)
+                                      pci_get_drvdata(dev));
 
        pci_read_config_dword(dev, drive_pci, &drive_conf);
        list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
        
-       if (speed < XFER_MW_DMA_0)
+       if (speed < XFER_MW_DMA_0) {
                list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
+       }
+
        pci_write_config_dword(dev, drive_pci, list_conf);
 
        return ide_config_drive_speed(drive, speed);
@@ -317,11 +411,10 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 
 static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 {
-       ide_hwif_t *hwif        = drive->hwif;
-       struct pci_dev *dev     = hwif->pci_dev;
-       struct hpt_info *info   = ide_get_hwifdata(hwif);
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
        u8 speed        = hpt3xx_ratefilter(drive, xferspeed);
-       u8 regfast      = (drive->hwif->channel) ? 0x55 : 0x51;
+//     u8 speed        = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
+       u8 regfast      = (HWIF(drive)->channel) ? 0x55 : 0x51;
        u8 drive_fast   = 0, drive_pci = 0x40 + (drive->dn * 4);
        u32 list_conf   = 0, drive_conf = 0;
        u32 conf_mask   = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
@@ -333,8 +426,10 @@ static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
        pci_read_config_byte(dev, regfast, &drive_fast);
        drive_fast &= ~0x07;
        pci_write_config_byte(dev, regfast, drive_fast);
-
-       list_conf = pci_bus_clock_list(speed, info->speed);
+                                       
+       list_conf = pci_bus_clock_list(speed,
+                       (struct chipset_bus_clock_list_entry *)
+                                       pci_get_drvdata(dev));
        pci_read_config_dword(dev, drive_pci, &drive_conf);
        list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
        if (speed < XFER_MW_DMA_0)
@@ -346,14 +441,19 @@ static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 
 static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed)
 {
-       ide_hwif_t *hwif        = drive->hwif;
-       struct hpt_info *info   = ide_get_hwifdata(hwif);
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
 
-       if (info->revision >= 8)
+       if (hpt_minimum_revision(dev, 8))
                return hpt372_tune_chipset(drive, speed); /* not a typo */
-       else if (info->revision >= 5)
+#if 0
+       else if (hpt_minimum_revision(dev, 7))
+               hpt371_tune_chipset(drive, speed);
+       else if (hpt_minimum_revision(dev, 6))
+               hpt302_tune_chipset(drive, speed);
+#endif
+       else if (hpt_minimum_revision(dev, 5))
                return hpt372_tune_chipset(drive, speed);
-       else if (info->revision >= 3)
+       else if (hpt_minimum_revision(dev, 3))
                return hpt370_tune_chipset(drive, speed);
        else    /* hpt368: hpt_minimum_revision(dev, 2) */
                return hpt36x_tune_chipset(drive, speed);
@@ -379,14 +479,12 @@ static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio)
 static int config_chipset_for_dma (ide_drive_t *drive)
 {
        u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive));
-       ide_hwif_t *hwif = drive->hwif;
-       struct hpt_info *info   = ide_get_hwifdata(hwif);
-       
+
        if (!speed)
                return 0;
                
        /* If we don't have any timings we can't do a lot */
-       if (info->speed == NULL)
+       if (pci_get_drvdata(HWIF(drive)->pci_dev) == NULL)
                return 0;
 
        (void) hpt3xx_tune_chipset(drive, speed);
@@ -400,7 +498,7 @@ static int hpt3xx_quirkproc (ide_drive_t *drive)
 
 static void hpt3xx_intrproc (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = drive->hwif;
+       ide_hwif_t *hwif = HWIF(drive);
 
        if (drive->quirk_list)
                return;
@@ -410,26 +508,24 @@ static void hpt3xx_intrproc (ide_drive_t *drive)
 
 static void hpt3xx_maskproc (ide_drive_t *drive, int mask)
 {
-       ide_hwif_t *hwif = drive->hwif;
-       struct hpt_info *info = ide_get_hwifdata(hwif);
-       struct pci_dev *dev = hwif->pci_dev;
+       struct pci_dev *dev = HWIF(drive)->pci_dev;
 
        if (drive->quirk_list) {
-               if (info->revision >= 3) {
+               if (hpt_minimum_revision(dev,3)) {
                        u8 reg5a = 0;
                        pci_read_config_byte(dev, 0x5a, &reg5a);
                        if (((reg5a & 0x10) >> 4) != mask)
                                pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
                } else {
                        if (mask) {
-                               disable_irq(hwif->irq);
+                               disable_irq(HWIF(drive)->irq);
                        } else {
-                               enable_irq(hwif->irq);
+                               enable_irq(HWIF(drive)->irq);
                        }
                }
        } else {
                if (IDE_CONTROL_REG)
-                       hwif->OUTB(mask ? (drive->ctl | 2) :
+                       HWIF(drive)->OUTB(mask ? (drive->ctl | 2) :
                                                 (drive->ctl & ~2),
                                                 IDE_CONTROL_REG);
        }
@@ -437,22 +533,41 @@ static void hpt3xx_maskproc (ide_drive_t *drive, int mask)
 
 static int hpt366_config_drive_xfer_rate (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = drive->hwif;
+       ide_hwif_t *hwif        = HWIF(drive);
        struct hd_driveid *id   = drive->id;
 
        drive->init_speed = 0;
 
-       if ((id->capability & 1) && drive->autodma) {
-
-               if (ide_use_dma(drive)) {
-                       if (config_chipset_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
+       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;
                }
-
-               goto fast_ata_pio;
-
+               return hwif->ide_dma_on(drive);
        } 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);
        }
@@ -476,6 +591,15 @@ static int hpt366_ide_dma_lostirq (ide_drive_t *drive)
                drive->name, __FUNCTION__, reg50h, reg52h, reg5ah);
        if (reg5ah & 0x10)
                pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
+#if 0
+       /* how about we flush and reset, mmmkay? */
+       pci_write_config_byte(dev, 0x51, 0x1F);
+       /* fall through to a reset */
+       case ide_dma_begin:
+       case ide_dma_end:
+       /* reset the chips state over and over.. */
+       pci_write_config_byte(dev, 0x51, 0x13);
+#endif
        return __ide_dma_lostirq(drive);
 }
 
@@ -486,12 +610,12 @@ static void hpt370_clear_engine (ide_drive_t *drive)
        udelay(10);
 }
 
-static void hpt370_ide_dma_start(ide_drive_t *drive)
+static int hpt370_ide_dma_begin (ide_drive_t *drive)
 {
 #ifdef HPT_RESET_STATE_ENGINE
        hpt370_clear_engine(drive);
 #endif
-       ide_dma_start(drive);
+       return __ide_dma_begin(drive);
 }
 
 static int hpt370_ide_dma_end (ide_drive_t *drive)
@@ -518,7 +642,7 @@ static void hpt370_lostirq_timeout (ide_drive_t *drive)
        u8 dma_stat = 0, dma_cmd = 0;
 
        pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo);
-       printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo);
+       printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
        hpt370_clear_engine(drive);
        /* get dma command mode */
        dma_cmd = hwif->INB(hwif->dma_command);
@@ -653,6 +777,15 @@ static ide_startstop_t hpt372n_rw_disk(ide_drive_t *drive, struct request *rq, s
 
 static void hpt3xx_reset (ide_drive_t *drive)
 {
+#if 0
+       unsigned long high_16   = pci_resource_start(HWIF(drive)->pci_dev, 4);
+       u8 reset        = (HWIF(drive)->channel) ? 0x80 : 0x40;
+       u8 reg59h       = 0;
+
+       pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, &reg59h);
+       pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset);
+       pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h);
+#endif
 }
 
 static int hpt3xx_tristate (ide_drive_t * drive, int state)
@@ -662,6 +795,8 @@ 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;
 
+//     hwif->bus_state = state;
+
        pci_read_config_byte(dev, 0x59, &reg59h);
        pci_read_config_byte(dev, state_reg, &regXXh);
 
@@ -688,7 +823,7 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state)
 #define TRISTATE_BIT  0x8000
 static int hpt370_busproc(ide_drive_t * drive, int state)
 {
-       ide_hwif_t *hwif        = drive->hwif;
+       ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = hwif->pci_dev;
        u8 tristate = 0, resetmask = 0, bus_reg = 0;
        u16 tri_reg;
@@ -743,37 +878,30 @@ static int hpt370_busproc(ide_drive_t * drive, int state)
        return 0;
 }
 
-static void __devinit hpt366_clocking(ide_hwif_t *hwif)
-{
-       u32 reg1        = 0;
-       struct hpt_info *info = ide_get_hwifdata(hwif);
-
-       pci_read_config_dword(hwif->pci_dev, 0x40, &reg1);
-
-       /* detect bus speed by looking at control reg timing: */
-       switch((reg1 >> 8) & 7) {
-               case 5:
-                       info->speed = forty_base_hpt366;
-                       break;
-               case 9:
-                       info->speed = twenty_five_base_hpt366;
-                       break;
-               case 7:
-               default:
-                       info->speed = thirty_three_base_hpt366;
-                       break;
-       }
-}
-
-static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
+static int __devinit init_hpt37x(struct pci_dev *dev)
 {
-       struct hpt_info *info = ide_get_hwifdata(hwif);
-       struct pci_device *dev = hwif->pci_dev;
        int adjust, i;
        u16 freq;
        u32 pll;
        u8 reg5bh;
+       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));
+
+       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
         * to prevent drives having problems with 40-pin cables. Needed
@@ -803,7 +931,9 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
         * Currently we always set up the PLL for the 372N
         */
         
-       if(info->flags & IS_372N)
+       pci_set_drvdata(dev, NULL);
+       
+       if(is_372n)
        {
                printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n");
                if(freq < 0x55)
@@ -831,38 +961,39 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
                        pll = F_LOW_PCI_66;
        
                if (pll == F_LOW_PCI_33) {
-                       if (info->revision >= 8)
-                               info->speed = thirty_three_base_hpt374;
-                       else if (info->revision >= 5)
-                               info->speed = thirty_three_base_hpt372;
-                       else if (info->revision >= 4)
-                               info->speed = thirty_three_base_hpt370a;
+                       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
-                               info->speed = thirty_three_base_hpt370;
-                       printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");
+                               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 (info->revision >= 8)
-                               info->speed = fifty_base_hpt370a;
-                       else if (info->revision >= 5)
-                               info->speed = fifty_base_hpt372;
-                       else if (info->revision >= 4)
-                               info->speed = fifty_base_hpt370a;
+                       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
-                               info->speed = fifty_base_hpt370a;
-                       printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");
+                               pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+                       printk("HPT37X: using 50MHz PCI clock\n");
                } else {
-                       if (info->revision >= 8) {
+                       if (hpt_minimum_revision(dev,8))
+                       {
                                printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
                        }
-                       else if (info->revision >= 5)
-                               info->speed = sixty_six_base_hpt372;
-                       else if (info->revision >= 4)
-                               info->speed = sixty_six_base_hpt370a;
+                       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
-                               info->speed = sixty_six_base_hpt370;
-                       printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n");
+                               pci_set_drvdata(dev, (void *) sixty_six_base_hpt370);
+                       printk("HPT37X: using 66MHz PCI clock\n");
                }
        }
        
@@ -876,15 +1007,10 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
         * ToDo: Use 66MHz PLL when ATA133 devices are present on a
         * 372 device so we can get ATA133 support
         */
-       if (info->speed
+       if (pci_get_drvdata(dev)
                goto init_hpt37X_done;
-
-       info->flags |= PLL_MODE;
        
        /*
-        * FIXME: make this work correctly, esp with 372N as per
-        * reference driver code. 
-        *
         * adjust PLL based upon PCI clock, enable it, and wait for
         * stabilization.
         */
@@ -909,14 +1035,14 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
                                pci_write_config_dword(dev, 0x5c, 
                                                       pll & ~0x100);
                                pci_write_config_byte(dev, 0x5b, 0x21);
-                               if (info->revision >= 8)
-                                       info->speed = fifty_base_hpt370a;
-                               else if (info->revision >= 5)
-                                       info->speed = fifty_base_hpt372;
-                               else if (info->revision >= 4)
-                                       info->speed = fifty_base_hpt370a;
+                               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
-                                       info->speed = fifty_base_hpt370a;
+                                       pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
                                printk("HPT37X: using 50MHz internal PLL\n");
                                goto init_hpt37X_done;
                        }
@@ -929,22 +1055,13 @@ pll_recal:
        } 
 
 init_hpt37X_done:
-       if (!info->speed)
+       if (!pci_get_drvdata(dev))
                printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n", 
-                       (info->flags & IS_372N)?"N":"", pll, freq);
+                       is_372n?"N":"", pll, freq);
        /* reset state engine */
        pci_write_config_byte(dev, 0x50, 0x37); 
        pci_write_config_byte(dev, 0x54, 0x37); 
        udelay(100);
-}
-
-static int __devinit init_hpt37x(struct pci_dev *dev)
-{
-       u8 reg5ah;
-       
-       pci_read_config_byte(dev, 0x5a, &reg5ah);
-       /* interrupt force enable */
-       pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));
        return 0;
 }
 
@@ -961,29 +1078,70 @@ static int __devinit init_hpt366(struct pci_dev *dev)
                pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
        pci_read_config_dword(dev, 0x40, &reg1);
                                                                        
+       /* detect bus speed by looking at control reg timing: */
+       switch((reg1 >> 8) & 7) {
+               case 5:
+                       pci_set_drvdata(dev, (void *) forty_base_hpt366);
+                       break;
+               case 9:
+                       pci_set_drvdata(dev, (void *) twenty_five_base_hpt366);
+                       break;
+               case 7:
+               default:
+                       pci_set_drvdata(dev, (void *) thirty_three_base_hpt366);
+                       break;
+       }
+
+       if (!pci_get_drvdata(dev))
+       {
+               printk(KERN_ERR "hpt366: unknown bus timing.\n");
+               pci_set_drvdata(dev, NULL);
+       }
        return 0;
 }
 
 static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
 {
        int ret = 0;
-       /* FIXME: Not portable */
+       u8 test = 0;
+
        if (dev->resource[PCI_ROM_RESOURCE].start)
                pci_write_config_byte(dev, PCI_ROM_ADDRESS,
                        dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
 
-       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
-       pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
-       pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
+       pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test);
+       if (test != (L1_CACHE_BYTES / 4))
+               pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+                       (L1_CACHE_BYTES / 4));
 
-       if (hpt_revision(dev) >= 3)
-               ret = init_hpt37x(dev);
-       else
-               ret = init_hpt366(dev);
+       pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test);
+       if (test != 0x78)
+               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
+
+       pci_read_config_byte(dev, PCI_MIN_GNT, &test);
+       if (test != 0x08)
+               pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
+
+       pci_read_config_byte(dev, PCI_MAX_LAT, &test);
+       if (test != 0x08)
+               pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
 
+       if (hpt_minimum_revision(dev, 3)) {
+               ret = init_hpt37x(dev);
+       } else {
+               ret =init_hpt366(dev);
+       }
        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;
 }
@@ -991,16 +1149,27 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
 static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
 {
        struct pci_dev *dev             = hwif->pci_dev;
-       struct hpt_info *info           = ide_get_hwifdata(hwif);
        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(info->flags & IS_372N)
+       if(is_372n)
                hwif->rw_disk = &hpt372n_rw_disk;
 
        /*
@@ -1008,7 +1177,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
         * address lines to access an external eeprom.  To read valid
         * cable detect state the pins must be enabled as inputs.
         */
-       if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) {
+       if (hpt_minimum_revision(dev, 8) && PCI_FUNC(dev->devfn) & 1) {
                /*
                 * HPT374 PCI function 1
                 * - set bit 15 of reg 0x52 to enable TCBLID as input
@@ -1023,7 +1192,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
                pci_read_config_byte(dev, 0x5a, &ata66);
                pci_write_config_word(dev, 0x52, mcr3);
                pci_write_config_word(dev, 0x56, mcr6);
-       } else if (info->revision >= 3) {
+       } else if (hpt_minimum_revision(dev, 3)) {
                /*
                 * HPT370/372 and 374 pcifn 0
                 * - clear bit 0 of 0x5b to enable P/SCBLID as inputs
@@ -1050,7 +1219,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
                hwif->serialized = hwif->mate->serialized = 1;
 #endif
 
-       if (info->revision >= 3) {
+       if (hpt_minimum_revision(dev,3)) {
                u8 reg5ah = 0;
                        pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
                /*
@@ -1060,7 +1229,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
                 */
                hwif->resetproc = &hpt3xx_reset;
                hwif->busproc   = &hpt370_busproc;
-       } else if (info->revision >= 2) {
+//             hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
+       } else if (hpt_minimum_revision(dev,2)) {
                hwif->resetproc = &hpt3xx_reset;
                hwif->busproc   = &hpt3xx_tristate;
        } else {
@@ -1081,18 +1251,18 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
                hwif->udma_four = ((ata66 & regmask) ? 0 : 1);
        hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
 
-       if (info->revision >= 8) {
+       if (hpt_minimum_revision(dev,8)) {
                hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
                hwif->ide_dma_end = &hpt374_ide_dma_end;
-       } else if (info->revision >= 5) {
+       } else if (hpt_minimum_revision(dev,5)) {
                hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
                hwif->ide_dma_end = &hpt374_ide_dma_end;
-       } else if (info->revision >= 3) {
-               hwif->ide_dma_start = &hpt370_ide_dma_start;
+       } else if (hpt_minimum_revision(dev,3)) {
+               hwif->ide_dma_begin = &hpt370_ide_dma_begin;
                hwif->ide_dma_end = &hpt370_ide_dma_end;
                hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
                hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq;
-       } else if (info->revision >= 2)
+       } else if (hpt_minimum_revision(dev,2))
                hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
        else
                hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
@@ -1105,7 +1275,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
 
 static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
 {
-       struct hpt_info *info   = ide_get_hwifdata(hwif);
        u8 masterdma    = 0, slavedma = 0;
        u8 dma_new      = 0, dma_old = 0;
        u8 primary      = hwif->channel ? 0x4b : 0x43;
@@ -1115,7 +1284,8 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
        if (!dmabase)
                return;
                
-       if(info->speed == NULL) {
+       if(pci_get_drvdata(hwif->pci_dev) == NULL)
+       {
                printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n");
                return;
        }
@@ -1138,41 +1308,6 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
        ide_setup_dma(hwif, dmabase, 8);
 }
 
-/*
- *     We "borrow" this hook in order to set the data structures
- *     up early enough before dma or init_hwif calls are made.
- */
-
-static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
-{
-       struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL);
-       unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4);
-       u8 did, rid;
-       
-       if(info == NULL) {
-               printk(KERN_WARNING "hpt366: out of memory.\n");
-               return;
-       }       
-       memset(info, 0, sizeof(struct hpt_info));
-       ide_set_hwifdata(hwif, info);
-       
-       if(dmabase) {
-               did = inb(dmabase + 0x22);
-               rid = inb(dmabase + 0x28);
-       
-               if((did == 4 && rid == 6) || (did == 5 && rid > 1))
-                       info->flags |= IS_372N;
-       }
-       
-       info->revision = hpt_revision(hwif->pci_dev);
-       
-       if (info->revision >= 3)
-               hpt37x_clocking(hwif);
-       else
-               hpt366_clocking(hwif);
-}              
-
-
 static void __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
 {
        struct pci_dev *findev = NULL;