📄 hpt366.c
字号:
#if 0 case ide_dma_begin: case ide_dma_end: /* reset the chips state over and over.. */ pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, 0x13);#endif break; case ide_dma_timeout: default: break; } return ide_dmaproc(func, drive); /* use standard DMA stuff */}int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); unsigned long dma_base = hwif->dma_base; byte regstate = 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); return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ case ide_dma_end: dma_stat = inb(dma_base + 2); if (dma_stat & 0x01) { udelay(20); /* wait a little */ dma_stat = inb(dma_base + 2); } if ((dma_stat & 0x01) == 0) break; func = ide_dma_timeout; /* fallthrough */ case ide_dma_timeout: case ide_dma_lostirq: pci_read_config_byte(hwif->pci_dev, reginfo, &dma_stat); printk("%s: %d bytes in FIFO\n", drive->name, dma_stat); pci_write_config_byte(hwif->pci_dev, regstate, 0x37); udelay(10); dma_stat = inb(dma_base); outb(dma_stat & ~0x1, dma_base); /* stop dma */ dma_stat = inb(dma_base + 2); outb(dma_stat | 0x6, dma_base+2); /* clear errors */ /* fallthrough */#ifdef HPT_RESET_STATE_ENGINE case ide_dma_begin:#endif pci_write_config_byte(hwif->pci_dev, regstate, 0x37); udelay(10); break; default: break; } return ide_dmaproc(func, drive); /* use standard DMA stuff */}#endif /* CONFIG_BLK_DEV_IDEDMA *//* * 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. */void hpt3xx_reset (ide_drive_t *drive){#if 0 unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); byte reset = (HWIF(drive)->channel) ? 0x80 : 0x40; byte 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; byte reset = (hwif->channel) ? 0x80 : 0x40; byte state_reg = (hwif->channel) ? 0x57 : 0x53; byte reg59h = 0; byte regXXh = 0; 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); byte tristate, resetmask, bus_reg; 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(hwif->pci_dev, tristate, &tri_reg); pci_read_config_byte(hwif->pci_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(hwif->pci_dev, 0x59, bus_reg); pci_write_config_word(hwif->pci_dev, tristate, tri_reg); return 0;}static void __init init_hpt370(struct pci_dev *dev){ int adjust, i; u16 freq; u32 pll; byte reg5bh; /* * 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; dev->sysdata = (void *) thirty_three_base_hpt370; printk("HPT370: 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"); } else { pll = F_LOW_PCI_66; dev->sysdata = (void *) sixty_six_base_hpt370; printk("HPT370: using 66MHz PCI clock\n"); } /* * only try the pll if we don't have a table for the clock * speed that we're running at. NOTE: the internal PLL will * result in slow reads when using a 33MHz PCI clock. we also * don't like to use the PLL because it will cause glitches * on PRST/SRST when the HPT state engine gets reset. */ if (dev->sysdata) goto init_hpt370_done; /* * adjust PLL based upon PCI clock, enable it, and wait for * stabilization. */ adjust = 0; freq = (pll < F_LOW_PCI_50) ? 2 : 4; while (adjust++ < 6) { pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 | pll | 0x100); /* wait for clock stabilization */ for (i = 0; i < 0x50000; i++) { pci_read_config_byte(dev, 0x5b, ®5bh); if (reg5bh & 0x80) { /* spin looking for the clock to destabilize */ for (i = 0; i < 0x1000; ++i) { pci_read_config_byte(dev, 0x5b, ®5bh); if ((reg5bh & 0x80) == 0) goto pll_recal; } pci_read_config_dword(dev, 0x5c, &pll); 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; } }pll_recal: if (adjust & 1) pll -= (adjust >> 1); else pll += (adjust >> 1); } init_hpt370_done: /* reset state engine */ pci_write_config_byte(dev, 0x50, 0x37); pci_write_config_byte(dev, 0x54, 0x37); udelay(100);}unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name){ byte test = 0; if (dev->resource[PCI_ROM_RESOURCE].start) pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); if (test != (L1_CACHE_BYTES / 4)) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); if (test != 0x78) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); pci_read_config_byte(dev, PCI_MIN_GNT, &test); if (test != 0x08) pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); pci_read_config_byte(dev, PCI_MAX_LAT, &test); if (test != 0x08) pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); if (pci_rev_check_hpt3xx(dev)) { init_hpt370(dev); hpt_devs[n_hpt_devs++] = dev; } else { 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;}unsigned int __init ata66_hpt366 (ide_hwif_t *hwif){ byte ata66 = 0; byte regmask = (hwif->channel) ? 0x01 : 0x02; pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66);#ifdef DEBUG printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", ata66, (ata66 & regmask) ? "33" : "66", PCI_FUNC(hwif->pci_dev->devfn));#endif /* DEBUG */ return ((ata66 & regmask) ? 0 : 1);}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; hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc;#ifdef HPT_SERIALIZE_IO /* serialize access to this device */ if (hwif->mate) 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) { 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; } else { hwif->dmaproc = &hpt366_dmaproc; } if (!noautodma) hwif->autodma = 1; else hwif->autodma = 0; } else { hwif->autodma = 0; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; }#else /* !CONFIG_BLK_DEV_IDEDMA */ hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; hwif->autodma = 0;#endif /* CONFIG_BLK_DEV_IDEDMA */}void __init ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase){ byte masterdma = 0, slavedma = 0; byte dma_new = 0, dma_old = inb(dmabase+2); byte primary = hwif->channel ? 0x4b : 0x43; byte secondary = hwif->channel ? 0x4f : 0x47; unsigned long flags; __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ dma_new = dma_old; pci_read_config_byte(hwif->pci_dev, primary, &masterdma); pci_read_config_byte(hwif->pci_dev, secondary, &slavedma); if (masterdma & 0x30) dma_new |= 0x20; if (slavedma & 0x30) dma_new |= 0x40; if (dma_new != dma_old) outb(dma_new, dmabase+2); __restore_flags(flags); /* local CPU only */ ide_setup_dma(hwif, dmabase, 8);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -