/* This one could be later extended to handle CMD IDE and be used by some kind * of /proc interface. I want to be able to get the devicetree path of a block * device for yaboot configuration */ struct device_node* pmac_ide_get_devnode(ide_drive_t *drive) { int i = pmac_ide_find(drive); if (i < 0) return NULL; return pmac_ide[i].node; }
/* 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; }
/* Setup timings for the selected drive (master/slave). I still need to verify if this * is enough, I beleive selectproc will be called whenever an IDE command is started, * but... */ static void pmac_ide_selectproc(ide_drive_t *drive) { int i = pmac_ide_find(drive); if (i < 0) return; if (drive->select.all & 0x10) out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[1]); else out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[0]); }
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; }
/* Calculate PIO timings */ static void pmac_ide_tuneproc(ide_drive_t *drive, byte pio) { ide_pio_data_t d; int i; u32 *timings; int accessTicks, recTicks; i = pmac_ide_find(drive); if (i < 0) return; pio = ide_get_best_pio_mode(drive, pio, 4, &d); accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time); if (drive->select.all & 0x10) timings = &pmac_ide[i].timings[1]; else timings = &pmac_ide[i].timings[0]; if (pmac_ide[i].kind == controller_kl_ata4) { /* The "ata-4" IDE controller of Core99 machines */ accessTicks = SYSCLK_TICKS_UDMA(ide_pio_timings[pio].active_time * 1000); recTicks = SYSCLK_TICKS_UDMA(d.cycle_time * 1000) - accessTicks; *timings = ((*timings) & 0x1FFFFFC00) | accessTicks | (recTicks << 5); } else { /* The old "ata-3" IDE controller */ accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time); if (accessTicks < 4) accessTicks = 4; recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4; if (recTicks < 1) recTicks = 1; *timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5); } #ifdef IDE_PMAC_DEBUG printk(KERN_ERR "ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n", pio, *timings); #endif if (drive->select.all == IN_BYTE(IDE_SELECT_REG)) pmac_ide_selectproc(drive); }
static int pmac_ide_check_dma(ide_drive_t *drive) { int ata4, udma, idx; struct hd_driveid *id = drive->id; int enable = 1; drive->using_dma = 0; idx = pmac_ide_find(drive); if (idx < 0) return 0; if (drive->media == ide_floppy) enable = 0; if (((id->capability & 1) == 0) && !check_drive_lists(drive, GOOD_DMA_DRIVE)) enable = 0; if (check_drive_lists(drive, BAD_DMA_DRIVE)) enable = 0; udma = 0; ata4 = (pmac_ide[idx].kind == controller_kl_ata4); if(enable) { if (ata4 && (drive->media == ide_disk) && (id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) { /* UltraDMA modes. */ drive->using_dma = pmac_ide_udma_enable(drive, idx); } if (!drive->using_dma && (id->dma_mword & 0x0007)) { /* Normal MultiWord DMA modes. */ drive->using_dma = pmac_ide_mdma_enable(drive, idx); } /* Without this, strange things will happen on Keylargo-based * machines */ OUT_BYTE(0, IDE_CONTROL_REG); /* Apply settings to controller */ pmac_ide_selectproc(drive); } 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; }