📄 pmac.c
字号:
*irq = pmac_ide[ix].irq; hw->dev = &pmac_ide[ix].mdev->ofdev.dev;}#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))/* * Apply the timings of the proper unit (master/slave) to the shared * timing register when selecting that unit. This version is for * ASICs with a single timing register */static voidpmac_ide_selectproc(ide_drive_t *drive){ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; if (pmif == NULL) return; if (drive->select.b.unit & 0x01) writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG)); else writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG)); (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));}/* * Apply the timings of the proper unit (master/slave) to the shared * timing register when selecting that unit. This version is for * ASICs with a dual timing register (Kauai) */static voidpmac_ide_kauai_selectproc(ide_drive_t *drive){ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; if (pmif == NULL) return; if (drive->select.b.unit & 0x01) { writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); } else { writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); } (void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));}/* * Force an update of controller timing values for a given drive */static voidpmac_ide_do_update_timings(ide_drive_t *drive){ pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; if (pmif == NULL) return; if (pmif->kind == controller_sh_ata6 || pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6) pmac_ide_kauai_selectproc(drive); else pmac_ide_selectproc(drive);}static voidpmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port){ u32 tmp; writeb(value, (void __iomem *) port); tmp = readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));}/* * Old tuning functions (called on hdparm -p), sets up drive PIO timings */static voidpmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio){ u32 *timings, t; unsigned accessTicks, recTicks; unsigned accessTime, recTime; pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; unsigned int cycle_time; if (pmif == NULL) return; /* which drive is it ? */ timings = &pmif->timings[drive->select.b.unit & 0x01]; t = *timings; cycle_time = ide_pio_cycle_time(drive, pio); switch (pmif->kind) { case controller_sh_ata6: { /* 133Mhz cell */ u32 tr = kauai_lookup_timing(shasta_pio_timings, cycle_time); t = (t & ~TR_133_PIOREG_PIO_MASK) | tr; break; } case controller_un_ata6: case controller_k2_ata6: { /* 100Mhz cell */ u32 tr = kauai_lookup_timing(kauai_pio_timings, cycle_time); t = (t & ~TR_100_PIOREG_PIO_MASK) | tr; break; } case controller_kl_ata4: /* 66Mhz cell */ recTime = cycle_time - ide_pio_timings[pio].active_time - ide_pio_timings[pio].setup_time; recTime = max(recTime, 150U); accessTime = ide_pio_timings[pio].active_time; accessTime = max(accessTime, 150U); accessTicks = SYSCLK_TICKS_66(accessTime); accessTicks = min(accessTicks, 0x1fU); recTicks = SYSCLK_TICKS_66(recTime); recTicks = min(recTicks, 0x1fU); t = (t & ~TR_66_PIO_MASK) | (accessTicks << TR_66_PIO_ACCESS_SHIFT) | (recTicks << TR_66_PIO_RECOVERY_SHIFT); break; default: { /* 33Mhz cell */ int ebit = 0; recTime = cycle_time - ide_pio_timings[pio].active_time - ide_pio_timings[pio].setup_time; recTime = max(recTime, 150U); accessTime = ide_pio_timings[pio].active_time; accessTime = max(accessTime, 150U); accessTicks = SYSCLK_TICKS(accessTime); accessTicks = min(accessTicks, 0x1fU); accessTicks = max(accessTicks, 4U); recTicks = SYSCLK_TICKS(recTime); recTicks = min(recTicks, 0x1fU); recTicks = max(recTicks, 5U) - 4; if (recTicks > 9) { recTicks--; /* guess, but it's only for PIO0, so... */ ebit = 1; } t = (t & ~TR_33_PIO_MASK) | (accessTicks << TR_33_PIO_ACCESS_SHIFT) | (recTicks << TR_33_PIO_RECOVERY_SHIFT); if (ebit) t |= TR_33_PIO_E; break; } }#ifdef IDE_PMAC_DEBUG printk(KERN_ERR "%s: Set PIO timing for mode %d, reg: 0x%08x\n", drive->name, pio, *timings);#endif *timings = t; pmac_ide_do_update_timings(drive);}#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC/* * Calculate KeyLargo ATA/66 UDMA timings */static intset_timings_udma_ata4(u32 *timings, u8 speed){ unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks; if (speed > XFER_UDMA_4) return 1; rdyToPauseTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].rdy2pause); wrDataSetupTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].wrDataSetup); addrTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].addrSetup); *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) | (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | (rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) | (addrTicks <<TR_66_UDMA_ADDRSETUP_SHIFT) | TR_66_UDMA_EN;#ifdef IDE_PMAC_DEBUG printk(KERN_ERR "ide_pmac: Set UDMA timing for mode %d, reg: 0x%08x\n", speed & 0xf, *timings);#endif return 0;}/* * Calculate Kauai ATA/100 UDMA timings */static intset_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed){ struct ide_timing *t = ide_timing_find_mode(speed); u32 tr; if (speed > XFER_UDMA_5 || t == NULL) return 1; tr = kauai_lookup_timing(kauai_udma_timings, (int)t->udma); *ultra_timings = ((*ultra_timings) & ~TR_100_UDMAREG_UDMA_MASK) | tr; *ultra_timings = (*ultra_timings) | TR_100_UDMAREG_UDMA_EN; return 0;}/* * Calculate Shasta ATA/133 UDMA timings */static intset_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed){ struct ide_timing *t = ide_timing_find_mode(speed); u32 tr; if (speed > XFER_UDMA_6 || t == NULL) return 1; tr = kauai_lookup_timing(shasta_udma133_timings, (int)t->udma); *ultra_timings = ((*ultra_timings) & ~TR_133_UDMAREG_UDMA_MASK) | tr; *ultra_timings = (*ultra_timings) | TR_133_UDMAREG_UDMA_EN; return 0;}/* * Calculate MDMA timings for all cells */static voidset_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, u8 speed){ int cycleTime, accessTime = 0, recTime = 0; unsigned accessTicks, recTicks; struct hd_driveid *id = drive->id; struct mdma_timings_t* tm = NULL; int i; /* Get default cycle time for mode */ switch(speed & 0xf) { case 0: cycleTime = 480; break; case 1: cycleTime = 150; break; case 2: cycleTime = 120; break; default: BUG(); break; } /* Check if drive provides explicit DMA cycle time */ if ((id->field_valid & 2) && id->eide_dma_time) cycleTime = max_t(int, id->eide_dma_time, cycleTime); /* OHare limits according to some old Apple sources */ if ((intf_type == controller_ohare) && (cycleTime < 150)) cycleTime = 150; /* Get the proper timing array for this controller */ switch(intf_type) { case controller_sh_ata6: case controller_un_ata6: case controller_k2_ata6: break; case controller_kl_ata4: tm = mdma_timings_66; break; case controller_kl_ata3: tm = mdma_timings_33k; break; default: tm = mdma_timings_33; break; } if (tm != NULL) { /* Lookup matching access & recovery times */ i = -1; for (;;) { if (tm[i+1].cycleTime < cycleTime) break; i++; } cycleTime = tm[i].cycleTime; accessTime = tm[i].accessTime; recTime = tm[i].recoveryTime;#ifdef IDE_PMAC_DEBUG printk(KERN_ERR "%s: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n", drive->name, cycleTime, accessTime, recTime);#endif } switch(intf_type) { case controller_sh_ata6: { /* 133Mhz cell */ u32 tr = kauai_lookup_timing(shasta_mdma_timings, cycleTime); *timings = ((*timings) & ~TR_133_PIOREG_MDMA_MASK) | tr; *timings2 = (*timings2) & ~TR_133_UDMAREG_UDMA_EN; } case controller_un_ata6: case controller_k2_ata6: { /* 100Mhz cell */ u32 tr = kauai_lookup_timing(kauai_mdma_timings, cycleTime); *timings = ((*timings) & ~TR_100_PIOREG_MDMA_MASK) | tr; *timings2 = (*timings2) & ~TR_100_UDMAREG_UDMA_EN; } break; case controller_kl_ata4: /* 66Mhz cell */ accessTicks = SYSCLK_TICKS_66(accessTime); accessTicks = min(accessTicks, 0x1fU); accessTicks = max(accessTicks, 0x1U); recTicks = SYSCLK_TICKS_66(recTime); recTicks = min(recTicks, 0x1fU); recTicks = max(recTicks, 0x3U); /* Clear out mdma bits and disable udma */ *timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) | (accessTicks << TR_66_MDMA_ACCESS_SHIFT) | (recTicks << TR_66_MDMA_RECOVERY_SHIFT); break; case controller_kl_ata3: /* 33Mhz cell on KeyLargo */ accessTicks = SYSCLK_TICKS(accessTime); accessTicks = max(accessTicks, 1U); accessTicks = min(accessTicks, 0x1fU); accessTime = accessTicks * IDE_SYSCLK_NS; recTicks = SYSCLK_TICKS(recTime); recTicks = max(recTicks, 1U); recTicks = min(recTicks, 0x1fU); *timings = ((*timings) & ~TR_33_MDMA_MASK) | (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | (recTicks << TR_33_MDMA_RECOVERY_SHIFT); break; default: { /* 33Mhz cell on others */ int halfTick = 0; int origAccessTime = accessTime; int origRecTime = recTime; accessTicks = SYSCLK_TICKS(accessTime); accessTicks = max(accessTicks, 1U); accessTicks = min(accessTicks, 0x1fU); accessTime = accessTicks * IDE_SYSCLK_NS; recTicks = SYSCLK_TICKS(recTime); recTicks = max(recTicks, 2U) - 1; recTicks = min(recTicks, 0x1fU); recTime = (recTicks + 1) * IDE_SYSCLK_NS; if ((accessTicks > 1) && ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) { halfTick = 1; accessTicks--; } *timings = ((*timings) & ~TR_33_MDMA_MASK) | (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | (recTicks << TR_33_MDMA_RECOVERY_SHIFT); if (halfTick) *timings |= TR_33_MDMA_HALFTICK; } }#ifdef IDE_PMAC_DEBUG printk(KERN_ERR "%s: Set MDMA timing for mode %d, reg: 0x%08x\n", drive->name, speed & 0xf, *timings);#endif }#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed){ int unit = (drive->select.b.unit & 0x01); int ret = 0; pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; u32 *timings, *timings2, tl[2]; timings = &pmif->timings[unit]; timings2 = &pmif->timings[unit+2]; /* Copy timings to local image */ tl[0] = *timings; tl[1] = *timings2; switch(speed) {#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC case XFER_UDMA_6: case XFER_UDMA_5: case XFER_UDMA_4: case XFER_UDMA_3: case XFER_UDMA_2: case XFER_UDMA_1: case XFER_UDMA_0: if (pmif->kind == controller_kl_ata4) ret = set_timings_udma_ata4(&tl[0], speed); else if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6) ret = set_timings_udma_ata6(&tl[0], &tl[1], speed); else if (pmif->kind == controller_sh_ata6) ret = set_timings_udma_shasta(&tl[0], &tl[1], speed); else ret = 1; break; case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_MW_DMA_0: set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed); break; case XFER_SW_DMA_2: case XFER_SW_DMA_1: case XFER_SW_DMA_0: return;#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ default: ret = 1; } if (ret) return; /* Apply timings to controller */ *timings = tl[0]; *timings2 = tl[1]; pmac_ide_do_update_timings(drive); }/* * Blast some well known "safe" values to the timing registers at init or * wakeup from sleep time, before we do real calculation */static voidsanitize_timings(pmac_ide_hwif_t *pmif){ unsigned int value, value2 = 0; switch(pmif->kind) { case controller_sh_ata6: value = 0x0a820c97; value2 = 0x00033031; break; case controller_un_ata6: case controller_k2_ata6: value = 0x08618a92; value2 = 0x00002921; break; case controller_kl_ata4: value = 0x0008438c; break; case controller_kl_ata3: value = 0x00084526; break; case controller_heathrow: case controller_ohare: default: value = 0x00074526;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -