summaryrefslogtreecommitdiffstats
path: root/drivers/ide/hpt366.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
commit6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch)
tree0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /drivers/ide/hpt366.c
parentecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff)
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine status unknown.
Diffstat (limited to 'drivers/ide/hpt366.c')
-rw-r--r--drivers/ide/hpt366.c436
1 files changed, 271 insertions, 165 deletions
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 28232b576..74d3018c5 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -1,13 +1,16 @@
/*
- * linux/drivers/ide/hpt366.c Version 0.17 Mar. 18, 2000
+ * linux/drivers/ide/hpt366.c Version 0.18 June. 9, 2000
*
- * Copyright (C) 1999-2000 Andre Hedrick <andre@suse.com>
+ * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* May be copied or modified under the terms of the GNU General Public License
*
* Thanks to HighPoint Technologies for their assistance, and hardware.
* Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
* donation of an ABit BP6 mainboard, processor, and memory acellerated
* development and support.
+ *
+ * Note that final HPT370 support was done by force extraction of GPL.
+ *
*/
#include <linux/config.h>
@@ -30,13 +33,26 @@
#include "ide_modes.h"
-#undef DISPLAY_HPT366_TIMINGS
+#define DISPLAY_HPT366_TIMINGS
#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) */
+extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
+
+const char *quirk_drives[] = {
+ "QUANTUM FIREBALLlct08 08",
+ "QUANTUM FIREBALLP KA6.4",
+ "QUANTUM FIREBALLP LM20.5",
+ NULL
+};
+
+const char *bad_ata100_5[] = {
+ NULL
+};
+
const char *bad_ata66_4[] = {
"WDC AC310200R",
NULL
@@ -60,70 +76,92 @@ const char *bad_ata33[] = {
struct chipset_bus_clock_list_entry {
byte xfer_speed;
- unsigned int chipset_settings;
+ unsigned int chipset_settings_write;
+ unsigned int chipset_settings_read;
};
struct chipset_bus_clock_list_entry forty_base [] = {
- { 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 }
+ { XFER_UDMA_4, 0x900fd943, 0x900fd943 },
+ { XFER_UDMA_3, 0x900ad943, 0x900ad943 },
+ { XFER_UDMA_2, 0x900bd943, 0x900bd943 },
+ { XFER_UDMA_1, 0x9008d943, 0x9008d943 },
+ { XFER_UDMA_0, 0x9008d943, 0x9008d943 },
+
+ { XFER_MW_DMA_2, 0xa008d943, 0xa008d943 },
+ { XFER_MW_DMA_1, 0xa010d955, 0xa010d955 },
+ { XFER_MW_DMA_0, 0xa010d9fc, 0xa010d9fc },
+
+ { XFER_PIO_4, 0xc008d963, 0xc008d963 },
+ { XFER_PIO_3, 0xc010d974, 0xc010d974 },
+ { XFER_PIO_2, 0xc010d997, 0xc010d997 },
+ { XFER_PIO_1, 0xc010d9c7, 0xc010d9c7 },
+ { XFER_PIO_0, 0xc018d9d9, 0xc018d9d9 },
+ { 0, 0x0120d9d9, 0x0120d9d9 }
};
struct chipset_bus_clock_list_entry thirty_three_base [] = {
- { 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 }
+ { XFER_UDMA_4, 0x90c9a731, 0x90c9a731 },
+ { XFER_UDMA_3, 0x90cfa731, 0x90cfa731 },
+ { XFER_UDMA_2, 0x90caa731, 0x90caa731 },
+ { XFER_UDMA_1, 0x90cba731, 0x90cba731 },
+ { XFER_UDMA_0, 0x90c8a731, 0x90c8a731 },
+
+ { XFER_MW_DMA_2, 0xa0c8a731, 0xa0c8a731 },
+ { XFER_MW_DMA_1, 0xa0c8a732, 0xa0c8a732 }, /* 0xa0c8a733 */
+ { XFER_MW_DMA_0, 0xa0c8a797, 0xa0c8a797 },
+
+ { XFER_PIO_4, 0xc0c8a731, 0xc0c8a731 },
+ { XFER_PIO_3, 0xc0c8a742, 0xc0c8a742 },
+ { XFER_PIO_2, 0xc0d0a753, 0xc0d0a753 },
+ { XFER_PIO_1, 0xc0d0a7a3, 0xc0d0a7a3 }, /* 0xc0d0a793 */
+ { XFER_PIO_0, 0xc0d0a7aa, 0xc0d0a7aa }, /* 0xc0d0a7a7 */
+ { 0, 0x0120a7a7, 0x0120a7a7 }
};
struct chipset_bus_clock_list_entry twenty_five_base [] = {
- { 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 }
+ { XFER_UDMA_4, 0x90c98521, 0x90c98521 },
+ { XFER_UDMA_3, 0x90cf8521, 0x90cf8521 },
+ { XFER_UDMA_2, 0x90cf8521, 0x90cf8521 },
+ { XFER_UDMA_1, 0x90cb8521, 0x90cb8521 },
+ { XFER_UDMA_0, 0x90cb8521, 0x90cb8521 },
+
+ { XFER_MW_DMA_2, 0xa0ca8521, 0xa0ca8521 },
+ { XFER_MW_DMA_1, 0xa0ca8532, 0xa0ca8532 },
+ { XFER_MW_DMA_0, 0xa0ca8575, 0xa0ca8575 },
+
+ { XFER_PIO_4, 0xc0ca8521, 0xc0ca8521 },
+ { XFER_PIO_3, 0xc0ca8532, 0xc0ca8532 },
+ { XFER_PIO_2, 0xc0ca8542, 0xc0ca8542 },
+ { XFER_PIO_1, 0xc0d08572, 0xc0d08572 },
+ { XFER_PIO_0, 0xc0d08585, 0xc0d08585 },
+ { 0, 0x01208585, 0x01208585 }
+};
+
+struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = {
+ { XFER_UDMA_5, 0x1A85F442, 0x16454e31 },
+ { XFER_UDMA_4, 0x16454e31, 0x16454e31 },
+ { XFER_UDMA_3, 0x166d4e31, 0x166d4e31 },
+ { XFER_UDMA_2, 0x16494e31, 0x16494e31 },
+ { XFER_UDMA_1, 0x164d4e31, 0x164d4e31 },
+ { XFER_UDMA_0, 0x16514e31, 0x16514e31 },
+
+ { XFER_MW_DMA_2, 0x26514e21, 0x26514e21 },
+ { XFER_MW_DMA_1, 0x26514e33, 0x26514e33 },
+ { XFER_MW_DMA_0, 0x26514e97, 0x26514e97 },
+
+ { XFER_PIO_4, 0x06514e21, 0x06514e21 },
+ { XFER_PIO_3, 0x06514e22, 0x06514e22 },
+ { XFER_PIO_2, 0x06514e33, 0x06514e33 },
+ { XFER_PIO_1, 0x06914e43, 0x06914e43 },
+ { XFER_PIO_0, 0x06914e57, 0x06914e57 },
+ { 0, 0x06514e57, 0x06514e57 }
};
#define HPT366_DEBUG_DRIVE_INFO 0
+#define HPT370_ALLOW_ATA100_5 1
#define HPT366_ALLOW_ATA66_4 1
#define HPT366_ALLOW_ATA66_3 1
@@ -139,7 +177,12 @@ static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count)
char *p = buffer;
u32 bibma = bmide_dev->resource[4].start;
u32 bibma2 = bmide2_dev->resource[4].start;
+ char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A"};
u8 c0 = 0, c1 = 0;
+ u32 class_rev;
+
+ pci_read_config_dword(bmide_dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xff;
/*
* at that point bibma+0x2 et bibma+0xa are byte registers
@@ -149,7 +192,7 @@ static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count)
if (bmide2_dev)
c1 = inb_p((unsigned short)bibma2 + 0x02);
- p += sprintf(p, "\n HPT366 Chipset.\n");
+ p += sprintf(p, "\n %s Chipset.\n", chipset_names[class_rev]);
p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
p += sprintf(p, " %sabled %sabled\n",
(c0&0x80) ? "dis" : " en",
@@ -173,74 +216,74 @@ extern char *ide_xfer_verbose (byte xfer_rate);
byte hpt363_shared_irq = 0;
byte hpt363_shared_pin = 0;
-static unsigned int pci_rev_check_hpt366 (struct pci_dev *dev)
+static unsigned int pci_rev_check_hpt3xx (struct pci_dev *dev)
{
unsigned int class_rev;
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
class_rev &= 0xff;
- return ((int) (class_rev == 0x03) ? 1 : 0);
+ return ((int) (class_rev > 0x02) ? 1 : 0);
}
static int check_in_drive_lists (ide_drive_t *drive, const char **list)
{
struct hd_driveid *id = drive->id;
-#if HPT366_DEBUG_DRIVE_INFO
- printk("check_in_drive_lists(%s, %p)\n", drive->name, list);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
- while (*list) {
- if (!strcmp(*list++,id->model)) {
-#ifdef DEBUG
- printk("%s: Broken ASIC, BackSpeeding (U)DMA for %s\n", drive->name, id->model);
-#endif /* DEBUG */
- return 1;
+ if (quirk_drives == list) {
+ while (*list) {
+ if (strstr(id->model, *list++)) {
+ return 1;
+ }
+ }
+ } else {
+ while (*list) {
+ if (!strcmp(*list++,id->model)) {
+ return 1;
+ }
}
}
return 0;
}
-static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+static unsigned int pci_bus_clock_list (byte speed, int direction, struct chipset_bus_clock_list_entry * chipset_table)
{
-#if HPT366_DEBUG_DRIVE_INFO
- printk("pci_bus_clock_list(speed=0x%02x, table=%p)\n", speed, chipset_table);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
for ( ; chipset_table->xfer_speed ; chipset_table++)
if (chipset_table->xfer_speed == speed) {
-#if HPT366_DEBUG_DRIVE_INFO
- printk("pci_bus_clock_list: found match: 0x%08x\n", chipset_table->chipset_settings);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
- return chipset_table->chipset_settings;
+ return (direction) ? chipset_table->chipset_settings_write : chipset_table->chipset_settings_read;
}
-#if HPT366_DEBUG_DRIVE_INFO
- printk("pci_bus_clock_list: using default: 0x%08x\n", 0x01208585);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
- return 0x01208585;
+ return (direction) ? chipset_table->chipset_settings_write : chipset_table->chipset_settings_read;
}
-static int hpt366_tune_chipset (ide_drive_t *drive, byte speed)
+static void hpt366_tune_chipset (ide_drive_t *drive, byte speed, int direction)
{
- int err;
byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
+ byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51;
+ /*
+ * since the channel is always 0 it does not matter.
+ */
+
unsigned int reg1 = 0;
unsigned int reg2 = 0;
+ byte drive_fast = 0;
-#if HPT366_DEBUG_DRIVE_INFO
- printk("hpt366_tune_chipset(%s, speed=0x%02x)\n", drive->name, speed);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
+ /*
+ * Disable the "fast interrupt" prediction.
+ */
+ pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast);
+ if (drive_fast & 0x02)
+ pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x20);
pci_read_config_dword(HWIF(drive)->pci_dev, regtime, &reg1);
/* detect bus speed by looking at control reg timing: */
switch((reg1 >> 8) & 7) {
case 5:
- reg2 = pci_bus_clock_list(speed, forty_base);
+ reg2 = pci_bus_clock_list(speed, direction, forty_base);
break;
case 9:
- reg2 = pci_bus_clock_list(speed, twenty_five_base);
+ reg2 = pci_bus_clock_list(speed, direction, twenty_five_base);
break;
default:
- printk("hpt366: assuming 33Mhz PCI bus\n");
case 7:
- reg2 = pci_bus_clock_list(speed, thirty_three_base);
+ reg2 = pci_bus_clock_list(speed, direction, thirty_three_base);
break;
}
/*
@@ -254,18 +297,56 @@ static int hpt366_tune_chipset (ide_drive_t *drive, byte speed)
reg2 &= ~0x80000000;
pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);
- err = ide_config_drive_speed(drive, speed);
+}
+
+static void hpt370_tune_chipset (ide_drive_t *drive, byte speed, int direction)
+{
+ byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51;
+ byte reg5bh = (speed != XFER_UDMA_5) ? 0x22 : (direction) ? 0x20 : 0x22;
+ unsigned int list_conf = pci_bus_clock_list(speed, direction, thirty_three_base_hpt370);
+ unsigned int drive_conf = 0;
+ unsigned int conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
+ byte drive_pci = 0;
+ byte drive_fast = 0;
+
+ switch (drive->dn) {
+ case 0: drive_pci = 0x40; break;
+ case 1: drive_pci = 0x44; break;
+ case 2: drive_pci = 0x48; break;
+ case 3: drive_pci = 0x4c; break;
+ default: return;
+ }
+ /*
+ * Disable the "fast interrupt" prediction.
+ */
+ pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast);
+ if (drive_fast & 0x80)
+ pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x80);
+
+ pci_read_config_dword(HWIF(drive)->pci_dev, drive_pci, &drive_conf);
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x5b, reg5bh);
+
+ list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
+ /*
+ * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later)
+ */
+ list_conf &= ~0x80000000;
+
+ pci_write_config_dword(HWIF(drive)->pci_dev, drive_pci, list_conf);
+}
+static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed)
+{
if (!drive->init_speed)
drive->init_speed = speed;
-#if HPT366_DEBUG_DRIVE_INFO
- printk("%s: speed=0x%02x(%s), drive%d, old=0x%08x, new=0x%08x, err=0x%04x\n",
- drive->name, speed, ide_xfer_verbose(speed),
- drive->dn, reg1, reg2, err);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
+ if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) {
+ hpt370_tune_chipset(drive, speed, 0);
+ } else {
+ hpt366_tune_chipset(drive, speed, 0);
+ }
drive->current_speed = speed;
- return(err);
+ return ((int) ide_config_drive_speed(drive, speed));
}
static void config_chipset_for_pio (ide_drive_t *drive)
@@ -274,9 +355,6 @@ static void config_chipset_for_pio (ide_drive_t *drive)
unsigned short xfer_pio = drive->id->eide_pio_modes;
byte timing, speed, pio;
-#if HPT366_DEBUG_DRIVE_INFO
- printk("%s: config_chipset_for_pio\n", drive->name);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
if (xfer_pio> 4)
@@ -306,13 +384,10 @@ static void config_chipset_for_pio (ide_drive_t *drive)
speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
break;
}
-#if HPT366_DEBUG_DRIVE_INFO
- printk("%s: config_chipset_for_pio: speed=0x%04x\n", drive->name, speed);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
- (void) hpt366_tune_chipset(drive, speed);
+ (void) hpt3xx_tune_chipset(drive, speed);
}
-static void hpt366_tune_drive (ide_drive_t *drive, byte pio)
+static void hpt3xx_tune_drive (ide_drive_t *drive, byte pio)
{
byte speed;
switch(pio) {
@@ -322,7 +397,7 @@ static void hpt366_tune_drive (ide_drive_t *drive, byte pio)
case 1: speed = XFER_PIO_1;break;
default: speed = XFER_PIO_0;break;
}
- (void) hpt366_tune_chipset(drive, speed);
+ (void) hpt3xx_tune_chipset(drive, speed);
}
#ifdef CONFIG_BLK_DEV_IDEDMA
@@ -341,18 +416,24 @@ static int config_chipset_for_dma (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
byte speed = 0x00;
- byte reg51h = 0;
+ byte ultra66 = eighty_ninty_three(drive);
int rval;
- if ((id->dma_ultra & 0x0010) &&
- (!check_in_drive_lists(drive, bad_ata66_4)) &&
- (HPT366_ALLOW_ATA66_4) &&
- (HWIF(drive)->udma_four)) {
+ if ((id->dma_ultra & 0x0020) &&
+ (!check_in_drive_lists(drive, bad_ata100_5)) &&
+ (HPT370_ALLOW_ATA100_5) &&
+ (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) &&
+ (ultra66)) {
+ speed = XFER_UDMA_5;
+ } else if ((id->dma_ultra & 0x0010) &&
+ (!check_in_drive_lists(drive, bad_ata66_4)) &&
+ (HPT366_ALLOW_ATA66_4) &&
+ (ultra66)) {
speed = XFER_UDMA_4;
} else if ((id->dma_ultra & 0x0008) &&
(!check_in_drive_lists(drive, bad_ata66_3)) &&
(HPT366_ALLOW_ATA66_3) &&
- (HWIF(drive)->udma_four)) {
+ (ultra66)) {
speed = XFER_UDMA_3;
} else if (id->dma_ultra && (!check_in_drive_lists(drive, bad_ata33))) {
if (id->dma_ultra & 0x0004) {
@@ -368,52 +449,56 @@ static int config_chipset_for_dma (ide_drive_t *drive)
speed = XFER_MW_DMA_1;
} else if (id->dma_mword & 0x0001) {
speed = XFER_MW_DMA_0;
- } else if (id->dma_1word & 0x0004) {
- speed = XFER_SW_DMA_2;
- } else if (id->dma_1word & 0x0002) {
- speed = XFER_SW_DMA_1;
- } else if (id->dma_1word & 0x0001) {
- speed = XFER_SW_DMA_0;
- } else {
-#if HPT366_DEBUG_DRIVE_INFO
- printk("%s: config_chipset_for_dma: returning 'ide_dma_off_quietly'\n", drive->name);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
+ } else {
return ((int) ide_dma_off_quietly);
}
- pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, &reg51h);
+ (void) hpt3xx_tune_chipset(drive, speed);
-#ifdef CONFIG_HPT366_FIP
- /*
- * Some drives prefer/allow for the method of handling interrupts.
- */
- if (!(reg51h & 0x80))
- pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h|0x80);
-#else /* ! CONFIG_HPT366_FIP */
- /*
- * Disable the "fast interrupt" prediction.
- * Instead, always wait for the real interrupt from the drive!
- */
- if (reg51h & 0x80)
- pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80);
-#endif /* CONFIG_HPT366_FIP */
-#if HPT366_DEBUG_DRIVE_INFO
- printk("%s: config_chipset_for_dma: speed=0x%04x\n", drive->name, speed);
-#endif /* HPT366_DEBUG_DRIVE_INFO */
- (void) hpt366_tune_chipset(drive, speed);
-
- rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+ rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
((id->dma_ultra >> 8) & 7) ? ide_dma_on :
((id->dma_mword >> 8) & 7) ? ide_dma_on :
- ((id->dma_1word >> 8) & 7) ? ide_dma_on :
ide_dma_off_quietly);
-
-#if HPT366_DEBUG_DRIVE_INFO
- printk("%s: config_chipset_for_dma: returning %d (%s)\n", drive->name, rval, rval == ide_dma_on ? "dma_on" : "dma_off");
-#endif /* HPT366_DEBUG_DRIVE_INFO */
return rval;
}
+int hpt3xx_quirkproc (ide_drive_t *drive)
+{
+ return ((int) check_in_drive_lists(drive, quirk_drives));
+}
+
+void hpt3xx_intrproc (ide_drive_t *drive)
+{
+}
+
+void hpt3xx_maskproc (ide_drive_t *drive, int mask)
+{
+ if (drive->quirk_list) {
+ if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) {
+ byte reg5a = 0;
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5a);
+ if (((reg5a & 0x10) >> 4) != mask)
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
+ } else {
+ if (mask) {
+ disable_irq(HWIF(drive)->irq);
+ } else {
+ enable_irq(HWIF(drive)->irq);
+ }
+ }
+ } else {
+ if (IDE_CONTROL_REG)
+ OUT_BYTE(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG);
+ }
+}
+
+void hpt370_rw_proc (ide_drive_t *drive, ide_dma_action_t func)
+{
+ if ((func != ide_dma_write) || (func != ide_dma_read))
+ return;
+ hpt370_tune_chipset(drive, drive->current_speed, (func == ide_dma_write));
+}
+
static int config_drive_xfer_rate (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
@@ -427,7 +512,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
}
dma_func = ide_dma_off_quietly;
if (id->field_valid & 4) {
- if (id->dma_ultra & 0x001F) {
+ if (id->dma_ultra & 0x002F) {
/* Force if Capable UltraDMA */
dma_func = config_chipset_for_dma(drive);
if ((id->field_valid & 2) &&
@@ -436,8 +521,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
}
} else if (id->field_valid & 2) {
try_dma_modes:
- if ((id->dma_mword & 0x0007) ||
- (id->dma_1word & 0x0007)) {
+ if (id->dma_mword & 0x0007) {
/* Force if Capable regular DMA modes */
dma_func = config_chipset_for_dma(drive);
if (dma_func != ide_dma_on)
@@ -472,24 +556,39 @@ no_dma_set:
*/
int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
{
- byte reg50h = 0;
+ byte reg50h = 0, reg52h = 0, reg5ah = 0;
switch (func) {
case ide_dma_check:
return config_drive_xfer_rate(drive);
case ide_dma_lostirq:
-#if 0
- pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
- pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0x03);
pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
- /* ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); */
-#endif
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
+ pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5ah);
+ printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",
+ drive->name,
+ ide_dmafunc_verbose(func),
+ reg50h, reg52h, reg5ah);
+ if (reg5ah & 0x10)
+ pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, reg5ah & ~0x10);
+ break;
case ide_dma_timeout:
default:
break;
}
return ide_dmaproc(func, drive); /* use standard DMA stuff */
}
+
+int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+ switch (func) {
+ case ide_dma_check:
+ return config_drive_xfer_rate(drive);
+ default:
+ break;
+ }
+ return ide_dmaproc(func, drive); /* use standard DMA stuff */
+}
#endif /* CONFIG_BLK_DEV_IDEDMA */
unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name)
@@ -519,7 +618,7 @@ unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name)
if (!hpt366_proc) {
hpt366_proc = 1;
bmide_dev = dev;
- if (pci_rev_check_hpt366(dev))
+ if (pci_rev_check_hpt3xx(dev))
bmide2_dev = dev;
hpt366_display_info = &hpt366_get_info;
}
@@ -546,14 +645,24 @@ unsigned int __init ata66_hpt366 (ide_hwif_t *hwif)
void __init ide_init_hpt366 (ide_hwif_t *hwif)
{
- if (pci_rev_check_hpt366(hwif->pci_dev)) return;
-
- hwif->tuneproc = &hpt366_tune_drive;
- hwif->speedproc = &hpt366_tune_chipset;
+ hwif->tuneproc = &hpt3xx_tune_drive;
+ hwif->speedproc = &hpt3xx_tune_chipset;
+ hwif->quirkproc = &hpt3xx_quirkproc;
+ hwif->intrproc = &hpt3xx_intrproc;
+ hwif->maskproc = &hpt3xx_maskproc;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
- hwif->dmaproc = &hpt366_dmaproc;
+ if (pci_rev_check_hpt3xx(hwif->pci_dev)) {
+ byte reg5ah = 0;
+ pci_read_config_byte(hwif->pci_dev, 0x5a, &reg5ah);
+ if (reg5ah & 0x10) /* interrupt force enable */
+ pci_write_config_byte(hwif->pci_dev, 0x5a, reg5ah & ~0x10);
+ hwif->dmaproc = &hpt370_dmaproc;
+ hwif->rwproc = &hpt370_rw_proc;
+ } else {
+ hwif->dmaproc = &hpt366_dmaproc;
+ }
hwif->autodma = 1;
} else {
hwif->autodma = 0;
@@ -571,19 +680,16 @@ void ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase)
{
byte masterdma = 0, slavedma = 0;
byte dma_new = 0, dma_old = inb(dmabase+2);
+ byte primary = hwif->channel ? 0x4b : 0x43;
+ byte secondary = hwif->channel ? 0x4f : 0x47;
unsigned long flags;
- if (pci_rev_check_hpt366(hwif->pci_dev)) {
- ide_setup_dma(hwif, dmabase, 8);
- return;
- }
-
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
dma_new = dma_old;
- pci_read_config_byte(hwif->pci_dev, 0x43, &masterdma);
- pci_read_config_byte(hwif->pci_dev, 0x47, &slavedma);
+ pci_read_config_byte(hwif->pci_dev, primary, &masterdma);
+ pci_read_config_byte(hwif->pci_dev, secondary, &slavedma);
if (masterdma & 0x30) dma_new |= 0x20;
if (slavedma & 0x30) dma_new |= 0x40;