svn commit: r320844 - in head: etc/mtree include lib/libcam sys/amd64/conf sys/arm/broadcom/bcm2835 sys/arm/conf sys/arm/ti sys/cam sys/cam/mmc sys/cam/scsi sys/conf sys/dev/mmc sys/dev/sdhci sys/m...

Warner Losh imp at FreeBSD.org
Sun Jul 9 16:57:27 UTC 2017


Author: imp
Date: Sun Jul  9 16:57:24 2017
New Revision: 320844
URL: https://svnweb.freebsd.org/changeset/base/320844

Log:
  An MMC/SD/SDIO stack using CAM
  
  Implement the MMC/SD/SDIO protocol within a CAM framework. CAM's
  flexible queueing will make it easier to write non-storage drivers
  than the legacy stack. SDIO drivers from both the kernel and as
  userland daemons are possible, though much of that functionality will
  come later.
  
  Some of the CAM integration isn't complete (there are sleeps in the
  device probe state machine, for example), but those minor issues can
  be improved in-tree more easily than out of tree and shouldn't gate
  progress on other fronts. Appologies to reviews if specific items
  have been overlooked.
  
  Submitted by: Ilya Bakulin
  Reviewed by: emaste, imp, mav, adrian, ian
  Differential Review: https://reviews.freebsd.org/D4761
  
  merge with first commit, various compile hacks.

Added:
  head/sys/amd64/conf/MMCCAM   (contents, props changed)
  head/sys/arm/conf/BEAGLEBONE-MMCCAM   (contents, props changed)
  head/sys/cam/mmc/
  head/sys/cam/mmc/mmc.h
     - copied, changed from r320843, head/sys/dev/mmc/mmcbrvar.h
  head/sys/cam/mmc/mmc_all.h
     - copied, changed from r320843, head/sys/dev/mmc/mmcbrvar.h
  head/sys/cam/mmc/mmc_bus.h   (contents, props changed)
  head/sys/cam/mmc/mmc_da.c   (contents, props changed)
  head/sys/cam/mmc/mmc_sdio.c   (contents, props changed)
  head/sys/cam/mmc/mmc_sdio.h
     - copied, changed from r320843, head/sys/dev/mmc/mmcbrvar.h
  head/sys/cam/mmc/mmc_xpt.c   (contents, props changed)
Modified:
  head/etc/mtree/BSD.include.dist
  head/include/Makefile
  head/lib/libcam/Makefile
  head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
  head/sys/arm/ti/ti_sdhci.c
  head/sys/cam/cam_ccb.h
  head/sys/cam/cam_periph.c
  head/sys/cam/cam_xpt.c
  head/sys/cam/cam_xpt.h
  head/sys/cam/cam_xpt_internal.h
  head/sys/cam/scsi/scsi_pass.c
  head/sys/conf/files
  head/sys/conf/options
  head/sys/dev/mmc/bridge.h
  head/sys/dev/mmc/mmcbrvar.h
  head/sys/dev/mmc/mmcreg.h
  head/sys/dev/sdhci/fsl_sdhci.c
  head/sys/dev/sdhci/sdhci.c
  head/sys/dev/sdhci/sdhci.h
  head/sys/dev/sdhci/sdhci_acpi.c
  head/sys/dev/sdhci/sdhci_pci.c
  head/sys/modules/Makefile

Modified: head/etc/mtree/BSD.include.dist
==============================================================================
--- head/etc/mtree/BSD.include.dist	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/etc/mtree/BSD.include.dist	Sun Jul  9 16:57:24 2017	(r320844)
@@ -90,6 +90,8 @@
     cam
         ata
         ..
+        mmc
+        ..
         nvme
         ..
         scsi

Modified: head/include/Makefile
==============================================================================
--- head/include/Makefile	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/include/Makefile	Sun Jul  9 16:57:24 2017	(r320844)
@@ -42,7 +42,7 @@ LHDRS=	aio.h errno.h fcntl.h linker_set.h poll.h stdat
 LDIRS=	bsm cam geom net net80211 netgraph netinet netinet6 \
 	netipsec netsmb nfs nfsclient nfsserver sys vm
 
-LSUBDIRS=	cam/ata cam/nvme cam/scsi \
+LSUBDIRS=	cam/ata cam/mmc cam/nvme cam/scsi \
 	dev/acpica dev/agp dev/an dev/bktr dev/ciss dev/filemon dev/firewire \
 	dev/hwpmc dev/hyperv \
 	dev/ic dev/iicbus dev/io dev/lmc dev/mfi dev/mmc dev/nvme \

Modified: head/lib/libcam/Makefile
==============================================================================
--- head/lib/libcam/Makefile	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/lib/libcam/Makefile	Sun Jul  9 16:57:24 2017	(r320844)
@@ -38,6 +38,7 @@ MLINKS+=	cam.3 cam_open_device.3 \
 
 .PATH:		${SRCTOP}/sys/cam \
 		${SRCTOP}/sys/cam/ata \
+		${SRCTOP}/sys/cam/mmc \
 		${SRCTOP}/sys/cam/scsi
 
 CFLAGS+=	-I${.CURDIR} -I${SRCTOP}/sys

Added: head/sys/amd64/conf/MMCCAM
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/amd64/conf/MMCCAM	Sun Jul  9 16:57:24 2017	(r320844)
@@ -0,0 +1,36 @@
+# MMCCAM is the kernel config for doing MMC on CAM development
+# and testing on bhyve
+# $FreeBSD$
+
+include         MINIMAL
+
+ident		MMCCAM
+
+# Access GPT-formatted and labeled root volume
+options         GEOM_PART_GPT
+options         GEOM_LABEL
+
+# UART -- for bhyve console
+device          uart
+
+# kgdb stub
+device          bvmdebug
+
+# VirtIO support, needed for bhyve
+device		virtio			# Generic VirtIO bus (required)
+device		virtio_pci		# VirtIO PCI device
+device		vtnet			# VirtIO Ethernet device
+device		virtio_blk		# VirtIO Block device
+device		virtio_scsi		# VirtIO SCSI device
+device		virtio_balloon		# VirtIO Memory Balloon device
+
+# CAM-specific stuff
+device		pass
+device		scbus
+device		da
+device		mmccam
+
+options	MMCCAM
+# Add CAMDEBUG stuff
+options CAMDEBUG
+options CAM_DEBUG_FLAGS=(CAM_DEBUG_INFO|CAM_DEBUG_PROBE|CAM_DEBUG_PERIPH|CAM_DEBUG_TRACE)

Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c	Sun Jul  9 16:57:24 2017	(r320844)
@@ -52,6 +52,8 @@ __FBSDID("$FreeBSD$");
 #include "mmcbr_if.h"
 #include "sdhci_if.h"
 
+#include "opt_mmccam.h"
+
 #include "bcm2835_dma.h"
 #include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
 #include "bcm2835_vcbus.h"
@@ -253,7 +255,11 @@ bcm_sdhci_attach(device_t dev)
 	bus_generic_probe(dev);
 	bus_generic_attach(dev);
 
+#ifdef MMCCAM
+	sdhci_cam_start_slot(&sc->sc_slot);
+#else
 	sdhci_start_slot(&sc->sc_slot);
+#endif
 
 	return (0);
 

Added: head/sys/arm/conf/BEAGLEBONE-MMCCAM
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/conf/BEAGLEBONE-MMCCAM	Sun Jul  9 16:57:24 2017	(r320844)
@@ -0,0 +1,21 @@
+#
+# BEAGLEBONE-MMCCAM
+#
+# Custom kernel for Beaglebone plus MMCCAM as opposed to the prior MMC stack. It is
+# present to keep it building in tree since it wouldn't work in LINT.
+#
+# $FreeBSD$
+
+include		BEAGLEBONE
+
+# Add CAMDEBUG stuff
+options 	CAMDEBUG
+options 	CAM_DEBUG_FLAGS=(CAM_DEBUG_INFO|CAM_DEBUG_PROBE|CAM_DEBUG_PERIPH|CAM_DEBUG_TRACE)
+
+# pass(4) device
+device		pass
+device		mmccam
+options		MMCCAM
+
+nodevice	mmc
+nodevice	mmcsd

Modified: head/sys/arm/ti/ti_sdhci.c
==============================================================================
--- head/sys/arm/ti/ti_sdhci.c	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/sys/arm/ti/ti_sdhci.c	Sun Jul  9 16:57:24 2017	(r320844)
@@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/rman.h>
 #include <sys/sysctl.h>
 #include <sys/taskqueue.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
@@ -60,6 +62,8 @@ __FBSDID("$FreeBSD$");
 #include <arm/ti/ti_hwmods.h>
 #include "gpio_if.h"
 
+#include "opt_mmccam.h"
+
 struct ti_sdhci_softc {
 	device_t		dev;
 	struct sdhci_fdt_gpio * gpio;
@@ -122,6 +126,11 @@ static struct ofw_compat_data compat_data[] = {
 #define	  MMCHS_SD_CAPA_VS30		  (1 << 25)
 #define	  MMCHS_SD_CAPA_VS33		  (1 << 24)
 
+/* Forward declarations, CAM-relataed */
+// static void ti_sdhci_cam_poll(struct cam_sim *);
+// static void ti_sdhci_cam_action(struct cam_sim *, union ccb *);
+// static int ti_sdhci_cam_settran_settings(struct ti_sdhci_softc *sc, union ccb *);
+
 static inline uint32_t
 ti_mmchs_read_4(struct ti_sdhci_softc *sc, bus_size_t off)
 {
@@ -241,6 +250,22 @@ ti_sdhci_write_1(device_t dev, struct sdhci_slot *slot
 	struct ti_sdhci_softc *sc = device_get_softc(dev);
 	uint32_t val32;
 
+#ifdef MMCCAM
+	uint32_t newval32;
+	if (off == SDHCI_HOST_CONTROL) {
+		val32 = ti_mmchs_read_4(sc, MMCHS_CON);
+		newval32  = val32;
+		if (val & SDHCI_CTRL_8BITBUS) {
+			device_printf(dev, "Custom-enabling 8-bit bus\n");
+			newval32 |= MMCHS_CON_DW8;
+		} else {
+			device_printf(dev, "Custom-disabling 8-bit bus\n");
+			newval32 &= ~MMCHS_CON_DW8;
+		}
+		if (newval32 != val32)
+			ti_mmchs_write_4(sc, MMCHS_CON, newval32);
+	}
+#endif
 	val32 = RD4(sc, off & ~3);
 	val32 &= ~(0xff << (off & 3) * 8);
 	val32 |= (val << (off & 3) * 8);
@@ -658,8 +683,11 @@ ti_sdhci_attach(device_t dev)
 	bus_generic_probe(dev);
 	bus_generic_attach(dev);
 
+#ifdef MMCCAM
+	sdhci_cam_start_slot(&sc->slot);
+#else
 	sdhci_start_slot(&sc->slot);
-
+#endif
 	return (0);
 
 fail:
@@ -730,4 +758,7 @@ static driver_t ti_sdhci_driver = {
 DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, NULL,
     NULL);
 MODULE_DEPEND(sdhci_ti, sdhci, 1, 1, 1);
+
+#ifndef MMCCAM
 MMC_DECLARE_BRIDGE(sdhci_ti);
+#endif

Modified: head/sys/cam/cam_ccb.h
==============================================================================
--- head/sys/cam/cam_ccb.h	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/sys/cam/cam_ccb.h	Sun Jul  9 16:57:24 2017	(r320844)
@@ -42,6 +42,7 @@
 #include <cam/scsi/scsi_all.h>
 #include <cam/ata/ata_all.h>
 #include <cam/nvme/nvme_all.h>
+#include <cam/mmc/mmc_all.h>
 
 /* General allocation length definitions for CCB structures */
 #define	IOCDBLEN	CAM_MAX_CDBLEN	/* Space for CDB bytes/pointer */
@@ -208,10 +209,10 @@ typedef enum {
 	XPT_NVME_IO		= 0x1c | XPT_FC_DEV_QUEUED,
 				/* Execiute the requestred NVMe I/O operation */
 
-	XPT_MMCSD_IO		= 0x1d | XPT_FC_DEV_QUEUED,
+	XPT_MMC_IO		= 0x1d | XPT_FC_DEV_QUEUED,
 				/* Placeholder for MMC / SD / SDIO I/O stuff */
 
-	XPT_SCAN_TGT		= 0x1E | XPT_FC_QUEUED | XPT_FC_USER_CCB
+	XPT_SCAN_TGT		= 0x1e | XPT_FC_QUEUED | XPT_FC_USER_CCB
 				       | XPT_FC_XPT_ONLY,
 				/* Scan Target */
 
@@ -267,6 +268,7 @@ typedef enum {
 	PROTO_SATAPM,	/* SATA Port Multiplier */
 	PROTO_SEMB,	/* SATA Enclosure Management Bridge */
 	PROTO_NVME,	/* NVME */
+	PROTO_MMCSD,	/* MMC, SD, SDIO */
 } cam_proto;
 
 typedef enum {
@@ -283,6 +285,7 @@ typedef enum {
 	XPORT_ISCSI,	/* iSCSI */
 	XPORT_SRP,	/* SCSI RDMA Protocol */
 	XPORT_NVME,	/* NVMe over PCIe */
+	XPORT_MMCSD,	/* MMC, SD, SDIO card */
 } cam_xport;
 
 #define XPORT_IS_NVME(t)	((t) == XPORT_NVME)
@@ -498,6 +501,7 @@ struct device_match_result {
 	cam_proto			protocol;
 	struct scsi_inquiry_data	inq_data;
 	struct ata_params		ident_data;
+        struct mmc_params               mmc_ident_data;
 	dev_result_flags		flags;
 };
 
@@ -773,6 +777,16 @@ struct ccb_ataio {
 	uint32_t   unused;
 };
 
+/*
+ * MMC I/O Request CCB used for the XPT_MMC_IO function code.
+ */
+struct ccb_mmcio {
+	struct	   ccb_hdr ccb_h;
+	union	   ccb *next_ccb;	/* Ptr for next CCB for action */
+	struct mmc_command cmd;
+        struct mmc_command stop;
+};
+
 struct ccb_accept_tio {
 	struct	   ccb_hdr ccb_h;
 	cdb_t	   cdb_io;		/* Union for CDB bytes/pointer */
@@ -1005,7 +1019,28 @@ struct ccb_trans_settings_nvme 
 	u_int		max_xfer;	/* Max transfer size (0 -> unlimited */
 	u_int		caps;
 };
-	
+
+#include <cam/mmc/mmc_bus.h>
+struct ccb_trans_settings_mmc {
+	struct mmc_ios ios;
+#define MMC_CLK		(1 << 1)
+#define MMC_VDD		(1 << 2)
+#define MMC_CS		(1 << 3)
+#define MMC_BW		(1 << 4)
+#define MMC_PM		(1 << 5)
+#define MMC_BT		(1 << 6)
+#define MMC_BM		(1 << 7)
+	uint32_t ios_valid;
+/* The folowing is used only for GET_TRAN_SETTINGS */
+	uint32_t	host_ocr;
+	int host_f_min;
+	int host_f_max;
+#define MMC_CAP_4_BIT_DATA	(1 << 0) /* Can do 4-bit data transfers */
+#define MMC_CAP_8_BIT_DATA	(1 << 1) /* Can do 8-bit data transfers */
+#define MMC_CAP_HSPEED		(1 << 2) /* Can do High Speed transfers */
+	uint32_t host_caps;
+};
+
 /* Get/Set transfer rate/width/disconnection/tag queueing settings */
 struct ccb_trans_settings {
 	struct	  ccb_hdr ccb_h;
@@ -1019,6 +1054,7 @@ struct ccb_trans_settings {
 		struct ccb_trans_settings_ata ata;
 		struct ccb_trans_settings_scsi scsi;
 		struct ccb_trans_settings_nvme nvme;
+		struct ccb_trans_settings_mmc mmc;
 	} proto_specific;
 	union {
 		u_int  valid;	/* Which fields to honor */
@@ -1284,6 +1320,7 @@ union ccb {
 	struct	ccb_dev_advinfo		cdai;
 	struct	ccb_async		casync;
 	struct	ccb_nvmeio		nvmeio;
+	struct	ccb_mmcio		mmcio;
 };
 
 #define CCB_CLEAR_ALL_EXCEPT_HDR(ccbp)			\
@@ -1327,6 +1364,13 @@ cam_fill_smpio(struct ccb_smpio *smpio, uint32_t retri
 	       uint32_t timeout);
 
 static __inline void
+cam_fill_mmcio(struct ccb_mmcio *mmcio, uint32_t retries,
+	       void (*cbfcnp)(struct cam_periph *, union ccb *), uint32_t flags,
+               uint32_t mmc_opcode, uint32_t mmc_arg, uint32_t mmc_flags,
+	       struct mmc_data *mmc_d,
+	       uint32_t timeout);
+
+static __inline void
 cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries,
 	      void (*cbfcnp)(struct cam_periph *, union ccb *),
 	      u_int32_t flags, u_int8_t tag_action,
@@ -1412,6 +1456,34 @@ cam_fill_smpio(struct ccb_smpio *smpio, uint32_t retri
 	smpio->smp_request_len = smp_request_len;
 	smpio->smp_response = smp_response;
 	smpio->smp_response_len = smp_response_len;
+}
+
+static __inline void
+cam_fill_mmcio(struct ccb_mmcio *mmcio, uint32_t retries,
+	       void (*cbfcnp)(struct cam_periph *, union ccb *), uint32_t flags,
+	       uint32_t mmc_opcode, uint32_t mmc_arg, uint32_t mmc_flags,
+	       struct mmc_data *mmc_d,
+	       uint32_t timeout)
+{
+	mmcio->ccb_h.func_code = XPT_MMC_IO;
+	mmcio->ccb_h.flags = flags;
+	mmcio->ccb_h.retry_count = retries;
+	mmcio->ccb_h.cbfcnp = cbfcnp;
+	mmcio->ccb_h.timeout = timeout;
+	mmcio->cmd.opcode = mmc_opcode;
+	mmcio->cmd.arg = mmc_arg;
+	mmcio->cmd.flags = mmc_flags;
+	mmcio->stop.opcode = 0;
+	mmcio->stop.arg = 0;
+	mmcio->stop.flags = 0;
+	if (mmc_d != NULL) {
+		mmcio->cmd.data = mmc_d;
+	} else
+		mmcio->cmd.data = NULL;
+	mmcio->cmd.resp[0] = 0;
+	mmcio->cmd.resp[1] = 0;
+	mmcio->cmd.resp[2] = 0;
+	mmcio->cmd.resp[3] = 0;
 }
 
 static __inline void

Modified: head/sys/cam/cam_periph.c
==============================================================================
--- head/sys/cam/cam_periph.c	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/sys/cam/cam_periph.c	Sun Jul  9 16:57:24 2017	(r320844)
@@ -827,6 +827,18 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_ma
 		dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
 		numbufs = 1;
 		break;
+	case XPT_MMC_IO:
+		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
+			return(0);
+		/* Two mappings: one for cmd->data and one for cmd->data->data */
+		data_ptrs[0] = (unsigned char **)&ccb->mmcio.cmd.data;
+		lengths[0] = sizeof(struct mmc_data *);
+		dirs[0] = ccb->ccb_h.flags & CAM_DIR_MASK;
+		data_ptrs[1] = (unsigned char **)&ccb->mmcio.cmd.data->data;
+		lengths[1] = ccb->mmcio.cmd.data->len;
+		dirs[1] = ccb->ccb_h.flags & CAM_DIR_MASK;
+		numbufs = 2;
+		break;
 	case XPT_SMP_IO:
 		data_ptrs[0] = &ccb->smpio.smp_request;
 		lengths[0] = ccb->smpio.smp_request_len;

Modified: head/sys/cam/cam_xpt.c
==============================================================================
--- head/sys/cam/cam_xpt.c	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/sys/cam/cam_xpt.c	Sun Jul  9 16:57:24 2017	(r320844)
@@ -329,7 +329,6 @@ static xpt_devicefunc_t	xptsetasyncfunc;
 static xpt_busfunc_t	xptsetasyncbusfunc;
 static cam_status	xptregister(struct cam_periph *periph,
 				    void *arg);
-static const char *	xpt_action_name(uint32_t action);
 static __inline int device_is_queued(struct cam_ed *device);
 
 static __inline int
@@ -412,7 +411,7 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, i
 	}
 	return (error);
 }
-	
+
 static int
 xptdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
 {
@@ -820,6 +819,8 @@ xpt_scanner_thread(void *dummy)
 			TAILQ_REMOVE(&xsoftc.ccb_scanq, &ccb->ccb_h, sim_links.tqe);
 			xpt_unlock_buses();
 
+                        printf("xpt_scanner_thread is firing on path ");
+                        xpt_print_path(ccb->ccb_h.path);printf("\n");
 			/*
 			 * Since lock can be dropped inside and path freed
 			 * by completion callback even before return here,
@@ -1503,7 +1504,7 @@ xptdevicematch(struct dev_match_pattern *patterns, u_i
 
 		cur_pattern = &patterns[i].pattern.device_pattern;
 
-		/* Error out if mutually exclusive options are specified. */ 
+		/* Error out if mutually exclusive options are specified. */
 		if ((cur_pattern->flags & (DEV_MATCH_INQUIRY|DEV_MATCH_DEVID))
 		 == (DEV_MATCH_INQUIRY|DEV_MATCH_DEVID))
 			return(DM_RET_ERROR);
@@ -1905,6 +1906,9 @@ xptedtdevicefunc(struct cam_ed *device, void *arg)
 		bcopy(&device->ident_data,
 		      &cdm->matches[j].result.device_result.ident_data,
 		      sizeof(struct ata_params));
+		bcopy(&device->mmc_ident_data,
+		      &cdm->matches[j].result.device_result.mmc_ident_data,
+		      sizeof(struct mmc_params));
 
 		/* Let the user know whether this device is unconfigured */
 		if (device->flags & CAM_DEV_UNCONFIGURED)
@@ -2690,6 +2694,8 @@ xpt_action_default(union ccb *start_ccb)
 		if (start_ccb->ccb_h.func_code == XPT_NVME_IO)
 			start_ccb->nvmeio.resid = 0;
 		/* FALLTHROUGH */
+	case XPT_MMC_IO:
+		/* XXX just like nmve_io? */
 	case XPT_RESET_DEV:
 	case XPT_ENG_EXEC:
 	case XPT_SMP_IO:
@@ -2801,11 +2807,12 @@ call_sim:
 			mtx_lock(mtx);
 		else
 			mtx = NULL;
+
 		CAM_DEBUG(path, CAM_DEBUG_TRACE,
-		    ("sim->sim_action: func=%#x\n", start_ccb->ccb_h.func_code));
+		    ("Calling sim->sim_action(): func=%#x\n", start_ccb->ccb_h.func_code));
 		(*(sim->sim_action))(sim, start_ccb);
 		CAM_DEBUG(path, CAM_DEBUG_TRACE,
-		    ("sim->sim_action: status=%#x\n", start_ccb->ccb_h.status));
+		    ("sim->sim_action returned: status=%#x\n", start_ccb->ccb_h.status));
 		if (mtx)
 			mtx_unlock(mtx);
 		break;
@@ -5540,7 +5547,7 @@ static struct kv map[] = {
 	{ XPT_GET_SIM_KNOB, "XPT_GET_SIM_KNOB" },
 	{ XPT_SET_SIM_KNOB, "XPT_SET_SIM_KNOB" },
 	{ XPT_NVME_IO, "XPT_NVME_IO" },
-	{ XPT_MMCSD_IO, "XPT_MMCSD_IO" },
+	{ XPT_MMC_IO, "XPT_MMC_IO" },
 	{ XPT_SMP_IO, "XPT_SMP_IO" },
 	{ XPT_SCAN_TGT, "XPT_SCAN_TGT" },
 	{ XPT_ENG_INQ, "XPT_ENG_INQ" },
@@ -5556,7 +5563,7 @@ static struct kv map[] = {
 	{ 0, 0 }
 };
 
-static const char *
+const char *
 xpt_action_name(uint32_t action) 
 {
 	static char buffer[32];	/* Only for unknown messages -- racy */

Modified: head/sys/cam/cam_xpt.h
==============================================================================
--- head/sys/cam/cam_xpt.h	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/sys/cam/cam_xpt.h	Sun Jul  9 16:57:24 2017	(r320844)
@@ -141,6 +141,8 @@ void			xpt_copy_path(struct cam_path *new_path,
 
 void			xpt_release_path(struct cam_path *path);
 
+const char *		xpt_action_name(uint32_t action);
+
 #endif /* _KERNEL */
 
 #endif /* _CAM_CAM_XPT_H */

Modified: head/sys/cam/cam_xpt_internal.h
==============================================================================
--- head/sys/cam/cam_xpt_internal.h	Sun Jul  9 15:41:49 2017	(r320843)
+++ head/sys/cam/cam_xpt_internal.h	Sun Jul  9 16:57:24 2017	(r320844)
@@ -125,6 +125,7 @@ struct cam_ed {
 	uint32_t	 rcap_len;
 	uint8_t		 *rcap_buf;
 	struct		 ata_params ident_data;
+        struct		 mmc_params mmc_ident_data;
 	u_int8_t	 inq_flags;	/*
 					 * Current settings for inquiry flags.
 					 * This allows us to override settings

Copied and modified: head/sys/cam/mmc/mmc.h (from r320843, head/sys/dev/mmc/mmcbrvar.h)
==============================================================================
--- head/sys/dev/mmc/mmcbrvar.h	Sun Jul  9 15:41:49 2017	(r320843, copy source)
+++ head/sys/cam/mmc/mmc.h	Sun Jul  9 16:57:24 2017	(r320844)
@@ -1,6 +1,5 @@
 /*-
- * Copyright (c) 2006 Bernd Walter.  All rights reserved.
- * Copyright (c) 2006 M. Warner Losh.  All rights reserved.
+ * Copyright (c) 2014-2016 Ilya Bakulin.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -49,77 +48,47 @@
  * or the SD Card Association to disclose or distribute any technical
  * information, know-how or other confidential information to any third party.
  *
+ * Inspired coded in sys/dev/mmc. Thanks to Warner Losh <imp at FreeBSD.org>,
+ * Bernd Walter <tisco at FreeBSD.org>, and other authors.
+ *
  * $FreeBSD$
  */
 
-#ifndef DEV_MMC_MMCBRVAR_H
-#define	DEV_MMC_MMCBRVAR_H
+#ifndef CAM_MMC_H
+#define CAM_MMC_H
 
 #include <dev/mmc/mmcreg.h>
-
-#include "mmcbr_if.h"
-
-enum mmcbr_device_ivars {
-    MMCBR_IVAR_BUS_MODE,
-    MMCBR_IVAR_BUS_WIDTH,
-    MMCBR_IVAR_CHIP_SELECT,
-    MMCBR_IVAR_CLOCK,
-    MMCBR_IVAR_F_MIN,
-    MMCBR_IVAR_F_MAX,
-    MMCBR_IVAR_HOST_OCR,
-    MMCBR_IVAR_MODE,
-    MMCBR_IVAR_OCR,
-    MMCBR_IVAR_POWER_MODE,
-    MMCBR_IVAR_VDD,
-    MMCBR_IVAR_VCCQ,
-    MMCBR_IVAR_CAPS,
-    MMCBR_IVAR_TIMING,
-    MMCBR_IVAR_MAX_DATA,
-    MMCBR_IVAR_MAX_BUSY_TIMEOUT
-};
-
 /*
- * Simplified accessors for bridge devices
+ * This structure describes an MMC/SD card
  */
-#define	MMCBR_ACCESSOR(var, ivar, type)					\
-	__BUS_ACCESSOR(mmcbr, var, MMCBR, ivar, type)
+struct mmc_params {
+        u_int8_t	model[40]; /* Card model */
 
-MMCBR_ACCESSOR(bus_mode, BUS_MODE, int)
-MMCBR_ACCESSOR(bus_width, BUS_WIDTH, int)
-MMCBR_ACCESSOR(chip_select, CHIP_SELECT, int)
-MMCBR_ACCESSOR(clock, CLOCK, int)
-MMCBR_ACCESSOR(f_max, F_MAX, int)
-MMCBR_ACCESSOR(f_min, F_MIN, int)
-MMCBR_ACCESSOR(host_ocr, HOST_OCR, int)
-MMCBR_ACCESSOR(mode, MODE, int)
-MMCBR_ACCESSOR(ocr, OCR, int)
-MMCBR_ACCESSOR(power_mode, POWER_MODE, int)
-MMCBR_ACCESSOR(vdd, VDD, int)
-MMCBR_ACCESSOR(vccq, VCCQ, int)
-MMCBR_ACCESSOR(caps, CAPS, int)
-MMCBR_ACCESSOR(timing, TIMING, int)
-MMCBR_ACCESSOR(max_data, MAX_DATA, int)
-MMCBR_ACCESSOR(max_busy_timeout, MAX_BUSY_TIMEOUT, u_int)
+        /* Card OCR */
+        uint32_t card_ocr;
 
-static int __inline
-mmcbr_update_ios(device_t dev)
-{
+        /* OCR of the IO portion of the card */
+        uint32_t io_ocr;
 
-	return (MMCBR_UPDATE_IOS(device_get_parent(dev), dev));
-}
+        /* Card CID -- raw and parsed */
+        uint32_t card_cid[4];
+        struct mmc_cid  cid;
 
-static int __inline
-mmcbr_switch_vccq(device_t dev)
-{
+        /* Card CSD -- raw */
+        uint32_t card_csd[4];
 
-	return (MMCBR_SWITCH_VCCQ(device_get_parent(dev), dev));
-}
+        /* Card RCA */
+        uint16_t card_rca;
 
-static int __inline
-mmcbr_get_ro(device_t dev)
-{
+        /* What kind of card is it */
+        uint32_t card_features;
+#define CARD_FEATURE_MEMORY 0x1
+#define CARD_FEATURE_SDHC   0x1 << 1
+#define CARD_FEATURE_SDIO   0x1 << 2
+#define CARD_FEATURE_SD20   0x1 << 3
+#define CARD_FEATURE_MMC    0x1 << 4
 
-	return (MMCBR_GET_RO(device_get_parent(dev), dev));
-}
+        uint8_t sdio_func_count;
+} __packed;
 
-#endif /* DEV_MMC_MMCBRVAR_H */
+#endif

Copied and modified: head/sys/cam/mmc/mmc_all.h (from r320843, head/sys/dev/mmc/mmcbrvar.h)
==============================================================================
--- head/sys/dev/mmc/mmcbrvar.h	Sun Jul  9 15:41:49 2017	(r320843, copy source)
+++ head/sys/cam/mmc/mmc_all.h	Sun Jul  9 16:57:24 2017	(r320844)
@@ -1,6 +1,5 @@
 /*-
- * Copyright (c) 2006 Bernd Walter.  All rights reserved.
- * Copyright (c) 2006 M. Warner Losh.  All rights reserved.
+ * Copyright (c) 2014-2016 Ilya Bakulin.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -52,74 +51,20 @@
  * $FreeBSD$
  */
 
-#ifndef DEV_MMC_MMCBRVAR_H
-#define	DEV_MMC_MMCBRVAR_H
-
-#include <dev/mmc/mmcreg.h>
-
-#include "mmcbr_if.h"
-
-enum mmcbr_device_ivars {
-    MMCBR_IVAR_BUS_MODE,
-    MMCBR_IVAR_BUS_WIDTH,
-    MMCBR_IVAR_CHIP_SELECT,
-    MMCBR_IVAR_CLOCK,
-    MMCBR_IVAR_F_MIN,
-    MMCBR_IVAR_F_MAX,
-    MMCBR_IVAR_HOST_OCR,
-    MMCBR_IVAR_MODE,
-    MMCBR_IVAR_OCR,
-    MMCBR_IVAR_POWER_MODE,
-    MMCBR_IVAR_VDD,
-    MMCBR_IVAR_VCCQ,
-    MMCBR_IVAR_CAPS,
-    MMCBR_IVAR_TIMING,
-    MMCBR_IVAR_MAX_DATA,
-    MMCBR_IVAR_MAX_BUSY_TIMEOUT
-};
-
 /*
- * Simplified accessors for bridge devices
+ * MMC function that should be visible to the CAM subsystem
+ * and are somehow useful should be declared here
+ *
+ * Like in other *_all.h, it's also a nice place to include
+ * some other transport-specific headers.
  */
-#define	MMCBR_ACCESSOR(var, ivar, type)					\
-	__BUS_ACCESSOR(mmcbr, var, MMCBR, ivar, type)
 
-MMCBR_ACCESSOR(bus_mode, BUS_MODE, int)
-MMCBR_ACCESSOR(bus_width, BUS_WIDTH, int)
-MMCBR_ACCESSOR(chip_select, CHIP_SELECT, int)
-MMCBR_ACCESSOR(clock, CLOCK, int)
-MMCBR_ACCESSOR(f_max, F_MAX, int)
-MMCBR_ACCESSOR(f_min, F_MIN, int)
-MMCBR_ACCESSOR(host_ocr, HOST_OCR, int)
-MMCBR_ACCESSOR(mode, MODE, int)
-MMCBR_ACCESSOR(ocr, OCR, int)
-MMCBR_ACCESSOR(power_mode, POWER_MODE, int)
-MMCBR_ACCESSOR(vdd, VDD, int)
-MMCBR_ACCESSOR(vccq, VCCQ, int)
-MMCBR_ACCESSOR(caps, CAPS, int)
-MMCBR_ACCESSOR(timing, TIMING, int)
-MMCBR_ACCESSOR(max_data, MAX_DATA, int)
-MMCBR_ACCESSOR(max_busy_timeout, MAX_BUSY_TIMEOUT, u_int)
+#ifndef CAM_MMC_ALL_H
+#define CAM_MMC_ALL_H
 
-static int __inline
-mmcbr_update_ios(device_t dev)
-{
+#include <cam/mmc/mmc.h>
+#include <dev/mmc/mmcreg.h>
 
-	return (MMCBR_UPDATE_IOS(device_get_parent(dev), dev));
-}
+void	mmc_print_ident(struct mmc_params *ident_data);
 
-static int __inline
-mmcbr_switch_vccq(device_t dev)
-{
-
-	return (MMCBR_SWITCH_VCCQ(device_get_parent(dev), dev));
-}
-
-static int __inline
-mmcbr_get_ro(device_t dev)
-{
-
-	return (MMCBR_GET_RO(device_get_parent(dev), dev));
-}
-
-#endif /* DEV_MMC_MMCBRVAR_H */
+#endif

Added: head/sys/cam/mmc/mmc_bus.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/cam/mmc/mmc_bus.h	Sun Jul  9 16:57:24 2017	(r320844)
@@ -0,0 +1,5 @@
+/*
+ * This file is in the public domain.
+ * $FreeBSD$
+ */
+#include <dev/mmc/bridge.h>

Added: head/sys/cam/mmc/mmc_da.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/cam/mmc/mmc_da.c	Sun Jul  9 16:57:24 2017	(r320844)
@@ -0,0 +1,1432 @@
+/*-
+ * Copyright (c) 2006 Bernd Walter <tisco at FreeBSD.org>
+ * Copyright (c) 2006 M. Warner Losh <imp at FreeBSD.org>
+ * Copyright (c) 2009 Alexander Motin <mav at FreeBSD.org>
+ * Copyright (c) 2015-2017 Ilya Bakulin <kibab at FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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 ``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 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.
+ *
+ * Some code derived from the sys/dev/mmc and sys/cam/ata
+ * Thanks to Warner Losh <imp at FreeBSD.org>, Alexander Motin <mav at FreeBSD.org>
+ * Bernd Walter <tisco at FreeBSD.org>, and other authors.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+//#include "opt_sdda.h"
+
+#include <sys/param.h>
+
+#ifdef _KERNEL
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bio.h>
+#include <sys/endian.h>
+#include <sys/taskqueue.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/conf.h>
+#include <sys/devicestat.h>
+#include <sys/eventhandler.h>
+#include <sys/malloc.h>
+#include <sys/cons.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <geom/geom_disk.h>
+#include <machine/_inttypes.h>  /* for PRIu64 */
+#endif /* _KERNEL */
+
+#ifndef _KERNEL
+#include <stdio.h>
+#include <string.h>
+#endif /* _KERNEL */
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_queue.h>
+#include <cam/cam_periph.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt.h>
+#include <cam/cam_xpt_sim.h>
+#include <cam/cam_xpt_periph.h>
+#include <cam/cam_xpt_internal.h>
+#include <cam/cam_debug.h>
+
+
+#include <cam/mmc/mmc_all.h>
+
+#include <machine/md_var.h>	/* geometry translation */
+
+#ifdef _KERNEL
+
+typedef enum {
+	SDDA_FLAG_OPEN		= 0x0002,
+	SDDA_FLAG_DIRTY		= 0x0004
+} sdda_flags;
+
+typedef enum {
+        SDDA_STATE_INIT,
+        SDDA_STATE_INVALID,
+        SDDA_STATE_NORMAL
+} sdda_state;
+
+struct sdda_softc {
+	struct	 bio_queue_head bio_queue;
+	int	 outstanding_cmds;	/* Number of active commands */
+	int	 refcount;		/* Active xpt_action() calls */
+	sdda_state state;
+	sdda_flags flags;
+	struct mmc_data *mmcdata;
+//	sdda_quirks quirks;
+	struct task start_init_task;
+	struct	 disk *disk;
+        uint32_t raw_csd[4];
+	uint8_t raw_ext_csd[512]; /* MMC only? */
+        struct mmc_csd csd;
+        struct mmc_cid cid;
+	struct mmc_scr scr;
+        /* Calculated from CSD */
+        uint64_t sector_count;
+        uint64_t mediasize;
+
+        /* Calculated from CID */
+	char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */
+	char card_sn_string[16];/* Formatted serial # for disk->d_ident */
+	/* Determined from CSD + is highspeed card*/
+	uint32_t card_f_max;
+};
+
+#define ccb_bp		ppriv_ptr1
+
+static	disk_strategy_t	sddastrategy;
+static	periph_init_t	sddainit;
+static	void		sddaasync(void *callback_arg, u_int32_t code,
+				struct cam_path *path, void *arg);
+static	periph_ctor_t	sddaregister;
+static	periph_dtor_t	sddacleanup;
+static	periph_start_t	sddastart;
+static	periph_oninv_t	sddaoninvalidate;
+static	void		sddadone(struct cam_periph *periph,
+			       union ccb *done_ccb);
+static  int		sddaerror(union ccb *ccb, u_int32_t cam_flags,
+				u_int32_t sense_flags);
+
+static uint16_t get_rca(struct cam_periph *periph);
+static cam_status sdda_hook_into_geom(struct cam_periph *periph);
+static void sdda_start_init(void *context, union ccb *start_ccb);
+static void sdda_start_init_task(void *context, int pending);
+
+static struct periph_driver sddadriver =
+{
+	sddainit, "sdda",
+	TAILQ_HEAD_INITIALIZER(sddadriver.units), /* generation */ 0
+};
+
+PERIPHDRIVER_DECLARE(sdda, sddadriver);
+
+static MALLOC_DEFINE(M_SDDA, "sd_da", "sd_da buffers");
+
+static const int exp[8] = {
+	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
+};
+
+static const int mant[16] = {
+	0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
+};
+
+static const int cur_min[8] = {
+	500, 1000, 5000, 10000, 25000, 35000, 60000, 100000
+};
+
+static const int cur_max[8] = {
+	1000, 5000, 10000, 25000, 35000, 45000, 800000, 200000
+};
+
+static uint16_t
+get_rca(struct cam_periph *periph) {
+	return periph->path->device->mmc_ident_data.card_rca;
+}
+
+static uint32_t
+mmc_get_bits(uint32_t *bits, int bit_len, int start, int size)
+{
+	const int i = (bit_len / 32) - (start / 32) - 1;
+	const int shift = start & 31;
+	uint32_t retval = bits[i] >> shift;
+	if (size + shift > 32)
+		retval |= bits[i - 1] << (32 - shift);
+	return (retval & ((1llu << size) - 1));
+}
+
+
+static void
+mmc_decode_csd_sd(uint32_t *raw_csd, struct mmc_csd *csd)
+{
+	int v;
+	int m;
+	int e;
+
+	memset(csd, 0, sizeof(*csd));
+	csd->csd_structure = v = mmc_get_bits(raw_csd, 128, 126, 2);
+	if (v == 0) {
+		m = mmc_get_bits(raw_csd, 128, 115, 4);
+		e = mmc_get_bits(raw_csd, 128, 112, 3);
+		csd->tacc = (exp[e] * mant[m] + 9) / 10;
+		csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100;
+		m = mmc_get_bits(raw_csd, 128, 99, 4);
+		e = mmc_get_bits(raw_csd, 128, 96, 3);
+		csd->tran_speed = exp[e] * 10000 * mant[m];
+		csd->ccc = mmc_get_bits(raw_csd, 128, 84, 12);
+		csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 128, 80, 4);
+		csd->read_bl_partial = mmc_get_bits(raw_csd, 128, 79, 1);
+		csd->write_blk_misalign = mmc_get_bits(raw_csd, 128, 78, 1);
+		csd->read_blk_misalign = mmc_get_bits(raw_csd, 128, 77, 1);
+		csd->dsr_imp = mmc_get_bits(raw_csd, 128, 76, 1);
+		csd->vdd_r_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 59, 3)];
+		csd->vdd_r_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 56, 3)];
+		csd->vdd_w_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 53, 3)];
+		csd->vdd_w_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 50, 3)];
+		m = mmc_get_bits(raw_csd, 128, 62, 12);
+		e = mmc_get_bits(raw_csd, 128, 47, 3);
+		csd->capacity = ((1 + m) << (e + 2)) * csd->read_bl_len;
+		csd->erase_blk_en = mmc_get_bits(raw_csd, 128, 46, 1);
+		csd->erase_sector = mmc_get_bits(raw_csd, 128, 39, 7) + 1;
+		csd->wp_grp_size = mmc_get_bits(raw_csd, 128, 32, 7);
+		csd->wp_grp_enable = mmc_get_bits(raw_csd, 128, 31, 1);
+		csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 128, 26, 3);
+		csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 128, 22, 4);
+		csd->write_bl_partial = mmc_get_bits(raw_csd, 128, 21, 1);
+	} else if (v == 1) {
+		m = mmc_get_bits(raw_csd, 128, 115, 4);
+		e = mmc_get_bits(raw_csd, 128, 112, 3);
+		csd->tacc = (exp[e] * mant[m] + 9) / 10;
+		csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100;
+		m = mmc_get_bits(raw_csd, 128, 99, 4);
+		e = mmc_get_bits(raw_csd, 128, 96, 3);
+		csd->tran_speed = exp[e] * 10000 * mant[m];
+		csd->ccc = mmc_get_bits(raw_csd, 128, 84, 12);
+		csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 128, 80, 4);
+		csd->read_bl_partial = mmc_get_bits(raw_csd, 128, 79, 1);
+		csd->write_blk_misalign = mmc_get_bits(raw_csd, 128, 78, 1);
+		csd->read_blk_misalign = mmc_get_bits(raw_csd, 128, 77, 1);
+		csd->dsr_imp = mmc_get_bits(raw_csd, 128, 76, 1);
+		csd->capacity = ((uint64_t)mmc_get_bits(raw_csd, 128, 48, 22) + 1) *
+		    512 * 1024;
+		csd->erase_blk_en = mmc_get_bits(raw_csd, 128, 46, 1);
+		csd->erase_sector = mmc_get_bits(raw_csd, 128, 39, 7) + 1;
+		csd->wp_grp_size = mmc_get_bits(raw_csd, 128, 32, 7);
+		csd->wp_grp_enable = mmc_get_bits(raw_csd, 128, 31, 1);
+		csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 128, 26, 3);
+		csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 128, 22, 4);
+		csd->write_bl_partial = mmc_get_bits(raw_csd, 128, 21, 1);
+	} else
+		panic("unknown SD CSD version");
+}
+
+static void
+mmc_decode_csd_mmc(uint32_t *raw_csd, struct mmc_csd *csd)
+{
+	int m;
+	int e;
+
+	memset(csd, 0, sizeof(*csd));
+	csd->csd_structure = mmc_get_bits(raw_csd, 128, 126, 2);
+	csd->spec_vers = mmc_get_bits(raw_csd, 128, 122, 4);
+	m = mmc_get_bits(raw_csd, 128, 115, 4);
+	e = mmc_get_bits(raw_csd, 128, 112, 3);
+	csd->tacc = exp[e] * mant[m] + 9 / 10;
+	csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100;
+	m = mmc_get_bits(raw_csd, 128, 99, 4);
+	e = mmc_get_bits(raw_csd, 128, 96, 3);
+	csd->tran_speed = exp[e] * 10000 * mant[m];
+	csd->ccc = mmc_get_bits(raw_csd, 128, 84, 12);
+	csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 128, 80, 4);
+	csd->read_bl_partial = mmc_get_bits(raw_csd, 128, 79, 1);
+	csd->write_blk_misalign = mmc_get_bits(raw_csd, 128, 78, 1);
+	csd->read_blk_misalign = mmc_get_bits(raw_csd, 128, 77, 1);
+	csd->dsr_imp = mmc_get_bits(raw_csd, 128, 76, 1);
+	csd->vdd_r_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 59, 3)];
+	csd->vdd_r_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 56, 3)];
+	csd->vdd_w_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 53, 3)];
+	csd->vdd_w_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 50, 3)];
+	m = mmc_get_bits(raw_csd, 128, 62, 12);
+	e = mmc_get_bits(raw_csd, 128, 47, 3);
+	csd->capacity = ((1 + m) << (e + 2)) * csd->read_bl_len;
+	csd->erase_blk_en = 0;
+	csd->erase_sector = (mmc_get_bits(raw_csd, 128, 42, 5) + 1) *
+	    (mmc_get_bits(raw_csd, 128, 37, 5) + 1);
+	csd->wp_grp_size = mmc_get_bits(raw_csd, 128, 32, 5);
+	csd->wp_grp_enable = mmc_get_bits(raw_csd, 128, 31, 1);
+	csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 128, 26, 3);
+	csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 128, 22, 4);
+	csd->write_bl_partial = mmc_get_bits(raw_csd, 128, 21, 1);
+}
+
+static void
+mmc_decode_cid_sd(uint32_t *raw_cid, struct mmc_cid *cid)
+{
+	int i;
+
+	/* There's no version info, so we take it on faith */
+	memset(cid, 0, sizeof(*cid));

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


More information about the svn-src-all mailing list