📄 hpt366.c
字号:
* */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->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);}/** * hpt372n_set_clock - perform clock switching dance * @drive: Drive to switch * @mode: Switching mode (0x21 for write, 0x23 otherwise) * * Switch the DPLL clock on the HPT372N devices. This is a * right mess. */ static void hpt372n_set_clock(ide_drive_t *drive, int mode){ ide_hwif_t *hwif = HWIF(drive); /* FIXME: should we check for DMA active and BUG() */ /* Tristate the bus */ outb(0x80, hwif->dma_base+0x73); outb(0x80, hwif->dma_base+0x77); /* Switch clock and reset channels */ outb(mode, hwif->dma_base+0x7B); outb(0xC0, hwif->dma_base+0x79); /* Reset state machines */ outb(0x37, hwif->dma_base+0x70); outb(0x37, hwif->dma_base+0x74); /* Complete reset */ outb(0x00, hwif->dma_base+0x79); /* Reconnect channels to bus */ outb(0x00, hwif->dma_base+0x73); outb(0x00, hwif->dma_base+0x79);}/** * hpt372n_rw_disk - wrapper for I/O * @drive: drive for command * @rq: block request structure * @block: block number * * This is called when a disk I/O is issued to the 372N instead * of the default functionality. We need it because of the clock * switching * */ static ide_startstop_t hpt372n_rw_disk(ide_drive_t *drive, struct request *rq, unsigned long block){ int wantclock; if(rq_data_dir(rq) == READ) wantclock = 0x21; else wantclock = 0x23; if(HWIF(drive)->config_data != wantclock) { hpt372n_set_clock(drive, wantclock); HWIF(drive)->config_data = wantclock; } return __ide_do_rw_disk(drive, rq, block);}/* * 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); switch(state) { case BUSSTATE_ON: (void) ide_do_reset(drive); pci_write_config_byte(dev, state_reg, regXXh|0x80); pci_write_config_byte(dev, 0x59, reg59h|reset); break; case BUSSTATE_OFF: pci_write_config_byte(dev, 0x59, reg59h & ~(reset)); pci_write_config_byte(dev, state_reg, regXXh & ~(0x80)); (void) ide_do_reset(drive); break; default: return -EINVAL; } 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; default: return -EINVAL; } 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; u8 reg5ah; unsigned long dmabase = pci_resource_start(dev, 4); u8 did, rid; int is_372n = 0;#if 1 pci_read_config_byte(dev, 0x5a, ®5ah); /* interrupt force enable */ pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));#endif if(dmabase) { did = inb(dmabase + 0x22); rid = inb(dmabase + 0x28); if((did == 4 && rid == 6) || (did == 5 && rid > 1)) is_372n = 1; } /* * default to pci clock. make sure MA15/16 are set to output * to prevent drives having problems with 40-pin cables. Needed * for some drives such as IBM-DTLA which will not enter ready * state on reset when PDIAG is a input. * * ToDo: should we set 0x21 when using PLL mode ? */ 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 * * Todo. For non x86 should probably check the dword is * set to 0xABCDExxx indicating the BIOS saved f_CNT */ pci_read_config_word(dev, 0x78, &freq); freq &= 0x1FF; /* * The 372N uses different PCI clock information and has * some other complications * On PCI33 timing we must clock switch * On PCI66 timing we must NOT use the PCI clock * * Currently we always set up the PLL for the 372N */ if(is_372n) { printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n"); if(freq < 0x55) pll = F_LOW_PCI_33; else if(freq < 0x70) pll = F_LOW_PCI_40; else if(freq < 0x7F) pll = F_LOW_PCI_50; else pll = F_LOW_PCI_66; printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll); /* We always use the pll not the PCI clock on 372N */ } else { if(freq < 0x9C) pll = F_LOW_PCI_33; else if(freq < 0xb0) pll = F_LOW_PCI_40; else if(freq <0xc8) pll = F_LOW_PCI_50; else pll = F_LOW_PCI_66; if (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 (pll == F_LOW_PCI_40) { } else if (pll == F_LOW_PCI_50) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -