> 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.