hpt366.c
来自「linux 内核源代码」· C语言 代码 · 共 1,677 行 · 第 1/4 页
C
1,677 行
{#ifdef HPT_RESET_STATE_ENGINE hpt370_clear_engine(drive);#endif ide_dma_start(drive);}static int hpt370_ide_dma_end(ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = inb(hwif->dma_status); if (dma_stat & 0x01) { /* wait a little */ udelay(20); dma_stat = inb(hwif->dma_status); if (dma_stat & 0x01) hpt370_irq_timeout(drive); } return __ide_dma_end(drive);}static void hpt370_dma_timeout(ide_drive_t *drive){ hpt370_irq_timeout(drive); ide_dma_timeout(drive);}/* returns 1 if DMA IRQ issued, 0 otherwise */static int hpt374_ide_dma_test_irq(ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u16 bfifo = 0; u8 dma_stat; pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo); if (bfifo & 0x1FF) {// printk("%s: %d bytes in FIFO\n", drive->name, bfifo); return 0; } dma_stat = inb(hwif->dma_status); /* return 1 if INTR asserted */ if (dma_stat & 4) return 1; if (!drive->waiting_for_dma) printk(KERN_WARNING "%s: (%s) called while not waiting\n", drive->name, __FUNCTION__); return 0;}static int hpt374_ide_dma_end(ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 mcr = 0, mcr_addr = hwif->select_data; u8 bwsr = 0, mask = hwif->channel ? 0x02 : 0x01; pci_read_config_byte(dev, 0x6a, &bwsr); pci_read_config_byte(dev, mcr_addr, &mcr); if (bwsr & mask) pci_write_config_byte(dev, mcr_addr, mcr | 0x30); return __ide_dma_end(drive);}/** * hpt3xxn_set_clock - perform clock switching dance * @hwif: hwif to switch * @mode: clocking mode (0x21 for write, 0x23 otherwise) * * Switch the DPLL clock on the HPT3xxN devices. This is a right mess. */static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode){ u8 scr2 = inb(hwif->dma_master + 0x7b); if ((scr2 & 0x7f) == mode) return; /* Tristate the bus */ outb(0x80, hwif->dma_master + 0x73); outb(0x80, hwif->dma_master + 0x77); /* Switch clock and reset channels */ outb(mode, hwif->dma_master + 0x7b); outb(0xc0, hwif->dma_master + 0x79); /* * Reset the state machines. * NOTE: avoid accidentally enabling the disabled channels. */ outb(inb(hwif->dma_master + 0x70) | 0x32, hwif->dma_master + 0x70); outb(inb(hwif->dma_master + 0x74) | 0x32, hwif->dma_master + 0x74); /* Complete reset */ outb(0x00, hwif->dma_master + 0x79); /* Reconnect channels to bus */ outb(0x00, hwif->dma_master + 0x73); outb(0x00, hwif->dma_master + 0x77);}/** * hpt3xxn_rw_disk - prepare for I/O * @drive: drive for command * @rq: block request structure * * This is called when a disk I/O is issued to HPT3xxN. * We need it because of the clock switching. */static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq){ hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21);}/* * Set/get power state for a drive. * NOTE: affects both drives on each channel. * * When we turn the power back on, we need to re-initialize things. */#define TRISTATE_BIT 0x8000static int hpt3xx_busproc(ide_drive_t *drive, int state){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 mcr_addr = hwif->select_data + 2; u8 resetmask = hwif->channel ? 0x80 : 0x40; u8 bsr2 = 0; u16 mcr = 0; hwif->bus_state = state; /* Grab the status. */ pci_read_config_word(dev, mcr_addr, &mcr); pci_read_config_byte(dev, 0x59, &bsr2); /* * 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: if (!(bsr2 & resetmask)) return 0; hwif->drives[0].failures = hwif->drives[1].failures = 0; pci_write_config_byte(dev, 0x59, bsr2 & ~resetmask); pci_write_config_word(dev, mcr_addr, mcr & ~TRISTATE_BIT); return 0; case BUSSTATE_OFF: if ((bsr2 & resetmask) && !(mcr & TRISTATE_BIT)) return 0; mcr &= ~TRISTATE_BIT; break; case BUSSTATE_TRISTATE: if ((bsr2 & resetmask) && (mcr & TRISTATE_BIT)) return 0; mcr |= TRISTATE_BIT; break; default: return -EINVAL; } hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; pci_write_config_word(dev, mcr_addr, mcr); pci_write_config_byte(dev, 0x59, bsr2 | resetmask); return 0;}/** * hpt37x_calibrate_dpll - calibrate the DPLL * @dev: PCI device * * Perform a calibration cycle on the DPLL. * Returns 1 if this succeeds */static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high){ u32 dpll = (f_high << 16) | f_low | 0x100; u8 scr2; int i; pci_write_config_dword(dev, 0x5c, dpll); /* Wait for oscillator ready */ for(i = 0; i < 0x5000; ++i) { udelay(50); pci_read_config_byte(dev, 0x5b, &scr2); if (scr2 & 0x80) break; } /* See if it stays ready (we'll just bail out if it's not yet) */ for(i = 0; i < 0x1000; ++i) { pci_read_config_byte(dev, 0x5b, &scr2); /* DPLL destabilized? */ if(!(scr2 & 0x80)) return 0; } /* Turn off tuning, we have the DPLL set */ pci_read_config_dword (dev, 0x5c, &dpll); pci_write_config_dword(dev, 0x5c, (dpll & ~0x100)); return 1;}static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name){ struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); unsigned long io_base = pci_resource_start(dev, 4); u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ u8 chip_type; enum ata_clock clock; if (info == NULL) { printk(KERN_ERR "%s: out of memory!\n", name); return -ENOMEM; } /* * Copy everything from a static "template" structure * to just allocated per-chip hpt_info structure. */ memcpy(info, pci_get_drvdata(dev), sizeof(struct hpt_info)); chip_type = info->chip_type; pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); /* * First, try to estimate the PCI clock frequency... */ if (chip_type >= HPT370) { u8 scr1 = 0; u16 f_cnt = 0; u32 temp = 0; /* Interrupt force enable. */ pci_read_config_byte(dev, 0x5a, &scr1); if (scr1 & 0x10) pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); /* * HighPoint does this for HPT372A. * NOTE: This register is only writeable via I/O space. */ if (chip_type == HPT372A) outb(0x0e, io_base + 0x9c); /* * 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); /* * We'll have to read f_CNT value in order to determine * the PCI clock frequency according to the following ratio: * * f_CNT = Fpci * 192 / Fdpll * * First try reading the register in which the HighPoint BIOS * saves f_CNT value before reprogramming the DPLL from its * default setting (which differs for the various chips). * * NOTE: This register is only accessible via I/O space; * HPT374 BIOS only saves it for the function 0, so we have to * always read it from there -- no need to check the result of * pci_get_slot() for the function 0 as the whole device has * been already "pinned" (via function 1) in init_setup_hpt374() */ if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { struct pci_dev *dev1 = pci_get_slot(dev->bus, dev->devfn - 1); unsigned long io_base = pci_resource_start(dev1, 4); temp = inl(io_base + 0x90); pci_dev_put(dev1); } else temp = inl(io_base + 0x90); /* * In case the signature check fails, we'll have to * resort to reading the f_CNT register itself in hopes * that nobody has touched the DPLL yet... */ if ((temp & 0xFFFFF000) != 0xABCDE000) { int i; printk(KERN_WARNING "%s: no clock data saved by BIOS\n", name); /* Calculate the average value of f_CNT. */ for (temp = i = 0; i < 128; i++) { pci_read_config_word(dev, 0x78, &f_cnt); temp += f_cnt & 0x1ff; mdelay(1); } f_cnt = temp / 128; } else f_cnt = temp & 0x1ff; dpll_clk = info->dpll_clk; pci_clk = (f_cnt * dpll_clk) / 192; /* Clamp PCI clock to bands. */ if (pci_clk < 40) pci_clk = 33; else if(pci_clk < 45) pci_clk = 40; else if(pci_clk < 55) pci_clk = 50; else pci_clk = 66; printk(KERN_INFO "%s: DPLL base: %d MHz, f_CNT: %d, " "assuming %d MHz PCI\n", name, dpll_clk, f_cnt, pci_clk); } else { u32 itr1 = 0; pci_read_config_dword(dev, 0x40, &itr1); /* Detect PCI clock by looking at cmd_high_time. */ switch((itr1 >> 8) & 0x07) { case 0x09: pci_clk = 40; break; case 0x05: pci_clk = 25; break; case 0x07: default: pci_clk = 33; break; } } /* Let's assume we'll use PCI clock for the ATA clock... */ switch (pci_clk) { case 25: clock = ATA_CLOCK_25MHZ; break; case 33: default: clock = ATA_CLOCK_33MHZ; break; case 40: clock = ATA_CLOCK_40MHZ; break; case 50: clock = ATA_CLOCK_50MHZ; break; case 66: clock = ATA_CLOCK_66MHZ; break; } /* * Only try the DPLL if we don't have a table for the PCI clock that * we are running at for HPT370/A, always use it for anything newer... * * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI. * We also don't like using the DPLL because this causes glitches * on PRST-/SRST- when the state engine gets reset... */ if (chip_type >= HPT374 || info->settings[clock] == NULL) { u16 f_low, delta = pci_clk < 50 ? 2 : 4; int adjust; /* * Select 66 MHz DPLL clock only if UltraATA/133 mode is * supported/enabled, use 50 MHz DPLL clock otherwise... */ if (info->udma_mask == ATA_UDMA6) { dpll_clk = 66; clock = ATA_CLOCK_66MHZ; } else if (dpll_clk) { /* HPT36x chips don't have DPLL */ dpll_clk = 50; clock = ATA_CLOCK_50MHZ; } if (info->settings[clock] == NULL) { printk(KERN_ERR "%s: unknown bus timing!\n", name); kfree(info); return -EIO; } /* Select the DPLL clock. */ pci_write_config_byte(dev, 0x5b, 0x21); /* * Adjust the DPLL based upon PCI clock, enable it, * and wait for stabilization... */ f_low = (pci_clk * 48) / dpll_clk; for (adjust = 0; adjust < 8; adjust++) { if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta)) break; /* * See if it'll settle at a fractionally different clock */ if (adjust & 1) f_low -= adjust >> 1; else f_low += adjust >> 1; } if (adjust == 8) { printk(KERN_ERR "%s: DPLL did not stabilize!\n", name); kfree(info); return -EIO; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?