Exemple #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;
}
Exemple #2
0
void
altera_sdcard_start(struct altera_sdcard_softc *sc)
{

	ALTERA_SDCARD_LOCK_ASSERT(sc);

	KASSERT(sc->as_state == ALTERA_SDCARD_STATE_IDLE,
	    ("%s: starting when not IDLE", __func__));

	taskqueue_cancel_timeout(sc->as_taskqueue, &sc->as_task, NULL);
	altera_sdcard_nextio(sc);
	taskqueue_enqueue_timeout(sc->as_taskqueue, &sc->as_task,
	    ALTERA_SDCARD_TIMEOUT_IO);
}
Exemple #3
0
/*
 * Set up and start the next I/O.  Transition to the I/O state, but allow the
 * caller to schedule the next timeout, as this may be called either from an
 * initial attach context, or from the task queue, which requires different
 * behaviour.
 */
static void
altera_sdcard_nextio(struct altera_sdcard_softc *sc)
{
	struct bio *bp;

	ALTERA_SDCARD_LOCK_ASSERT(sc);
	KASSERT(sc->as_currentbio == NULL,
	    ("%s: bio already active", __func__));

	bp = bioq_takefirst(&sc->as_bioq);
	if (bp == NULL)
		panic("%s: bioq empty", __func__);
	altera_sdcard_io_start(sc, bp);
	sc->as_state = ALTERA_SDCARD_STATE_IO;
}
Exemple #4
0
void
altera_sdcard_start(struct altera_sdcard_softc *sc)
{

	ALTERA_SDCARD_LOCK_ASSERT(sc);

	KASSERT(sc->as_state == ALTERA_SDCARD_STATE_IDLE,
	    ("%s: starting when not IDLE", __func__));

	taskqueue_cancel_timeout(sc->as_taskqueue, &sc->as_task, NULL);
	altera_sdcard_nextio(sc);
#ifdef ALTERA_SDCARD_FAST_SIM
	altera_sdcard_task_io(sc);
#endif
	altera_sdcard_task_rechedule(sc);
}
Exemple #5
0
static void
altera_sdcard_task_nocard(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;
	}

	/*
	 * If there is no card insertion, remain in NOCARD.
	 */
	if (!(altera_sdcard_read_asr(sc) & ALTERA_SDCARD_ASR_CARDPRESENT))
		return;

	/*
	 * Read the CSD -- it may contain values that the driver can't handle,
	 * either because of an unsupported version/feature, or because the
	 * card is misbehaving.  This triggers a transition to
	 * ALTERA_SDCARD_STATE_BADCARD.  We rely on the CSD read to print a
	 * banner about how the card is problematic, since it has more
	 * information.  The bad card state allows us to print that banner
	 * once rather than each time we notice the card is there, and still
	 * bad.
	 */
	if (altera_sdcard_read_csd(sc) != 0) {
		sc->as_state = ALTERA_SDCARD_STATE_BADCARD;
		return;
	}

	/*
	 * Process card insertion and upgrade to the IDLE state.
	 */
	altera_sdcard_disk_insert(sc);
	sc->as_state = ALTERA_SDCARD_STATE_IDLE;
}
Exemple #6
0
static void
altera_sdcard_task_badcard(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 -- no teardown is required, just a state
	 * transition.
	 */
	if (!(altera_sdcard_read_asr(sc) & ALTERA_SDCARD_ASR_CARDPRESENT))
		sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
}
Exemple #7
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;
	}
}