int ide_timing_compute(ide_drive_t *drive, u8 speed, struct ide_timing *t, int T, int UT) { u16 *id = drive->id; struct ide_timing *s, p; s = ide_timing_find_mode(speed); if (s == NULL) return -EINVAL; *t = *s; if (id[ATA_ID_FIELD_VALID] & 2) { memset(&p, 0, sizeof(p)); if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO]; else if ((speed <= XFER_PIO_4) || (speed == XFER_PIO_5 && !ata_id_is_cfa(id))) p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY]; else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) p.cycle = id[ATA_ID_EIDE_DMA_MIN]; ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B); } ide_timing_quantize(t, t, T, UT); if (speed >= XFER_SW_DMA_0) { u8 pio = ide_get_best_pio_mode(drive, 255, 5); ide_timing_compute(drive, XFER_PIO_0 + pio, &p, T, UT); ide_timing_merge(&p, t, t, IDE_TIMING_ALL); } if (t->act8b + t->rec8b < t->cyc8b) { t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2; t->rec8b = t->cyc8b - t->act8b; } if (t->active + t->recover < t->cycle) { t->active += (t->cycle - (t->active + t->recover)) / 2; t->recover = t->cycle - t->active; } return 0; }
int ide_timing_compute(ide_drive_t *drive, u8 speed, struct ide_timing *t, int T, int UT) { u16 *id = drive->id; struct ide_timing *s, p; /* * Find the mode. */ s = ide_timing_find_mode(speed); if (s == NULL) return -EINVAL; /* * Copy the timing from the table. */ *t = *s; /* * If the drive is an EIDE drive, it can tell us it needs extended * PIO/MWDMA cycle timing. */ if (id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */ memset(&p, 0, sizeof(p)); if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO]; else if (speed <= XFER_PIO_5) p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY]; else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) p.cycle = id[ATA_ID_EIDE_DMA_MIN]; ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B); } /* * Convert the timing to bus clock counts. */ ide_timing_quantize(t, t, T, UT); /* * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, * S.M.A.R.T and some other commands. We have to ensure that the * DMA cycle timing is slower/equal than the fastest PIO timing. */ if (speed >= XFER_SW_DMA_0) { u8 pio = ide_get_best_pio_mode(drive, 255, 5); ide_timing_compute(drive, XFER_PIO_0 + pio, &p, T, UT); ide_timing_merge(&p, t, t, IDE_TIMING_ALL); } /* * Lengthen active & recovery time so that cycle time is correct. */ if (t->act8b + t->rec8b < t->cyc8b) { t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2; t->rec8b = t->cyc8b - t->act8b; } if (t->active + t->recover < t->cycle) { t->active += (t->cycle - (t->active + t->recover)) / 2; t->recover = t->cycle - t->active; } return 0; }