Skip to content

Commit

Permalink
An MMC/SD/SDIO stack using CAM
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bsdimp committed Jul 9, 2017
1 parent d2c5c68 commit a87c7a8
Show file tree
Hide file tree
Showing 31 changed files with 3,731 additions and 25 deletions.
2 changes: 2 additions & 0 deletions etc/mtree/BSD.include.dist
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
cam
ata
..
mmc
..
nvme
..
scsi
Expand Down
2 changes: 1 addition & 1 deletion include/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ LHDRS= aio.h errno.h fcntl.h linker_set.h poll.h stdatomic.h stdint.h \
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 \
Expand Down
1 change: 1 addition & 0 deletions lib/libcam/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 36 additions & 0 deletions sys/amd64/conf/MMCCAM
Original file line number Diff line number Diff line change
@@ -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)
6 changes: 6 additions & 0 deletions sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);

Expand Down
21 changes: 21 additions & 0 deletions sys/arm/conf/BEAGLEBONE-MMCCAM
Original file line number Diff line number Diff line change
@@ -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
33 changes: 32 additions & 1 deletion sys/arm/ti/ti_sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -241,6 +250,22 @@ ti_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off,
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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
78 changes: 75 additions & 3 deletions sys/cam/cam_ccb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */

Expand Down Expand Up @@ -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 {
Expand All @@ -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)
Expand Down Expand Up @@ -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;
};

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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) \
Expand Down Expand Up @@ -1326,6 +1363,13 @@ cam_fill_smpio(struct ccb_smpio *smpio, uint32_t retries,
uint8_t *smp_response, int smp_response_len,
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 *),
Expand Down Expand Up @@ -1414,6 +1458,34 @@ cam_fill_smpio(struct ccb_smpio *smpio, uint32_t retries,
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
cam_set_ccbstatus(union ccb *ccb, cam_status status)
{
Expand Down
12 changes: 12 additions & 0 deletions sys/cam/cam_periph.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,18 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo,
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;
Expand Down
Loading

0 comments on commit a87c7a8

Please sign in to comment.