From owner-svn-src-all@freebsd.org Sun Jul 9 16:57:27 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 3394CD90C74; Sun, 9 Jul 2017 16:57:27 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id F2AF8656EF; Sun, 9 Jul 2017 16:57:26 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v69GvQVI096959; Sun, 9 Jul 2017 16:57:26 GMT (envelope-from imp@FreeBSD.org) Received: (from imp@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v69GvOar096942; Sun, 9 Jul 2017 16:57:24 GMT (envelope-from imp@FreeBSD.org) Message-Id: <201707091657.v69GvOar096942@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: imp set sender to imp@FreeBSD.org using -f From: Warner Losh Date: Sun, 9 Jul 2017 16:57:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: 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... X-SVN-Group: head X-SVN-Commit-Author: imp X-SVN-Commit-Paths: 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/modules X-SVN-Commit-Revision: 320844 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 09 Jul 2017 16:57:27 -0000 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 #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 #include #include +#include +#include #include #include @@ -60,6 +62,8 @@ __FBSDID("$FreeBSD$"); #include #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 #include #include +#include /* 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 +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 , + * Bernd Walter , and other authors. + * * $FreeBSD$ */ -#ifndef DEV_MMC_MMCBRVAR_H -#define DEV_MMC_MMCBRVAR_H +#ifndef CAM_MMC_H +#define CAM_MMC_H #include - -#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 - -#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 +#include - 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 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 + * Copyright (c) 2006 M. Warner Losh + * Copyright (c) 2009 Alexander Motin + * Copyright (c) 2015-2017 Ilya Bakulin + * 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 , Alexander Motin + * Bernd Walter , and other authors. + */ + +#include +__FBSDID("$FreeBSD$"); + +//#include "opt_sdda.h" + +#include + +#ifdef _KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for PRIu64 */ +#endif /* _KERNEL */ + +#ifndef _KERNEL +#include +#include +#endif /* _KERNEL */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include /* 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 ***