ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) { ide_hwif_t *hwif = HWIF(drive); struct ide_taskfile *tf = &task->tf; ide_handler_t *handler = NULL; const struct ide_tp_ops *tp_ops = hwif->tp_ops; const struct ide_dma_ops *dma_ops = hwif->dma_ops; if (task->data_phase == TASKFILE_MULTI_IN || task->data_phase == TASKFILE_MULTI_OUT) { if (!drive->mult_count) { printk(KERN_ERR "%s: multimode not set!\n", drive->name); return ide_stopped; } } if (task->tf_flags & IDE_TFLAG_FLAGGED) task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS; if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { ide_tf_dump(drive->name, tf); tp_ops->set_irq(hwif, 1); SELECT_MASK(drive, 0); tp_ops->tf_load(drive, task); } switch (task->data_phase) { case TASKFILE_MULTI_OUT: case TASKFILE_OUT: tp_ops->exec_command(hwif, tf->command); ndelay(400); /* FIXME */ return pre_task_out_intr(drive, task->rq); case TASKFILE_MULTI_IN: case TASKFILE_IN: handler = task_in_intr; /* fall-through */ case TASKFILE_NO_DATA: if (handler == NULL) handler = task_no_data_intr; /* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */ if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) { switch (tf->command) { case WIN_SPECIFY: handler = set_geometry_intr; break; case WIN_RESTORE: handler = recal_intr; break; case WIN_SETMULT: handler = set_multmode_intr; break; } } ide_execute_command(drive, tf->command, handler, WAIT_WORSTCASE, NULL); return ide_started; default: if (drive->using_dma == 0 || dma_ops->dma_setup(drive)) return ide_stopped; dma_ops->dma_exec_cmd(drive, tf->command); dma_ops->dma_start(drive); return ide_started; } }
ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) { ide_hwif_t *hwif = drive->hwif; struct ide_taskfile *tf = &task->tf; ide_handler_t *handler = NULL; const struct ide_tp_ops *tp_ops = hwif->tp_ops; const struct ide_dma_ops *dma_ops = hwif->dma_ops; if (task->data_phase == TASKFILE_MULTI_IN || task->data_phase == TASKFILE_MULTI_OUT) { if (!drive->mult_count) { printk(KERN_ERR "%s: multimode not set!\n", drive->name); return ide_stopped; } } if (task->tf_flags & IDE_TFLAG_FLAGGED) task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS; memcpy(&hwif->task, task, sizeof(*task)); if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { ide_tf_dump(drive->name, tf); tp_ops->set_irq(hwif, 1); SELECT_MASK(drive, 0); tp_ops->tf_load(drive, task); } switch (task->data_phase) { case TASKFILE_MULTI_OUT: case TASKFILE_OUT: tp_ops->exec_command(hwif, tf->command); ndelay(400); /* FIXME */ return pre_task_out_intr(drive, task->rq); case TASKFILE_MULTI_IN: case TASKFILE_IN: handler = task_in_intr; /* fall-through */ case TASKFILE_NO_DATA: if (handler == NULL) handler = task_no_data_intr; ide_execute_command(drive, tf->command, handler, WAIT_WORSTCASE, NULL); return ide_started; default: if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 || dma_ops->dma_setup(drive)) return ide_stopped; dma_ops->dma_exec_cmd(drive, tf->command); dma_ops->dma_start(drive); return ide_started; } }
ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) { ide_hwif_t *hwif = drive->hwif; struct ide_cmd *cmd = &hwif->cmd; struct ide_taskfile *tf = &cmd->tf; ide_handler_t *handler = NULL; const struct ide_tp_ops *tp_ops = hwif->tp_ops; const struct ide_dma_ops *dma_ops = hwif->dma_ops; if (orig_cmd->protocol == ATA_PROT_PIO && (orig_cmd->tf_flags & IDE_TFLAG_MULTI_PIO) && drive->mult_count == 0) { pr_err("%s: multimode not set!\n", drive->name); return ide_stopped; } if (orig_cmd->ftf_flags & IDE_FTFLAG_FLAGGED) orig_cmd->ftf_flags |= IDE_FTFLAG_SET_IN_FLAGS; memcpy(cmd, orig_cmd, sizeof(*cmd)); if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { ide_tf_dump(drive->name, cmd); tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { u8 data[2] = { cmd->tf.data, cmd->hob.data }; tp_ops->output_data(drive, cmd, data, 2); } if (cmd->valid.out.tf & IDE_VALID_DEVICE) { u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; if (!(cmd->ftf_flags & IDE_FTFLAG_FLAGGED)) cmd->tf.device &= HIHI; cmd->tf.device |= drive->select; } tp_ops->tf_load(drive, &cmd->hob, cmd->valid.out.hob); tp_ops->tf_load(drive, &cmd->tf, cmd->valid.out.tf); } switch (cmd->protocol) { case ATA_PROT_PIO: if (cmd->tf_flags & IDE_TFLAG_WRITE) { tp_ops->exec_command(hwif, tf->command); ndelay(400); return pre_task_out_intr(drive, cmd); } handler = task_pio_intr; /* fall-through */ case ATA_PROT_NODATA: if (handler == NULL) handler = task_no_data_intr; ide_execute_command(drive, cmd, handler, WAIT_WORSTCASE); return ide_started; case ATA_PROT_DMA: if (ide_dma_prepare(drive, cmd)) return ide_stopped; hwif->expiry = dma_ops->dma_timer_expiry; ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD); dma_ops->dma_start(drive); default: return ide_started; } }