1 1.25 tsutsui /* $NetBSD: dma.c,v 1.25 2024/12/20 23:52:00 tsutsui Exp $ */ 2 1.1 jeremy 3 1.1 jeremy /* 4 1.1 jeremy * Copyright (c) 1994 Paul Kranenburg. All rights reserved. 5 1.1 jeremy * Copyright (c) 1994 Peter Galbavy. All rights reserved. 6 1.1 jeremy * 7 1.1 jeremy * Redistribution and use in source and binary forms, with or without 8 1.1 jeremy * modification, are permitted provided that the following conditions 9 1.1 jeremy * are met: 10 1.1 jeremy * 1. Redistributions of source code must retain the above copyright 11 1.1 jeremy * notice, this list of conditions and the following disclaimer. 12 1.1 jeremy * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jeremy * notice, this list of conditions and the following disclaimer in the 14 1.1 jeremy * documentation and/or other materials provided with the distribution. 15 1.1 jeremy * 3. All advertising materials mentioning features or use of this software 16 1.1 jeremy * must display the following acknowledgement: 17 1.1 jeremy * This product includes software developed by Peter Galbavy. 18 1.1 jeremy * 4. The name of the author may not be used to endorse or promote products 19 1.1 jeremy * derived from this software without specific prior written permission. 20 1.1 jeremy * 21 1.1 jeremy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 1.1 jeremy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 1.1 jeremy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 1.1 jeremy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 1.1 jeremy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 1.1 jeremy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 1.1 jeremy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 1.1 jeremy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 1.1 jeremy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 1.1 jeremy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 1.1 jeremy */ 32 1.14 lukem 33 1.14 lukem #include <sys/cdefs.h> 34 1.25 tsutsui __KERNEL_RCSID(0, "$NetBSD: dma.c,v 1.25 2024/12/20 23:52:00 tsutsui Exp $"); 35 1.1 jeremy 36 1.1 jeremy #include <sys/types.h> 37 1.1 jeremy #include <sys/param.h> 38 1.1 jeremy #include <sys/systm.h> 39 1.1 jeremy #include <sys/kernel.h> 40 1.1 jeremy #include <sys/errno.h> 41 1.1 jeremy #include <sys/device.h> 42 1.1 jeremy 43 1.1 jeremy #include <machine/autoconf.h> 44 1.1 jeremy #include <machine/dvma.h> 45 1.1 jeremy 46 1.6 bouyer #include <dev/scsipi/scsi_all.h> 47 1.6 bouyer #include <dev/scsipi/scsipi_all.h> 48 1.6 bouyer #include <dev/scsipi/scsiconf.h> 49 1.1 jeremy 50 1.4 gwr #include <dev/ic/ncr53c9xreg.h> 51 1.4 gwr #include <dev/ic/ncr53c9xvar.h> 52 1.4 gwr 53 1.8 gwr #include <sun3/dev/dmareg.h> 54 1.8 gwr #include <sun3/dev/dmavar.h> 55 1.1 jeremy 56 1.20 tsutsui #include "ioconf.h" 57 1.20 tsutsui 58 1.10 gwr #define MAX_DMA_SZ 0x01000000 /* 16MB */ 59 1.10 gwr 60 1.20 tsutsui static int dmamatch(device_t, cfdata_t, void *); 61 1.20 tsutsui static void dmaattach(device_t, device_t, void *); 62 1.10 gwr 63 1.20 tsutsui CFATTACH_DECL_NEW(dma, sizeof(struct dma_softc), 64 1.13 thorpej dmamatch, dmaattach, NULL, NULL); 65 1.10 gwr 66 1.25 tsutsui static int 67 1.20 tsutsui dmamatch(device_t parent, cfdata_t cf, void *aux) 68 1.1 jeremy { 69 1.10 gwr struct confargs *ca = aux; 70 1.1 jeremy 71 1.1 jeremy /* 72 1.10 gwr * Check for the DMA registers. 73 1.1 jeremy */ 74 1.10 gwr if (bus_peek(ca->ca_bustype, ca->ca_paddr, 4) == -1) 75 1.20 tsutsui return 0; 76 1.10 gwr 77 1.10 gwr /* If default ipl, fill it in. */ 78 1.10 gwr if (ca->ca_intpri == -1) 79 1.10 gwr ca->ca_intpri = 2; 80 1.1 jeremy 81 1.20 tsutsui return 1; 82 1.10 gwr } 83 1.1 jeremy 84 1.25 tsutsui static void 85 1.20 tsutsui dmaattach(device_t parent, device_t self, void *aux) 86 1.10 gwr { 87 1.20 tsutsui struct dma_softc *sc = device_private(self); 88 1.10 gwr struct confargs *ca = aux; 89 1.10 gwr int id; 90 1.4 gwr 91 1.20 tsutsui sc->sc_dev = self; 92 1.20 tsutsui 93 1.4 gwr #if 0 94 1.4 gwr /* indirect functions */ 95 1.4 gwr sc->intr = espdmaintr; 96 1.10 gwr sc->setup = dma_setup; 97 1.4 gwr sc->reset = dma_reset; 98 1.4 gwr #endif 99 1.4 gwr 100 1.10 gwr /* 101 1.10 gwr * Map in the registers. 102 1.10 gwr */ 103 1.17 tsutsui sc->sc_bst = ca->ca_bustag; 104 1.17 tsutsui sc->sc_dmatag = ca->ca_dmatag; 105 1.17 tsutsui if (bus_space_map(sc->sc_bst, ca->ca_paddr, DMAREG_SIZE, 106 1.17 tsutsui 0, &sc->sc_bsh) != 0) { 107 1.20 tsutsui aprint_error(": can't map register\n"); 108 1.17 tsutsui return; 109 1.17 tsutsui } 110 1.17 tsutsui /* 111 1.17 tsutsui * Allocate dmamap. 112 1.17 tsutsui */ 113 1.17 tsutsui if (bus_dmamap_create(sc->sc_dmatag, MAXPHYS, 1, MAXPHYS, 114 1.17 tsutsui 0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) { 115 1.20 tsutsui aprint_error(": can't create DMA map\n"); 116 1.17 tsutsui return; 117 1.17 tsutsui } 118 1.17 tsutsui 119 1.17 tsutsui sc->sc_rev = DMA_GCSR(sc) & D_DEV_ID; 120 1.10 gwr id = (sc->sc_rev >> 28) & 0xf; 121 1.20 tsutsui aprint_normal(": rev %d\n", id); 122 1.4 gwr 123 1.10 gwr /* 124 1.10 gwr * Make sure the DMA chip is supported revision. 125 1.10 gwr * The Sun3/80 used only the old rev zero chip, 126 1.10 gwr * so the initialization has been simplified. 127 1.10 gwr */ 128 1.1 jeremy switch (sc->sc_rev) { 129 1.1 jeremy case DMAREV_0: 130 1.1 jeremy case DMAREV_1: 131 1.1 jeremy break; 132 1.1 jeremy default: 133 1.10 gwr panic("unsupported dma rev"); 134 1.1 jeremy } 135 1.4 gwr } 136 1.1 jeremy 137 1.10 gwr /* 138 1.10 gwr * This is called by espattach to get our softc. 139 1.10 gwr */ 140 1.10 gwr struct dma_softc * 141 1.10 gwr espdmafind(int unit) 142 1.10 gwr { 143 1.20 tsutsui struct dma_softc *dma; 144 1.20 tsutsui 145 1.20 tsutsui dma = device_lookup_private(&dma_cd, unit); 146 1.20 tsutsui if (dma == NULL) 147 1.20 tsutsui panic("%s: no dma", __func__); 148 1.20 tsutsui return dma; 149 1.10 gwr } 150 1.1 jeremy 151 1.1 jeremy #define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) { \ 152 1.10 gwr int count = 100000; \ 153 1.17 tsutsui while ((COND) && --count > 0) \ 154 1.17 tsutsui DELAY(5); \ 155 1.1 jeremy if (count == 0) { \ 156 1.10 gwr printf("%s: line %d: CSR = 0x%x\n", \ 157 1.17 tsutsui __FILE__, __LINE__, DMA_GCSR(SC)); \ 158 1.1 jeremy if (DONTPANIC) \ 159 1.1 jeremy printf(MSG); \ 160 1.1 jeremy else \ 161 1.1 jeremy panic(MSG); \ 162 1.1 jeremy } \ 163 1.17 tsutsui } while (/* CONSTCOND */0) 164 1.1 jeremy 165 1.1 jeremy #define DMA_DRAIN(sc, dontpanic) do { \ 166 1.17 tsutsui uint32_t _csr; \ 167 1.1 jeremy /* \ 168 1.1 jeremy * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ 169 1.1 jeremy * and "drain" bits while it is still thinking about a \ 170 1.1 jeremy * request. \ 171 1.1 jeremy * other revs: D_R_PEND bit reads as 0 \ 172 1.1 jeremy */ \ 173 1.17 tsutsui DMAWAIT(sc, DMA_GCSR(sc) & D_R_PEND, "R_PEND", dontpanic); \ 174 1.1 jeremy /* \ 175 1.10 gwr * Select drain bit (always rev 0,1) \ 176 1.1 jeremy * also clears errors and D_TC flag \ 177 1.1 jeremy */ \ 178 1.17 tsutsui _csr = DMA_GCSR(sc); \ 179 1.17 tsutsui _csr |= D_DRAIN; \ 180 1.17 tsutsui DMA_SCSR(sc, _csr); \ 181 1.1 jeremy /* \ 182 1.1 jeremy * Wait for draining to finish \ 183 1.1 jeremy */ \ 184 1.17 tsutsui DMAWAIT(sc, DMA_GCSR(sc) & D_PACKCNT, "DRAINING", dontpanic); \ 185 1.17 tsutsui } while (/* CONSTCOND */0) 186 1.10 gwr 187 1.10 gwr #define DMA_FLUSH(sc, dontpanic) do { \ 188 1.17 tsutsui uint32_t _csr; \ 189 1.10 gwr /* \ 190 1.10 gwr * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ 191 1.10 gwr * and "drain" bits while it is still thinking about a \ 192 1.10 gwr * request. \ 193 1.10 gwr * other revs: D_R_PEND bit reads as 0 \ 194 1.10 gwr */ \ 195 1.17 tsutsui DMAWAIT(sc, DMA_GCSR(sc) & D_R_PEND, "R_PEND", dontpanic); \ 196 1.17 tsutsui _csr = DMA_GCSR(sc); \ 197 1.17 tsutsui _csr &= ~(D_WRITE|D_EN_DMA); \ 198 1.17 tsutsui DMA_SCSR(sc, _csr); \ 199 1.17 tsutsui _csr |= D_FLUSH; \ 200 1.17 tsutsui DMA_SCSR(sc, _csr); \ 201 1.17 tsutsui } while (/* CONSTCOND */0) 202 1.1 jeremy 203 1.25 tsutsui void 204 1.15 chs dma_reset(struct dma_softc *sc) 205 1.1 jeremy { 206 1.17 tsutsui uint32_t csr; 207 1.17 tsutsui 208 1.17 tsutsui if (sc->sc_dmamap->dm_nsegs > 0) 209 1.17 tsutsui bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap); 210 1.10 gwr 211 1.10 gwr DMA_FLUSH(sc, 1); 212 1.17 tsutsui csr = DMA_GCSR(sc); 213 1.17 tsutsui 214 1.17 tsutsui csr |= D_RESET; /* reset DMA */ 215 1.17 tsutsui DMA_SCSR(sc, csr); 216 1.10 gwr DELAY(200); /* what should this be ? */ 217 1.17 tsutsui 218 1.1 jeremy /*DMAWAIT1(sc); why was this here? */ 219 1.17 tsutsui csr = DMA_GCSR(sc); 220 1.17 tsutsui csr &= ~D_RESET; /* de-assert reset line */ 221 1.17 tsutsui DMA_SCSR(sc, csr); 222 1.10 gwr DELAY(5); /* allow a few ticks to settle */ 223 1.1 jeremy 224 1.10 gwr /* 225 1.10 gwr * Get transfer burst size from (?) and plug it into the 226 1.10 gwr * controller registers. This is needed on the Sun4m... 227 1.10 gwr * Do we need it too? Apparently not, because the 3/80 228 1.10 gwr * always has the old, REV zero DMA chip. 229 1.10 gwr */ 230 1.17 tsutsui csr = DMA_GCSR(sc); 231 1.17 tsutsui csr |= D_INT_EN; /* enable interrupts */ 232 1.17 tsutsui 233 1.17 tsutsui DMA_SCSR(sc, csr); 234 1.1 jeremy 235 1.10 gwr sc->sc_active = 0; 236 1.1 jeremy } 237 1.1 jeremy 238 1.1 jeremy 239 1.10 gwr #define DMAMAX(a) (MAX_DMA_SZ - ((a) & (MAX_DMA_SZ-1))) 240 1.1 jeremy 241 1.1 jeremy /* 242 1.1 jeremy * setup a dma transfer 243 1.1 jeremy */ 244 1.25 tsutsui int 245 1.20 tsutsui dma_setup(struct dma_softc *sc, uint8_t **addr, size_t *len, int datain, 246 1.15 chs size_t *dmasize) 247 1.1 jeremy { 248 1.15 chs uint32_t csr; 249 1.1 jeremy 250 1.10 gwr DMA_FLUSH(sc, 0); 251 1.1 jeremy 252 1.1 jeremy #if 0 253 1.17 tsutsui DMA_SCSR(sc, DMA_GCSR(sc) & ~D_INT_EN); 254 1.1 jeremy #endif 255 1.1 jeremy sc->sc_dmaaddr = addr; 256 1.1 jeremy sc->sc_dmalen = len; 257 1.1 jeremy 258 1.20 tsutsui NCR_DMA(("%s: start %d@%p,%d\n", device_xname(sc->sc_dev), 259 1.20 tsutsui *sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0)); 260 1.1 jeremy 261 1.1 jeremy /* 262 1.1 jeremy * the rules say we cannot transfer more than the limit 263 1.1 jeremy * of this DMA chip (64k for old and 16Mb for new), 264 1.1 jeremy * and we cannot cross a 16Mb boundary. 265 1.1 jeremy */ 266 1.1 jeremy *dmasize = sc->sc_dmasize = 267 1.23 riastrad uimin(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr)); 268 1.1 jeremy 269 1.20 tsutsui NCR_DMA(("%s: dmasize = %d\n", __func__, sc->sc_dmasize)); 270 1.1 jeremy 271 1.1 jeremy /* Program the DMA address */ 272 1.1 jeremy if (sc->sc_dmasize) { 273 1.17 tsutsui if (bus_dmamap_load(sc->sc_dmatag, sc->sc_dmamap, 274 1.17 tsutsui *sc->sc_dmaaddr, sc->sc_dmasize, 275 1.17 tsutsui NULL /* kernel address */, BUS_DMA_NOWAIT)) 276 1.17 tsutsui panic("%s: cannot allocate DVMA address", 277 1.20 tsutsui device_xname(sc->sc_dev)); 278 1.17 tsutsui bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, 0, sc->sc_dmasize, 279 1.17 tsutsui datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 280 1.17 tsutsui bus_space_write_4(sc->sc_bst, sc->sc_bsh, DMA_REG_ADDR, 281 1.17 tsutsui sc->sc_dmamap->dm_segs[0].ds_addr); 282 1.10 gwr } 283 1.10 gwr 284 1.10 gwr /* We never have DMAREV_ESC. */ 285 1.1 jeremy 286 1.1 jeremy /* Setup DMA control register */ 287 1.17 tsutsui csr = DMA_GCSR(sc); 288 1.1 jeremy if (datain) 289 1.1 jeremy csr |= D_WRITE; 290 1.1 jeremy else 291 1.1 jeremy csr &= ~D_WRITE; 292 1.1 jeremy csr |= D_INT_EN; 293 1.17 tsutsui DMA_SCSR(sc, csr); 294 1.1 jeremy 295 1.1 jeremy return 0; 296 1.1 jeremy } 297 1.1 jeremy 298 1.1 jeremy /* 299 1.1 jeremy * Pseudo (chained) interrupt from the esp driver to kick the 300 1.10 gwr * current running DMA transfer. I am relying on espintr() to 301 1.1 jeremy * pickup and clean errors for now 302 1.1 jeremy * 303 1.1 jeremy * return 1 if it was a DMA continue. 304 1.1 jeremy */ 305 1.25 tsutsui int 306 1.15 chs espdmaintr(struct dma_softc *sc) 307 1.1 jeremy { 308 1.17 tsutsui struct ncr53c9x_softc *nsc = sc->sc_client; 309 1.1 jeremy char bits[64]; 310 1.1 jeremy int trans, resid; 311 1.15 chs uint32_t csr; 312 1.10 gwr 313 1.17 tsutsui csr = DMA_GCSR(sc); 314 1.1 jeremy 315 1.21 christos #ifdef NCR53C9X_DEBUG 316 1.21 christos if (ncr53c9x_debug & NCR_SHOWDMA) 317 1.21 christos snprintb(bits, sizeof(bits), DMACSRBITS, csr); 318 1.21 christos #endif 319 1.10 gwr NCR_DMA(("%s: intr: addr 0x%x, csr %s\n", 320 1.21 christos device_xname(sc->sc_dev), DMADDR(sc), bits)); 321 1.1 jeremy 322 1.1 jeremy if (csr & D_ERR_PEND) { 323 1.21 christos snprintb(bits, sizeof(bits), DMACSRBITS, csr); 324 1.21 christos printf("%s: error: csr=%s\n", device_xname(sc->sc_dev), bits); 325 1.17 tsutsui csr &= ~D_EN_DMA; /* Stop DMA */ 326 1.17 tsutsui DMA_SCSR(sc, csr); 327 1.17 tsutsui csr |= D_FLUSH; 328 1.17 tsutsui DMA_SCSR(sc, csr); 329 1.17 tsutsui return -1; 330 1.1 jeremy } 331 1.1 jeremy 332 1.1 jeremy /* This is an "assertion" :) */ 333 1.1 jeremy if (sc->sc_active == 0) 334 1.20 tsutsui panic("%s: DMA wasn't active", __func__); 335 1.1 jeremy 336 1.1 jeremy DMA_DRAIN(sc, 0); 337 1.1 jeremy 338 1.1 jeremy /* DMA has stopped */ 339 1.17 tsutsui csr &= ~D_EN_DMA; 340 1.17 tsutsui DMA_SCSR(sc, csr); 341 1.1 jeremy sc->sc_active = 0; 342 1.1 jeremy 343 1.1 jeremy if (sc->sc_dmasize == 0) { 344 1.1 jeremy /* A "Transfer Pad" operation completed */ 345 1.20 tsutsui NCR_DMA(("%s: discarded %d bytes (tcl=%d, tcm=%d)\n", 346 1.20 tsutsui __func__, 347 1.20 tsutsui NCR_READ_REG(nsc, NCR_TCL) | 348 1.20 tsutsui (NCR_READ_REG(nsc, NCR_TCM) << 8), 349 1.20 tsutsui NCR_READ_REG(nsc, NCR_TCL), 350 1.20 tsutsui NCR_READ_REG(nsc, NCR_TCM))); 351 1.1 jeremy return 0; 352 1.1 jeremy } 353 1.1 jeremy 354 1.1 jeremy resid = 0; 355 1.1 jeremy /* 356 1.1 jeremy * If a transfer onto the SCSI bus gets interrupted by the device 357 1.1 jeremy * (e.g. for a SAVEPOINTER message), the data in the FIFO counts 358 1.1 jeremy * as residual since the ESP counter registers get decremented as 359 1.1 jeremy * bytes are clocked into the FIFO. 360 1.1 jeremy */ 361 1.1 jeremy if (!(csr & D_WRITE) && 362 1.4 gwr (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { 363 1.20 tsutsui NCR_DMA(("%s: empty esp FIFO of %d ", __func__, resid)); 364 1.1 jeremy } 365 1.1 jeremy 366 1.4 gwr if ((nsc->sc_espstat & NCRSTAT_TC) == 0) { 367 1.1 jeremy /* 368 1.1 jeremy * `Terminal count' is off, so read the residue 369 1.1 jeremy * out of the ESP counter registers. 370 1.1 jeremy */ 371 1.4 gwr resid += (NCR_READ_REG(nsc, NCR_TCL) | 372 1.20 tsutsui (NCR_READ_REG(nsc, NCR_TCM) << 8) | 373 1.20 tsutsui ((nsc->sc_cfg2 & NCRCFG2_FE) ? 374 1.20 tsutsui (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0)); 375 1.1 jeremy 376 1.1 jeremy if (resid == 0 && sc->sc_dmasize == 65536 && 377 1.4 gwr (nsc->sc_cfg2 & NCRCFG2_FE) == 0) 378 1.1 jeremy /* A transfer of 64K is encoded as `TCL=TCM=0' */ 379 1.1 jeremy resid = 65536; 380 1.1 jeremy } 381 1.1 jeremy 382 1.1 jeremy trans = sc->sc_dmasize - resid; 383 1.1 jeremy if (trans < 0) { /* transferred < 0 ? */ 384 1.10 gwr #if 0 385 1.5 jeremy /* 386 1.5 jeremy * This situation can happen in perfectly normal operation 387 1.5 jeremy * if the ESP is reselected while using DMA to select 388 1.5 jeremy * another target. As such, don't print the warning. 389 1.5 jeremy */ 390 1.1 jeremy printf("%s: xfer (%d) > req (%d)\n", 391 1.22 tsutsui device_xname(sc->sc_dev), trans, sc->sc_dmasize); 392 1.5 jeremy #endif 393 1.1 jeremy trans = sc->sc_dmasize; 394 1.1 jeremy } 395 1.1 jeremy 396 1.20 tsutsui NCR_DMA(("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", 397 1.20 tsutsui __func__, 398 1.20 tsutsui NCR_READ_REG(nsc, NCR_TCL), 399 1.20 tsutsui NCR_READ_REG(nsc, NCR_TCM), 400 1.20 tsutsui (nsc->sc_cfg2 & NCRCFG2_FE) ? 401 1.20 tsutsui NCR_READ_REG(nsc, NCR_TCH) : 0, 402 1.20 tsutsui trans, resid)); 403 1.1 jeremy 404 1.1 jeremy #ifdef SUN3X_470_EVENTUALLY 405 1.1 jeremy if (csr & D_WRITE) 406 1.1 jeremy cache_flush(*sc->sc_dmaaddr, trans); 407 1.1 jeremy #endif 408 1.1 jeremy 409 1.17 tsutsui if (sc->sc_dmamap->dm_nsegs > 0) { 410 1.17 tsutsui bus_dmamap_sync(sc->sc_dmatag, sc->sc_dmamap, 0, sc->sc_dmasize, 411 1.17 tsutsui (csr & D_WRITE) != 0 ? 412 1.17 tsutsui BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 413 1.17 tsutsui bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap); 414 1.17 tsutsui } 415 1.1 jeremy 416 1.1 jeremy *sc->sc_dmalen -= trans; 417 1.20 tsutsui *sc->sc_dmaaddr += trans; 418 1.1 jeremy 419 1.1 jeremy #if 0 /* this is not normal operation just yet */ 420 1.1 jeremy if (*sc->sc_dmalen == 0 || 421 1.4 gwr nsc->sc_phase != nsc->sc_prevphase) 422 1.1 jeremy return 0; 423 1.1 jeremy 424 1.1 jeremy /* and again */ 425 1.17 tsutsui dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMA_GCSR(sc) & D_WRITE); 426 1.1 jeremy return 1; 427 1.1 jeremy #endif 428 1.1 jeremy return 0; 429 1.1 jeremy } 430