Esempio n. 1
0
static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
{
	ide_task_t *args = rq->special;

	memset(args, 0, sizeof(*args));

	if (drive->media != ide_disk) {
		/* skip idedisk_pm_idle for ATAPI devices */
		if (rq->pm->pm_step == idedisk_pm_idle)
			rq->pm->pm_step = ide_pm_restore_dma;
	}

	switch (rq->pm->pm_step) {
	case ide_pm_flush_cache:	/* Suspend step 1 (flush cache) */
		if (drive->media != ide_disk)
			break;
		/* Not supported? Switch to next step now. */
		if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) {
			ide_complete_power_step(drive, rq, 0, 0);
			return ide_stopped;
		}
		if (ide_id_has_flush_cache_ext(drive->id))
			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
		else
			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
		args->command_type = IDE_DRIVE_TASK_NO_DATA;
		args->handler	   = &task_no_data_intr;
		return do_rw_taskfile(drive, args);

	case idedisk_pm_standby:	/* Suspend step 2 (standby) */
		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
		args->command_type = IDE_DRIVE_TASK_NO_DATA;
		args->handler	   = &task_no_data_intr;
		return do_rw_taskfile(drive, args);

	case idedisk_pm_idle:		/* Resume step 1 (idle) */
		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
		args->command_type = IDE_DRIVE_TASK_NO_DATA;
		args->handler = task_no_data_intr;
		return do_rw_taskfile(drive, args);

	case ide_pm_restore_dma:	/* Resume step 2 (restore DMA) */
		/*
		 * Right now, all we do is call hwif->ide_dma_check(drive),
		 * we could be smarter and check for current xfer_speed
		 * in struct drive etc...
		 */
		if ((drive->id->capability & 1) == 0)
			break;
		if (drive->hwif->ide_dma_check == NULL)
			break;
		drive->hwif->ide_dma_check(drive);
		break;
	}
	rq->pm->pm_step = ide_pm_state_completed;
	return ide_stopped;
}
Esempio n. 2
0
static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
{
	struct request_pm_state *pm = rq->data;
	ide_task_t *args = rq->special;

	memset(args, 0, sizeof(*args));

	switch (pm->pm_step) {
	case ide_pm_flush_cache:	/* Suspend step 1 (flush cache) */
		if (drive->media != ide_disk)
			break;
		/* Not supported? Switch to next step now. */
		if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) {
			ide_complete_power_step(drive, rq, 0, 0);
			return ide_stopped;
		}
		if (ide_id_has_flush_cache_ext(drive->id))
			args->tf.command = WIN_FLUSH_CACHE_EXT;
		else
			args->tf.command = WIN_FLUSH_CACHE;
		goto out_do_tf;

	case idedisk_pm_standby:	/* Suspend step 2 (standby) */
		args->tf.command = WIN_STANDBYNOW1;
		goto out_do_tf;

	case idedisk_pm_restore_pio:	/* Resume step 1 (restore PIO) */
		ide_set_max_pio(drive);
		/*
		 * skip idedisk_pm_idle for ATAPI devices
		 */
		if (drive->media != ide_disk)
			pm->pm_step = ide_pm_restore_dma;
		else
			ide_complete_power_step(drive, rq, 0, 0);
		return ide_stopped;

	case idedisk_pm_idle:		/* Resume step 2 (idle) */
		args->tf.command = WIN_IDLEIMMEDIATE;
		goto out_do_tf;

	case ide_pm_restore_dma:	/* Resume step 3 (restore DMA) */
		/*
		 * Right now, all we do is call ide_set_dma(drive),
		 * we could be smarter and check for current xfer_speed
		 * in struct drive etc...
		 */
		if (drive->hwif->dma_host_set == NULL)
			break;
		/*
		 * TODO: respect ->using_dma setting
		 */
		ide_set_dma(drive);
		break;
	}
	pm->pm_step = ide_pm_state_completed;
	return ide_stopped;

out_do_tf:
	args->tf_flags	 = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
	args->data_phase = TASKFILE_NO_DATA;
	return do_rw_taskfile(drive, args);
}