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; }
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); }
/* * 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; }
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); }
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; }
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; }
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; } }