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_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); }
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; } }