hpt366.c
来自「linux 内核源代码」· C语言 代码 · 共 1,677 行 · 第 1/4 页
C
1,677 行
static u32 sixty_six_base_hpt37x[] = { /* XFER_UDMA_6 */ 0x1c86fe62, /* XFER_UDMA_5 */ 0x1caefe62, /* 0x1c8afe62 */ /* XFER_UDMA_4 */ 0x1c8afe62, /* XFER_UDMA_3 */ 0x1c8efe62, /* XFER_UDMA_2 */ 0x1c92fe62, /* XFER_UDMA_1 */ 0x1c9afe62, /* XFER_UDMA_0 */ 0x1c82fe62, /* XFER_MW_DMA_2 */ 0x2c82fe62, /* XFER_MW_DMA_1 */ 0x2c82fe66, /* XFER_MW_DMA_0 */ 0x2c82ff2e, /* XFER_PIO_4 */ 0x0c82fe62, /* XFER_PIO_3 */ 0x0c82fe84, /* XFER_PIO_2 */ 0x0c82fea6, /* XFER_PIO_1 */ 0x0d02ff26, /* XFER_PIO_0 */ 0x0d42ff7f};#endif#define HPT366_DEBUG_DRIVE_INFO 0#define HPT371_ALLOW_ATA133_6 1#define HPT302_ALLOW_ATA133_6 1#define HPT372_ALLOW_ATA133_6 1#define HPT370_ALLOW_ATA100_5 0#define HPT366_ALLOW_ATA66_4 1#define HPT366_ALLOW_ATA66_3 1#define HPT366_MAX_DEVS 8/* Supported ATA clock frequencies */enum ata_clock { ATA_CLOCK_25MHZ, ATA_CLOCK_33MHZ, ATA_CLOCK_40MHZ, ATA_CLOCK_50MHZ, ATA_CLOCK_66MHZ, NUM_ATA_CLOCKS};/* * Hold all the HighPoint chip information in one place. */struct hpt_info { char *chip_name; /* Chip name */ u8 chip_type; /* Chip type */ u8 udma_mask; /* Allowed UltraDMA modes mask. */ u8 dpll_clk; /* DPLL clock in MHz */ u8 pci_clk; /* PCI clock in MHz */ u32 **settings; /* Chipset settings table */};/* Supported HighPoint chips */enum { HPT36x, HPT370, HPT370A, HPT374, HPT372, HPT372A, HPT302, HPT371, HPT372N, HPT302N, HPT371N};static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = { twenty_five_base_hpt36x, thirty_three_base_hpt36x, forty_base_hpt36x, NULL, NULL};static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = { NULL, thirty_three_base_hpt37x, NULL, fifty_base_hpt37x, sixty_six_base_hpt37x};static const struct hpt_info hpt36x __devinitdata = { .chip_name = "HPT36x", .chip_type = HPT36x, .udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2, .dpll_clk = 0, /* no DPLL */ .settings = hpt36x_settings};static const struct hpt_info hpt370 __devinitdata = { .chip_name = "HPT370", .chip_type = HPT370, .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, .dpll_clk = 48, .settings = hpt37x_settings};static const struct hpt_info hpt370a __devinitdata = { .chip_name = "HPT370A", .chip_type = HPT370A, .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, .dpll_clk = 48, .settings = hpt37x_settings};static const struct hpt_info hpt374 __devinitdata = { .chip_name = "HPT374", .chip_type = HPT374, .udma_mask = ATA_UDMA5, .dpll_clk = 48, .settings = hpt37x_settings};static const struct hpt_info hpt372 __devinitdata = { .chip_name = "HPT372", .chip_type = HPT372, .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 55, .settings = hpt37x_settings};static const struct hpt_info hpt372a __devinitdata = { .chip_name = "HPT372A", .chip_type = HPT372A, .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 66, .settings = hpt37x_settings};static const struct hpt_info hpt302 __devinitdata = { .chip_name = "HPT302", .chip_type = HPT302, .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 66, .settings = hpt37x_settings};static const struct hpt_info hpt371 __devinitdata = { .chip_name = "HPT371", .chip_type = HPT371, .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 66, .settings = hpt37x_settings};static const struct hpt_info hpt372n __devinitdata = { .chip_name = "HPT372N", .chip_type = HPT372N, .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 77, .settings = hpt37x_settings};static const struct hpt_info hpt302n __devinitdata = { .chip_name = "HPT302N", .chip_type = HPT302N, .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 77, .settings = hpt37x_settings};static const struct hpt_info hpt371n __devinitdata = { .chip_name = "HPT371N", .chip_type = HPT371N, .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, .dpll_clk = 77, .settings = hpt37x_settings};static int check_in_drive_list(ide_drive_t *drive, const char **list){ struct hd_driveid *id = drive->id; while (*list) if (!strcmp(*list++,id->model)) return 1; return 0;}/* * The Marvell bridge chips used on the HighPoint SATA cards do not seem * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes... */static u8 hpt3xx_udma_filter(ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); struct hpt_info *info = pci_get_drvdata(hwif->pci_dev); u8 mask = hwif->ultra_mask; switch (info->chip_type) { case HPT36x: if (!HPT366_ALLOW_ATA66_4 || check_in_drive_list(drive, bad_ata66_4)) mask = ATA_UDMA3; if (!HPT366_ALLOW_ATA66_3 || check_in_drive_list(drive, bad_ata66_3)) mask = ATA_UDMA2; break; case HPT370: if (!HPT370_ALLOW_ATA100_5 || check_in_drive_list(drive, bad_ata100_5)) mask = ATA_UDMA4; break; case HPT370A: if (!HPT370_ALLOW_ATA100_5 || check_in_drive_list(drive, bad_ata100_5)) return ATA_UDMA4; case HPT372 : case HPT372A: case HPT372N: case HPT374 : if (ide_dev_is_sata(drive->id)) mask &= ~0x0e; /* Fall thru */ default: return mask; } return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;}static u8 hpt3xx_mdma_filter(ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); struct hpt_info *info = pci_get_drvdata(hwif->pci_dev); switch (info->chip_type) { case HPT372 : case HPT372A: case HPT372N: case HPT374 : if (ide_dev_is_sata(drive->id)) return 0x00; /* Fall thru */ default: return 0x07; }}static u32 get_speed_setting(u8 speed, struct hpt_info *info){ int i; /* * Lookup the transfer mode table to get the index into * the timing table. * * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used. */ for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) if (xfer_speeds[i] == speed) break; /* * NOTE: info->settings only points to the pointer * to the list of the actual register values */ return (*info->settings)[i];}static void hpt36x_set_mode(ide_drive_t *drive, const u8 speed){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); u8 itr_addr = drive->dn ? 0x44 : 0x40; u32 old_itr = 0; u32 itr_mask, new_itr; itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); new_itr = get_speed_setting(speed, info); /* * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) * to avoid problems handling I/O errors later */ pci_read_config_dword(dev, itr_addr, &old_itr); new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); new_itr &= ~0xc0000000; pci_write_config_dword(dev, itr_addr, new_itr);}static void hpt37x_set_mode(ide_drive_t *drive, const u8 speed){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); u8 itr_addr = 0x40 + (drive->dn * 4); u32 old_itr = 0; u32 itr_mask, new_itr; itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); new_itr = get_speed_setting(speed, info); pci_read_config_dword(dev, itr_addr, &old_itr); new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); if (speed < XFER_MW_DMA_0) new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ pci_write_config_dword(dev, itr_addr, new_itr);}static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed){ ide_hwif_t *hwif = HWIF(drive); struct hpt_info *info = pci_get_drvdata(hwif->pci_dev); if (info->chip_type >= HPT370) hpt37x_set_mode(drive, speed); else /* hpt368: hpt_minimum_revision(dev, 2) */ hpt36x_set_mode(drive, speed);}static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio){ hpt3xx_set_mode(drive, XFER_PIO_0 + pio);}static int hpt3xx_quirkproc(ide_drive_t *drive){ struct hd_driveid *id = drive->id; const char **list = quirk_drives; while (*list) if (strstr(id->model, *list++)) return 1; return 0;}static void hpt3xx_intrproc(ide_drive_t *drive){ if (drive->quirk_list) return; /* drives in the quirk_list may not like intr setups/cleanups */ outb(drive->ctl | 2, IDE_CONTROL_REG);}static void hpt3xx_maskproc(ide_drive_t *drive, int mask){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); if (drive->quirk_list) { if (info->chip_type >= HPT370) { u8 scr1 = 0; pci_read_config_byte(dev, 0x5a, &scr1); if (((scr1 & 0x10) >> 4) != mask) { if (mask) scr1 |= 0x10; else scr1 &= ~0x10; pci_write_config_byte(dev, 0x5a, scr1); } } else { if (mask) disable_irq(hwif->irq); else enable_irq (hwif->irq); } } else outb(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG);}/* * This is specific to the HPT366 UDMA chipset * by HighPoint|Triones Technologies, Inc. */static void hpt366_dma_lost_irq(ide_drive_t *drive){ struct pci_dev *dev = HWIF(drive)->pci_dev; u8 mcr1 = 0, mcr3 = 0, scr1 = 0; pci_read_config_byte(dev, 0x50, &mcr1); pci_read_config_byte(dev, 0x52, &mcr3); pci_read_config_byte(dev, 0x5a, &scr1); printk("%s: (%s) mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n", drive->name, __FUNCTION__, mcr1, mcr3, scr1); if (scr1 & 0x10) pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); ide_dma_lost_irq(drive);}static void hpt370_clear_engine(ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37); udelay(10);}static void hpt370_irq_timeout(ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u16 bfifo = 0; u8 dma_cmd; pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo); printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff); /* get DMA command mode */ dma_cmd = inb(hwif->dma_command); /* stop DMA */ outb(dma_cmd & ~0x1, hwif->dma_command); hpt370_clear_engine(drive);}static void hpt370_ide_dma_start(ide_drive_t *drive)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?