diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
commit | 6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch) | |
tree | 0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /drivers/ide/hpt366.c | |
parent | ecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (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.c | 436 |
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, ®1); /* 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, ®51h); + (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, ®5a); + 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, ®50h); - pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0x03); pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); - /* ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); */ -#endif + pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, ®52h); + pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, ®5ah); + 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, ®5ah); + 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; |