Beispiel #1
0
static void
altera_sdcard_task_io(struct altera_sdcard_softc *sc)
{
	uint16_t asr;

	ALTERA_SDCARD_LOCK_ASSERT(sc);
	KASSERT(sc->as_currentbio != NULL, ("%s: no current I/O", __func__));

#ifdef ALTERA_SDCARD_FAST_SIM
recheck:
#endif
	asr = altera_sdcard_read_asr(sc);

	/*
	 * Check for unexpected card removal during an I/O.
	 */
	if (!(asr & ALTERA_SDCARD_ASR_CARDPRESENT)) {
		altera_sdcard_disk_remove(sc);
		if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ)
			sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
		else
			sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
		return;
	}

	/*
	 * If the I/O isn't complete, remain in the IO state without further
	 * action, even if DETACHREQ is in flight.
	 */
	if (asr & ALTERA_SDCARD_ASR_CMDINPROGRESS)
		return;

	/*
	 * Handle various forms of I/O completion, successful and otherwise.
	 * The I/O layer may restart the transaction if an error occurred, in
	 * which case remain in the IO state and reschedule.
	 */
	if (!altera_sdcard_io_complete(sc, asr))
		return;

	/*
	 * Now that I/O is complete, process detach requests in preference to
	 * starting new I/O.
	 */
	if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
		sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
		return;
	}

	/*
	 * Finally, either start the next I/O or transition to the IDLE state.
	 */
	if (bioq_first(&sc->as_bioq) != NULL) {
		altera_sdcard_nextio(sc);
#ifdef ALTERA_SDCARD_FAST_SIM
		goto recheck;
#endif
	} else
		sc->as_state = ALTERA_SDCARD_STATE_IDLE;
}
Beispiel #2
0
void
altera_sdcard_detach(struct altera_sdcard_softc *sc)
{

	KASSERT(sc->as_taskqueue != NULL, ("%s: taskqueue not present",
	    __func__));

	/*
	 * Winding down the driver on detach is a bit complex.  Update the
	 * flags to indicate that a detach has been requested, and then wait
	 * for in-progress I/O to wind down before continuing.
	 */
	ALTERA_SDCARD_LOCK(sc);
	sc->as_flags |= ALTERA_SDCARD_FLAG_DETACHREQ;
	while (sc->as_state != ALTERA_SDCARD_STATE_DETACHED)
		ALTERA_SDCARD_CONDVAR_WAIT(sc);
	ALTERA_SDCARD_UNLOCK(sc);

	/*
	 * Now wait for the possibly still executing taskqueue to drain.  In
	 * principle no more events will be scheduled as we've transitioned to
	 * a detached state, but there might still be a request in execution.
	 */
	while (taskqueue_cancel_timeout(sc->as_taskqueue, &sc->as_task, NULL))
		taskqueue_drain_timeout(sc->as_taskqueue, &sc->as_task);

	/*
	 * Simulate a disk removal if one is present to deal with any pending
	 * or queued I/O.
	 */
	if (sc->as_disk != NULL)
		altera_sdcard_disk_remove(sc);
	KASSERT(bioq_first(&sc->as_bioq) == NULL,
	    ("%s: non-empty bioq", __func__));

	/*
	 * Free any remaining allocated resources.
	 */
	taskqueue_free(sc->as_taskqueue);
	sc->as_taskqueue = NULL;
	ALTERA_SDCARD_CONDVAR_DESTROY(sc);
	ALTERA_SDCARD_LOCK_DESTROY(sc);
}
Beispiel #3
0
static void
altera_sdcard_task_idle(struct altera_sdcard_softc *sc)
{

	ALTERA_SDCARD_LOCK_ASSERT(sc);

	/*
	 * Handle device driver detach.
	 */
	if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
		sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
		return;
	}

	/*
	 * Handle safe card removal.
	 */
	if (!(altera_sdcard_read_asr(sc) & ALTERA_SDCARD_ASR_CARDPRESENT)) {
		altera_sdcard_disk_remove(sc);
		sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
	}
}