Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Aug 2012 11:19:20 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r239675 - in head: share/man/man4 sys/conf sys/dev/altera/sdcard
Message-ID:  <201208251119.q7PBJKtf029543@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Sat Aug 25 11:19:20 2012
New Revision: 239675
URL: http://svn.freebsd.org/changeset/base/239675

Log:
  Add a device driver for the Altera University Program SD Card IP Core,
  which can be synthesised in Altera FPGAs.  An altera_sdcardc device
  probes during the boot, and /dev/altera_sdcard devices come and go as
  inserted and removed.  The device driver attaches directly to the
  Nexus, as is common for system-on-chip device drivers.
  
  This IP core suffers a number of significant limitations, including a
  lack of interrupt-driven I/O -- we must implement timer-driven polling,
  only CSD 0 cards (up to 2G) are supported, there are serious memory
  access issues that require the driver to verify writes to memory-mapped
  buffers, undocumented alignment requirements, and erroneous error
  returns.  The driver must therefore work quite hard, despite a fairly
  simple hardware-software interface.  The IP core also supports at most
  one outstanding I/O at a time, so is not a speed demon.
  
  However, with the above workarounds, and subject to performance
  problems, it works quite reliably in practice, and we can use it for
  read-write mounts of root file systems, etc.
  
  Sponsored by:	DARPA, AFRL

Added:
  head/share/man/man4/altera_sdcard.4   (contents, props changed)
  head/sys/dev/altera/sdcard/
  head/sys/dev/altera/sdcard/altera_sdcard.c   (contents, props changed)
  head/sys/dev/altera/sdcard/altera_sdcard.h   (contents, props changed)
  head/sys/dev/altera/sdcard/altera_sdcard_disk.c   (contents, props changed)
  head/sys/dev/altera/sdcard/altera_sdcard_io.c   (contents, props changed)
  head/sys/dev/altera/sdcard/altera_sdcard_nexus.c   (contents, props changed)
Modified:
  head/share/man/man4/Makefile
  head/sys/conf/files

Modified: head/share/man/man4/Makefile
==============================================================================
--- head/share/man/man4/Makefile	Sat Aug 25 11:07:43 2012	(r239674)
+++ head/share/man/man4/Makefile	Sat Aug 25 11:19:20 2012	(r239675)
@@ -33,6 +33,7 @@ MAN=	aac.4 \
 	ale.4 \
 	alpm.4 \
 	altera_avgen.4 \
+	altera_sdcard.4 \
 	altq.4 \
 	amdpm.4 \
 	${_amdsbwd.4} \

Added: head/share/man/man4/altera_sdcard.4
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man4/altera_sdcard.4	Sat Aug 25 11:19:20 2012	(r239675)
@@ -0,0 +1,118 @@
+.\"-
+.\" Copyright (c) 2012 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by SRI International and the University of
+.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+.\" ("CTSRD"), as part of the DARPA CRASH research programme.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 18, 2012
+.Dt ALTERA_SDCARD 4
+.Os
+.Sh NAME
+.Nm altera_sdcard
+.Nd driver for the Altera University Program Secure Data Card IP Core
+.Sh SYNOPSIS
+.Cd "device altera_sdcard"
+.Pp
+In
+.Pa /boot/device.hints :
+.Cd hint.altera_sdcardc.0.at="nexus0"
+.Cd hint.altera_sdcardc.0.maddr=0x7f008000
+.Cd hint.altera_sdcardc.0.msize=0x400
+.Sh DESCRIPTION
+The
+.Nm
+device driver provides support for the Altera University Program Secure Data
+Card (SD Card) IP Core device.
+A controller device,
+.Li altera_sdcardcX ,
+will be attached during boot.
+Inserted disks are presented as
+.Xr disk 9
+devices,
+.Li altera_sdcardX ,
+corresponding to the controller number.
+.Sh HARDWARE
+The current version of the
+.Nm
+driver supports the SD Card IP core as described in the August 2011 version of
+Altera's documentation.
+The core supports only cards up to 2G (CSD 0); larger cards, or cards using
+newer CSD versions, will not be detected.
+The IP core has two key limitations: a lack of interrupt support, requiring
+timer-driven polling to detect I/O completion, and support for only single
+512-byte block read and write operations at a time.
+The combined effect of those two limits is that the system clock rate,
+.Dv HZ ,
+must be set to at least 200 in order to accomplish the maximum 100KB/s data
+rate supported by the IP core.
+.Sh SEE ALSO
+.Xr disk 9
+.Rs
+.%T Altera University Program Secure Data Card IP Core
+.%D August 2011
+.%I Altera Corporation - University Program
+.%U ftp://ftp.altera.com/up/pub/Altera_Material/11.0/University_Program_IP_Cores/Memory/SD_Card_Interface_for_SoPC_Builder.pdf
+.Re
+.Sh HISTORY
+The
+.Nm
+device driver first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+The
+.Nm
+device driver and this manual page were
+developed by SRI International and the University of Cambridge Computer
+Laboratory under DARPA/AFRL contract
+.Pq FA8750-10-C-0237
+.Pq Do CTSRD Dc ,
+as part of the DARPA CRASH research programme.
+This device driver was written by
+.An Robert N. M. Watson .
+.Sh BUGS
+.Nm
+contains a number of work-arounds for IP core bugs.
+Perhaps most critically,
+.Nm
+ignores the CRC error bit returned in the RR1 register, which appears to be
+unexpectedly set by the IP core.
+.Pp
+.Nm
+uses fixed polling intervals are used for card insertion/removal and
+I/O completion detection; an adaptive strategy might improve performance by
+reducing the latency to detecting completed I/O.
+However, in our experiments, using polling rates greater than 200 times a
+second did not improve performance.
+.Pp
+.Nm
+supports only a
+.Li nexus
+bus attachment, which is appropriate for system-on-chip busses such as
+Altera's Avalon bus.
+If the IP core is configured off of another bus type, then additional bus
+attachments will be required.

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sat Aug 25 11:07:43 2012	(r239674)
+++ head/sys/conf/files	Sat Aug 25 11:19:20 2012	(r239675)
@@ -660,6 +660,10 @@ dev/aic7xxx/aic7xxx_pci.c	optional ahc p
 dev/alc/if_alc.c		optional alc pci
 dev/ale/if_ale.c		optional ale pci
 dev/altera/avgen/altera_avgen.c		optional altera_avgen
+dev/altera/sdcard/altera_sdcard.c	optional altera_sdcard
+dev/altera/sdcard/altera_sdcard_disk.c	optional altera_sdcard
+dev/altera/sdcard/altera_sdcard_io.c	optional altera_sdcard
+dev/altera/sdcard/altera_sdcard_nexus.c	optional altera_sdcard
 dev/amr/amr.c			optional amr
 dev/amr/amr_cam.c		optional amrp amr
 dev/amr/amr_disk.c		optional amr

Added: head/sys/dev/altera/sdcard/altera_sdcard.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/altera/sdcard/altera_sdcard.c	Sat Aug 25 11:19:20 2012	(r239675)
@@ -0,0 +1,402 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/sdcard/altera_sdcard.h>
+
+/*
+ * Device driver for the Altera University Program Secure Data Card IP Core,
+ * as described in the similarly named SOPC Builder IP Core specification.
+ * This soft core is not a full SD host controller interface (SDHCI) but
+ * instead provides a set of memory mapped registers and memory buffer that
+ * mildly abstract the SD Card protocol, but without providing DMA or
+ * interrupts.  However, it does hide the details of voltage and
+ * communications negotiation.  This driver implements disk(9), but due to the
+ * lack of interrupt support, must rely on timer-driven polling to determine
+ * when I/Os have completed.
+ *
+ * TODO:
+ *
+ * 1. Implement DISKFLAG_CANDELETE / SD Card sector erase support.
+ * 2. Implement d_ident from SD Card CID serial number field.
+ * 3. Handle read-only SD Cards.
+ * 4. Tune timeouts based on real-world SD Card speeds.
+ */
+
+void
+altera_sdcard_attach(struct altera_sdcard_softc *sc)
+{
+
+	ALTERA_SDCARD_LOCK_INIT(sc);
+	ALTERA_SDCARD_CONDVAR_INIT(sc);
+	sc->as_disk = NULL;
+	bioq_init(&sc->as_bioq);
+	sc->as_currentbio = NULL;
+	sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
+	sc->as_taskqueue = taskqueue_create("altera_sdcardc taskq", M_WAITOK,
+	    taskqueue_thread_enqueue, &sc->as_taskqueue);
+	taskqueue_start_threads(&sc->as_taskqueue, 1, PI_DISK,
+	    "altera_sdcardc%d taskqueue", sc->as_unit);
+	TIMEOUT_TASK_INIT(sc->as_taskqueue, &sc->as_task, 0,
+	    altera_sdcard_task, sc);
+
+	/*
+	 * Kick off timer-driven processing with a manual poll so that we
+	 * synchronously detect an already-inserted SD Card during the boot or
+	 * other driver attach point.
+	 */
+	altera_sdcard_task(sc, 1);
+}
+
+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);
+}
+
+/*
+ * 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;
+}
+
+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;
+	}
+}
+
+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__));
+
+	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);
+	else
+		sc->as_state = ALTERA_SDCARD_STATE_IDLE;
+}
+
+static void
+altera_sdcard_task_rechedule(struct altera_sdcard_softc *sc)
+{
+	int interval;
+
+	/*
+	 * Reschedule based on new state.  Or not, if detaching the device
+	 * driver.  Treat a bad card as though it were no card at all.
+	 */
+	switch (sc->as_state) {
+	case ALTERA_SDCARD_STATE_NOCARD:
+	case ALTERA_SDCARD_STATE_BADCARD:
+		interval = ALTERA_SDCARD_TIMEOUT_NOCARD;
+		break;
+
+	case ALTERA_SDCARD_STATE_IDLE:
+		interval = ALTERA_SDCARD_TIMEOUT_IDLE;
+		break;
+
+	case ALTERA_SDCARD_STATE_IO:
+		if (sc->as_flags & ALTERA_SDCARD_FLAG_IOERROR)
+			interval = ALTERA_SDCARD_TIMEOUT_IOERROR;
+		else
+			interval = ALTERA_SDCARD_TIMEOUT_IO;
+		break;
+
+	default:
+		panic("%s: invalid exit state %d", __func__, sc->as_state);
+	}
+	taskqueue_enqueue_timeout(sc->as_taskqueue, &sc->as_task, interval);
+}
+
+/*
+ * Because the Altera SD Card IP Core doesn't support interrupts, we do all
+ * asynchronous work from a timeout.  Poll at two different rates -- an
+ * infrequent check for card insertion status changes, and a frequent one for
+ * I/O completion.  The task should never start in DETACHED, as that would
+ * imply that a previous instance failed to cancel rather than reschedule.
+ */
+void
+altera_sdcard_task(void *arg, int pending)
+{
+	struct altera_sdcard_softc *sc;
+
+	sc = arg;
+	KASSERT(sc->as_state != ALTERA_SDCARD_STATE_DETACHED,
+	    ("%s: already in detached", __func__));
+
+	ALTERA_SDCARD_LOCK(sc);
+	switch (sc->as_state) {
+	case ALTERA_SDCARD_STATE_NOCARD:
+		altera_sdcard_task_nocard(sc);
+		break;
+
+	case ALTERA_SDCARD_STATE_BADCARD:
+		altera_sdcard_task_badcard(sc);
+		break;
+
+	case ALTERA_SDCARD_STATE_IDLE:
+		altera_sdcard_task_idle(sc);
+		break;
+
+	case ALTERA_SDCARD_STATE_IO:
+		altera_sdcard_task_io(sc);
+		break;
+
+	default:
+		panic("%s: invalid enter state %d", __func__, sc->as_state);
+	}
+
+	/*
+	 * If we have transitioned to DETACHED, signal the detach thread and
+	 * cancel the timeout-driven task.  Otherwise reschedule on an
+	 * appropriate timeout.
+	 */
+	if (sc->as_state == ALTERA_SDCARD_STATE_DETACHED)
+		ALTERA_SDCARD_CONDVAR_SIGNAL(sc);
+	else
+		altera_sdcard_task_rechedule(sc);
+	ALTERA_SDCARD_UNLOCK(sc);
+}
+
+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);
+}

Added: head/sys/dev/altera/sdcard/altera_sdcard.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/altera/sdcard/altera_sdcard.h	Sat Aug 25 11:19:20 2012	(r239675)
@@ -0,0 +1,247 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_ALTERA_SDCARD_H_
+#define	_DEV_ALTERA_SDCARD_H_
+
+#define	ALTERA_SDCARD_CSD_SIZE	16
+struct altera_sdcard_csd {
+	uint8_t		 csd_data[ALTERA_SDCARD_CSD_SIZE];
+} __aligned(2);		/* CSD is read in 16-bit chunks, so align to match. */
+
+struct altera_sdcard_softc {
+	device_t		 as_dev;
+	int			 as_unit;
+	struct resource		*as_res;
+	int			 as_rid;
+	struct mtx		 as_lock;
+	struct cv		 as_condvar;
+	int			 as_state;
+	int			 as_flags;
+	struct disk		*as_disk;
+	struct taskqueue	*as_taskqueue;
+	struct timeout_task	 as_task;
+
+	/*
+	 * Fields relating to in-progress and pending I/O, if any.
+	 */
+	struct bio_queue_head	 as_bioq;
+	struct bio		*as_currentbio;
+	u_int			 as_retriesleft;
+
+	/*
+	 * Infrequently changing fields cached from the SD Card IP Core.
+	 */
+	struct altera_sdcard_csd	 as_csd;
+	uint8_t			 as_csd_structure;	/* CSD version. */
+	uint64_t		 as_mediasize;
+};
+
+#define	ALTERA_SDCARD_LOCK(sc)		mtx_lock(&(sc)->as_lock)
+#define	ALTERA_SDCARD_LOCK_ASSERT(sc)	mtx_assert(&(sc)->as_lock, MA_OWNED)
+#define	ALTERA_SDCARD_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->as_lock)
+#define	ALTERA_SDCARD_LOCK_INIT(sc)	mtx_init(&(sc)->as_lock,	\
+					    "altera_sdcard", NULL, MTX_DEF)
+#define	ALTERA_SDCARD_UNLOCK(sc)	mtx_unlock(&(sc)->as_lock)
+
+#define	ALTERA_SDCARD_CONDVAR_DESTROY(sc)	cv_destroy(&(sc)->as_condvar)
+#define	ALTERA_SDCARD_CONDVAR_INIT(sc)		cv_init(&(sc)->as_condvar, \
+						    "altera_sdcard_detach_wait")
+#define	ALTERA_SDCARD_CONDVAR_SIGNAL(dc)	cv_signal(&(sc)->as_condvar)
+#define	ALTERA_SDCARD_CONDVAR_WAIT(sc)		cv_wait(&(sc)->as_condvar, \
+						    &(sc)->as_lock)
+
+/*
+ * States an instance can be in at any given moment.
+ */
+#define	ALTERA_SDCARD_STATE_NOCARD	1	/* No card inserted. */
+#define	ALTERA_SDCARD_STATE_BADCARD	2	/* Card bad/not supported. */
+#define	ALTERA_SDCARD_STATE_IDLE	3	/* Card present but idle. */
+#define	ALTERA_SDCARD_STATE_IO		4	/* Card in I/O currently. */
+#define	ALTERA_SDCARD_STATE_DETACHED	5	/* Driver is detaching. */
+
+/*
+ * Different timeout intervals based on state.  When just looking for a card
+ * status change, check twice a second.  When we're actively waiting on I/O
+ * completion, check every millisecond.
+ */
+#define	ALTERA_SDCARD_TIMEOUT_NOCARD	(hz/2)
+#define	ALTERA_SDCARD_TIMEOUT_IDLE	(hz/2)
+#define	ALTERA_SDCARD_TIMEOUT_IO	(1)
+#define	ALTERA_SDCARD_TIMEOUT_IOERROR	(hz/5)
+
+/*
+ * Maximum number of retries on an I/O.
+ */
+#define	ALTERA_SDCARD_RETRY_LIMIT	10
+
+/*
+ * Driver status flags.
+ */
+#define	ALTERA_SDCARD_FLAG_DETACHREQ	0x00000001	/* Detach requested. */
+#define	ALTERA_SDCARD_FLAG_IOERROR	0x00000002	/* Error in progress. */
+
+/*
+ * Functions for performing low-level register and memory I/O to/from the SD
+ * Card IP Core.  In general, only code in altera_sdcard_io.c is aware of the
+ * hardware interface.
+ */
+uint16_t	altera_sdcard_read_asr(struct altera_sdcard_softc *sc);
+int		altera_sdcard_read_csd(struct altera_sdcard_softc *sc);
+
+int	altera_sdcard_io_complete(struct altera_sdcard_softc *sc,
+	    uint16_t asr);
+void	altera_sdcard_io_start(struct altera_sdcard_softc *sc,
+	    struct bio *bp);
+
+/*
+ * Constants for interpreting the SD Card Card Specific Data (CSD) register.
+ */
+#define	ALTERA_SDCARD_CSD_STRUCTURE_BYTE	15
+#define	ALTERA_SDCARD_CSD_STRUCTURE_MASK	0xc0	/* 2 bits */
+#define	ALTERA_SDCARD_CSD_STRUCTURE_RSHIFT	6
+
+#define	ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE	10
+#define	ALTERA_SDCARD_CSD_READ_BL_LEN_MASK	0x0f	/* 4 bits */
+
+/*
+ * C_SIZE is a 12-bit field helpfully split over three differe bytes of CSD
+ * data.  Software ease of use was not a design consideration.
+ */
+#define	ALTERA_SDCARD_CSD_C_SIZE_BYTE0		7
+#define	ALTERA_SDCARD_CSD_C_SIZE_MASK0		0xc	/* top 2 bits */
+#define	ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0	6
+
+#define	ALTERA_SDCARD_CSD_C_SIZE_BYTE1		8
+#define	ALTERA_SDCARD_CSD_C_SIZE_MASK1		0xff	/* 8 bits */
+#define	ALTERA_SDCARD_CSD_C_SIZE_LSHIFT1	2
+
+#define	ALTERA_SDCARD_CSD_C_SIZE_BYTE2		9
+#define	ALTERA_SDCARD_CSD_C_SIZE_MASK2		0x03	/* bottom 2 bits */
+#define	ALTERA_SDCARD_CSD_C_SIZE_LSHIFT2	10
+
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0	5
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0	0x80	/* top 1 bit */
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0	7
+
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1	6
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1	0x03	/* bottom 2 bits */
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1	1
+
+/*
+ * I/O register/buffer offsets, from Table 4.1.1 in the Altera University
+ * Program SD Card IP Core specification.
+ */
+#define	ALTERA_SDCARD_OFF_RXTX_BUFFER	0	/* 512-byte I/O buffer */
+#define	ALTERA_SDCARD_OFF_CID		512	/* 16-byte Card ID number */
+#define	ALTERA_SDCARD_OFF_CSD		528	/* 16-byte Card Specific Data */
+#define	ALTERA_SDCARD_OFF_OCR		544	/* Operating Conditions Reg */
+#define	ALTERA_SDCARD_OFF_SR		548	/* SD Card Status Register */
+#define	ALTERA_SDCARD_OFF_RCA		552	/* Relative Card Address Reg */
+#define	ALTERA_SDCARD_OFF_CMD_ARG	556	/* Command Argument Register */
+#define	ALTERA_SDCARD_OFF_CMD		560	/* Command Register */
+#define	ALTERA_SDCARD_OFF_ASR		564	/* Auxiliary Status Register */
+#define	ALTERA_SDCARD_OFF_RR1		568	/* Response R1 */
+
+/*
+ * The Altera IP Core provides a 16-bit "Additional Status Register" (ASR)
+ * beyond those described in the SD Card specification that captures IP Core
+ * transaction state, such as whether the last command is in progress, the
+ * card has been removed, etc.
+ */
+#define	ALTERA_SDCARD_ASR_CMDVALID	0x0001
+#define	ALTERA_SDCARD_ASR_CARDPRESENT	0x0002
+#define	ALTERA_SDCARD_ASR_CMDINPROGRESS	0x0004
+#define	ALTERA_SDCARD_ASR_SRVALID	0x0008
+#define	ALTERA_SDCARD_ASR_CMDTIMEOUT	0x0010
+#define	ALTERA_SDCARD_ASR_CMDDATAERROR	0x0020
+
+/*
+ * The Altera IP Core claims to provide a 16-bit "Response R1" register (RR1)
+ * to provide more detailed error reporting when a read or write fails.
+ *
+ * XXXRW: The specification claims that this field is 16-bit, but then
+ * proceeds to define values as though it is 32-bit.  In practice, 16-bit
+ * seems more likely as the register is not 32-bit aligned.
+ */
+#define	ALTERA_SDCARD_RR1_INITPROCRUNNING	0x0100
+#define	ALTERA_SDCARD_RR1_ERASEINTERRUPTED	0x0200
+#define	ALTERA_SDCARD_RR1_ILLEGALCOMMAND	0x0400
+#define	ALTERA_SDCARD_RR1_COMMANDCRCFAILED	0x0800
+#define	ALTERA_SDCARD_RR1_ADDRESSMISALIGNED	0x1000
+#define	ALTERA_SDCARD_RR1_ADDRBLOCKRANGE	0x2000
+
+/*
+ * Not all RR1 values are "errors" per se -- check only for the ones that are
+ * when performing error handling.
+ */
+#define	ALTERA_SDCARD_RR1_ERRORMASK					      \
+    (ALTERA_SDCARD_RR1_ERASEINTERRUPTED | ALTERA_SDCARD_RR1_ILLEGALCOMMAND |  \
+    ALTERA_SDCARD_RR1_COMMANDCRCFAILED | ALTERA_SDCARD_RR1_ADDRESSMISALIGNED |\
+    ALTERA_SDCARD_RR1_ADDRBLOCKRANGE)
+
+/*
+ * Although SD Cards may have various sector sizes, the Altera IP Core
+ * requires that I/O be done in 512-byte chunks.
+ */
+#define	ALTERA_SDCARD_SECTORSIZE	512
+
+/*
+ * SD Card commands used in this driver.
+ */
+#define	ALTERA_SDCARD_CMD_SEND_RCA	0x03	/* Retrieve card RCA. */
+#define	ALTERA_SDCARD_CMD_SEND_CSD	0x09	/* Retrieve CSD register. */
+#define	ALTERA_SDCARD_CMD_SEND_CID	0x0A	/* Retrieve CID register. */
+#define	ALTERA_SDCARD_CMD_READ_BLOCK	0x11	/* Read block from disk. */
+#define	ALTERA_SDCARD_CMD_WRITE_BLOCK	0x18	/* Write block to disk. */
+
+/*
+ * Functions exposed by the device driver core to newbus(9) bus attachment
+ * implementations.
+ */
+void	altera_sdcard_attach(struct altera_sdcard_softc *sc);
+void	altera_sdcard_detach(struct altera_sdcard_softc *sc);
+void	altera_sdcard_task(void *arg, int pending);
+
+/*
+ * Functions exposed by the device driver core to the disk(9) front-end.
+ */
+void	altera_sdcard_start(struct altera_sdcard_softc *sc);
+
+/*
+ * Functions relating to the implementation of disk(9) KPIs for the SD Card
+ * driver.
+ */
+void	altera_sdcard_disk_insert(struct altera_sdcard_softc *sc);
+void	altera_sdcard_disk_remove(struct altera_sdcard_softc *sc);
+
+#endif	/* _DEV_ALTERA_SDCARD_H_ */

Added: head/sys/dev/altera/sdcard/altera_sdcard_disk.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/altera/sdcard/altera_sdcard_disk.c	Sat Aug 25 11:19:20 2012	(r239675)
@@ -0,0 +1,185 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/sdcard/altera_sdcard.h>
+
+static int
+altera_sdcard_disk_dump(void *arg, void *virtual, vm_offset_t physical,
+    off_t offset, size_t length)
+{
+
+	panic("%s: not yet", __func__);
+}
+
+static int
+altera_sdcard_disk_ioctl(struct disk *disk, u_long cmd, void *data, int fflag,
+    struct thread *td)
+{
+
+	/* XXXRW: more here? */
+	return (EINVAL);
+}
+
+static void
+altera_sdcard_disk_strategy(struct bio *bp)
+{
+	struct altera_sdcard_softc *sc;
+
+	/*
+	 * Although the SD Card doesn't need sorting, we don't want to
+	 * introduce barriers, so use bioq_disksort().
+	 */
+	sc = bp->bio_disk->d_drv1;
+	ALTERA_SDCARD_LOCK(sc);
+	switch (sc->as_state) {
+	case ALTERA_SDCARD_STATE_NOCARD:
+		device_printf(sc->as_dev, "%s: unexpected I/O on NOCARD",
+		    __func__);
+		biofinish(bp, NULL, ENXIO);
+		break;
+
+	case ALTERA_SDCARD_STATE_BADCARD:
+		device_printf(sc->as_dev, "%s: unexpected I/O on BADCARD",
+		    __func__);
+		biofinish(bp, NULL, ENXIO);
+		break;
+
+	case ALTERA_SDCARD_STATE_DETACHED:
+		device_printf(sc->as_dev, "%s: unexpected I/O on DETACHED",
+		    __func__);
+		biofinish(bp, NULL, ENXIO);
+
+	case ALTERA_SDCARD_STATE_IDLE:
+		bioq_disksort(&sc->as_bioq, bp);
+		altera_sdcard_start(sc);
+		break;
+
+	case ALTERA_SDCARD_STATE_IO:
+		bioq_disksort(&sc->as_bioq, bp);
+		break;
+
+	default:
+		panic("%s: invalid state %d", __func__, sc->as_state);
+	}
+	ALTERA_SDCARD_UNLOCK(sc);
+}
+
+void
+altera_sdcard_disk_insert(struct altera_sdcard_softc *sc)
+{
+	struct disk *disk;
+	uint64_t size;
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+
+	/*
+	 * Because the disk insertion routine occupies the driver instance's
+	 * task queue thread, and the disk(9) instance isn't hooked up yet by
+	 * definition, the only other source of events of concern is a thread
+	 * initiating driver detach.  That thread has to issue a detach
+	 * request and await an ACK from the taskqueue thread.  It is
+	 * therefore safe to drop the lock here.
+	 */
+	ALTERA_SDCARD_UNLOCK(sc);
+	disk = disk_alloc();
+	disk->d_drv1 = sc;
+	disk->d_name = "altera_sdcard";
+	disk->d_unit = sc->as_unit;
+	disk->d_strategy = altera_sdcard_disk_strategy;
+	disk->d_dump = altera_sdcard_disk_dump;
+	disk->d_ioctl = altera_sdcard_disk_ioctl;
+	disk->d_sectorsize = ALTERA_SDCARD_SECTORSIZE;
+	disk->d_mediasize = sc->as_mediasize;
+	disk->d_maxsize = ALTERA_SDCARD_SECTORSIZE;
+	sc->as_disk = disk;
+	disk_create(disk, DISK_VERSION);
+	ALTERA_SDCARD_LOCK(sc);
+
+	/*
+	 * Print a pretty-ish card insertion string.  We could stand to
+	 * decorate this further, e.g., with card vendor information.
+	 */
+	size = sc->as_mediasize / (1000 * 1000);
+	device_printf(sc->as_dev, "%juM SD Card inserted\n", (uintmax_t)size);
+}
+
+void
+altera_sdcard_disk_remove(struct altera_sdcard_softc *sc)
+{
+	struct disk *disk;
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+	KASSERT(sc->as_disk != NULL, ("%s: as_disk NULL", __func__));
+
+	/*
+	 * sc->as_state will be updated by the caller.
+	 *
+	 * XXXRW: Is it OK to call disk_destroy() under the mutex, or should
+	 * we be deferring that to the calling context once it is released?
+	 */
+	disk = sc->as_disk;
+	disk_gone(disk);
+	disk_destroy(disk);
+	sc->as_disk = NULL;
+
+	/*
+	 * Cancel all outstanding I/O on the SD Card.
+	 */
+	if (sc->as_currentbio != NULL) {
+		device_printf(sc->as_dev, "%s: SD Card removed during I/O",
+		    __func__);
+		biofinish(sc->as_currentbio, NULL, ENXIO);
+		sc->as_currentbio = NULL;
+	}
+	bioq_flush(&sc->as_bioq, NULL, ENXIO);
+	device_printf(sc->as_dev, "SD Card removed\n");
+}

Added: head/sys/dev/altera/sdcard/altera_sdcard_io.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/altera/sdcard/altera_sdcard_io.c	Sat Aug 25 11:19:20 2012	(r239675)
@@ -0,0 +1,447 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208251119.q7PBJKtf029543>