Messages in this thread Patch in this message | | | Date | Sat, 07 Dec 2002 13:53:56 -0800 | From | Andrew Morton <> | Subject | Re: status of HPT374 support in 2.4.20 and 2.5.50 |
| |
jorg de jong wrote: > > Hi, > > I just bought a Highpoint Rocketraid 404 controler. To my suppirce I > found that > the kernel I was using does not like it one bit. The kernel entered a > kernel panic/BUG > in file hpt666.c:1031. The kernel was a Redhat stock kernel > 2.4.18-18.8.0smp. > > Not afraid to build my own kernel I tried: > - 2.4.20; which also stoped with a kernel panic. > - 2.4.20-ac1; this kernel boots just fine. It even sees the controller > but does not detect > the drive. > - 2.5.46; sees the controler but no drive > - 2.5.50; sees the controler but no drive >
This patch (against 2.4.20) is the one I use when I need to use the hpt374 in 2.4 kernels.
drivers/ide/hpt366.c | 468 ++++++++++++++++++++++++++++++++++++++++---------- drivers/ide/ide-pci.c | 69 ++++++- 2 files changed, 446 insertions(+), 91 deletions(-)
--- 24/drivers/ide/hpt366.c~hpt374 Sat Dec 7 13:51:38 2002 +++ 24-akpm/drivers/ide/hpt366.c Sat Dec 7 13:51:38 2002 @@ -166,9 +166,8 @@ struct chipset_bus_clock_list_entry { * PIO. * 31 FIFO enable. */ -struct chipset_bus_clock_list_entry forty_base [] = { - - { XFER_UDMA_4, 0x900fd943 }, +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 }, @@ -186,8 +185,7 @@ struct chipset_bus_clock_list_entry fort { 0, 0x0120d9d9 } }; -struct chipset_bus_clock_list_entry thirty_three_base [] = { - +struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { { XFER_UDMA_4, 0x90c9a731 }, { XFER_UDMA_3, 0x90cfa731 }, { XFER_UDMA_2, 0x90caa731 }, @@ -206,7 +204,7 @@ struct chipset_bus_clock_list_entry thir { 0, 0x0120a7a7 } }; -struct chipset_bus_clock_list_entry twenty_five_base [] = { +struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { { XFER_UDMA_4, 0x90c98521 }, { XFER_UDMA_3, 0x90cf8521 }, @@ -331,6 +329,144 @@ struct chipset_bus_clock_list_entry fift { 0, 0x0ac1f48a } }; +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 } +}; + +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 } +}; + +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 } +}; + +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 } +}; + +#if 0 +struct chipset_bus_clock_list_entry fifty_base_hpt374[] = { + { XFER_UDMA_6, }, + { XFER_UDMA_5, }, + { XFER_UDMA_4, }, + { XFER_UDMA_3, }, + { XFER_UDMA_2, }, + { XFER_UDMA_1, }, + { XFER_UDMA_0, }, + { XFER_MW_DMA_2, }, + { XFER_MW_DMA_1, }, + { XFER_MW_DMA_0, }, + { XFER_PIO_4, }, + { XFER_PIO_3, }, + { XFER_PIO_2, }, + { XFER_PIO_1, }, + { XFER_PIO_0, }, + { 0, } +}; +#endif +#if 0 +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 HPT370_ALLOW_ATA100_5 1 #define HPT366_ALLOW_ATA66_4 1 @@ -347,6 +483,10 @@ static int n_hpt_devs; static unsigned int pci_rev_check_hpt3xx(struct pci_dev *dev); static unsigned int pci_rev2_check_hpt3xx(struct pci_dev *dev); +static unsigned int pci_rev3_check_hpt3xx(struct pci_dev *dev); +static unsigned int pci_rev5_check_hpt3xx(struct pci_dev *dev); +static unsigned int pci_rev7_check_hpt3xx(struct pci_dev *dev); + byte hpt366_proc = 0; byte hpt363_shared_irq; byte hpt363_shared_pin; @@ -360,11 +500,13 @@ extern char *ide_media_verbose(ide_drive 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"}; + char *chipset_nums[] = {"366", "366", "368", + "370", "370A", "372", + "??", "374" }; int i; p += sprintf(p, "\n " - "HighPoint HPT366/368/370\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; @@ -388,7 +530,7 @@ static int hpt366_get_info (char *buffer (c0 & 0x80) ? "no" : "yes", (c1 & 0x80) ? "no" : "yes"); - if (pci_rev_check_hpt3xx(dev)) { + if (pci_rev3_check_hpt3xx(dev)) { u8 cbl; cbl = inb_p(iobase + 0x7b); outb_p(cbl | 1, iobase + 0x7b); @@ -437,7 +579,19 @@ static int hpt366_get_info (char *buffer } #endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ -static unsigned int pci_rev_check_hpt3xx (struct pci_dev *dev) +/* + * fixme: it really needs to be a switch. + */ + +static unsigned int pci_rev2_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 > 0x01) ? 1 : 0); +} + +static unsigned int pci_rev3_check_hpt3xx (struct pci_dev *dev) { unsigned int class_rev; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); @@ -445,12 +599,20 @@ static unsigned int pci_rev_check_hpt3xx return ((int) (class_rev > 0x02) ? 1 : 0); } -static unsigned int pci_rev2_check_hpt3xx (struct pci_dev *dev) +static unsigned int pci_rev5_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 > 0x01) ? 1 : 0); + return ((int) (class_rev > 0x04) ? 1 : 0); +} + +static unsigned int pci_rev7_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 > 0x06) ? 1 : 0); } static int check_in_drive_lists (ide_drive_t *drive, const char **list) @@ -484,6 +646,7 @@ static unsigned int pci_bus_clock_list ( static void hpt366_tune_chipset (ide_drive_t *drive, byte speed) { + struct pci_dev *dev = HWIF(drive)->pci_dev; byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; /* @@ -497,30 +660,13 @@ static void hpt366_tune_chipset (ide_dri /* * Disable the "fast interrupt" prediction. */ - pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast); + pci_read_config_byte(dev, regfast, &drive_fast); if (drive_fast & 0x02) - pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x20); + pci_write_config_byte(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); - break; - case 9: - reg2 = pci_bus_clock_list(speed, twenty_five_base); - break; - default: - case 7: - reg2 = pci_bus_clock_list(speed, thirty_three_base); - break; - } -#if 0 - /* this is a nice idea ... */ - list_conf = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) - dev->sysdata); -#endif + pci_read_config_dword(dev, regtime, ®1); + reg2 = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) dev->sysdata); /* * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later) */ @@ -531,7 +677,12 @@ static void hpt366_tune_chipset (ide_dri } reg2 &= ~0x80000000; - pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2); + pci_write_config_dword(dev, regtime, reg2); +} + +static void hpt368_tune_chipset (ide_drive_t *drive, byte speed) +{ + hpt366_tune_chipset(drive, speed); } static void hpt370_tune_chipset (ide_drive_t *drive, byte speed) @@ -577,6 +728,39 @@ static void hpt370_tune_chipset (ide_dri pci_write_config_dword(dev, drive_pci, list_conf); } +static void hpt372_tune_chipset (ide_drive_t *drive, byte speed) +{ + byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; + unsigned int list_conf = 0; + unsigned int drive_conf = 0; + unsigned int conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + byte drive_pci = 0x40 + (drive->dn * 4); + byte drive_fast = 0; + struct pci_dev *dev = HWIF(drive)->pci_dev; + + /* + * Disable the "fast interrupt" prediction. + * don't holdoff on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, regfast, &drive_fast); + drive_fast &= ~0x07; + pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast); + + list_conf = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) + dev->sysdata); + 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) + 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, byte speed) +{ + hpt372_tune_chipset(drive, speed); +} + static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed) { if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) @@ -585,9 +769,15 @@ static int hpt3xx_tune_chipset (ide_driv if (!drive->init_speed) drive->init_speed = speed; - if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) { + if (pci_rev7_check_hpt3xx(HWIF(drive)->pci_dev)) { + hpt374_tune_chipset(drive, speed); + } else if (pci_rev5_check_hpt3xx(HWIF(drive)->pci_dev)) { + hpt372_tune_chipset(drive, speed); + } else if (pci_rev3_check_hpt3xx(HWIF(drive)->pci_dev)) { hpt370_tune_chipset(drive, speed); - } else { + } else if (pci_rev2_check_hpt3xx(HWIF(drive)->pci_dev)) { + hpt368_tune_chipset(drive, speed); + } else { hpt366_tune_chipset(drive, speed); } drive->current_speed = speed; @@ -664,13 +854,20 @@ static int config_chipset_for_dma (ide_d byte ultra66 = eighty_ninty_three(drive); int rval; + config_chipset_for_pio(drive); + drive->init_speed = 0; + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return ((int) ide_dma_off_quietly); - if ((id->dma_ultra & 0x0020) && + if ((id->dma_ultra & 0x0040) && + (pci_rev5_check_hpt3xx(HWIF(drive)->pci_dev)) && + (ultra66)) { + speed = XFER_UDMA_6; + } else 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)) && + (pci_rev3_check_hpt3xx(HWIF(drive)->pci_dev)) && (ultra66)) { speed = XFER_UDMA_5; } else if ((id->dma_ultra & 0x0010) && @@ -703,7 +900,8 @@ static int config_chipset_for_dma (ide_d (void) hpt3xx_tune_chipset(drive, speed); - rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on : + rval = (int)( ((id->dma_ultra >> 14) & 3) ? ide_dma_on : + ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); @@ -726,12 +924,14 @@ void hpt3xx_intrproc (ide_drive_t *drive void hpt3xx_maskproc (ide_drive_t *drive, int mask) { + struct pci_dev *dev = HWIF(drive)->pci_dev; + if (drive->quirk_list) { - if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) { + if (pci_rev3_check_hpt3xx(dev)) { byte reg5a = 0; - pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, ®5a); + pci_read_config_byte(dev, 0x5a, ®5a); if (((reg5a & 0x10) >> 4) != mask) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); + pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); } else { if (mask) { disable_irq(HWIF(drive)->irq); @@ -758,7 +958,7 @@ static int config_drive_xfer_rate (ide_d } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x002F) { + if (id->dma_ultra & 0x007F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && @@ -889,6 +1089,43 @@ int hpt370_dmaproc (ide_dma_action_t fun } return ide_dmaproc(func, drive); /* use standard DMA stuff */ } + +int hpt374_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte mscreg = hwif->channel ? 0x54 : 0x50; +// byte reginfo = hwif->channel ? 0x56 : 0x52; + byte dma_stat; + + switch (func) { + case ide_dma_check: + return config_drive_xfer_rate(drive); + case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ + dma_stat = inb(dma_base+2); +#if 0 /* do not set unless you know what you are doing */ + if (dma_stat & 4) { + byte stat = GET_STAT(); + outb(dma_base+2, dma_stat & 0xE4); + } +#endif + /* return 1 if INTR asserted */ + return (dma_stat & 4) == 4; + case ide_dma_end: + { + byte bwsr_mask = hwif->channel ? 0x02 : 0x01; + byte bwsr_stat, msc_stat; + pci_read_config_byte(dev, 0x6a, &bwsr_stat); + pci_read_config_byte(dev, mscreg, &msc_stat); + if ((bwsr_stat & bwsr_mask) == bwsr_mask) + pci_write_config_byte(dev, mscreg, msc_stat|0x30); + } + default: + break; + } + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} #endif /* CONFIG_BLK_DEV_IDEDMA */ /* @@ -1006,7 +1243,7 @@ static int hpt370_busproc(ide_drive_t * return 0; } -static void __init init_hpt370(struct pci_dev *dev) +static void __init init_hpt37x(struct pci_dev *dev) { int adjust, i; u16 freq; @@ -1027,18 +1264,44 @@ static void __init init_hpt370(struct pc freq &= 0x1FF; if (freq < 0x9c) { pll = F_LOW_PCI_33; - dev->sysdata = (void *) thirty_three_base_hpt370; - printk("HPT370: using 33MHz PCI clock\n"); + if (pci_rev7_check_hpt3xx(dev)) { + dev->sysdata = (void *) thirty_three_base_hpt374; + } else if (pci_rev5_check_hpt3xx(dev)) { + dev->sysdata = (void *) thirty_three_base_hpt372; + } else if (dev->device == PCI_DEVICE_ID_TTI_HPT372) { + dev->sysdata = (void *) thirty_three_base_hpt372; + } else { + dev->sysdata = (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; - dev->sysdata = (void *) fifty_base_hpt370; - printk("HPT370: using 50MHz PCI clock\n"); + if (pci_rev7_check_hpt3xx(dev)) { + // dev->sysdata = (void *) fifty_base_hpt374; + BUG(); + } else if (pci_rev5_check_hpt3xx(dev)) { + dev->sysdata = (void *) fifty_base_hpt372; + } else if (dev->device == PCI_DEVICE_ID_TTI_HPT372) { + dev->sysdata = (void *) fifty_base_hpt372; + } else { + dev->sysdata = (void *) fifty_base_hpt370; + } + printk("HPT37X: using 50MHz PCI clock\n"); } else { pll = F_LOW_PCI_66; - dev->sysdata = (void *) sixty_six_base_hpt370; - printk("HPT370: using 66MHz PCI clock\n"); + if (pci_rev7_check_hpt3xx(dev)) { + // dev->sysdata = (void *) sixty_six_base_hpt374; + BUG(); + } else if (pci_rev5_check_hpt3xx(dev)) { + dev->sysdata = (void *) sixty_six_base_hpt372; + } else if (dev->device == PCI_DEVICE_ID_TTI_HPT372) { + dev->sysdata = (void *) sixty_six_base_hpt372; + } else { + dev->sysdata = (void *) sixty_six_base_hpt370; + } + printk("HPT37X: using 66MHz PCI clock\n"); } /* @@ -1049,7 +1312,7 @@ static void __init init_hpt370(struct pc * on PRST/SRST when the HPT state engine gets reset. */ if (dev->sysdata) - goto init_hpt370_done; + goto init_hpt37X_done; /* * adjust PLL based upon PCI clock, enable it, and wait for @@ -1076,9 +1339,18 @@ static void __init init_hpt370(struct pc pci_write_config_dword(dev, 0x5c, pll & ~0x100); pci_write_config_byte(dev, 0x5b, 0x21); - dev->sysdata = (void *) fifty_base_hpt370; - printk("HPT370: using 50MHz internal PLL\n"); - goto init_hpt370_done; + if (pci_rev7_check_hpt3xx(dev)) { + // dev->sysdata = (void *) fifty_base_hpt374; + BUG(); + } else if (pci_rev5_check_hpt3xx(dev)) { + dev->sysdata = (void *) fifty_base_hpt372; + } else if (dev->device == PCI_DEVICE_ID_TTI_HPT372) { + dev->sysdata = (void *) fifty_base_hpt372; + } else { + dev->sysdata = (void *) fifty_base_hpt370; + } + printk("HPT37X: using 50MHz internal PLL\n"); + goto init_hpt37X_done; } } pll_recal: @@ -1088,13 +1360,41 @@ pll_recal: pll += (adjust >> 1); } -init_hpt370_done: +init_hpt37X_done: /* reset state engine */ pci_write_config_byte(dev, 0x50, 0x37); pci_write_config_byte(dev, 0x54, 0x37); udelay(100); } +static void __init init_hpt366 (struct pci_dev *dev) +{ + unsigned int reg1 = 0; + byte drive_fast = 0; + + /* + * Disable the "fast interrupt" prediction. + */ + pci_read_config_byte(dev, 0x51, &drive_fast); + if (drive_fast & 0x80) + pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); + pci_read_config_dword(dev, 0x40, ®1); + + /* detect bus speed by looking at control reg timing: */ + switch((reg1 >> 8) & 7) { + case 5: + dev->sysdata = (void *) forty_base_hpt366; + break; + case 9: + dev->sysdata = (void *) twenty_five_base_hpt366; + break; + case 7: + default: + dev->sysdata = (void *) thirty_three_base_hpt366; + break; + } +} + unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name) { byte test = 0; @@ -1118,20 +1418,14 @@ unsigned int __init pci_init_hpt366 (str if (test != 0x08) pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - if (pci_rev_check_hpt3xx(dev)) { - init_hpt370(dev); + if (pci_rev3_check_hpt3xx(dev)) { + init_hpt37x(dev); hpt_devs[n_hpt_devs++] = dev; } else { + init_hpt366(dev); hpt_devs[n_hpt_devs++] = dev; } -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) - if (!hpt366_proc) { - hpt366_proc = 1; - hpt366_display_info = &hpt366_get_info; - } -#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */ - return dev->irq; } @@ -1151,8 +1445,6 @@ unsigned int __init ata66_hpt366 (ide_hw void __init ide_init_hpt366 (ide_hwif_t *hwif) { - int hpt_rev; - hwif->tuneproc = &hpt3xx_tune_drive; hwif->speedproc = &hpt3xx_tune_chipset; hwif->quirkproc = &hpt3xx_quirkproc; @@ -1165,31 +1457,37 @@ void __init ide_init_hpt366 (ide_hwif_t hwif->serialized = hwif->mate->serialized = 1; #endif - hpt_rev = pci_rev_check_hpt3xx(hwif->pci_dev); - if (hpt_rev) { - /* set up ioctl for power status. note: power affects both - * drives on each channel */ - hwif->busproc = &hpt370_busproc; - } - - if (pci_rev2_check_hpt3xx(hwif->pci_dev)) { - /* do nothing now but will split device types */ - hwif->resetproc = &hpt3xx_reset; -/* - * don't do until we can parse out the cobalt box argh ... - * hwif->busproc = &hpt3xx_tristate; - */ - } - #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { - if (hpt_rev) { + if (pci_rev3_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; + /* + * set up ioctl for power status. + * note: power affects both + * drives on each channel + */ + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt370_busproc; + + if (pci_rev7_check_hpt3xx(hwif->pci_dev)) { + hwif->dmaproc = &hpt374_dmaproc; + } else if (pci_rev5_check_hpt3xx(hwif->pci_dev)) { + hwif->dmaproc = &hpt374_dmaproc; + } else if (hwif->pci_dev->device == PCI_DEVICE_ID_TTI_HPT372) { + hwif->dmaproc = &hpt374_dmaproc; + } else if (pci_rev3_check_hpt3xx(hwif->pci_dev)) { + hwif->dmaproc = &hpt370_dmaproc; + } + } else if (pci_rev2_check_hpt3xx(hwif->pci_dev)) { +// hwif->resetproc = &hpt3xx_reset; +// hwif->busproc = &hpt3xx_tristate; + hwif->dmaproc = &hpt366_dmaproc; } else { +// hwif->resetproc = &hpt3xx_reset; +// hwif->busproc = &hpt3xx_tristate; hwif->dmaproc = &hpt366_dmaproc; } if (!noautodma) --- 24/drivers/ide/ide-pci.c~hpt374 Sat Dec 7 13:51:38 2002 +++ 24-akpm/drivers/ide/ide-pci.c Sat Dec 7 13:51:38 2002 @@ -79,6 +79,8 @@ #define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) #define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) #define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366}) +#define DEVID_HPT372 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372}) +#define DEVID_HPT374 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374}) #define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229}) #define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693}) #define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013}) @@ -450,6 +452,13 @@ static ide_pci_device_t ide_pci_chipsets {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, +#if 1 + {DEVID_HPT372, "HPT372", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_HPT374, "HPT374", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, +#else + {DEVID_HPT372, "HPT372", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_HPT374, "HPT374", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, +#endif {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, @@ -474,6 +483,7 @@ static unsigned int __init ide_special_s { switch(dev->device) { case PCI_DEVICE_ID_TTI_HPT366: + case PCI_DEVICE_ID_TTI_HPT374: case PCI_DEVICE_ID_PROMISE_20246: case PCI_DEVICE_ID_PROMISE_20262: case PCI_DEVICE_ID_PROMISE_20265: @@ -824,6 +834,7 @@ controller_ok: IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT374) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) || @@ -906,6 +917,44 @@ static void __init pdc20270_device_order ide_setup_pci_device(dev2, d2); } +static void __init hpt374_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *dev2 = NULL, *findev; + ide_pci_device_t *d2; + + if (PCI_FUNC(dev->devfn) & 1) + return; + + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + dev2 = findev; + break; + } + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + if (!dev2) { + return; + } else { + byte irq = 0, irq2 = 0; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); + if (irq != irq2) { + pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); + dev2->irq = dev->irq; + printk("%s: pci-config space interrupt fixed.\n", d->name); + } + } + d2 = d; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); + ide_setup_pci_device(dev2, d2); + +} + static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *dev2 = NULL, *findev; @@ -919,12 +968,11 @@ static void __init hpt366_device_order_f pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; - if (class_rev > 5) - class_rev = 5; - + strcpy(d->name, chipset_names[class_rev]); switch(class_rev) { + case 5: case 4: case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); ide_setup_pci_device(dev, d); @@ -944,11 +992,18 @@ static void __init hpt366_device_order_f hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0; if (hpt363_shared_pin && hpt363_shared_irq) { d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2); + printk("%s: onboard version of chipset, " + "pin1=%d pin2=%d\n", d->name, + pin1, pin2); #if 0 - /* I forgot why I did this once, but it fixed something. */ + /* + * This is the third undocumented detection + * method and is generally required for the + * ABIT-BP6 boards. + */ pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq); - printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2); + printk("PCI: %s: Fixing interrupt %d pin %d " + "to ZERO \n", d->name, dev2->irq, pin2); pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0); #endif } @@ -988,6 +1043,8 @@ void __init ide_scan_pcidev (struct pci_ return; /* UM8886A/BF pair */ else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366)) hpt366_device_order_fixup(dev, d); + else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT374)) + hpt374_device_order_fixup(dev, d); else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20270)) pdc20270_device_order_fixup(dev, d); else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { _ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |