1 /* $NetBSD: dma.c,v 1.9 1998/12/13 18:00:10 kleink Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Paul Kranenburg. All rights reserved. 5 * Copyright (c) 1994 Peter Galbavy. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Peter Galbavy. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/errno.h> 38 #include <sys/ioctl.h> 39 #include <sys/device.h> 40 #include <sys/malloc.h> 41 #include <sys/buf.h> 42 #include <sys/proc.h> 43 #include <sys/user.h> 44 45 #include <machine/autoconf.h> 46 #include <machine/dvma.h> 47 48 #include <dev/scsipi/scsi_all.h> 49 #include <dev/scsipi/scsipi_all.h> 50 #include <dev/scsipi/scsiconf.h> 51 52 #include <dev/ic/ncr53c9xreg.h> 53 #include <dev/ic/ncr53c9xvar.h> 54 55 #include <sun3/dev/dmareg.h> 56 #include <sun3/dev/dmavar.h> 57 58 /* 59 * Pseudo-attach function. Called from the esp driver during its 60 * attach function. This needs to be silent. 61 */ 62 void 63 dmaattach(parent, self, aux) 64 struct device *parent, *self; 65 void *aux; 66 { 67 struct dma_softc *sc = (void *)self; 68 69 /* 70 * The esp driver has filled in the virtual address used to 71 * address the dma registers at this point. Normally we would 72 * map them in here and assign them ourselves. 73 * 74 * It has also filled itself in to our sc->sc_esp register. 75 */ 76 77 /* 78 * Get transfer burst size from PROM and plug it into the 79 * controller registers. This is needed on the Sun4m; do 80 * others need it too? 81 * 82 * Sun3x works ok (so far) without it. 83 */ 84 85 sc->sc_rev = sc->sc_regs->csr & D_DEV_ID; 86 87 #if 0 88 /* indirect functions */ 89 sc->intr = espdmaintr; 90 sc->enintr = dma_enintr; 91 sc->isintr = dma_isintr; 92 sc->reset = dma_reset; 93 sc->setup = dma_setup; 94 sc->go = dma_go; 95 #endif 96 } 97 98 void 99 dma_print_rev(sc) 100 struct dma_softc *sc; 101 { 102 103 printf("espdma: rev "); 104 switch (sc->sc_rev) { 105 case DMAREV_0: 106 printf("0"); 107 break; 108 case DMAREV_ESC: 109 printf("esc"); 110 break; 111 case DMAREV_1: 112 printf("1"); 113 break; 114 case DMAREV_PLUS: 115 printf("1+"); 116 break; 117 case DMAREV_2: 118 printf("2"); 119 break; 120 default: 121 printf("unknown (0x%x)", sc->sc_rev); 122 } 123 printf("\n"); 124 } 125 126 127 #define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) { \ 128 int count = 500000; \ 129 while ((COND) && --count > 0) DELAY(1); \ 130 if (count == 0) { \ 131 printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \ 132 (SC)->sc_regs->csr); \ 133 if (DONTPANIC) \ 134 printf(MSG); \ 135 else \ 136 panic(MSG); \ 137 } \ 138 } while (0) 139 140 #define DMA_DRAIN(sc, dontpanic) do { \ 141 /* \ 142 * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ 143 * and "drain" bits while it is still thinking about a \ 144 * request. \ 145 * other revs: D_R_PEND bit reads as 0 \ 146 */ \ 147 DMAWAIT(sc, sc->sc_regs->csr & D_R_PEND, "R_PEND", dontpanic); \ 148 /* \ 149 * Select drain bit based on revision \ 150 * also clears errors and D_TC flag \ 151 */ \ 152 if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0) \ 153 DMACSR(sc) |= D_DRAIN; \ 154 else \ 155 DMACSR(sc) |= D_INVALIDATE; \ 156 /* \ 157 * Wait for draining to finish \ 158 * rev0 & rev1 call this PACKCNT \ 159 */ \ 160 DMAWAIT(sc, sc->sc_regs->csr & D_DRAINING, "DRAINING", dontpanic);\ 161 } while(0) 162 163 void 164 dma_reset(sc) 165 struct dma_softc *sc; 166 { 167 DMA_DRAIN(sc, 1); 168 DMACSR(sc) &= ~D_EN_DMA; /* Stop DMA */ 169 DMACSR(sc) |= D_RESET; /* reset DMA */ 170 DELAY(200); /* what should this be ? */ 171 /*DMAWAIT1(sc); why was this here? */ 172 DMACSR(sc) &= ~D_RESET; /* de-assert reset line */ 173 DMACSR(sc) |= D_INT_EN; /* enable interrupts */ 174 175 sc->sc_active = 0; /* and of course we aren't */ 176 } 177 178 179 void 180 dma_enintr(sc) 181 struct dma_softc *sc; 182 { 183 sc->sc_regs->csr |= D_INT_EN; 184 } 185 186 int 187 dma_isintr(sc) 188 struct dma_softc *sc; 189 { 190 return (sc->sc_regs->csr & (D_INT_PEND|D_ERR_PEND)); 191 } 192 193 #define DMAMAX(a) (0x01000000 - ((a) & 0x00ffffff)) 194 195 196 /* 197 * setup a dma transfer 198 */ 199 int 200 dma_setup(sc, addr, len, datain, dmasize) 201 struct dma_softc *sc; 202 caddr_t *addr; 203 size_t *len; 204 int datain; 205 size_t *dmasize; /* IN-OUT */ 206 { 207 u_long csr; 208 209 DMA_DRAIN(sc, 0); 210 211 #if 0 212 DMACSR(sc) &= ~D_INT_EN; 213 #endif 214 sc->sc_dmaaddr = addr; 215 sc->sc_dmalen = len; 216 217 NCR_DMA(("%s: start %d@%p,%d\n", sc->sc_dev.dv_xname, 218 *sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0)); 219 220 /* 221 * the rules say we cannot transfer more than the limit 222 * of this DMA chip (64k for old and 16Mb for new), 223 * and we cannot cross a 16Mb boundary. 224 */ 225 *dmasize = sc->sc_dmasize = 226 min(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr)); 227 228 NCR_DMA(("dma_setup: dmasize = %d\n", sc->sc_dmasize)); 229 230 /* Program the DMA address */ 231 if (sc->sc_dmasize) { 232 /* 233 * Use dvma mapin routines to map the buffer into DVMA space. 234 */ 235 sc->sc_dvmaaddr = *sc->sc_dmaaddr; 236 sc->sc_dvmakaddr = dvma_mapin(sc->sc_dvmaaddr, 237 sc->sc_dmasize, 0); 238 if (sc->sc_dvmakaddr == NULL) 239 panic("dma: cannot allocate DVMA address"); 240 sc->sc_dmasaddr = dvma_kvtopa(sc->sc_dvmakaddr, BUS_OBIO); 241 DMADDR(sc) = sc->sc_dmasaddr; 242 } else 243 DMADDR(sc) = (u_long) *sc->sc_dmaaddr; 244 245 if (sc->sc_rev == DMAREV_ESC) { 246 /* DMA ESC chip bug work-around */ 247 register long bcnt = sc->sc_dmasize; 248 register long eaddr = bcnt + (long)*sc->sc_dmaaddr; 249 if ((eaddr & PGOFSET) != 0) 250 bcnt = roundup(bcnt, NBPG); 251 DMACNT(sc) = bcnt; 252 } 253 /* Setup DMA control register */ 254 csr = DMACSR(sc); 255 if (datain) 256 csr |= D_WRITE; 257 else 258 csr &= ~D_WRITE; 259 csr |= D_INT_EN; 260 DMACSR(sc) = csr; 261 262 return 0; 263 } 264 265 void 266 dma_go(sc) 267 struct dma_softc *sc; 268 { 269 270 /* Start DMA */ 271 DMACSR(sc) |= D_EN_DMA; 272 sc->sc_active = 1; 273 } 274 275 /* 276 * Pseudo (chained) interrupt from the esp driver to kick the 277 * current running DMA transfer. I am replying on espintr() to 278 * pickup and clean errors for now 279 * 280 * return 1 if it was a DMA continue. 281 */ 282 int 283 espdmaintr(sc) 284 struct dma_softc *sc; 285 { 286 struct ncr53c9x_softc *nsc = sc->sc_esp; 287 char bits[64]; 288 int trans, resid; 289 u_long csr; 290 csr = DMACSR(sc); 291 292 NCR_DMA(("%s: intr: addr 0x%lx, csr %s\n", 293 sc->sc_dev.dv_xname, DMADDR(sc), 294 bitmask_snprintf(csr, DMACSRBITS, bits, sizeof(bits)))); 295 296 if (csr & D_ERR_PEND) { 297 DMACSR(sc) &= ~D_EN_DMA; /* Stop DMA */ 298 DMACSR(sc) |= D_INVALIDATE; 299 printf("%s: error: csr=%s\n", sc->sc_dev.dv_xname, 300 bitmask_snprintf(csr, DMACSRBITS, bits, sizeof(bits))); 301 return -1; 302 } 303 304 /* This is an "assertion" :) */ 305 if (sc->sc_active == 0) 306 panic("dmaintr: DMA wasn't active"); 307 308 DMA_DRAIN(sc, 0); 309 310 /* DMA has stopped */ 311 DMACSR(sc) &= ~D_EN_DMA; 312 sc->sc_active = 0; 313 314 if (sc->sc_dmasize == 0) { 315 /* A "Transfer Pad" operation completed */ 316 NCR_DMA(("dmaintr: discarded %d bytes (tcl=%d, tcm=%d)\n", 317 NCR_READ_REG(nsc, NCR_TCL) | 318 (NCR_READ_REG(nsc, NCR_TCM) << 8), 319 NCR_READ_REG(nsc, NCR_TCL), 320 NCR_READ_REG(nsc, NCR_TCM))); 321 return 0; 322 } 323 324 resid = 0; 325 /* 326 * If a transfer onto the SCSI bus gets interrupted by the device 327 * (e.g. for a SAVEPOINTER message), the data in the FIFO counts 328 * as residual since the ESP counter registers get decremented as 329 * bytes are clocked into the FIFO. 330 */ 331 if (!(csr & D_WRITE) && 332 (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) { 333 NCR_DMA(("dmaintr: empty esp FIFO of %d ", resid)); 334 } 335 336 if ((nsc->sc_espstat & NCRSTAT_TC) == 0) { 337 /* 338 * `Terminal count' is off, so read the residue 339 * out of the ESP counter registers. 340 */ 341 resid += (NCR_READ_REG(nsc, NCR_TCL) | 342 (NCR_READ_REG(nsc, NCR_TCM) << 8) | 343 ((nsc->sc_cfg2 & NCRCFG2_FE) 344 ? (NCR_READ_REG(nsc, NCR_TCH) << 16) 345 : 0)); 346 347 if (resid == 0 && sc->sc_dmasize == 65536 && 348 (nsc->sc_cfg2 & NCRCFG2_FE) == 0) 349 /* A transfer of 64K is encoded as `TCL=TCM=0' */ 350 resid = 65536; 351 } 352 353 trans = sc->sc_dmasize - resid; 354 if (trans < 0) { /* transferred < 0 ? */ 355 #if 0 356 /* 357 * This situation can happen in perfectly normal operation 358 * if the ESP is reselected while using DMA to select 359 * another target. As such, don't print the warning. 360 */ 361 printf("%s: xfer (%d) > req (%d)\n", 362 sc->sc_dev.dv_xname, trans, sc->sc_dmasize); 363 #endif 364 trans = sc->sc_dmasize; 365 } 366 367 NCR_DMA(("dmaintr: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n", 368 NCR_READ_REG(nsc, NCR_TCL), 369 NCR_READ_REG(nsc, NCR_TCM), 370 (nsc->sc_cfg2 & NCRCFG2_FE) 371 ? NCR_READ_REG(nsc, NCR_TCH) : 0, 372 trans, resid)); 373 374 #ifdef SUN3X_470_EVENTUALLY 375 if (csr & D_WRITE) 376 cache_flush(*sc->sc_dmaaddr, trans); 377 #endif 378 379 if (sc->sc_dvmakaddr) 380 dvma_mapout(sc->sc_dvmakaddr, sc->sc_dmasize); 381 382 *sc->sc_dmalen -= trans; 383 *sc->sc_dmaaddr += trans; 384 385 #if 0 /* this is not normal operation just yet */ 386 if (*sc->sc_dmalen == 0 || 387 nsc->sc_phase != nsc->sc_prevphase) 388 return 0; 389 390 /* and again */ 391 dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE); 392 return 1; 393 #endif 394 return 0; 395 } 396