int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); int ix, dstat; volatile struct dbdma_regs *dma; /* Can we stuff a pointer to our intf structure in config_data * or select_data in hwif ? */ ix = pmac_ide_find(drive); if (ix < 0) return 0; dma = pmac_ide[ix].dma_regs; switch (func) { case ide_dma_on: case ide_dma_off: case ide_dma_off_quietly: pmac_ide_dma_onoff(drive, (func == ide_dma_on)); break; case ide_dma_check: if (hwif->autodma) pmac_ide_dma_onoff(drive, 1); break; case ide_dma_read: case ide_dma_write: if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write)) return 1; drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA, IDE_COMMAND_REG); case ide_dma_begin: out_le32(&dma->control, (RUN << 16) | RUN); break; case ide_dma_end: drive->waiting_for_dma = 0; dstat = in_le32(&dma->status); out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16)); /* verify good dma status */ return (dstat & (RUN|DEAD|ACTIVE)) != RUN; case ide_dma_test_irq: return (in_le32(&dma->status) & (RUN|ACTIVE)) == RUN; default: printk(KERN_ERR "pmac_ide_dmaproc: bad func %d\n", func); } return 0; }
/* * Prepare a DMA transfer. We build the DMA table, adjust the timings for * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion */ static int pmac_ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) { ide_hwif_t *hwif = drive->hwif; pmac_ide_hwif_t *pmif = dev_get_drvdata(hwif->gendev.parent); u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4); u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE); if (pmac_ide_build_dmatable(drive, cmd) == 0) return 1; /* Apple adds 60ns to wrDataSetup on reads */ if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { writel(pmif->timings[unit] + (write ? 0 : 0x00800000UL), PMAC_IDE_REG(IDE_TIMING_CONFIG)); (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); } return 0; }
int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { int ix, dstat, i; volatile struct dbdma_regs *dma; /* Can we stuff a pointer to our intf structure in config_data * or select_data in hwif ? */ ix = pmac_ide_find(drive); if (ix < 0) return 0; dma = pmac_ide[ix].dma_regs; switch (func) { case ide_dma_off: printk(KERN_INFO "%s: DMA disabled\n", drive->name); case ide_dma_off_quietly: drive->using_dma = 0; break; case ide_dma_on: case ide_dma_check: pmac_ide_check_dma(drive); break; case ide_dma_read: case ide_dma_write: if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write)) return 1; drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA, IDE_COMMAND_REG); case ide_dma_begin: out_le32(&dma->control, (RUN << 16) | RUN); break; case ide_dma_end: drive->waiting_for_dma = 0; dstat = in_le32(&dma->status); out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16)); /* verify good dma status */ return (dstat & (RUN|DEAD|ACTIVE)) != RUN; case ide_dma_test_irq: if ((in_le32(&dma->status) & (RUN|ACTIVE)) == RUN) return 1; /* That's a bit ugly and dangerous, but works in our case * to workaround a problem with the channel status staying * active if the drive returns an error */ if (IDE_CONTROL_REG) { byte stat; stat = GET_ALTSTAT(); if (stat & ERR_STAT) return 1; } /* In some edge cases, some datas may still be in the dbdma * engine fifo, we wait a bit for dbdma to complete */ while ((in_le32(&dma->status) & (RUN|ACTIVE)) != RUN) { if (++i > 100) return 0; udelay(1); } return 1; /* Let's implement tose just in case someone wants them */ case ide_dma_bad_drive: case ide_dma_good_drive: return check_drive_lists(drive, (func == ide_dma_good_drive)); case ide_dma_verbose: return report_drive_dmaing(drive); case ide_dma_retune: case ide_dma_lostirq: case ide_dma_timeout: printk(KERN_WARNING "ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func); return 1; default: printk(KERN_WARNING "ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func); return 1; } return 0; }