PERFORCE change 208898 for review
Robert Watson
rwatson at FreeBSD.org
Sat Mar 31 23:36:41 UTC 2012
http://p4web.freebsd.org/@@208898?ac=10
Change 208898 by rwatson at 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);
}
More information about the p4-projects
mailing list