Tue Apr 14 18:45:25 2015 UTC ()
Add support for DMA transfers. From Jared D. McNeill, with final debug by me.
With this I can get nearly 20MB/s from my sdcard on the BB black at 1Ghz
(not bad for a 50Mhz 4-bits bus), and still 15MB/s on the BB white at
low speed (275Mhz).


(bouyer)
diff -r1.15 -r1.16 src/sys/arch/arm/omap/omap3_sdhc.c

cvs diff -r1.15 -r1.16 src/sys/arch/arm/omap/Attic/omap3_sdhc.c (expand / switch to unified diff)

--- src/sys/arch/arm/omap/Attic/omap3_sdhc.c 2015/01/12 01:02:35 1.15
+++ src/sys/arch/arm/omap/Attic/omap3_sdhc.c 2015/04/14 18:45:25 1.16
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: omap3_sdhc.c,v 1.15 2015/01/12 01:02:35 jakllsch Exp $ */ 1/* $NetBSD: omap3_sdhc.c,v 1.16 2015/04/14 18:45:25 bouyer Exp $ */
2/*- 2/*-
3 * Copyright (c) 2011 The NetBSD Foundation, Inc. 3 * Copyright (c) 2011 The NetBSD Foundation, Inc.
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Matt Thomas of 3am Software Foundry. 7 * by Matt Thomas of 3am Software Foundry.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -19,76 +19,112 @@ @@ -19,76 +19,112 @@
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE. 28 * POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.15 2015/01/12 01:02:35 jakllsch Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.16 2015/04/14 18:45:25 bouyer Exp $");
33 33
34#include "opt_omap.h" 34#include "opt_omap.h"
 35#include "edma.h"
35 36
36#include <sys/param.h> 37#include <sys/param.h>
37#include <sys/systm.h> 38#include <sys/systm.h>
38#include <sys/device.h> 39#include <sys/device.h>
39#include <sys/kernel.h> 40#include <sys/kernel.h>
40#include <sys/proc.h> 41#include <sys/proc.h>
41#include <sys/queue.h> 42#include <sys/queue.h>
42 43#include <sys/mutex.h>
 44#include <sys/condvar.h>
43#include <sys/bus.h> 45#include <sys/bus.h>
44 46
45#include <arm/omap/omap2_obiovar.h> 47#include <arm/omap/omap2_obiovar.h>
46#include <arm/omap/omap2_reg.h> 48#include <arm/omap/omap2_reg.h>
47#include <arm/omap/omap3_sdmmcreg.h> 49#include <arm/omap/omap3_sdmmcreg.h>
48 50
49#ifdef TI_AM335X 51#ifdef TI_AM335X
50# include <arm/omap/am335x_prcm.h> 52# include <arm/omap/am335x_prcm.h>
51# include <arm/omap/omap2_prcm.h> 53# include <arm/omap/omap2_prcm.h>
52#endif 54#endif
53 55
 56#if NEDMA > 0
 57# include <arm/omap/omap_edma.h>
 58#endif
 59
54#include <dev/sdmmc/sdhcreg.h> 60#include <dev/sdmmc/sdhcreg.h>
55#include <dev/sdmmc/sdhcvar.h> 61#include <dev/sdmmc/sdhcvar.h>
 62#include <dev/sdmmc/sdmmcvar.h>
 63
 64#ifdef TI_AM335X
 65#define EDMA_MAX_PARAMS 32
 66#endif
 67
 68#ifdef OM3SDHC_DEBUG
 69int om3sdhcdebug = 1;
 70#define DPRINTF(n,s) do { if ((n) <= om3sdhcdebug) device_printf s; } while (0)
 71#else
 72#define DPRINTF(n,s) do {} while (0)
 73#endif
 74
56 75
57#define CLKD(kz) (sc->sc.sc_clkbase / (kz)) 76#define CLKD(kz) (sc->sc.sc_clkbase / (kz))
58 77
59#define SDHC_READ(sc, reg) \ 78#define SDHC_READ(sc, reg) \
60 bus_space_read_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg)) 79 bus_space_read_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg))
61#define SDHC_WRITE(sc, reg, val) \ 80#define SDHC_WRITE(sc, reg, val) \
62 bus_space_write_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg), (val)) 81 bus_space_write_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg), (val))
63 82
64static int obiosdhc_match(device_t, cfdata_t, void *); 83static int obiosdhc_match(device_t, cfdata_t, void *);
65static void obiosdhc_attach(device_t, device_t, void *); 84static void obiosdhc_attach(device_t, device_t, void *);
66static int obiosdhc_detach(device_t, int); 85static int obiosdhc_detach(device_t, int);
67 86
68static int obiosdhc_bus_clock(struct sdhc_softc *, int); 87static int obiosdhc_bus_clock(struct sdhc_softc *, int);
69static int obiosdhc_rod(struct sdhc_softc *, int); 88static int obiosdhc_rod(struct sdhc_softc *, int);
70static int obiosdhc_write_protect(struct sdhc_softc *); 89static int obiosdhc_write_protect(struct sdhc_softc *);
71static int obiosdhc_card_detect(struct sdhc_softc *); 90static int obiosdhc_card_detect(struct sdhc_softc *);
72 91
73struct obiosdhc_softc { 92struct obiosdhc_softc {
74 struct sdhc_softc sc; 93 struct sdhc_softc sc;
75 bus_space_tag_t sc_bst; 94 bus_space_tag_t sc_bst;
76 bus_space_handle_t sc_bsh; 95 bus_space_handle_t sc_bsh;
77 bus_space_handle_t sc_sdhc_bsh; 96 bus_space_handle_t sc_sdhc_bsh;
78 struct sdhc_host *sc_hosts[1]; 97 struct sdhc_host *sc_hosts[1];
79 void *sc_ih; /* interrupt vectoring */ 98 void *sc_ih; /* interrupt vectoring */
 99
 100#if NEDMA > 0
 101 struct edma_channel *sc_edma_tx;
 102 struct edma_channel *sc_edma_rx;
 103 uint16_t sc_edma_param_tx[EDMA_MAX_PARAMS];
 104 uint16_t sc_edma_param_rx[EDMA_MAX_PARAMS];
 105 kmutex_t sc_edma_lock;
 106 kcondvar_t sc_edma_cv;
 107 bus_addr_t sc_edma_fifo;
 108 bool sc_edma_pending;
 109#endif
80}; 110};
81 111
 112#if NEDMA > 0
 113static void obiosdhc_edma_init(struct obiosdhc_softc *, unsigned int);
 114static int obiosdhc_edma_xfer_data(struct sdhc_softc *, struct sdmmc_command *);
 115static void obiosdhc_edma_done(void *);
 116#endif
 117
82#ifdef TI_AM335X 118#ifdef TI_AM335X
83struct am335x_sdhc { 119struct am335x_sdhc {
84 const char *as_name; 120 const char *as_name;
85 bus_addr_t as_base_addr; 121 bus_addr_t as_base_addr;
86 int as_intr; 122 int as_intr;
87 struct omap_module as_module; 123 struct omap_module as_module;
88}; 124};
89 125
90static const struct am335x_sdhc am335x_sdhc[] = { 126static const struct am335x_sdhc am335x_sdhc[] = {
91 /* XXX All offset by 0x100 because of the am335x's mmc registers. */ 127 /* XXX All offset by 0x100 because of the am335x's mmc registers. */
92 { "MMCHS0", SDMMC1_BASE_TIAM335X, 64, { AM335X_PRCM_CM_PER, 0x3c } }, 128 { "MMCHS0", SDMMC1_BASE_TIAM335X, 64, { AM335X_PRCM_CM_PER, 0x3c } },
93 { "MMC1", SDMMC2_BASE_TIAM335X, 28, { AM335X_PRCM_CM_PER, 0xf4 } }, 129 { "MMC1", SDMMC2_BASE_TIAM335X, 28, { AM335X_PRCM_CM_PER, 0xf4 } },
94 { "MMCHS2", SDMMC3_BASE_TIAM335X, 29, { AM335X_PRCM_CM_WKUP, 0xf8 } }, 130 { "MMCHS2", SDMMC3_BASE_TIAM335X, 29, { AM335X_PRCM_CM_WKUP, 0xf8 } },
@@ -137,35 +173,35 @@ obiosdhc_match(device_t parent, cfdata_t @@ -137,35 +173,35 @@ obiosdhc_match(device_t parent, cfdata_t
137 173
138 return 0; 174 return 0;
139} 175}
140 176
141static void 177static void
142obiosdhc_attach(device_t parent, device_t self, void *aux) 178obiosdhc_attach(device_t parent, device_t self, void *aux)
143{ 179{
144 struct obiosdhc_softc * const sc = device_private(self); 180 struct obiosdhc_softc * const sc = device_private(self);
145 struct obio_attach_args * const oa = aux; 181 struct obio_attach_args * const oa = aux;
146 prop_dictionary_t prop = device_properties(self); 182 prop_dictionary_t prop = device_properties(self);
147 uint32_t clkd, stat; 183 uint32_t clkd, stat;
148 int error, timo, clksft, n; 184 int error, timo, clksft, n;
149 bool support8bit = false; 185 bool support8bit = false;
 186 const char *transfer_mode = "PIO";
150#ifdef TI_AM335X 187#ifdef TI_AM335X
151 size_t i; 188 size_t i;
152#endif 189#endif
153 190
154 prop_dictionary_get_bool(prop, "8bit", &support8bit); 191 prop_dictionary_get_bool(prop, "8bit", &support8bit);
155 192
156 sc->sc.sc_dmat = oa->obio_dmat; 193 sc->sc.sc_dmat = oa->obio_dmat;
157 sc->sc.sc_dev = self; 194 sc->sc.sc_dev = self;
158 //sc->sc.sc_flags |= SDHC_FLAG_USE_DMA; 
159 sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS; 195 sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS;
160 sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON; 196 sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON;
161 sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC; 197 sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC;
162 sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY; 198 sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY;
163 if (support8bit) 199 if (support8bit)
164 sc->sc.sc_flags |= SDHC_FLAG_8BIT_MODE; 200 sc->sc.sc_flags |= SDHC_FLAG_8BIT_MODE;
165#ifdef TI_AM335X 201#ifdef TI_AM335X
166 sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET; 202 sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET;
167 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY; 203 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY;
168#endif 204#endif
169#if defined(OMAP_3530) 205#if defined(OMAP_3530)
170 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY; 206 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY;
171#endif 207#endif
@@ -182,28 +218,44 @@ obiosdhc_attach(device_t parent, device_ @@ -182,28 +218,44 @@ obiosdhc_attach(device_t parent, device_
182 clksft = ffs(sc->sc.sc_clkmsk) - 1; 218 clksft = ffs(sc->sc.sc_clkmsk) - 1;
183 219
184 error = bus_space_map(sc->sc_bst, oa->obio_addr, oa->obio_size, 0, 220 error = bus_space_map(sc->sc_bst, oa->obio_addr, oa->obio_size, 0,
185 &sc->sc_bsh); 221 &sc->sc_bsh);
186 if (error) { 222 if (error) {
187 aprint_error_dev(self, 223 aprint_error_dev(self,
188 "can't map registers: %d\n", error); 224 "can't map registers: %d\n", error);
189 return; 225 return;
190 } 226 }
191 227
192 bus_space_subregion(sc->sc_bst, sc->sc_bsh, OMAP3_SDMMC_SDHC_OFFSET, 228 bus_space_subregion(sc->sc_bst, sc->sc_bsh, OMAP3_SDMMC_SDHC_OFFSET,
193 OMAP3_SDMMC_SDHC_SIZE, &sc->sc_sdhc_bsh); 229 OMAP3_SDMMC_SDHC_SIZE, &sc->sc_sdhc_bsh);
194 230
195 aprint_naive(": SDHC controller\n"); 231#if NEDMA > 0
196 aprint_normal(": SDHC controller\n"); 232 if (oa->obio_edmabase != -1) {
 233 mutex_init(&sc->sc_edma_lock, MUTEX_DEFAULT, IPL_SCHED);
 234 cv_init(&sc->sc_edma_cv, "sdhcedma");
 235 sc->sc_edma_fifo = oa->obio_addr +
 236 OMAP3_SDMMC_SDHC_OFFSET + SDHC_DATA;
 237 obiosdhc_edma_init(sc, oa->obio_edmabase);
 238 sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
 239 sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA;
 240 sc->sc.sc_flags |= SDHC_FLAG_EXTDMA_DMAEN;
 241 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY;
 242 sc->sc.sc_vendor_transfer_data_dma = obiosdhc_edma_xfer_data;
 243 transfer_mode = "EDMA";
 244 }
 245#endif
 246
 247 aprint_naive("\n");
 248 aprint_normal(": SDHC controller (%s)\n", transfer_mode);
197 249
198#ifdef TI_AM335X 250#ifdef TI_AM335X
199 /* XXX Not really AM335X-specific. */ 251 /* XXX Not really AM335X-specific. */
200 for (i = 0; i < __arraycount(am335x_sdhc); i++) 252 for (i = 0; i < __arraycount(am335x_sdhc); i++)
201 if ((oa->obio_addr == am335x_sdhc[i].as_base_addr) && 253 if ((oa->obio_addr == am335x_sdhc[i].as_base_addr) &&
202 (oa->obio_intr == am335x_sdhc[i].as_intr)) { 254 (oa->obio_intr == am335x_sdhc[i].as_intr)) {
203 prcm_module_enable(&am335x_sdhc[i].as_module); 255 prcm_module_enable(&am335x_sdhc[i].as_module);
204 break; 256 break;
205 } 257 }
206 KASSERT(i < __arraycount(am335x_sdhc)); 258 KASSERT(i < __arraycount(am335x_sdhc));
207#endif 259#endif
208 260
209 /* XXXXXX: Turn-on regulator via I2C. */ 261 /* XXXXXX: Turn-on regulator via I2C. */
@@ -370,13 +422,155 @@ obiosdhc_bus_clock(struct sdhc_softc *sc @@ -370,13 +422,155 @@ obiosdhc_bus_clock(struct sdhc_softc *sc
370 struct obiosdhc_softc *osc = (struct obiosdhc_softc *)sc; 422 struct obiosdhc_softc *osc = (struct obiosdhc_softc *)sc;
371 uint32_t ctl; 423 uint32_t ctl;
372 424
373 ctl = bus_space_read_4(osc->sc_bst, osc->sc_bsh, MMCHS_SYSCTL); 425 ctl = bus_space_read_4(osc->sc_bst, osc->sc_bsh, MMCHS_SYSCTL);
374 if (clk == 0) { 426 if (clk == 0) {
375 ctl &= ~SYSCTL_CEN; 427 ctl &= ~SYSCTL_CEN;
376 } else { 428 } else {
377 ctl |= SYSCTL_CEN; 429 ctl |= SYSCTL_CEN;
378 } 430 }
379 bus_space_write_4(osc->sc_bst, osc->sc_bsh, MMCHS_SYSCTL, ctl); 431 bus_space_write_4(osc->sc_bst, osc->sc_bsh, MMCHS_SYSCTL, ctl);
380 432
381 return 0; 433 return 0;
382} 434}
 435
 436#if NEDMA > 0
 437static void
 438obiosdhc_edma_init(struct obiosdhc_softc *sc, unsigned int edmabase)
 439{
 440 int i;
 441
 442 /* Request tx and rx DMA channels */
 443 sc->sc_edma_tx = edma_channel_alloc(EDMA_TYPE_DMA, edmabase + 0,
 444 obiosdhc_edma_done, sc);
 445 KASSERT(sc->sc_edma_tx != NULL);
 446 sc->sc_edma_rx = edma_channel_alloc(EDMA_TYPE_DMA, edmabase + 1,
 447 obiosdhc_edma_done, sc);
 448 KASSERT(sc->sc_edma_rx != NULL);
 449
 450 device_printf(sc->sc.sc_dev, "EDMA tx channel %d, rx channel %d\n",
 451 edma_channel_index(sc->sc_edma_tx),
 452 edma_channel_index(sc->sc_edma_rx));
 453
 454 /* Allocate some PaRAM pages */
 455 for (i = 0; i < __arraycount(sc->sc_edma_param_tx); i++) {
 456 sc->sc_edma_param_tx[i] = edma_param_alloc(sc->sc_edma_tx);
 457 KASSERT(sc->sc_edma_param_tx[i] != 0xffff);
 458 }
 459 for (i = 0; i < __arraycount(sc->sc_edma_param_rx); i++) {
 460 sc->sc_edma_param_rx[i] = edma_param_alloc(sc->sc_edma_rx);
 461 KASSERT(sc->sc_edma_param_rx[i] != 0xffff);
 462 }
 463
 464 return;
 465}
 466
 467static int
 468obiosdhc_edma_xfer_data(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd)
 469{
 470 struct obiosdhc_softc *sc = device_private(sdhc_sc->sc_dev);
 471 struct edma_channel *edma;
 472 uint16_t *edma_param;
 473 struct edma_param ep;
 474 size_t seg;
 475 int error;
 476 int blksize = MIN(cmd->c_datalen, cmd->c_blklen);
 477
 478 edma = ISSET(cmd->c_flags, SCF_CMD_READ) ?
 479 sc->sc_edma_rx : sc->sc_edma_tx;
 480 edma_param = ISSET(cmd->c_flags, SCF_CMD_READ) ?
 481 sc->sc_edma_param_rx : sc->sc_edma_param_tx;
 482
 483 DPRINTF(1, (sc->sc.sc_dev, "edma xfer: nsegs=%d ch# %d\n",
 484 cmd->c_dmamap->dm_nsegs, edma_channel_index(edma)));
 485
 486 if (cmd->c_dmamap->dm_nsegs > EDMA_MAX_PARAMS) {
 487 return ENOMEM;
 488 }
 489
 490 for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
 491 ep.ep_opt = __SHIFTIN(2, EDMA_PARAM_OPT_FWID) /* 32-bit */;
 492 ep.ep_opt |= __SHIFTIN(edma_channel_index(edma),
 493 EDMA_PARAM_OPT_TCC);
 494 if (seg == cmd->c_dmamap->dm_nsegs - 1) {
 495 ep.ep_opt |= EDMA_PARAM_OPT_TCINTEN;
 496 ep.ep_link = 0xffff;
 497 } else {
 498 ep.ep_link = EDMA_PARAM_BASE(edma_param[seg+1]);
 499 }
 500 if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
 501 ep.ep_opt |= EDMA_PARAM_OPT_SAM;
 502 ep.ep_src = sc->sc_edma_fifo;
 503 ep.ep_dst = cmd->c_dmamap->dm_segs[seg].ds_addr;
 504 } else {
 505 ep.ep_opt |= EDMA_PARAM_OPT_DAM;
 506 ep.ep_src = cmd->c_dmamap->dm_segs[seg].ds_addr;
 507 ep.ep_dst = sc->sc_edma_fifo;
 508 }
 509
 510 KASSERT(cmd->c_dmamap->dm_segs[seg].ds_len <= 65536 * 4);
 511
 512 /*
 513 * For unknown reason, the A-DMA transfers never completes for
 514 * transfers larger than 64 butes. So use a AB transfer,
 515 * with a 64 bytes A len
 516 */
 517 ep.ep_bcntrld = 0; /* not used for AB-synchronous mode */
 518 ep.ep_opt |= EDMA_PARAM_OPT_SYNCDIM;
 519 ep.ep_acnt = min(cmd->c_dmamap->dm_segs[seg].ds_len, 64);
 520 ep.ep_bcnt = min(cmd->c_dmamap->dm_segs[seg].ds_len, blksize) /
 521 ep.ep_acnt;
 522 ep.ep_ccnt = cmd->c_dmamap->dm_segs[seg].ds_len /
 523 (ep.ep_acnt * ep.ep_bcnt);
 524 ep.ep_srcbidx = ep.ep_dstbidx = 0;
 525 ep.ep_srccidx = ep.ep_dstcidx = 0;
 526 if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
 527 ep.ep_dstbidx = ep.ep_acnt;
 528 ep.ep_dstcidx = ep.ep_acnt * ep.ep_bcnt;
 529 } else {
 530 ep.ep_srcbidx = ep.ep_acnt;
 531 ep.ep_srccidx = ep.ep_acnt * ep.ep_bcnt;
 532 }
 533
 534 edma_set_param(edma, edma_param[seg], &ep);
 535#ifdef OM3SDHC_DEBUG
 536 if (om3sdhcdebug >= 1) {
 537 printf("target OPT: %08x\n", ep.ep_opt);
 538 edma_dump_param(edma, edma_param[seg]);
 539 }
 540#endif
 541 }
 542
 543 mutex_enter(&sc->sc_edma_lock);
 544 error = 0;
 545 sc->sc_edma_pending = true;
 546 edma_transfer_enable(edma, edma_param[0]);
 547 while (sc->sc_edma_pending) {
 548 error = cv_timedwait(&sc->sc_edma_cv, &sc->sc_edma_lock, hz*10);
 549 if (error == EWOULDBLOCK) {
 550 device_printf(sc->sc.sc_dev, "transfer timeout!\n");
 551 edma_dump(edma);
 552 edma_dump_param(edma, edma_param[0]);
 553 edma_halt(edma);
 554 sc->sc_edma_pending = false;
 555 error = ETIMEDOUT;
 556 break;
 557 }
 558 }
 559 edma_halt(edma);
 560 mutex_exit(&sc->sc_edma_lock);
 561
 562 return error;
 563}
 564
 565static void
 566obiosdhc_edma_done(void *priv)
 567{
 568 struct obiosdhc_softc *sc = priv;
 569
 570 mutex_enter(&sc->sc_edma_lock);
 571 KASSERT(sc->sc_edma_pending == true);
 572 sc->sc_edma_pending = false;
 573 cv_broadcast(&sc->sc_edma_cv);
 574 mutex_exit(&sc->sc_edma_lock);
 575}
 576#endif