/* Calculate Ultra DMA timings */ static int pmac_ide_udma_enable(ide_drive_t *drive, int idx) { byte bits = drive->id->dma_ultra & 0x1f; byte feature = udma_bits_to_command(bits); int cycleTime, accessTime; int rdyToPauseTicks, cycleTicks; u32 *timings; /* Set feature on drive */ printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf); if (pmac_ide_do_setfeature(drive, feature)) { printk("%s: Failed !\n", drive->name); return 0; } /* which drive is it ? */ if (drive->select.all & 0x10) timings = &pmac_ide[idx].timings[1]; else timings = &pmac_ide[idx].timings[0]; cycleTime = udma_timings[feature & 0xf].cycleTime; accessTime = udma_timings[feature & 0xf].accessTime; rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000); cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000); *timings = ((*timings) & 0xe00fffff) | ((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20; return 1; }
/* You may notice we don't use this function on normal operation, * our, normal mdma function is supposed to be more precise */ static int pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) { int intf = pmac_ide_find(drive); int unit = (drive->select.all & 0x10) ? 1:0; int ret = 0; u32 *timings; if (intf < 0) return 1; timings = &pmac_ide[intf].timings[unit]; switch(speed) { #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC case XFER_UDMA_4: case XFER_UDMA_3: case XFER_UDMA_2: case XFER_UDMA_1: case XFER_UDMA_0: ret = set_timings_udma(intf, timings, speed); break; case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_MW_DMA_0: case XFER_SW_DMA_2: case XFER_SW_DMA_1: case XFER_SW_DMA_0: ret = set_timings_mdma(intf, timings, speed); break; #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ case XFER_PIO_4: case XFER_PIO_3: case XFER_PIO_2: case XFER_PIO_1: case XFER_PIO_0: pmac_ide_tuneproc(drive, speed & 0x07); break; default: ret = 1; } if (ret) return ret; ret = pmac_ide_do_setfeature(drive, speed); if (ret) return ret; pmac_ide_selectproc(drive); drive->current_speed = speed; return 0; }
/* Calculate MultiWord DMA timings */ static int pmac_ide_mdma_enable(ide_drive_t *drive, int idx) { byte bits = drive->id->dma_mword & 0x07; byte feature = dma_bits_to_command(bits); u32 *timings; int cycleTime, accessTime; int accessTicks, recTicks; struct hd_driveid *id = drive->id; int ret; /* Set feature on drive */ printk(KERN_INFO "%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf); ret = pmac_ide_do_setfeature(drive, feature); if (ret) { printk(KERN_WARNING "%s: Failed !\n", drive->name); return 0; } if (!drive->init_speed) drive->init_speed = feature; /* which drive is it ? */ if (drive->select.all & 0x10) timings = &pmac_ide[idx].timings[1]; else timings = &pmac_ide[idx].timings[0]; /* Calculate accesstime and cycle time */ cycleTime = mdma_timings[feature & 0xf].cycleTime; accessTime = mdma_timings[feature & 0xf].accessTime; if ((id->field_valid & 2) && (id->eide_dma_time)) cycleTime = id->eide_dma_time; if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150)) cycleTime = 150; /* For ata-4 controller */ if (pmac_ide[idx].kind == controller_kl_ata4) { accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000); recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks; *timings = ((*timings) & 0xffe003ff) | (accessTicks | (recTicks << 5)) << 10; } else { int halfTick = 0; int origAccessTime = accessTime; int origCycleTime = cycleTime; accessTicks = SYSCLK_TICKS(accessTime); if (accessTicks < 1) accessTicks = 1; accessTime = accessTicks * IDE_SYSCLK_NS; recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1; if (recTicks < 1) recTicks = 1; cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS; /* KeyLargo ata-3 don't support the half-tick stuff */ if ((pmac_ide[idx].kind != controller_kl_ata3) && (accessTicks > 1) && ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && ((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) { halfTick = 1; accessTicks--; } *timings = ((*timings) & 0x7FF) | (accessTicks | (recTicks << 5) | (halfTick << 10)) << 11; } #ifdef IDE_PMAC_DEBUG printk(KERN_INFO "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n", feature & 0xf, *timings); #endif drive->current_speed = feature; return 1; }