📄 hpt366.c
字号:
hpt372_tune_chipset(drive, speed);}static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed){ struct pci_dev *dev = HWIF(drive)->pci_dev; if (hpt_minimum_revision(dev, 8)) hpt374_tune_chipset(drive, speed);#if 0 else if (hpt_minimum_revision(dev, 7)) hpt371_tune_chipset(drive, speed); else if (hpt_minimum_revision(dev, 6)) hpt302_tune_chipset(drive, speed);#endif else if (hpt_minimum_revision(dev, 5)) hpt372_tune_chipset(drive, speed); else if (hpt_minimum_revision(dev, 3)) hpt370_tune_chipset(drive, speed); else if (hpt_minimum_revision(dev, 2)) hpt368_tune_chipset(drive, speed); else hpt366_tune_chipset(drive, speed); return ((int) ide_config_drive_speed(drive, speed));}static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio){ pio = ide_get_best_pio_mode(drive, pio, 5, 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. Initally 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)); if (!(speed)) 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 = HWIF(drive); 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){ struct pci_dev *dev = HWIF(drive)->pci_dev; if (drive->quirk_list) { if (hpt_minimum_revision(dev,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(drive)->irq); } else { enable_irq(HWIF(drive)->irq); } } } else { if (IDE_CONTROL_REG) HWIF(drive)->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 = HWIF(drive); struct hd_driveid *id = drive->id; drive->init_speed = 0; if (id && (id->capability & 1) && drive->autodma) { /* Consult the list of known "bad" drives */ if (hwif->ide_dma_bad_drive(drive)) goto fast_ata_pio; if (id->field_valid & 4) { if (id->dma_ultra & hwif->ultra_mask) { /* Force if Capable UltraDMA */ int dma = config_chipset_for_dma(drive); if ((id->field_valid & 2) && !dma) goto try_dma_modes; } } else if (id->field_valid & 2) {try_dma_modes: if (id->dma_mword & hwif->mwdma_mask) { /* Force if Capable regular DMA modes */ if (!config_chipset_for_dma(drive)) goto no_dma_set; } } else if (hwif->ide_dma_good_drive(drive) && (id->eide_dma_time < 150)) { /* Consult the list of known "good" drives */ if (!config_chipset_for_dma(drive)) goto no_dma_set; } else { goto fast_ata_pio; } } else if ((id->capability & 8) || (id->field_valid & 2)) {fast_ata_pio:no_dma_set: hpt3xx_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } return hwif->ide_dma_on(drive);}/* * 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);#if 0 /* how about we flush and reset, mmmkay? */ pci_write_config_byte(dev, 0x51, 0x1F); /* fall through to a reset */ case ide_dma_begin: case ide_dma_end: /* reset the chips state over and over.. */ pci_write_config_byte(dev, 0x51, 0x13);#endif 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 int hpt370_ide_dma_begin (ide_drive_t *drive){#ifdef HPT_RESET_STATE_ENGINE hpt370_clear_engine(drive);#endif return __ide_dma_begin(drive);}static int hpt370_ide_dma_end (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = hwif->INB(hwif->dma_status); if (dma_stat & 0x01) { /* wait a little */ udelay(20); dma_stat = hwif->INB(hwif->dma_status); } if ((dma_stat & 0x01) != 0) /* fallthrough */ (void) HWIF(drive)->ide_dma_timeout(drive); return __ide_dma_end(drive);}static void hpt370_lostirq_timeout (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 bfifo = 0, reginfo = hwif->channel ? 0x56 : 0x52; u8 dma_stat = 0, dma_cmd = 0; pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo); printk("%s: %d bytes in FIFO\n", drive->name, bfifo); hpt370_clear_engine(drive); /* get dma command mode */ dma_cmd = hwif->INB(hwif->dma_command); /* stop dma */ hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command); dma_stat = hwif->INB(hwif->dma_status); /* clear errors */ hwif->OUTB(dma_stat | 0x6, hwif->dma_status);}static int hpt370_ide_dma_timeout (ide_drive_t *drive){ hpt370_lostirq_timeout(drive); hpt370_clear_engine(drive); return __ide_dma_timeout(drive);}static int hpt370_ide_dma_lostirq (ide_drive_t *drive){ hpt370_lostirq_timeout(drive); hpt370_clear_engine(drive); return __ide_dma_lostirq(drive);}static int hpt374_ide_dma_end (ide_drive_t *drive){ struct pci_dev *dev = HWIF(drive)->pci_dev; ide_hwif_t *hwif = HWIF(drive); u8 msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50; u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01; 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); return __ide_dma_end(drive);}/* * Since SUN Cobalt is attempting to do this operation, I should disclose * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date * HOTSWAP ATA Infrastructure. */static void hpt3xx_reset (ide_drive_t *drive){#if 0 unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); u8 reset = (HWIF(drive)->channel) ? 0x80 : 0x40; u8 reg59h = 0; pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, ®59h); pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset); pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h);#endif}static int hpt3xx_tristate (ide_drive_t * drive, int state){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40; u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53; if (!hwif) return -EINVAL;// hwif->bus_state = state; pci_read_config_byte(dev, 0x59, ®59h); pci_read_config_byte(dev, state_reg, ®XXh); if (state) { (void) ide_do_reset(drive); pci_write_config_byte(dev, state_reg, regXXh|0x80); pci_write_config_byte(dev, 0x59, reg59h|reset); } else { pci_write_config_byte(dev, 0x59, reg59h & ~(reset)); pci_write_config_byte(dev, state_reg, regXXh & ~(0x80)); (void) ide_do_reset(drive); } return 0;}/* * set/get power state for a drive. * turning the power off does the following things: * 1) soft-reset the drive * 2) tri-states the ide bus * * when we turn things back on, we need to re-initialize things. */#define TRISTATE_BIT 0x8000static int hpt370_busproc(ide_drive_t * drive, int state){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 tristate = 0, resetmask = 0, bus_reg = 0; u16 tri_reg; if (!hwif) return -EINVAL; hwif->bus_state = state; if (hwif->channel) { /* secondary channel */ tristate = 0x56; resetmask = 0x80; } else { /* primary channel */ tristate = 0x52; resetmask = 0x40; } /* grab status */ pci_read_config_word(dev, tristate, &tri_reg); pci_read_config_byte(dev, 0x59, &bus_reg); /* set the state. we don't set it if we don't need to do so. * make sure that the drive knows that it has failed if it's off */ switch (state) { case BUSSTATE_ON: hwif->drives[0].failures = 0; hwif->drives[1].failures = 0; if ((bus_reg & resetmask) == 0) return 0; tri_reg &= ~TRISTATE_BIT; bus_reg &= ~resetmask; break; case BUSSTATE_OFF: hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask)) return 0; tri_reg &= ~TRISTATE_BIT; bus_reg |= resetmask; break; case BUSSTATE_TRISTATE: hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask)) return 0; tri_reg |= TRISTATE_BIT; bus_reg |= resetmask; break; } pci_write_config_byte(dev, 0x59, bus_reg); pci_write_config_word(dev, tristate, tri_reg); return 0;}static int __init init_hpt37x(struct pci_dev *dev){ int adjust, i; u16 freq; u32 pll; u8 reg5bh;#if 1 u8 reg5ah = 0; pci_read_config_byte(dev, 0x5a, ®5ah); /* interrupt force enable */ pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));#endif /* * default to pci clock. make sure MA15/16 are set to output * to prevent drives having problems with 40-pin cables. */ pci_write_config_byte(dev, 0x5b, 0x23); /* * set up the PLL. we need to adjust it so that it's stable. * freq = Tpll * 192 / Tpci */ pci_read_config_word(dev, 0x78, &freq); freq &= 0x1FF; if (freq < 0x9c) { pll = F_LOW_PCI_33; if (hpt_minimum_revision(dev,8)) pci_set_drvdata(dev, (void *) thirty_three_base_hpt374); else if (hpt_minimum_revision(dev,5)) pci_set_drvdata(dev, (void *) thirty_three_base_hpt372); else if (hpt_minimum_revision(dev,4)) pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a); else pci_set_drvdata(dev, (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; if (hpt_minimum_revision(dev,8)) pci_set_drvdata(dev, NULL); else if (hpt_minimum_revision(dev,5)) pci_set_drvdata(dev, (void *) fifty_base_hpt372); else if (hpt_minimum_revision(dev,4)) pci_set_drvdata(dev, (void *) fifty_base_hpt370a); else pci_set_drvdata(dev, (void *) fifty_base_hpt370a); printk("HPT37X: using 50MHz PCI clock\n"); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -