Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 31 Mar 2012 23:36:40 GMT
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 208898 for review
Message-ID:  <201203312336.q2VNaewO048947@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@208898?ac=10

Change 208898 by rwatson@rwatson_svr_ctsrd_mipsbuild on 2012/03/31 23:36:23

	Provide a naive first cut at the actual I/O path for the Altera
	SD Card IP Core driver, allowing data buffers, registers, etc, to
	be read and written.
	
	Reading the CSD C_SIZE field is not yet supported, and will be
	required before this driver can function.
	
	We are unable to check for certain types of core errors currently
	due to a documentation bug: it's unclear whether the RR1 register
	is a 16-bit or 32-bit register, as the specification is ambiguous.
	Hopefully we can resolve this easily by simply looking at the
	Verilog next week.
	
	We may be able to improve performance by using 64-bit region
	read/write operations.

Affected files ...

.. //depot/projects/ctsrd/beribsd/src/sys/dev/altera/sdcard/altera_sdcard.h#3 edit
.. //depot/projects/ctsrd/beribsd/src/sys/dev/altera/sdcard/altera_sdcard_io.c#2 edit

Differences ...

==== //depot/projects/ctsrd/beribsd/src/sys/dev/altera/sdcard/altera_sdcard.h#3 (text+ko) ====

@@ -124,6 +124,16 @@
 #define	ALTERA_SDCARD_ASR_CMDDATAERROR	0x0020
 
 /*
+ * The Altera IP Core provides a 16-bit "Response R1" regster (RR1) beyond
+ * those described in the SD Card specification that holds additional
+ * information on the most recently completed command sent to the unit.
+ *
+ * XXXRW: The specification claims that this field is 16-bit, but then
+ * proceeds to define values as though it is 32-bit.  Which piece of the
+ * documentation is correct?
+ */
+
+/*
  * Although SD Cards may have various sector sizes, the Altera IP Core
  * requires that I/O be done in 512-byte chunks.
  */

==== //depot/projects/ctsrd/beribsd/src/sys/dev/altera/sdcard/altera_sdcard_io.c#2 (text+ko) ====

@@ -36,6 +36,7 @@
 #include <sys/condvar.h>
 #include <sys/conf.h>
 #include <sys/bio.h>
+#include <sys/endian.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -59,7 +60,7 @@
 altera_sdcard_read_asr(struct altera_sdcard_softc *sc)
 {
 
-	panic("%s: not yet", __func__);
+	return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_ASR)));
 }
 
 uint64_t
@@ -69,6 +70,53 @@
 	panic("%s: not yet", __func__);
 }
 
+#if 0
+uint16_t
+altera_sdcard_read_rr1(struct altera_sdcard_softc *sc)
+{
+
+	return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_RR1)));
+}
+#endif
+
+static void
+altera_sdcard_write_cmd_arg(struct altera_sdcard_softc *sc, uint32_t cmd_arg)
+{
+
+	bus_write_4(sc->as_res, ALTERA_SDCARD_OFF_CMD_ARG, htole32(cmd_arg));
+}
+
+static void
+altera_sdcard_write_cmd(struct altera_sdcard_softc *sc, uint16_t cmd)
+{
+
+	bus_write_2(sc->as_res, ALTERA_SDCARD_OFF_CMD_ARG, htole16(cmd));
+}
+
+static void
+altera_sdcard_read_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
+    size_t len)
+{
+
+	KASSERT(len > ALTERA_SDCARD_SECTORSIZE,
+	    ("%s: invalid length %ju", __func__, len));
+
+	bus_read_region_1(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER, data,
+	    len);
+}
+
+static void
+altera_sdcard_write_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
+    size_t len)
+{
+
+	KASSERT(len > ALTERA_SDCARD_SECTORSIZE,
+	    ("%s: invalid length %ju", __func__, len));
+
+	bus_write_region_1(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER, data,
+	    len);
+}
+
 void
 altera_sdcard_io_start(struct altera_sdcard_softc *sc, struct bio *bp)
 {
@@ -77,12 +125,30 @@
 	KASSERT(sc->as_currentbio == NULL,
 	    ("%s: bio already started", __func__));
 
+	/*
+	 * We advertise a block size and maximum I/O size up the stack of the
+	 * SD Card IP Core sector size.  Catch any attempts to not follow the
+	 * rules.
+	 */
+	KASSERT(bp->bio_bcount == bp->bio_resid,
+	    ("%s: bcount != resid", __func__));
+	KASSERT(bp->bio_bcount == ALTERA_SDCARD_SECTORSIZE,
+	    ("%s: I/O size not %d", __func__, ALTERA_SDCARD_SECTORSIZE));
+
 	switch (bp->bio_cmd) {
 	case BIO_READ:
-		panic("%s: BIO_READ - not yet", __func__);
+		altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
+		    ALTERA_SDCARD_SECTORSIZE);
+		altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_READ_BLOCK);
+		break;
 
 	case BIO_WRITE:
-		panic("%s: BIO_WRITE - not yet", __func__);
+		altera_sdcard_write_rxtx_buffer(sc, bp->bio_data,
+		    bp->bio_bcount);
+		altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
+		    ALTERA_SDCARD_SECTORSIZE);
+		altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_WRITE_BLOCK);
+		break;
 
 	default:
 		panic("%s: unsupported I/O operation %d", __func__,
@@ -95,27 +161,51 @@
 altera_sdcard_io_complete(struct altera_sdcard_softc *sc, uint16_t asr)
 {
 	struct bio *bp;
-	int error;
+#if 0
+	uint16_t rr1;
+#endif
 
 	ALTERA_SDCARD_LOCK_ASSERT(sc);
 	KASSERT(!(asr & ALTERA_SDCARD_ASR_CMDINPROGRESS),
 	    ("%s: still in progress", __func__));
+	KASSERT(asr & ALTERA_SDCARD_ASR_CARDPRESENT,
+	    ("%s: card removed", __func__));
 
-	error = 0;
 	bp = sc->as_currentbio;
+	sc->as_currentbio = NULL;
+
+	/*
+	 * Handle I/O errors.  Assume that the caller has already checked for
+	 * unexpected removal.
+	 */
+	if (asr &
+	    (ALTERA_SDCARD_ASR_CMDTIMEOUT | ALTERA_SDCARD_ASR_CMDDATAERROR)) {
+		biofinish(bp, NULL, EIO);
+		return;
+	}
+
+#if 0
+	/*
+	 * XXXRW: We would like to use RR1 to check on the status of the last
+	 * command handled by the unit.  Unfortunately, the documentation on
+	 * its use is inconsistent, so we don't do that yet.
+	 */
+	rr1 = altera_sdcard_read_rr1(sc);
+#endif
+
 	switch (bp->bio_cmd) {
 	case BIO_READ:
-		panic("%s: BIO_READ - not yet", __func__);
+		altera_sdcard_read_rxtx_buffer(sc, bp->bio_data,
+		    bp->bio_bcount);
 		break;
 
 	case BIO_WRITE:
-		panic("%s: BIO_WRITE - not yet", __func__);
 		break;
 
 	default:
 		panic("%s: unsupported I/O operation %d", __func__,
 		    bp->bio_cmd);
 	}
-	biofinish(bp, NULL, error);
-	sc->as_currentbio = NULL;
+	bp->bio_resid = 0;
+	biofinish(bp, NULL, 0);
 }



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