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 <i...@freebsd.org>,
+ * Bernd Walter <ti...@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 <ti...@freebsd.org>
+ * Copyright (c) 2006 M. Warner Losh <i...@freebsd.org>
+ * Copyright (c) 2009 Alexander Motin <m...@freebsd.org>
+ * Copyright (c) 2015-2017 Ilya Bakulin <ki...@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 <i...@freebsd.org>, Alexander Motin <m...@freebsd.org>
+ * Bernd Walter <ti...@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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to