> Date: Thu, 28 Apr 2016 12:28:59 +0200 (CEST)
> From: Mark Kettenis <[email protected]>
> 
> The diff below implements some speedups for sdhc(4).  In particular:
> 
> * Implement high speed mode
> * Implement support for 4-bit and 8-bit busses
> * Use DMA for block transfers
> 
> High speed mode and wider bus support are only used for (e)MMC for
> now, but DMA support should benefit SD cards as well.
> 
> Most of this code was derived from the imrpovements made over at
> NetBSD.  However, I chose to only implement for ADMA2 and not for the
> older SDMA and ADMA1 mechanisms.  These older DMA mechanism have
> severe limitations and it seems that most of the available hardware
> supports ADAM2.  And of course PIO (programmed IO) will continue to
> work just fine for hardware that doesn't support ADMA2.
> 
> Emulates SCSI transfers continue to be bounced through the sdmmc task
> thread.  That probably limits the total throughput a bit.
> Nevertheless, with this diff I can read from eMMC in the Lenovo Bay
> Trail stick at 40MB/s, which is quite an improvement from the 5MB/s I
> reached before.
> 
> This is probably several commit's worth of changes, but this provides
> them all in an easily testable form.

So here are just the bits that add DMA support.  Since Theo likes this
so much, I'd like to move forward with this.

ok?


Index: sdmmc/sdhc.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdhc.c,v
retrieving revision 1.43
diff -u -p -r1.43 sdhc.c
--- sdmmc/sdhc.c        30 Mar 2016 09:58:01 -0000      1.43
+++ sdmmc/sdhc.c        28 Apr 2016 18:26:21 -0000
@@ -36,6 +36,7 @@
 #define SDHC_COMMAND_TIMEOUT   hz
 #define SDHC_BUFFER_TIMEOUT    hz
 #define SDHC_TRANSFER_TIMEOUT  hz
+#define SDHC_DMA_TIMEOUT       (hz*3)
 
 struct sdhc_host {
        struct sdhc_softc *sc;          /* host controller device */
@@ -50,6 +51,10 @@ struct sdhc_host {
        u_int8_t regs[14];              /* host controller state */
        u_int16_t intr_status;          /* soft interrupt status */
        u_int16_t intr_error_status;    /* soft error status */
+
+       bus_dmamap_t adma_map;
+       bus_dma_segment_t adma_segs[1];
+       caddr_t adma2;
 };
 
 /* flag values */
@@ -174,7 +179,7 @@ sdhc_host_found(struct sdhc_softc *sc, b
                caps = HREAD4(hp, SDHC_CAPABILITIES);
 
        /* Use DMA if the host system and the controller support it. */
-       if (usedma && ISSET(caps, SDHC_DMA_SUPPORT))
+       if (usedma && ISSET(caps, SDHC_ADMA2_SUPP))
                SET(hp->flags, SHF_USE_DMA);
 
        /*
@@ -236,6 +241,46 @@ sdhc_host_found(struct sdhc_softc *sc, b
                break;
        }
 
+       if (ISSET(hp->flags, SHF_USE_DMA)) {
+               int rseg;
+
+               /* Allocate ADMA2 descriptor memory */
+               error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
+                   PAGE_SIZE, hp->adma_segs, 1, &rseg,
+                   BUS_DMA_WAITOK | BUS_DMA_ZERO);
+               if (error)
+                       goto adma_done;
+               error = bus_dmamem_map(sc->sc_dmat, hp->adma_segs, rseg,
+                   PAGE_SIZE, &hp->adma2, BUS_DMA_WAITOK);
+               if (error) {
+                       bus_dmamem_free(sc->sc_dmat, hp->adma_segs, rseg);
+                       goto adma_done;
+               }
+               error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
+                   0, BUS_DMA_WAITOK, &hp->adma_map);
+               if (error) {
+                       bus_dmamem_unmap(sc->sc_dmat, hp->adma2, PAGE_SIZE);
+                       bus_dmamem_free(sc->sc_dmat, hp->adma_segs, rseg);
+                       goto adma_done;
+               }
+               error = bus_dmamap_load(sc->sc_dmat, hp->adma_map,
+                   hp->adma2, PAGE_SIZE, NULL,
+                   BUS_DMA_WAITOK | BUS_DMA_WRITE);
+               if (error) {
+                       bus_dmamap_destroy(sc->sc_dmat, hp->adma_map);
+                       bus_dmamem_unmap(sc->sc_dmat, hp->adma2, PAGE_SIZE);
+                       bus_dmamem_free(sc->sc_dmat, hp->adma_segs, rseg);
+                       goto adma_done;
+               }
+
+       adma_done:
+               if (error) {
+                       printf("%s: can't allocate DMA descriptor table\n",
+                           DEVNAME(hp->sc));
+                       CLR(hp->flags, SHF_USE_DMA);
+               }
+       }
+
        /*
         * Attach the generic SD/MMC bus driver.  (The bus driver must
         * not invoke any chipset functions before it is attached.)
@@ -244,6 +289,9 @@ sdhc_host_found(struct sdhc_softc *sc, b
        saa.saa_busname = "sdmmc";
        saa.sct = &sdhc_functions;
        saa.sch = hp;
+       saa.dmat = sc->sc_dmat;
+       if (ISSET(hp->flags, SHF_USE_DMA))
+               saa.caps |= SMC_CAPS_DMA;
 
        hp->sdmmc = config_found(&sc->sc_dev, &saa, NULL);
        if (hp->sdmmc == NULL) {
@@ -641,11 +689,14 @@ sdhc_exec_command(sdmmc_chipset_handle_t
 int
 sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
 {
+       struct sdhc_adma2_descriptor32 *desc = (void *)hp->adma2;
+       struct sdhc_softc *sc = hp->sc;
        u_int16_t blksize = 0;
        u_int16_t blkcount = 0;
        u_int16_t mode;
        u_int16_t command;
        int error;
+       int seg;
        int s;
        
        DPRINTF(1,("%s: start cmd %u arg=%#x data=%#x dlen=%d flags=%#x "
@@ -688,10 +739,9 @@ sdhc_start_command(struct sdhc_host *hp,
                        mode |= SDHC_AUTO_CMD12_ENABLE;
                }
        }
-#ifdef notyet
-       if (ISSET(hp->flags, SHF_USE_DMA))
+       if (cmd->c_dmamap && cmd->c_datalen > 0 &&
+           ISSET(hp->flags, SHF_USE_DMA))
                mode |= SDHC_DMA_ENABLE;
-#endif
 
        /*
         * Prepare command register value. (2.2.6)
@@ -724,7 +774,36 @@ sdhc_start_command(struct sdhc_host *hp,
        /* Alert the user not to remove the card. */
        HSET1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
 
-       /* XXX: Set DMA start address if SHF_USE_DMA is set. */
+       /* Set DMA start address if SHF_USE_DMA is set. */
+       if (cmd->c_dmamap && ISSET(hp->flags, SHF_USE_DMA)) {
+               for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
+                       bus_addr_t paddr =
+                           cmd->c_dmamap->dm_segs[seg].ds_addr;
+                       uint16_t len =
+                           cmd->c_dmamap->dm_segs[seg].ds_len == 65536 ?
+                           0 : cmd->c_dmamap->dm_segs[seg].ds_len;
+                       uint16_t attr;
+
+                       attr = SDHC_ADMA2_VALID | SDHC_ADMA2_ACT_TRANS;
+                       if (seg == cmd->c_dmamap->dm_nsegs - 1)
+                               attr |= SDHC_ADMA2_END;
+
+                       desc[seg].attribute = htole16(attr);
+                       desc[seg].length = htole16(len);
+                       desc[seg].address = htole32(paddr);
+               }
+
+               desc[cmd->c_dmamap->dm_nsegs].attribute = htole16(0);
+
+               bus_dmamap_sync(sc->sc_dmat, hp->adma_map, 0, PAGE_SIZE,
+                   BUS_DMASYNC_PREWRITE);
+
+               HCLR1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT);
+               HSET1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT_ADMA2);
+
+               HWRITE4(hp, SDHC_ADMA_SYSTEM_ADDR,
+                   hp->adma_map->dm_segs[0].ds_addr);
+       }
 
        DPRINTF(1,("%s: cmd=%#x mode=%#x blksize=%d blkcount=%d\n",
            DEVNAME(hp->sc), command, mode, blksize, blkcount));
@@ -752,6 +831,25 @@ sdhc_transfer_data(struct sdhc_host *hp,
        int mask;
        int error;
 
+       if (cmd->c_dmamap) {
+               int status;
+
+               error = 0;
+               for (;;) {
+                       status = sdhc_wait_intr(hp,
+                           SDHC_DMA_INTERRUPT|SDHC_TRANSFER_COMPLETE,
+                           SDHC_DMA_TIMEOUT);
+                       if (status & SDHC_TRANSFER_COMPLETE)
+                               break;
+                       if (!status) {
+                               error = ETIMEDOUT;
+                               break;
+                       }
+               }
+
+               goto done;
+       }
+
        mask = ISSET(cmd->c_flags, SCF_CMD_READ) ?
            SDHC_BUFFER_READ_ENABLE : SDHC_BUFFER_WRITE_ENABLE;
        error = 0;
@@ -792,6 +890,7 @@ sdhc_transfer_data(struct sdhc_host *hp,
            SDHC_TRANSFER_TIMEOUT))
                error = ETIMEDOUT;
 
+done:
        if (error != 0)
                cmd->c_error = error;
        SET(cmd->c_flags, SCF_ITSDONE);
Index: sdmmc/sdhcreg.h
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdhcreg.h,v
retrieving revision 1.5
diff -u -p -r1.5 sdhcreg.h
--- sdmmc/sdhcreg.h     11 Jan 2016 06:54:53 -0000      1.5
+++ sdmmc/sdhcreg.h     28 Apr 2016 18:26:21 -0000
@@ -80,6 +80,10 @@
 #define  SDHC_CMD_INHIBIT_CMD          (1<<0)
 #define  SDHC_CMD_INHIBIT_MASK         0x0003
 #define SDHC_HOST_CTL                  0x28
+#define  SDHC_8BIT_MODE                        (1<<5)
+#define  SDHC_DMA_SELECT               (3<<3)
+#define  SDHC_DMA_SELECT_SDMA          (0<<3)
+#define  SDHC_DMA_SELECT_ADMA2         (2<<3)
 #define  SDHC_HIGH_SPEED               (1<<2)
 #define  SDHC_4BIT_MODE                        (1<<1)
 #define  SDHC_LED_ON                   (1<<0)
@@ -137,12 +141,25 @@
 #define SDHC_EINTR_SIGNAL_EN           0x3a
 #define  SDHC_EINTR_SIGNAL_MASK                0x01ff  /* excluding vendor 
signals */
 #define SDHC_CMD12_ERROR_STATUS                0x3c
+#define SDHC_HOST_CTL2                 0x3e
+#define  SDHC_SAMPLING_CLOCK_SEL       (1<<7)
+#define  SDHC_EXECUTE_TUNING           (1<<6)
+#define  SDHC_1_8V_SIGNAL_EN           (1<<3)
+#define  SDHC_UHS_MODE_SELECT_SHIFT    0
+#define  SDHC_UHS_MODE_SELECT_MASK     0x7
+#define  SDHC_UHS_MODE_SELECT_SDR12    0
+#define  SDHC_UHS_MODE_SELECT_SDR25    1
+#define  SDHC_UHS_MODE_SELECT_SDR50    2
+#define  SDHC_UHS_MODE_SELECT_SDR104   3
+#define  SDHC_UHS_MODE_SELECT_DDR50    4
 #define SDHC_CAPABILITIES              0x40
 #define  SDHC_VOLTAGE_SUPP_1_8V                (1<<26)
 #define  SDHC_VOLTAGE_SUPP_3_0V                (1<<25)
 #define  SDHC_VOLTAGE_SUPP_3_3V                (1<<24)
-#define  SDHC_DMA_SUPPORT              (1<<22)
+#define  SDHC_SDMA_SUPP                        (1<<22)
 #define  SDHC_HIGH_SPEED_SUPP          (1<<21)
+#define  SDHC_ADMA2_SUPP               (1<<19)
+#define  SDHC_8BIT_MODE_SUPP           (1<<18)
 #define  SDHC_MAX_BLK_LEN_512          0
 #define  SDHC_MAX_BLK_LEN_1024         1
 #define  SDHC_MAX_BLK_LEN_2048         2
@@ -154,7 +171,27 @@
 #define  SDHC_TIMEOUT_FREQ_UNIT                (1<<7)  /* 0=KHz, 1=MHz */
 #define  SDHC_TIMEOUT_FREQ_SHIFT       0
 #define  SDHC_TIMEOUT_FREQ_MASK                0x1f
-#define SDHC_CAPABILITIES_1            0x44
+#define SDHC_CAPABILITIES2             0x44
+#define  SDHC_SDR50_SUPP               (1<<0)
+#define  SDHC_SDR104_SUPP              (1<<1)
+#define  SDHC_DDR50_SUPP               (1<<2)
+#define  SDHC_DRIVER_TYPE_A            (1<<4)
+#define  SDHC_DRIVER_TYPE_C            (1<<5)
+#define  SDHC_DRIVER_TYPE_D            (1<<6)
+#define  SDHC_TIMER_COUNT_SHIFT                8
+#define  SDHC_TIMER_COUNT_MASK         0xf
+#define  SDHC_TUNING_SDR50             (1<<13)
+#define  SDHC_RETUNING_MODES_SHIFT     14
+#define  SDHC_RETUNING_MODES_MASK      0x3
+#define  SDHC_RETUNING_MODE_1          (0 << SDHC_RETUNING_MODES_SHIFT)
+#define  SDHC_RETUNING_MODE_2          (1 << SDHC_RETUNING_MODES_SHIFT)
+#define  SDHC_RETUNING_MODE_3          (2 << SDHC_RETUNING_MODES_SHIFT)
+#define  SDHC_CLOCK_MULTIPLIER_SHIFT   16
+#define  SDHC_CLOCK_MULTIPLIER_MASK    0xff
+#define SDHC_ADMA_ERROR_STATUS         0x54
+#define  SDHC_ADMA_LENGTH_MISMATCH     (1<<2)
+#define  SDHC_ADMA_ERROR_STATE         (3<<0)
+#define SDHC_ADMA_SYSTEM_ADDR          0x58
 #define SDHC_MAX_CAPABILITIES          0x48
 #define SDHC_SLOT_INTR_STATUS          0xfc
 #define SDHC_HOST_CTL_VERSION          0xfe
@@ -201,5 +238,19 @@
        "\20\11ACMD12\10CL\7DEB\6DCRC\5DT\4CI\3CEB\2CCRC\1CT"
 #define SDHC_CAPABILITIES_BITS                                         \
        "\20\33Vdd1.8V\32Vdd3.0V\31Vdd3.3V\30SUSPEND\27DMA\26HIGHSPEED"
+
+#define SDHC_ADMA2_VALID       (1<<0)
+#define SDHC_ADMA2_END         (1<<1)
+#define SDHC_ADMA2_INT         (1<<2)
+#define SDHC_ADMA2_ACT         (3<<4)
+#define SDHC_ADMA2_ACT_NOP     (0<<4)
+#define SDHC_ADMA2_ACT_TRANS   (2<<4)
+#define SDHC_ADMA2_ACT_LINK    (3<<4)
+
+struct sdhc_adma2_descriptor32 {
+       uint16_t        attribute;
+       uint16_t        length;
+       uint32_t        address;
+} __packed;
 
 #endif
Index: sdmmc/sdhcvar.h
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdhcvar.h,v
retrieving revision 1.8
diff -u -p -r1.8 sdhcvar.h
--- sdmmc/sdhcvar.h     30 Mar 2016 09:58:01 -0000      1.8
+++ sdmmc/sdhcvar.h     28 Apr 2016 18:26:21 -0000
@@ -29,6 +29,8 @@ struct sdhc_softc {
        int sc_nhosts;
        u_int sc_flags;
 
+       bus_dma_tag_t sc_dmat;
+
        int (*sc_card_detect)(struct sdhc_softc *);
 };
 
Index: sdmmc/sdmmc.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v
retrieving revision 1.39
diff -u -p -r1.39 sdmmc.c
--- sdmmc/sdmmc.c       19 Mar 2016 11:41:56 -0000      1.39
+++ sdmmc/sdmmc.c       28 Apr 2016 18:26:21 -0000
@@ -97,14 +97,25 @@ sdmmc_attach(struct device *parent, stru
 {
        struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
        struct sdmmcbus_attach_args *saa = aux;
+       int error;
 
        printf("\n");
 
        sc->sct = saa->sct;
        sc->sch = saa->sch;
+       sc->sc_dmat = saa->dmat;
        sc->sc_flags = saa->flags;
        sc->sc_caps = saa->caps;
        sc->sc_max_xfer = saa->max_xfer;
+
+       if (ISSET(sc->sc_caps, SMC_CAPS_DMA)) {
+               error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, SDMMC_MAXNSEGS,
+                   MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_dmap);
+               if (error) {
+                       printf("%s: can't create DMA map\n", DEVNAME(sc));
+                       return;
+               }
+       }
 
        SIMPLEQ_INIT(&sc->sf_head);
        TAILQ_INIT(&sc->sc_tskq);
Index: sdmmc/sdmmc_mem.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_mem.c,v
retrieving revision 1.22
diff -u -p -r1.22 sdmmc_mem.c
--- sdmmc/sdmmc_mem.c   8 Nov 2015 12:10:27 -0000       1.22
+++ sdmmc/sdmmc_mem.c   28 Apr 2016 18:26:21 -0000
@@ -44,12 +44,12 @@ int sdmmc_mem_sd_init(struct sdmmc_softc
 int    sdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *);
 int    sdmmc_mem_single_read_block(struct sdmmc_function *, int, u_char *,
        size_t);
-int    sdmmc_mem_read_block_subr(struct sdmmc_function *, int, u_char *,
-       size_t);
+int    sdmmc_mem_read_block_subr(struct sdmmc_function *, bus_dmamap_t,
+       int, u_char *, size_t);
 int    sdmmc_mem_single_write_block(struct sdmmc_function *, int, u_char *,
        size_t);
-int    sdmmc_mem_write_block_subr(struct sdmmc_function *, int, u_char *,
-       size_t);
+int    sdmmc_mem_write_block_subr(struct sdmmc_function *, bus_dmamap_t,
+       int, u_char *, size_t);
 
 #ifdef SDMMC_DEBUG
 #define DPRINTF(s)     printf s
@@ -566,8 +566,8 @@ sdmmc_mem_set_blocklen(struct sdmmc_soft
 }
 
 int
-sdmmc_mem_read_block_subr(struct sdmmc_function *sf, int blkno, u_char *data,
-    size_t datalen)
+sdmmc_mem_read_block_subr(struct sdmmc_function *sf, bus_dmamap_t dmap,
+    int blkno, u_char *data, size_t datalen)
 {
        struct sdmmc_softc *sc = sf->sc;
        struct sdmmc_command cmd;
@@ -588,6 +588,7 @@ sdmmc_mem_read_block_subr(struct sdmmc_f
        else
                cmd.c_arg = blkno << 9;
        cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
+       cmd.c_dmamap = dmap;
 
        error = sdmmc_mmc_command(sc, &cmd);
        if (error != 0)
@@ -627,8 +628,8 @@ sdmmc_mem_single_read_block(struct sdmmc
        int i;
 
        for (i = 0; i < datalen / sf->csd.sector_size; i++) {
-               error = sdmmc_mem_read_block_subr(sf, blkno + i, data + i *
-                   sf->csd.sector_size, sf->csd.sector_size);
+               error = sdmmc_mem_read_block_subr(sf,NULL,  blkno + i,
+                   data + i * sf->csd.sector_size, sf->csd.sector_size);
                if (error)
                        break;
        }
@@ -647,17 +648,42 @@ sdmmc_mem_read_block(struct sdmmc_functi
 
        if (ISSET(sc->sc_caps, SMC_CAPS_SINGLE_ONLY)) {
                error = sdmmc_mem_single_read_block(sf, blkno, data, datalen);
-       } else {
-               error = sdmmc_mem_read_block_subr(sf, blkno, data, datalen);
+               goto out;
+       }
+
+       if (!ISSET(sc->sc_caps, SMC_CAPS_DMA)) {
+               error = sdmmc_mem_read_block_subr(sf, NULL, blkno,
+                   data, datalen);
+               goto out;
        }
 
+       /* DMA transfer */
+       error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, data, datalen,
+           NULL, BUS_DMA_NOWAIT|BUS_DMA_READ);
+       if (error)
+               goto out;
+
+       bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
+           BUS_DMASYNC_PREREAD);
+
+       error = sdmmc_mem_read_block_subr(sf, sc->sc_dmap, blkno, data,
+           datalen);
+       if (error)
+               goto unload;
+
+       bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
+           BUS_DMASYNC_POSTREAD);
+unload:
+       bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap);
+
+out:
        rw_exit(&sc->sc_lock);
        return (error);
 }
 
 int
-sdmmc_mem_write_block_subr(struct sdmmc_function *sf, int blkno, u_char *data,
-    size_t datalen)
+sdmmc_mem_write_block_subr(struct sdmmc_function *sf, bus_dmamap_t dmap,
+    int blkno, u_char *data, size_t datalen)
 {
        struct sdmmc_softc *sc = sf->sc;
        struct sdmmc_command cmd;
@@ -677,6 +703,7 @@ sdmmc_mem_write_block_subr(struct sdmmc_
        else
                cmd.c_arg = blkno << 9;
        cmd.c_flags = SCF_CMD_ADTC | SCF_RSP_R1;
+       cmd.c_dmamap = dmap;
 
        error = sdmmc_mmc_command(sc, &cmd);
        if (error != 0)
@@ -715,8 +742,8 @@ sdmmc_mem_single_write_block(struct sdmm
        int i;
 
        for (i = 0; i < datalen / sf->csd.sector_size; i++) {
-               error = sdmmc_mem_write_block_subr(sf, blkno + i, data + i *
-                   sf->csd.sector_size, sf->csd.sector_size);
+               error = sdmmc_mem_write_block_subr(sf, NULL, blkno + i,
+                   data + i * sf->csd.sector_size, sf->csd.sector_size);
                if (error)
                        break;
        }
@@ -735,10 +762,35 @@ sdmmc_mem_write_block(struct sdmmc_funct
 
        if (ISSET(sc->sc_caps, SMC_CAPS_SINGLE_ONLY)) {
                error = sdmmc_mem_single_write_block(sf, blkno, data, datalen);
-       } else {
-               error = sdmmc_mem_write_block_subr(sf, blkno, data, datalen);
+               goto out;
+       }
+
+       if (!ISSET(sc->sc_caps, SMC_CAPS_DMA)) {
+               error = sdmmc_mem_write_block_subr(sf, NULL, blkno,
+                   data, datalen);
+               goto out;
        }
 
+       /* DMA transfer */
+       error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, data, datalen,
+           NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE);
+       if (error)
+               goto out;
+
+       bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
+           BUS_DMASYNC_PREWRITE);
+
+       error = sdmmc_mem_write_block_subr(sf, sc->sc_dmap, blkno, data,
+           datalen);
+       if (error)
+               goto unload;
+
+       bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
+           BUS_DMASYNC_POSTWRITE);
+unload:
+       bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap);
+
+out:
        rw_exit(&sc->sc_lock);
        return (error);
 }
Index: sdmmc/sdmmcchip.h
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmcchip.h,v
retrieving revision 1.5
diff -u -p -r1.5 sdmmcchip.h
--- sdmmc/sdmmcchip.h   12 Sep 2013 11:54:04 -0000      1.5
+++ sdmmc/sdmmcchip.h   28 Apr 2016 18:26:21 -0000
@@ -19,6 +19,8 @@
 #ifndef _SDMMC_CHIP_H_
 #define _SDMMC_CHIP_H_
 
+#include <machine/bus.h>
+
 struct sdmmc_command;
 
 typedef struct sdmmc_chip_functions *sdmmc_chipset_tag_t;
@@ -77,6 +79,7 @@ struct sdmmcbus_attach_args {
        const char *saa_busname;
        sdmmc_chipset_tag_t sct;
        sdmmc_chipset_handle_t sch;
+       bus_dma_tag_t dmat;
        int     flags;
        int     caps;
        long    max_xfer;
Index: sdmmc/sdmmcvar.h
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmcvar.h,v
retrieving revision 1.22
diff -u -p -r1.22 sdmmcvar.h
--- sdmmc/sdmmcvar.h    12 Sep 2013 11:54:04 -0000      1.22
+++ sdmmc/sdmmcvar.h    28 Apr 2016 18:26:21 -0000
@@ -22,6 +22,8 @@
 #include <sys/queue.h>
 #include <sys/rwlock.h>
 
+#include <machine/bus.h>
+
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 
@@ -72,6 +74,7 @@ struct sdmmc_command {
        u_int16_t        c_opcode;      /* SD or MMC command index */
        u_int32_t        c_arg;         /* SD/MMC command argument */
        sdmmc_response   c_resp;        /* response buffer */
+       bus_dmamap_t     c_dmamap;
        void            *c_data;        /* buffer to send or read into */
        int              c_datalen;     /* length of data buffer */
        int              c_blklen;      /* block length */
@@ -156,6 +159,11 @@ struct sdmmc_softc {
 #define DEVNAME(sc)    ((sc)->sc_dev.dv_xname)
        sdmmc_chipset_tag_t sct;        /* host controller chipset tag */
        sdmmc_chipset_handle_t sch;     /* host controller chipset handle */
+
+       bus_dma_tag_t sc_dmat;
+       bus_dmamap_t sc_dmap;
+#define SDMMC_MAXNSEGS ((MAXPHYS / PAGE_SIZE) + 1)
+
        int sc_flags;
 #define SMF_SD_MODE            0x0001  /* host in SD mode (MMC otherwise) */
 #define SMF_IO_MODE            0x0002  /* host in I/O mode (SD mode only) */
Index: acpi/sdhc_acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/sdhc_acpi.c,v
retrieving revision 1.6
diff -u -p -r1.6 sdhc_acpi.c
--- acpi/sdhc_acpi.c    2 Apr 2016 00:34:47 -0000       1.6
+++ acpi/sdhc_acpi.c    28 Apr 2016 18:26:21 -0000
@@ -29,6 +29,8 @@
 #include <dev/sdmmc/sdhcvar.h>
 #include <dev/sdmmc/sdmmcvar.h>
 
+extern struct bus_dma_tag pci_bus_dma_tag;
+
 struct sdhc_acpi_softc {
        struct sdhc_softc sc;
        struct acpi_softc *sc_acpi;
@@ -132,7 +134,8 @@ sdhc_acpi_attach(struct device *parent, 
        printf("\n");
 
        sc->sc.sc_host = &sc->sc_host;
-       sdhc_host_found(&sc->sc, sc->sc_memt, sc->sc_memh, sc->sc_size, 0, 0);
+       sc->sc.sc_dmat = &pci_bus_dma_tag;
+       sdhc_host_found(&sc->sc, sc->sc_memt, sc->sc_memh, sc->sc_size, 1, 0);
 }
 
 int
Index: pci/sdhc_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/sdhc_pci.c,v
retrieving revision 1.19
diff -u -p -r1.19 sdhc_pci.c
--- pci/sdhc_pci.c      24 Nov 2015 19:38:01 -0000      1.19
+++ pci/sdhc_pci.c      28 Apr 2016 18:26:21 -0000
@@ -149,6 +149,7 @@ sdhc_pci_attach(struct device *parent, s
 
        /* Enable use of DMA if supported by the interface. */
        usedma = PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA;
+       sc->sc.sc_dmat = pa->pa_dmat;
 
        /*
         * Map and attach all hosts supported by the host controller.

Reply via email to