[rtems-libbsd commit] mmc: Update to FreeBSD trunk 2016-08-23

Sebastian Huber sebh at rtems.org
Tue Aug 23 13:21:29 UTC 2016


Module:    rtems-libbsd
Branch:    master
Commit:    0c24e06130bd034474a33a191c6da095f4f59a5e
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=0c24e06130bd034474a33a191c6da095f4f59a5e

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Tue Aug 23 14:22:26 2016 +0200

mmc: Update to FreeBSD trunk 2016-08-23

---

 freebsd/sys/dev/mmc/bridge.h |   5 ++
 freebsd/sys/dev/mmc/mmc.c    | 200 ++++++++++++++++++++++++++++++-------------
 freebsd/sys/dev/mmc/mmcreg.h |  11 ++-
 freebsd/sys/dev/mmc/mmcsd.c  | 120 ++++++++++++++++++--------
 freebsd/sys/dev/mmc/mmcvar.h |  16 ++--
 libbsd.txt                   |   1 +
 rtemsbsd/include/geom/geom.h |   0
 7 files changed, 241 insertions(+), 112 deletions(-)

diff --git a/freebsd/sys/dev/mmc/bridge.h b/freebsd/sys/dev/mmc/bridge.h
index bd61c15..a26c31e 100644
--- a/freebsd/sys/dev/mmc/bridge.h
+++ b/freebsd/sys/dev/mmc/bridge.h
@@ -54,6 +54,8 @@
 #ifndef DEV_MMC_BRIDGE_H
 #define DEV_MMC_BRIDGE_H
 
+#include <sys/bus.h>
+
 /*
  * This file defines interfaces for the mmc bridge.  The names chosen
  * are similar to or the same as the names used in Linux to allow for
@@ -135,4 +137,7 @@ struct mmc_host {
 	struct mmc_ios ios;	/* Current state of the host */
 };
 
+extern driver_t   mmc_driver;
+extern devclass_t mmc_devclass;
+
 #endif /* DEV_MMC_BRIDGE_H */
diff --git a/freebsd/sys/dev/mmc/mmc.c b/freebsd/sys/dev/mmc/mmc.c
index 7a94dc4..d3c9fcb 100644
--- a/freebsd/sys/dev/mmc/mmc.c
+++ b/freebsd/sys/dev/mmc/mmc.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/bus.h>
 #include <sys/endian.h>
 #include <sys/sysctl.h>
+#include <sys/time.h>
 
 #include <dev/mmc/mmcreg.h>
 #include <dev/mmc/mmcbrvar.h>
@@ -78,8 +79,13 @@ struct mmc_softc {
 	struct intr_config_hook config_intrhook;
 	device_t owner;
 	uint32_t last_rca;
+	int	 squelched; /* suppress reporting of (expected) errors */
+	int	 log_count;
+	struct timeval log_time;
 };
 
+#define	LOG_PPS		5 /* Log no more than 5 errors per second. */
+
 /*
  * Per-card data
  */
@@ -104,14 +110,17 @@ struct mmc_ivars {
 	uint32_t hs_tran_speed;	/* Max speed in high speed mode */
 	uint32_t erase_sector;	/* Card native erase sector size */
 	char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */
+	char card_sn_string[16];/* Formatted serial # for disk->d_ident */
 };
 
 #define CMD_RETRIES	3
 
+#define	CARD_ID_FREQUENCY 400000 /* Spec requires 400kHz max during ID phase. */
+
 static SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver");
 
 static int mmc_debug;
-SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RW, &mmc_debug, 0, "Debug level");
+SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RWTUN, &mmc_debug, 0, "Debug level");
 
 /* bus entry points */
 static int mmc_acquire_bus(device_t busdev, device_t dev);
@@ -355,7 +364,8 @@ mmc_highest_voltage(uint32_t ocr)
 {
 	int i;
 
-	for (i = 30; i >= 0; i--)
+	for (i = MMC_OCR_MAX_VOLTAGE_SHIFT;
+	    i >= MMC_OCR_MIN_VOLTAGE_SHIFT; i--)
 		if (ocr & (1 << i))
 			return (i);
 	return (-1);
@@ -392,8 +402,9 @@ mmc_wait_for_req(struct mmc_softc *sc, struct mmc_request *req)
 	while ((req->flags & MMC_REQ_DONE) == 0)
 		msleep(req, &sc->sc_mtx, 0, "mmcreq", 0);
 	MMC_UNLOCK(sc);
-	if (mmc_debug > 2 || (mmc_debug > 1 && req->cmd->error))
-		device_printf(sc->dev, "RESULT: %d\n", req->cmd->error);
+	if (mmc_debug > 2 || (mmc_debug > 0 && req->cmd->error != MMC_ERR_NONE))
+		device_printf(sc->dev, "CMD%d RESULT: %d\n", 
+		    req->cmd->opcode, req->cmd->error);
 	return (0);
 }
 
@@ -409,13 +420,28 @@ static int
 mmc_wait_for_cmd(struct mmc_softc *sc, struct mmc_command *cmd, int retries)
 {
 	struct mmc_request mreq;
+	int err;
 
-	memset(&mreq, 0, sizeof(mreq));
-	memset(cmd->resp, 0, sizeof(cmd->resp));
-	cmd->retries = retries;
-	mreq.cmd = cmd;
-	mmc_wait_for_req(sc, &mreq);
-	return (cmd->error);
+	do {
+		memset(&mreq, 0, sizeof(mreq));
+		memset(cmd->resp, 0, sizeof(cmd->resp));
+		cmd->retries = 0; /* Retries done here, not in hardware. */
+		cmd->mrq = &mreq;
+		mreq.cmd = cmd;
+		if (mmc_wait_for_req(sc, &mreq) != 0)
+			err = MMC_ERR_FAILED;
+		else
+			err = cmd->error;
+	} while (err != MMC_ERR_NONE && retries-- > 0);
+
+	if (err != MMC_ERR_NONE && sc->squelched == 0) {
+		if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) {
+			device_printf(sc->dev, "CMD%d failed, RESULT: %d\n",
+			    cmd->opcode, err);
+		}
+	}
+
+	return (err);
 }
 
 static int
@@ -423,24 +449,38 @@ mmc_wait_for_app_cmd(struct mmc_softc *sc, uint32_t rca,
     struct mmc_command *cmd, int retries)
 {
 	struct mmc_command appcmd;
-	int err = MMC_ERR_NONE, i;
+	int err;
 
-	for (i = 0; i <= retries; i++) {
+	/* Squelch error reporting at lower levels, we report below. */
+	sc->squelched++;
+	do {
+		memset(&appcmd, 0, sizeof(appcmd));
 		appcmd.opcode = MMC_APP_CMD;
 		appcmd.arg = rca << 16;
 		appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 		appcmd.data = NULL;
-		mmc_wait_for_cmd(sc, &appcmd, 0);
-		err = appcmd.error;
-		if (err != MMC_ERR_NONE)
-			continue;
-		if (!(appcmd.resp[0] & R1_APP_CMD))
-			return MMC_ERR_FAILED;
-		mmc_wait_for_cmd(sc, cmd, 0);
-		err = cmd->error;
-		if (err == MMC_ERR_NONE)
-			break;
+		if (mmc_wait_for_cmd(sc, &appcmd, 0) != 0)
+			err = MMC_ERR_FAILED;
+		else
+			err = appcmd.error;
+		if (err == MMC_ERR_NONE) {
+			if (!(appcmd.resp[0] & R1_APP_CMD))
+				err = MMC_ERR_FAILED;
+			else if (mmc_wait_for_cmd(sc, cmd, 0) != 0)
+				err = MMC_ERR_FAILED;
+			else
+				err = cmd->error;
+		}
+	} while (err != MMC_ERR_NONE && retries-- > 0);
+	sc->squelched--;
+
+	if (err != MMC_ERR_NONE && sc->squelched == 0) {
+		if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) {
+			device_printf(sc->dev, "ACMD%d failed, RESULT: %d\n",
+			    cmd->opcode, err);
+		}
 	}
+
 	return (err);
 }
 
@@ -459,8 +499,6 @@ mmc_wait_for_command(struct mmc_softc *sc, uint32_t opcode,
 	err = mmc_wait_for_cmd(sc, &cmd, retries);
 	if (err)
 		return (err);
-	if (cmd.error)
-		return (cmd.error);
 	if (resp) {
 		if (flags & MMC_RSP_136)
 			memcpy(resp, cmd.resp, 4 * sizeof(uint32_t));
@@ -486,7 +524,7 @@ mmc_idle_cards(struct mmc_softc *sc)
 	cmd.arg = 0;
 	cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
 	cmd.data = NULL;
-	mmc_wait_for_cmd(sc, &cmd, 0);
+	mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
 	mmc_ms_delay(1);
 
 	mmcbr_set_chip_select(dev, cs_dontcare);
@@ -579,7 +617,7 @@ mmc_power_up(struct mmc_softc *sc)
 	mmcbr_update_ios(dev);
 	mmc_ms_delay(1);
 
-	mmcbr_set_clock(dev, mmcbr_get_f_min(sc->dev));
+	mmcbr_set_clock(dev, CARD_ID_FREQUENCY);
 	mmcbr_set_timing(dev, bus_timing_normal);
 	mmcbr_set_power_mode(dev, power_on);
 	mmcbr_update_ios(dev);
@@ -616,6 +654,7 @@ mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value)
 	struct mmc_command cmd;
 	int err;
 
+	memset(&cmd, 0, sizeof(cmd));
 	cmd.opcode = MMC_SWITCH_FUNC;
 	cmd.arg = (MMC_SWITCH_FUNC_WR << 24) |
 	    (index << 16) |
@@ -623,7 +662,7 @@ mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value)
 	    set;
 	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
 	cmd.data = NULL;
-	err = mmc_wait_for_cmd(sc, &cmd, 0);
+	err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
 	return (err);
 }
 
@@ -635,8 +674,8 @@ mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value,
 	struct mmc_command cmd;
 	struct mmc_data data;
 
-	memset(&cmd, 0, sizeof(struct mmc_command));
-	memset(&data, 0, sizeof(struct mmc_data));
+	memset(&cmd, 0, sizeof(cmd));
+	memset(&data, 0, sizeof(data));
 	memset(res, 0, 64);
 
 	cmd.opcode = SD_SWITCH_FUNC;
@@ -663,14 +702,14 @@ mmc_set_card_bus_width(struct mmc_softc *sc, uint16_t rca, int width)
 	uint8_t	value;
 
 	if (mmcbr_get_mode(sc->dev) == mode_sd) {
-		memset(&cmd, 0, sizeof(struct mmc_command));
+		memset(&cmd, 0, sizeof(cmd));
 		cmd.opcode = ACMD_SET_CLR_CARD_DETECT;
 		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 		cmd.arg = SD_CLR_CARD_DETECT;
 		err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES);
 		if (err != 0)
 			return (err);
-		memset(&cmd, 0, sizeof(struct mmc_command));
+		memset(&cmd, 0, sizeof(cmd));
 		cmd.opcode = ACMD_SET_BUS_WIDTH;
 		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 		switch (width) {
@@ -746,6 +785,9 @@ mmc_test_bus_width(struct mmc_softc *sc)
 		mmcbr_set_bus_width(sc->dev, bus_width_8);
 		mmcbr_update_ios(sc->dev);
 
+		sc->squelched++; /* Errors are expected, squelch reporting. */
+		memset(&cmd, 0, sizeof(cmd));
+		memset(&data, 0, sizeof(data));
 		cmd.opcode = MMC_BUSTEST_W;
 		cmd.arg = 0;
 		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@@ -756,6 +798,8 @@ mmc_test_bus_width(struct mmc_softc *sc)
 		data.flags = MMC_DATA_WRITE;
 		mmc_wait_for_cmd(sc, &cmd, 0);
 		
+		memset(&cmd, 0, sizeof(cmd));
+		memset(&data, 0, sizeof(data));
 		cmd.opcode = MMC_BUSTEST_R;
 		cmd.arg = 0;
 		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@@ -765,6 +809,7 @@ mmc_test_bus_width(struct mmc_softc *sc)
 		data.len = 8;
 		data.flags = MMC_DATA_READ;
 		err = mmc_wait_for_cmd(sc, &cmd, 0);
+		sc->squelched--;
 		
 		mmcbr_set_bus_width(sc->dev, bus_width_1);
 		mmcbr_update_ios(sc->dev);
@@ -777,6 +822,9 @@ mmc_test_bus_width(struct mmc_softc *sc)
 		mmcbr_set_bus_width(sc->dev, bus_width_4);
 		mmcbr_update_ios(sc->dev);
 
+		sc->squelched++; /* Errors are expected, squelch reporting. */
+		memset(&cmd, 0, sizeof(cmd));
+		memset(&data, 0, sizeof(data));
 		cmd.opcode = MMC_BUSTEST_W;
 		cmd.arg = 0;
 		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@@ -787,6 +835,8 @@ mmc_test_bus_width(struct mmc_softc *sc)
 		data.flags = MMC_DATA_WRITE;
 		mmc_wait_for_cmd(sc, &cmd, 0);
 		
+		memset(&cmd, 0, sizeof(cmd));
+		memset(&data, 0, sizeof(data));
 		cmd.opcode = MMC_BUSTEST_R;
 		cmd.arg = 0;
 		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@@ -796,6 +846,7 @@ mmc_test_bus_width(struct mmc_softc *sc)
 		data.len = 4;
 		data.flags = MMC_DATA_READ;
 		err = mmc_wait_for_cmd(sc, &cmd, 0);
+		sc->squelched--;
 
 		mmcbr_set_bus_width(sc->dev, bus_width_1);
 		mmcbr_update_ios(sc->dev);
@@ -866,6 +917,9 @@ mmc_format_card_id_string(struct mmc_ivars *ivar)
 	 * mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 Mfg 08/2008 by 3 TN> at mmc0
 	 * 22.5MHz/4bit/128-block
 	 *
+	 * Also format just the card serial number, which the mmcsd driver will
+	 * use as the disk->d_ident string.
+	 *
 	 * The card_id_string in mmc_ivars is currently allocated as 64 bytes,
 	 * and our max formatted length is currently 55 bytes if every field
 	 * contains the largest value.
@@ -879,8 +933,10 @@ mmc_format_card_id_string(struct mmc_ivars *ivar)
 		snprintf(oidstr, sizeof(oidstr), "%c%c", c1, c2);
 	else
 		snprintf(oidstr, sizeof(oidstr), "0x%04x", ivar->cid.oid);
+	snprintf(ivar->card_sn_string, sizeof(ivar->card_sn_string),
+	    "%08X", ivar->cid.psn);
 	snprintf(ivar->card_id_string, sizeof(ivar->card_id_string),
-	    "%s%s %s %d.%d SN %u MFG %02d/%04d by %d %s",
+	    "%s%s %s %d.%d SN %08X MFG %02d/%04d by %d %s",
 	    ivar->mode == mode_sd ? "SD" : "MMC", ivar->high_cap ? "HC" : "",
 	    ivar->cid.pnm, ivar->cid.prv >> 4, ivar->cid.prv & 0x0f,
 	    ivar->cid.psn, ivar->cid.mdt_month, ivar->cid.mdt_year,
@@ -1048,11 +1104,12 @@ mmc_all_send_cid(struct mmc_softc *sc, uint32_t *rawcid)
 	struct mmc_command cmd;
 	int err;
 
+	memset(&cmd, 0, sizeof(cmd));
 	cmd.opcode = MMC_ALL_SEND_CID;
 	cmd.arg = 0;
 	cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
 	cmd.data = NULL;
-	err = mmc_wait_for_cmd(sc, &cmd, 0);
+	err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
 	memcpy(rawcid, cmd.resp, 4 * sizeof(uint32_t));
 	return (err);
 }
@@ -1063,11 +1120,12 @@ mmc_send_csd(struct mmc_softc *sc, uint16_t rca, uint32_t *rawcsd)
 	struct mmc_command cmd;
 	int err;
 
+	memset(&cmd, 0, sizeof(cmd));
 	cmd.opcode = MMC_SEND_CSD;
 	cmd.arg = rca << 16;
 	cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
 	cmd.data = NULL;
-	err = mmc_wait_for_cmd(sc, &cmd, 0);
+	err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
 	memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t));
 	return (err);
 }
@@ -1079,8 +1137,8 @@ mmc_app_send_scr(struct mmc_softc *sc, uint16_t rca, uint32_t *rawscr)
 	struct mmc_command cmd;
 	struct mmc_data data;
 
-	memset(&cmd, 0, sizeof(struct mmc_command));
-	memset(&data, 0, sizeof(struct mmc_data));
+	memset(&cmd, 0, sizeof(cmd));
+	memset(&data, 0, sizeof(data));
 
 	memset(rawscr, 0, 8);
 	cmd.opcode = ACMD_SEND_SCR;
@@ -1105,8 +1163,8 @@ mmc_send_ext_csd(struct mmc_softc *sc, uint8_t *rawextcsd)
 	struct mmc_command cmd;
 	struct mmc_data data;
 
-	memset(&cmd, 0, sizeof(struct mmc_command));
-	memset(&data, 0, sizeof(struct mmc_data));
+	memset(&cmd, 0, sizeof(cmd));
+	memset(&data, 0, sizeof(data));
 
 	memset(rawextcsd, 0, 512);
 	cmd.opcode = MMC_SEND_EXT_CSD;
@@ -1129,8 +1187,8 @@ mmc_app_sd_status(struct mmc_softc *sc, uint16_t rca, uint32_t *rawsdstatus)
 	struct mmc_command cmd;
 	struct mmc_data data;
 
-	memset(&cmd, 0, sizeof(struct mmc_command));
-	memset(&data, 0, sizeof(struct mmc_data));
+	memset(&cmd, 0, sizeof(cmd));
+	memset(&data, 0, sizeof(data));
 
 	memset(rawsdstatus, 0, 64);
 	cmd.opcode = ACMD_SD_STATUS;
@@ -1154,11 +1212,12 @@ mmc_set_relative_addr(struct mmc_softc *sc, uint16_t resp)
 	struct mmc_command cmd;
 	int err;
 
+	memset(&cmd, 0, sizeof(cmd));
 	cmd.opcode = MMC_SET_RELATIVE_ADDR;
 	cmd.arg = resp << 16;
 	cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
 	cmd.data = NULL;
-	err = mmc_wait_for_cmd(sc, &cmd, 0);
+	err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
 	return (err);
 }
 
@@ -1168,11 +1227,12 @@ mmc_send_relative_addr(struct mmc_softc *sc, uint32_t *resp)
 	struct mmc_command cmd;
 	int err;
 
+	memset(&cmd, 0, sizeof(cmd));
 	cmd.opcode = SD_SEND_RELATIVE_ADDR;
 	cmd.arg = 0;
 	cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
 	cmd.data = NULL;
-	err = mmc_wait_for_cmd(sc, &cmd, 0);
+	err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
 	*resp = cmd.resp[0];
 	return (err);
 }
@@ -1183,11 +1243,12 @@ mmc_send_status(struct mmc_softc *sc, uint16_t rca, uint32_t *status)
 	struct mmc_command cmd;
 	int err;
 
+	memset(&cmd, 0, sizeof(cmd));
 	cmd.opcode = MMC_SEND_STATUS;
 	cmd.arg = rca << 16;
 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 	cmd.data = NULL;
-	err = mmc_wait_for_cmd(sc, &cmd, 0);
+	err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
 	*status = cmd.resp[0];
 	return (err);
 }
@@ -1198,18 +1259,19 @@ mmc_set_blocklen(struct mmc_softc *sc, uint32_t len)
 	struct mmc_command cmd;
 	int err;
 
+	memset(&cmd, 0, sizeof(cmd));
 	cmd.opcode = MMC_SET_BLOCKLEN;
 	cmd.arg = len;
 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 	cmd.data = NULL;
-	err = mmc_wait_for_cmd(sc, &cmd, 0);
+	err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
 	return (err);
 }
 
 static void
 mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard)
 {
-	device_printf(dev, "Card at relative address %d%s:\n",
+	device_printf(dev, "Card at relative address 0x%04x%s:\n",
 	    ivar->rca, newcard ? " added" : "");
 	device_printf(dev, " card: %s\n", ivar->card_id_string);
 	device_printf(dev, " bus: %ubit, %uMHz%s\n",
@@ -1237,7 +1299,9 @@ mmc_discover_cards(struct mmc_softc *sc)
 	if (bootverbose || mmc_debug)
 		device_printf(sc->dev, "Probing cards\n");
 	while (1) {
+		sc->squelched++; /* Errors are expected, squelch reporting. */
 		err = mmc_all_send_cid(sc, raw_cid);
+		sc->squelched--;
 		if (err == MMC_ERR_TIMEOUT)
 			break;
 		if (err != MMC_ERR_NONE) {
@@ -1263,8 +1327,6 @@ mmc_discover_cards(struct mmc_softc *sc)
 		if (newcard) {
 			ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF,
 			    M_WAITOK | M_ZERO);
-			if (!ivar)
-				return;
 			memcpy(ivar->raw_cid, raw_cid, sizeof(raw_cid));
 		}
 		if (mmcbr_get_ro(sc->dev))
@@ -1319,6 +1381,21 @@ mmc_discover_cards(struct mmc_softc *sc)
 					ivar->hs_tran_speed = SD_MAX_HS;
 				}
 			}
+
+			/*
+			 * We deselect then reselect the card here.  Some cards
+			 * become unselected and timeout with the above two
+			 * commands, although the state tables / diagrams in the
+			 * standard suggest they go back to the transfer state.
+			 * Other cards don't become deselected, and if we
+			 * atttempt to blindly re-select them, we get timeout
+			 * errors from some controllers.  So we deselect then
+			 * reselect to handle all situations.  The only thing we
+			 * use from the sd_status is the erase sector size, but
+			 * it is still nice to get that right.
+			 */
+			mmc_select_card(sc, 0);
+			mmc_select_card(sc, ivar->rca);
 			mmc_app_sd_status(sc, ivar->rca, ivar->raw_sd_status);
 			mmc_app_decode_sd_status(ivar->raw_sd_status,
 			    &ivar->sd_status);
@@ -1326,7 +1403,6 @@ mmc_discover_cards(struct mmc_softc *sc)
 				ivar->erase_sector =
 				    16 << ivar->sd_status.au_size;
 			}
-			mmc_select_card(sc, 0);
 			/* Find max supported bus width. */
 			if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) &&
 			    (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4))
@@ -1354,6 +1430,7 @@ mmc_discover_cards(struct mmc_softc *sc)
 				child = device_add_child(sc->dev, NULL, -1);
 				device_set_ivars(child, ivar);
 			}
+			mmc_select_card(sc, 0);
 			return;
 		}
 		mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid);
@@ -1386,10 +1463,10 @@ mmc_discover_cards(struct mmc_softc *sc)
 			break;
 		}
 
+		mmc_select_card(sc, ivar->rca);
+
 		/* Only MMC >= 4.x cards support EXT_CSD. */
 		if (ivar->csd.spec_vers >= 4) {
-			/* Card must be selected to fetch EXT_CSD. */
-			mmc_select_card(sc, ivar->rca);
 			mmc_send_ext_csd(sc, ivar->raw_ext_csd);
 			/* Handle extended capacity from EXT_CSD */
 			sec_count = ivar->raw_ext_csd[EXT_CSD_SEC_CNT] +
@@ -1412,7 +1489,6 @@ mmc_discover_cards(struct mmc_softc *sc)
 				ivar->hs_tran_speed = ivar->tran_speed;
 			/* Find max supported bus width. */
 			ivar->bus_width = mmc_test_bus_width(sc);
-			mmc_select_card(sc, 0);
 			/* Handle HC erase sector size. */
 			if (ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) {
 				ivar->erase_sector = 1024 *
@@ -1446,6 +1522,7 @@ mmc_discover_cards(struct mmc_softc *sc)
 			child = device_add_child(sc->dev, NULL, -1);
 			device_set_ivars(child, ivar);
 		}
+		mmc_select_card(sc, 0);
 	}
 }
 
@@ -1505,6 +1582,7 @@ mmc_go_discovery(struct mmc_softc *sc)
 		/*
 		 * First, try SD modes
 		 */
+		sc->squelched++; /* Errors are expected, squelch reporting. */
 		mmcbr_set_mode(dev, mode_sd);
 		mmc_power_up(sc);
 		mmcbr_set_bus_mode(dev, pushpull);
@@ -1530,13 +1608,14 @@ mmc_go_discovery(struct mmc_softc *sc)
 				    "MMC probe: OK (OCR: 0x%08x)\n", ocr);
 		} else if (bootverbose || mmc_debug)
 			device_printf(sc->dev, "SD probe: OK (OCR: 0x%08x)\n", ocr);
+		sc->squelched--;
 
 		mmcbr_set_ocr(dev, mmc_select_vdd(sc, ocr));
 		if (mmcbr_get_ocr(dev) != 0)
 			mmc_idle_cards(sc);
 	} else {
 		mmcbr_set_bus_mode(dev, opendrain);
-		mmcbr_set_clock(dev, mmcbr_get_f_min(dev));
+		mmcbr_set_clock(dev, CARD_ID_FREQUENCY);
 		mmcbr_update_ios(dev);
 		/* XXX recompute vdd based on new cards? */
 	}
@@ -1547,6 +1626,7 @@ mmc_go_discovery(struct mmc_softc *sc)
 	if (bootverbose || mmc_debug)
 		device_printf(sc->dev, "Current OCR: 0x%08x\n", mmcbr_get_ocr(dev));
 	if (mmcbr_get_ocr(dev) == 0) {
+		device_printf(sc->dev, "No compatible cards found on bus\n");
 		mmc_delete_cards(sc);
 		mmc_power_down(sc);
 		return;
@@ -1559,7 +1639,7 @@ mmc_go_discovery(struct mmc_softc *sc)
 		mmc_send_app_op_cond(sc,
 		    (err ? 0 : MMC_OCR_CCS) | mmcbr_get_ocr(dev), NULL);
 	} else
-		mmc_send_op_cond(sc, mmcbr_get_ocr(dev), NULL);
+		mmc_send_op_cond(sc, MMC_OCR_CCS | mmcbr_get_ocr(dev), NULL);
 	mmc_discover_cards(sc);
 	mmc_rescan_cards(sc);
 
@@ -1574,11 +1654,10 @@ static int
 mmc_calculate_clock(struct mmc_softc *sc)
 {
 	int max_dtr, max_hs_dtr, max_timing;
-	int nkid, i, f_min, f_max;
+	int nkid, i, f_max;
 	device_t *kids;
 	struct mmc_ivars *ivar;
 	
-	f_min = mmcbr_get_f_min(sc->dev);
 	f_max = mmcbr_get_f_max(sc->dev);
 	max_dtr = max_hs_dtr = f_max;
 	if ((mmcbr_get_caps(sc->dev) & MMC_CAP_HSPEED))
@@ -1673,6 +1752,9 @@ mmc_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
 	case MMC_IVAR_CARD_ID_STRING:
 		*(char **)result = ivar->card_id_string;
 		break;
+	case MMC_IVAR_CARD_SN_STRING:
+		*(char **)result = ivar->card_sn_string;
+		break;
 	}
 	return (0);
 }
@@ -1725,13 +1807,11 @@ static device_method_t mmc_methods[] = {
 	DEVMETHOD_END
 };
 
-static driver_t mmc_driver = {
+driver_t mmc_driver = {
 	"mmc",
 	mmc_methods,
 	sizeof(struct mmc_softc),
 };
-static devclass_t mmc_devclass;
+devclass_t mmc_devclass;
 
-DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
-DRIVER_MODULE(mmc, dw_mmc, mmc_driver, mmc_devclass, NULL, NULL);
-DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_VERSION(mmc, 1);
diff --git a/freebsd/sys/dev/mmc/mmcreg.h b/freebsd/sys/dev/mmc/mmcreg.h
index 3d2b569..f25c0f6 100644
--- a/freebsd/sys/dev/mmc/mmcreg.h
+++ b/freebsd/sys/dev/mmc/mmcreg.h
@@ -85,8 +85,11 @@ struct mmc_command {
 #define	MMC_RSP_R1B	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
 #define	MMC_RSP_R2	(MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
 #define	MMC_RSP_R3	(MMC_RSP_PRESENT)
-#define	MMC_RSP_R6	(MMC_RSP_PRESENT | MMC_RSP_CRC)
-#define	MMC_RSP_R7	(MMC_RSP_PRESENT | MMC_RSP_CRC)
+#define	MMC_RSP_R4	(MMC_RSP_PRESENT)
+#define	MMC_RSP_R5	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define	MMC_RSP_R5B	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
+#define	MMC_RSP_R6	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define	MMC_RSP_R7	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
 #define	MMC_RSP(x)	((x) & MMC_RSP_MASK)
 	uint32_t	retries;
 	uint32_t	error;
@@ -353,6 +356,7 @@ struct mmc_request {
 #define	MMC_OCR_VOLTAGE	0x3fffffffU	/* Vdd Voltage mask */
 #define	MMC_OCR_LOW_VOLTAGE (1u << 7)	/* Low Voltage Range -- tbd */
 #define	MMC_OCR_200_210	(1U << 8)	/* Vdd voltage 2.00 ~ 2.10 */
+#define	MMC_OCR_MIN_VOLTAGE_SHIFT	8
 #define	MMC_OCR_210_220	(1U << 9)	/* Vdd voltage 2.10 ~ 2.20 */
 #define	MMC_OCR_220_230	(1U << 10)	/* Vdd voltage 2.20 ~ 2.30 */
 #define	MMC_OCR_230_240	(1U << 11)	/* Vdd voltage 2.30 ~ 2.40 */
@@ -368,6 +372,7 @@ struct mmc_request {
 #define	MMC_OCR_330_340	(1U << 21)	/* Vdd voltage 3.30 ~ 3.40 */
 #define	MMC_OCR_340_350	(1U << 22)	/* Vdd voltage 3.40 ~ 3.50 */
 #define	MMC_OCR_350_360	(1U << 23)	/* Vdd voltage 3.50 ~ 3.60 */
+#define	MMC_OCR_MAX_VOLTAGE_SHIFT	23
 #define	MMC_OCR_CCS	(1u << 30)	/* Card Capacity status (SD vs SDHC) */
 #define	MMC_OCR_CARD_BUSY (1U << 31)	/* Card Power up status */
 
@@ -436,7 +441,7 @@ struct mmc_sd_status
  * Older versions of the MMC standard had a variable sector size.  However,
  * I've been able to find no old MMC or SD cards that have a non 512
  * byte sector size anywhere, so we assume that such cards are very rare
- * and only note their existance in passing here...
+ * and only note their existence in passing here...
  */
 #define MMC_SECTOR_SIZE	512
 
diff --git a/freebsd/sys/dev/mmc/mmcsd.c b/freebsd/sys/dev/mmc/mmcsd.c
index 42c45cf..d02abf1 100644
--- a/freebsd/sys/dev/mmc/mmcsd.c
+++ b/freebsd/sys/dev/mmc/mmcsd.c
@@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/mutex.h>
+#include <sys/time.h>
+#include <geom/geom.h>
 #include <geom/geom_disk.h>
 
 #include <dev/mmc/mmcbrvar.h>
@@ -96,9 +98,26 @@ struct mmcsd_softc {
 	daddr_t eblock, eend;	/* Range remaining after the last erase. */
 	int running;
 	int suspend;
+	int log_count;
+	struct timeval log_time;
 #endif /* __rtems__ */
 };
 
+#ifndef __rtems__
+static const char *errmsg[] =
+{
+	"None",
+	"Timeout",
+	"Bad CRC",
+	"Fifo",
+	"Failed",
+	"Invalid",
+	"NO MEMORY"
+};
+#endif /* __rtems__ */
+
+#define	LOG_PPS		5 /* Log no more than 5 errors per second. */
+
 /* bus entry points */
 static int mmcsd_attach(device_t dev);
 static int mmcsd_detach(device_t dev);
@@ -347,6 +366,11 @@ mmcsd_attach(device_t dev)
 	struct mmcsd_softc *sc;
 #ifndef __rtems__
 	struct disk *d;
+#else /* __rtems__ */
+	struct {
+		char d_ident[16];
+		char d_descr[64];
+	} x, *d = &x;
 #endif /* __rtems__ */
 	intmax_t mb;
 	uint32_t speed;
@@ -365,45 +389,49 @@ mmcsd_attach(device_t dev)
 	d->d_dump = mmcsd_dump;
 	d->d_name = "mmcsd";
 	d->d_drv1 = sc;
-	d->d_maxsize = 4*1024*1024;	/* Maximum defined SD card AU size. */
 	d->d_sectorsize = mmc_get_sector_size(dev);
+	d->d_maxsize = mmc_get_max_data(dev) * d->d_sectorsize;
 	d->d_mediasize = (off_t)mmc_get_media_size(dev) * d->d_sectorsize;
-	d->d_stripeoffset = 0;
 	d->d_stripesize = mmc_get_erase_sector(dev) * d->d_sectorsize;
 	d->d_unit = device_get_unit(dev);
 	d->d_flags = DISKFLAG_CANDELETE;
+	d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize;
+#endif /* __rtems__ */
+	strlcpy(d->d_ident, mmc_get_card_sn_string(dev), sizeof(d->d_ident));
+	strlcpy(d->d_descr, mmc_get_card_id_string(dev), sizeof(d->d_descr));
+
+#ifndef __rtems__
 	/*
-	 * Display in most natural units.  There's no cards < 1MB.
-	 * The SD standard goes to 2GiB, but the data format supports
-	 * up to 4GiB and some card makers push it up to this limit.
-	 * The SDHC standard only goes to 32GiB (the data format in
-	 * SDHC is good to 2TiB however, which isn't too ugly at
-	 * 2048GiBm, so we note it in passing here and don't add the
-	 * code to print TiB).
+	 * Display in most natural units.  There's no cards < 1MB.  The SD
+	 * standard goes to 2GiB due to its reliance on FAT, but the data
+	 * format supports up to 4GiB and some card makers push it up to this
+	 * limit.  The SDHC standard only goes to 32GiB due to FAT32, but the
+	 * data format supports up to 2TiB however. 2048GB isn't too ugly, so
+	 * we note it in passing here and don't add the code to print
+	 * TB). Since these cards are sold in terms of MB and GB not MiB and
+	 * GiB, report them like that. We also round to the nearest unit, since
+	 * many cards are a few percent short, even of the power of 10 size.
 	 */
-	mb = d->d_mediasize >> 20;	/* 1MiB == 1 << 20 */
+	mb = (d->d_mediasize + 1000000 / 2 - 1) / 1000000;
 #else /* __rtems__ */
 	mb = mmc_get_media_size(dev);
 	mb *= mmc_get_sector_size(dev);
-	mb >>= 20;
+	mb = (mb + 1000000 / 2 - 1) / 1000000;
 #endif /* __rtems__ */
 	unit = 'M';
-	if (mb >= 10240) {		/* 1GiB = 1024 MiB */
+	if (mb >= 1000) {
 		unit = 'G';
-		mb /= 1024;
+		mb = (mb + 1000 / 2 - 1) / 1000;
 	}
 	/*
 	 * Report the clock speed of the underlying hardware, which might be
 	 * different than what the card reports due to hardware limitations.
-	 * Report how many blocks the hardware transfers at once, but clip the
-	 * number to MAXPHYS since the system won't initiate larger transfers.
+	 * Report how many blocks the hardware transfers at once.
 	 */
 	speed = mmcbr_get_clock(device_get_parent(dev));
 	maxblocks = mmc_get_max_data(dev);
-	if (maxblocks > MAXPHYS)
-		maxblocks = MAXPHYS;
 	device_printf(dev, "%ju%cB <%s>%s at %s %d.%01dMHz/%dbit/%d-block\n",
-	    mb, unit, mmc_get_card_id_string(dev),
+	    mb, unit, d->d_descr,
 	    mmc_get_read_only(dev) ? " (read-only)" : "",
 	    device_get_nameunit(device_get_parent(dev)),
 	    speed / 1000000, (speed / 100000) % 10,
@@ -415,7 +443,8 @@ mmcsd_attach(device_t dev)
 	sc->running = 1;
 	sc->suspend = 0;
 	sc->eblock = sc->eend = 0;
-	kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "task: mmc/sd card");
+	kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "%s: mmc/sd card", 
+	    device_get_nameunit(dev));
 #else /* __rtems__ */
 	rtems_status_code status_code = rtems_media_server_disk_attach(
 		device_get_name(dev),
@@ -493,7 +522,8 @@ mmcsd_resume(device_t dev)
 	if (sc->running <= 0) {
 		sc->running = 1;
 		MMCSD_UNLOCK(sc);
-		kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "task: mmc/sd card");
+		kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "%s: mmc/sd card",
+		    device_get_nameunit(dev));
 	} else
 		MMCSD_UNLOCK(sc);
 #else /* __rtems__ */
@@ -534,6 +564,14 @@ mmcsd_strategy(struct bio *bp)
 	}
 }
 
+static const char *
+mmcsd_errmsg(int e)
+{
+	if (e < 0 || e > MMC_ERR_MAX)
+		return "Bad error code";
+	return errmsg[e];
+}
+
 static daddr_t
 mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
 {
@@ -544,6 +582,7 @@ mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
 	struct mmc_data data;
 	device_t dev = sc->dev;
 	int sz = sc->disk->d_sectorsize;
+	device_t mmcbr = device_get_parent(dev);
 
 	block = bp->bio_pblkno;
 	end = bp->bio_pblkno + (bp->bio_bcount / sz);
@@ -554,6 +593,8 @@ mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
 		memset(&req, 0, sizeof(req));
     		memset(&cmd, 0, sizeof(cmd));
 		memset(&stop, 0, sizeof(stop));
+		memset(&data, 0, sizeof(data));
+		cmd.mrq = &req;
 		req.cmd = &cmd;
 		cmd.data = &data;
 		if (bp->bio_cmd == BIO_READ) {
@@ -583,14 +624,17 @@ mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
 			stop.opcode = MMC_STOP_TRANSMISSION;
 			stop.arg = 0;
 			stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
+			stop.mrq = &req;
 			req.stop = &stop;
 		}
-//		printf("Len %d  %lld-%lld flags %#x sz %d\n",
-//		    (int)data.len, (long long)block, (long long)end, data.flags, sz);
-		MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
-		    &req);
-		if (req.cmd->error != MMC_ERR_NONE)
+		MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
+		if (req.cmd->error != MMC_ERR_NONE) {
+			if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) {
+				device_printf(dev, "Error indicated: %d %s\n",
+				    req.cmd->error, mmcsd_errmsg(req.cmd->error));
+			}
 			break;
+		}
 		block += numblocks;
 	}
 	return (block);
@@ -605,6 +649,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
 	device_t dev = sc->dev;
 	int sz = sc->disk->d_sectorsize;
 	int erase_sector;
+	device_t mmcbr = device_get_parent(dev);
 
 	block = bp->bio_pblkno;
 	end = bp->bio_pblkno + (bp->bio_bcount / sz);
@@ -629,6 +674,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
 	/* Set erase start position. */
 	memset(&req, 0, sizeof(req));
 	memset(&cmd, 0, sizeof(cmd));
+	cmd.mrq = &req;
 	req.cmd = &cmd;
 	if (mmc_get_card_type(dev) == mode_sd)
 		cmd.opcode = SD_ERASE_WR_BLK_START;
@@ -638,8 +684,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
 	if (!mmc_get_high_cap(dev))
 		cmd.arg <<= 9;
 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-	MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
-	    &req);
+	MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
 	if (req.cmd->error != MMC_ERR_NONE) {
 	    printf("erase err1: %d\n", req.cmd->error);
 	    return (block);
@@ -657,8 +702,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
 		cmd.arg <<= 9;
 	cmd.arg--;
 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-	MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
-	    &req);
+	MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
 	if (req.cmd->error != MMC_ERR_NONE) {
 	    printf("erase err2: %d\n", req.cmd->error);
 	    return (block);
@@ -670,8 +714,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
 	cmd.opcode = MMC_ERASE;
 	cmd.arg = 0;
 	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
-	MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev,
-	    &req);
+	MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
 	if (req.cmd->error != MMC_ERR_NONE) {
 	    printf("erase err3 %d\n", req.cmd->error);
 	    return (block);
@@ -696,21 +739,22 @@ mmcsd_dump(void *arg, void *virtual, vm_offset_t physical,
 	device_t dev = sc->dev;
 	struct bio bp;
 	daddr_t block, end;
+	device_t mmcbr = device_get_parent(dev);
 
 	/* length zero is special and really means flush buffers to media */
 	if (!length)
 		return (0);
 
-	bzero(&bp, sizeof(struct bio));
+	g_reset_bio(&bp);
 	bp.bio_disk = disk;
 	bp.bio_pblkno = offset / disk->d_sectorsize;
 	bp.bio_bcount = length;
 	bp.bio_data = virtual;
 	bp.bio_cmd = BIO_WRITE;
 	end = bp.bio_pblkno + bp.bio_bcount / sc->disk->d_sectorsize;
-	MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev);
+	MMCBUS_ACQUIRE_BUS(mmcbr, dev);
 	block = mmcsd_rw(sc, &bp);
-	MMCBUS_RELEASE_BUS(device_get_parent(dev), dev);
+	MMCBUS_RELEASE_BUS(mmcbr, dev);
 	return ((end < block) ? EIO : 0);
 }
 
@@ -721,9 +765,9 @@ mmcsd_task(void *arg)
 	struct bio *bp;
 	int sz;
 	daddr_t block, end;
-	device_t dev;
+	device_t dev = sc->dev;
+	device_t mmcbr = device_get_parent(sc->dev);
 
-	dev = sc->dev;
 	while (1) {
 		MMCSD_LOCK(sc);
 		do {
@@ -741,7 +785,7 @@ mmcsd_task(void *arg)
 			biodone(bp);
 			continue;
 		}
-		MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev);
+		MMCBUS_ACQUIRE_BUS(mmcbr, dev);
 		sz = sc->disk->d_sectorsize;
 		block = bp->bio_pblkno;
 		end = bp->bio_pblkno + (bp->bio_bcount / sz);
@@ -753,7 +797,7 @@ mmcsd_task(void *arg)
 		} else if (bp->bio_cmd == BIO_DELETE) {
 			block = mmcsd_delete(sc, bp);
 		}
-		MMCBUS_RELEASE_BUS(device_get_parent(dev), dev);
+		MMCBUS_RELEASE_BUS(mmcbr, dev);
 		if (block < end) {
 			bp->bio_error = EIO;
 			bp->bio_resid = (end - block) * sz;
diff --git a/freebsd/sys/dev/mmc/mmcvar.h b/freebsd/sys/dev/mmc/mmcvar.h
index 99b8a6a..c7a4af9 100644
--- a/freebsd/sys/dev/mmc/mmcvar.h
+++ b/freebsd/sys/dev/mmc/mmcvar.h
@@ -69,25 +69,18 @@ enum mmc_device_ivars {
     MMC_IVAR_BUS_WIDTH,
     MMC_IVAR_ERASE_SECTOR,
     MMC_IVAR_MAX_DATA,
-    MMC_IVAR_CARD_ID_STRING
+    MMC_IVAR_CARD_ID_STRING,
+    MMC_IVAR_CARD_SN_STRING,
 };
 
 /*
- * Simplified accessors for pci devices
+ * Simplified accessors for mmc devices
  */
 #define MMC_ACCESSOR(var, ivar, type)					\
 	__BUS_ACCESSOR(mmc, var, MMC, ivar, type)
 
 MMC_ACCESSOR(dsr_imp, DSR_IMP, int)
-#ifndef __rtems__
-MMC_ACCESSOR(media_size, MEDIA_SIZE, off_t)
-#else /* __rtems__ */
-/*
- * The instance variable value storage is limited by the uintptr_t type.  Since
- * off_t has more bits than uintptr_t on most RTEMS targets, we need this hack.
- */
-MMC_ACCESSOR(media_size, MEDIA_SIZE, uintptr_t)
-#endif /* __rtems__ */
+MMC_ACCESSOR(media_size, MEDIA_SIZE, long)
 MMC_ACCESSOR(rca, RCA, int)
 MMC_ACCESSOR(sector_size, SECTOR_SIZE, int)
 MMC_ACCESSOR(tran_speed, TRAN_SPEED, int)
@@ -98,5 +91,6 @@ MMC_ACCESSOR(bus_width, BUS_WIDTH, int)
 MMC_ACCESSOR(erase_sector, ERASE_SECTOR, int)
 MMC_ACCESSOR(max_data, MAX_DATA, int)
 MMC_ACCESSOR(card_id_string, CARD_ID_STRING, const char *)
+MMC_ACCESSOR(card_sn_string, CARD_SN_STRING, const char *)
 
 #endif /* DEV_MMC_MMCVAR_H */
diff --git a/libbsd.txt b/libbsd.txt
index 6b9e2a9..8af302f 100644
--- a/libbsd.txt
+++ b/libbsd.txt
@@ -766,6 +766,7 @@ detail and debug level information from the command.
 == FreeBSD version of imported files and directories
 
 . sys/dev/dwc/*, trunk, 2015-03-26, cfc3df2b8f708ce8494d9d556e3472a5c8c21b8a
+. sys/dev/mmc/*, trunk, 2016-08-23, 9fe7c416e6abb28b1398fd3e5687099846800cfd
 . sys/dev/usb/*, trunk, 2015-10-30, 968dafb4fcf133cb8beb6fa3c558fecd7dc00ef0
 . *, stable/9, 2015-04-08, 99a648a912e81e29d9c4c159cbbe263462f2d719
 
diff --git a/rtemsbsd/include/geom/geom.h b/rtemsbsd/include/geom/geom.h
new file mode 100644
index 0000000..e69de29




More information about the vc mailing list