Esempio n. 1
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->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_restore_pio:	/* Resume step 1 (restore PIO) */
		if (drive->hwif->tuneproc != NULL)
			drive->hwif->tuneproc(drive, 255);
		/*
		 * 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->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 3 (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->dma_off_quietly(drive);
		ide_set_dma(drive);
		break;
	}
	pm->pm_step = ide_pm_state_completed;
	return ide_stopped;
}
Esempio n. 2
0
ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
{
	struct request_pm_state *pm = rq->special;
	struct ide_cmd cmd = { };

	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 (ata_id_flush_enabled(drive->id) == 0 ||
		    (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
			ide_complete_power_step(drive, rq);
			return ide_stopped;
		}
		if (ata_id_flush_ext_enabled(drive->id))
			cmd.tf.command = ATA_CMD_FLUSH_EXT;
		else
			cmd.tf.command = ATA_CMD_FLUSH;
		goto out_do_tf;
	case IDE_PM_STANDBY:		/* Suspend step 2 (standby) */
		cmd.tf.command = ATA_CMD_STANDBYNOW1;
		goto out_do_tf;
	case IDE_PM_RESTORE_PIO:	/* Resume step 1 (restore PIO) */
		ide_set_max_pio(drive);
		/*
		 * skip IDE_PM_IDLE for ATAPI devices
		 */
		if (drive->media != ide_disk)
			pm->pm_step = IDE_PM_RESTORE_DMA;
		else
			ide_complete_power_step(drive, rq);
		return ide_stopped;
	case IDE_PM_IDLE:		/* Resume step 2 (idle) */
		cmd.tf.command = ATA_CMD_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_ops == NULL)
			break;
		/*
		 * TODO: respect IDE_DFLAG_USING_DMA
		 */
		ide_set_dma(drive);
		break;
	}

	pm->pm_step = IDE_PM_COMPLETED;

	return ide_stopped;

out_do_tf:
	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
	cmd.protocol = ATA_PROT_NODATA;

	return do_rw_taskfile(drive, &cmd);
}