📄 hpt366.c
字号:
{ 0, 0x06814ea7 }};#endif#define HPT366_DEBUG_DRIVE_INFO 0#define HPT374_ALLOW_ATA133_6 0#define HPT371_ALLOW_ATA133_6 0#define HPT302_ALLOW_ATA133_6 0#define HPT372_ALLOW_ATA133_6 1#define HPT370_ALLOW_ATA100_5 1#define HPT366_ALLOW_ATA66_4 1#define HPT366_ALLOW_ATA66_3 1#define HPT366_MAX_DEVS 8#define F_LOW_PCI_33 0x23#define F_LOW_PCI_40 0x29#define F_LOW_PCI_50 0x2d#define F_LOW_PCI_66 0x42/* * Hold all the highpoint quirks and revision information in one * place. */struct hpt_info{ 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;};/* * This wants fixing so that we do everything not by classrev * (which breaks on the newest chips) but by creating an * enumeration of chip variants and using that */static __devinit u32 hpt_revision (struct pci_dev *dev){ u32 class_rev; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; switch(dev->device) { /* Remap new 372N onto 372 */ case PCI_DEVICE_ID_TTI_HPT372N: class_rev = PCI_DEVICE_ID_TTI_HPT372; break; case PCI_DEVICE_ID_TTI_HPT374: class_rev = PCI_DEVICE_ID_TTI_HPT374; break; case PCI_DEVICE_ID_TTI_HPT371: class_rev = PCI_DEVICE_ID_TTI_HPT371; break; case PCI_DEVICE_ID_TTI_HPT302: class_rev = PCI_DEVICE_ID_TTI_HPT302; break; case PCI_DEVICE_ID_TTI_HPT372: class_rev = PCI_DEVICE_ID_TTI_HPT372; break; default: break; } return class_rev;}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); u8 mode = 0; /* FIXME: TODO - move this to set info->mode once at boot */ if (info->revision >= 8) { /* HPT374 */ mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3; } else if (info->revision >= 7) { /* HPT371 */ mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3; } else if (info->revision >= 6) { /* HPT302 */ mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3; } else if (info->revision >= 5) { /* HPT372 */ mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3; } else if (info->revision >= 4) { /* HPT370A */ mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; } else if (info->revision >= 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) mode = min(mode, (u8)1); return mode;}/* * Note for the future; the SATA hpt37x we must set * either PIO or UDMA modes 0,4,5 */ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed){ ide_hwif_t *hwif = drive->hwif; struct hpt_info *info = ide_get_hwifdata(hwif); u8 mode = hpt3xx_ratemask(drive); if (drive->media != ide_disk) return min(speed, (u8)XFER_PIO_4); switch(mode) { case 0x04: speed = min(speed, (u8)XFER_UDMA_6); break; case 0x03: speed = min(speed, (u8)XFER_UDMA_5); if (info->revision >= 5) break; if (check_in_drive_lists(drive, bad_ata100_5)) speed = min(speed, (u8)XFER_UDMA_4); break; case 0x02: speed = min(speed, (u8)XFER_UDMA_4); /* * CHECK ME, Does this need to be set to 5 ?? */ if (info->revision >= 3) break; if ((check_in_drive_lists(drive, bad_ata66_4)) || (!(HPT366_ALLOW_ATA66_4))) speed = min(speed, (u8)XFER_UDMA_3); if ((check_in_drive_lists(drive, bad_ata66_3)) || (!(HPT366_ALLOW_ATA66_3))) speed = min(speed, (u8)XFER_UDMA_2); break; case 0x01: speed = min(speed, (u8)XFER_UDMA_2); /* * CHECK ME, Does this need to be set to 5 ?? */ if (info->revision >= 3) break; if (check_in_drive_lists(drive, bad_ata33)) speed = min(speed, (u8)XFER_MW_DMA_2); break; case 0x00: default: speed = min(speed, (u8)XFER_MW_DMA_2); break; } return speed;}static int check_in_drive_lists (ide_drive_t *drive, const char **list){ struct hd_driveid *id = drive->id; 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 (u8 speed, struct chipset_bus_clock_list_entry * chipset_table){ for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) return chipset_table->chipset_settings; return chipset_table->chipset_settings;}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); u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; u8 regfast = (hwif->channel) ? 0x55 : 0x51; u8 drive_fast = 0; u32 reg1 = 0, reg2 = 0; /* * Disable the "fast interrupt" prediction. */ pci_read_config_byte(dev, regfast, &drive_fast); if (drive_fast & 0x80) pci_write_config_byte(dev, regfast, drive_fast & ~0x80); reg2 = pci_bus_clock_list(speed, info->speed); /* * Disable on-chip PIO FIFO/buffer * (to avoid problems handling I/O errors later) */ pci_read_config_dword(dev, regtime, ®1); if (speed >= XFER_MW_DMA_0) { reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); } else { reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000); } reg2 &= ~0x80000000; pci_write_config_dword(dev, regtime, reg2); return ide_config_drive_speed(drive, speed);}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); u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; u8 drive_pci = 0x40 + (drive->dn * 4); u8 new_fast = 0, drive_fast = 0; u32 list_conf = 0, drive_conf = 0; u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; /* * Disable the "fast interrupt" prediction. * don't holdoff on interrupts. (== 0x01 despite what the docs say) */ pci_read_config_byte(dev, regfast, &drive_fast); new_fast = drive_fast; if (new_fast & 0x02) new_fast &= ~0x02;#ifdef HPT_DELAY_INTERRUPT if (new_fast & 0x01) new_fast &= ~0x01;#else if ((new_fast & 0x01) == 0) new_fast |= 0x01;#endif if (new_fast != drive_fast) pci_write_config_byte(dev, regfast, new_fast); list_conf = pci_bus_clock_list(speed, info->speed); 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); return ide_config_drive_speed(drive, speed);}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); u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 regfast = (drive->hwif->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; /* * 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(dev, regfast, drive_fast); list_conf = pci_bus_clock_list(speed, info->speed); 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); return ide_config_drive_speed(drive, speed);}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); if (info->revision >= 8) return hpt372_tune_chipset(drive, speed); /* not a typo */ else if (info->revision >= 5) return hpt372_tune_chipset(drive, speed); else if (info->revision >= 3) return hpt370_tune_chipset(drive, speed); else /* hpt368: hpt_minimum_revision(dev, 2) */ return hpt36x_tune_chipset(drive, speed);}static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio){ pio = ide_get_best_pio_mode(drive, 255, pio, NULL); (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio));}/* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities * after the drive is reported by the OS. Initially for designed for * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. * * check_in_drive_lists(drive, bad_ata66_4) * check_in_drive_lists(drive, bad_ata66_3) * check_in_drive_lists(drive, bad_ata33) * */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) return 0; (void) hpt3xx_tune_chipset(drive, speed); return ide_dma_enable(drive);}static int hpt3xx_quirkproc (ide_drive_t *drive){ return ((int) check_in_drive_lists(drive, quirk_drives));}static void hpt3xx_intrproc (ide_drive_t *drive){ ide_hwif_t *hwif = drive->hwif; if (drive->quirk_list) return; /* drives in the quirk_list may not like intr setups/cleanups */ hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);}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; if (drive->quirk_list) { if (info->revision >= 3) { u8 reg5a = 0; pci_read_config_byte(dev, 0x5a, ®5a); if (((reg5a & 0x10) >> 4) != mask) pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); } else { if (mask) { disable_irq(hwif->irq); } else { enable_irq(hwif->irq); } } } else { if (IDE_CONTROL_REG) hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG); }}static int hpt366_config_drive_xfer_rate (ide_drive_t *drive){ ide_hwif_t *hwif = drive->hwif; 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); } goto fast_ata_pio; } else if ((id->capability & 8) || (id->field_valid & 2)) {fast_ata_pio: hpt3xx_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } /* IORDY not supported */ return 0;}/* * This is specific to the HPT366 UDMA bios chipset * by HighPoint|Triones Technologies, Inc. */static int hpt366_ide_dma_lostirq (ide_drive_t *drive){ struct pci_dev *dev = HWIF(drive)->pci_dev; u8 reg50h = 0, reg52h = 0, reg5ah = 0; pci_read_config_byte(dev, 0x50, ®50h); pci_read_config_byte(dev, 0x52, ®52h); pci_read_config_byte(dev, 0x5a, ®5ah); printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); if (reg5ah & 0x10) pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); return __ide_dma_lostirq(drive);}static void hpt370_clear_engine (ide_drive_t *drive){ u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50; pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37); udelay(10);}static void hpt370_ide_dma_start(ide_drive_t *drive){#ifdef HPT_RESET_STATE_ENGINE hpt370_clear_engine(drive);#endif ide_dma_start(drive);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -