1 /* $NetBSD: dma.c,v 1.14 2003/07/15 03:36:14 lukem 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/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: dma.c,v 1.14 2003/07/15 03:36:14 lukem Exp $"); 35 36 #include <sys/types.h> 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/errno.h> 41 #include <sys/device.h> 42 #include <sys/malloc.h> 43 44 #include <machine/autoconf.h> 45 #include <machine/dvma.h> 46 47 #include <dev/scsipi/scsi_all.h> 48 #include <dev/scsipi/scsipi_all.h> 49 #include <dev/scsipi/scsiconf.h> 50 51 #include <dev/ic/ncr53c9xreg.h> 52 #include <dev/ic/ncr53c9xvar.h> 53 54 #include <sun3/dev/dmareg.h> 55 #include <sun3/dev/dmavar.h> 56 57 #define MAX_DMA_SZ 0x01000000 /* 16MB */ 58 59 static int dmamatch __P((struct device *, struct cfdata *, void *)); 60 static void dmaattach __P((struct device *, struct device *, void *)); 61 62 CFATTACH_DECL(dma, sizeof(struct dma_softc), 63 dmamatch, dmaattach, NULL, NULL); 64 65 extern struct cfdriver dma_cd; 66 67 static int 68 dmamatch(parent, cf, aux) 69 struct device *parent; 70 struct cfdata *cf; 71 void *aux; 72 { 73 struct confargs *ca = aux; 74 75 /* 76 * Check for the DMA registers. 77 */ 78 if (bus_peek(ca->ca_bustype, ca->ca_paddr, 4) == -1) 79 return (0); 80 81 /* If default ipl, fill it in. */ 82 if (ca->ca_intpri == -1) 83 ca->ca_intpri = 2; 84 85 return (1); 86 } 87 88 static void 89 dmaattach(parent, self, aux) 90 struct device *parent, *self; 91 void *aux; 92 { 93 struct confargs *ca = aux; 94 struct dma_softc *sc = (void *)self; 95 int id; 96 97 #if 0 98 /* indirect functions */ 99 sc->intr = espdmaintr; 100 sc->setup = dma_setup; 101 sc->reset = dma_reset; 102 #endif 103 104 /* 105 * Map in the registers. 106 */ 107 sc->sc_regs = bus_mapin(ca->ca_bustype, ca->ca_paddr, 108 sizeof(struct dma_regs)); 109 sc->sc_rev = DMACSR(sc) & D_DEV_ID; 110 id = (sc->sc_rev >> 28) & 0xf; 111 printf(": rev %d\n", id); 112 113 /* 114 * Make sure the DMA chip is supported revision. 115 * The Sun3/80 used only the old rev zero chip, 116 * so the initialization has been simplified. 117 */ 118 switch (sc->sc_rev) { 119 case DMAREV_0: 120 case DMAREV_1: 121 break; 122 default: 123 panic("unsupported dma rev"); 124 } 125 } 126 127 /* 128 * This is called by espattach to get our softc. 129 */ 130 struct dma_softc * 131 espdmafind(int unit) 132 { 133 if (unit < 0 || unit >= dma_cd.cd_ndevs || 134 dma_cd.cd_devs[unit] == NULL) 135 panic("no dma"); 136 return (dma_cd.cd_devs[unit]); 137 } 138 139 #define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) { \ 140 int count = 100000; \ 141 while ((COND) && --count > 0) DELAY(5); \ 142 if (count == 0) { \ 143 printf("%s: line %d: CSR = 0x%x\n", \ 144 __FILE__, __LINE__, DMACSR(SC)); \ 145 if (DONTPANIC) \ 146 printf(MSG); \ 147 else \ 148 panic(MSG); \ 149 } \ 150 } while (0) 151 152 #define DMA_DRAIN(sc, dontpanic) do { \ 153 /* \ 154 * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ 155 * and "drain" bits while it is still thinking about a \ 156 * request. \ 157 * other revs: D_R_PEND bit reads as 0 \ 158 */ \ 159 DMAWAIT(sc, DMACSR(sc) & D_R_PEND, "R_PEND", dontpanic); \ 160 /* \ 161 * Select drain bit (always rev 0,1) \ 162 * also clears errors and D_TC flag \ 163 */ \ 164 DMACSR(sc) |= D_DRAIN; \ 165 /* \ 166 * Wait for draining to finish \ 167 */ \ 168 DMAWAIT(sc, DMACSR(sc) & D_PACKCNT, "DRAINING", dontpanic); \ 169 } while(0) 170 171 #define DMA_FLUSH(sc, dontpanic) do { \ 172 /* \ 173 * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \ 174 * and "drain" bits while it is still thinking about a \ 175 * request. \ 176 * other revs: D_R_PEND bit reads as 0 \ 177 */ \ 178 DMAWAIT(sc, DMACSR(sc) & D_R_PEND, "R_PEND", dontpanic); \ 179 DMACSR(sc) &= ~(D_WRITE|D_EN_DMA); \ 180 DMACSR(sc) |= D_FLUSH; \ 181 } while(0) 182 183 void 184 dma_reset(sc) 185 struct dma_softc *sc; 186 { 187 188 DMA_FLUSH(sc, 1); 189 DMACSR(sc) |= D_RESET; /* reset DMA */ 190 DELAY(200); /* what should this be ? */ 191 /*DMAWAIT1(sc); why was this here? */ 192 DMACSR(sc) &= ~D_RESET; /* de-assert reset line */ 193 DELAY(5); /* allow a few ticks to settle */ 194 195 /* 196 * Get transfer burst size from (?) and plug it into the 197 * controller registers. This is needed on the Sun4m... 198 * Do we need it too? Apparently not, because the 3/80 199 * always has the old, REV zero DMA chip. 200 */ 201 DMACSR(sc) |= D_INT_EN; /* enable interrupts */ 202 203 sc->sc_active = 0; 204 } 205 206 207 #define DMAMAX(a) (MAX_DMA_SZ - ((a) & (MAX_DMA_SZ-1))) 208 209 /* 210 * setup a dma transfer 211 */ 212 int 213 dma_setup(sc, addr, len, datain, dmasize) 214 struct dma_softc *sc; 215 caddr_t *addr; 216 size_t *len; 217 int datain; 218 size_t *dmasize; /* IN-OUT */ 219 { 220 u_int32_t csr; 221 222 DMA_FLUSH(sc, 0); 223 224 #if 0 225 DMACSR(sc) &= ~D_INT_EN; 226 #endif 227 sc->sc_dmaaddr = addr; 228 sc->sc_dmalen = len; 229 230 NCR_DMA(("%s: start %d@%p,%d\n", sc->sc_dev.dv_xname, 231 *sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0)); 232 233 /* 234 * the rules say we cannot transfer more than the limit 235 * of this DMA chip (64k for old and 16Mb for new), 236 * and we cannot cross a 16Mb boundary. 237 */ 238 *dmasize = sc->sc_dmasize = 239 min(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr)); 240 241 NCR_DMA(("dma_setup: dmasize = %d\n", sc->sc_dmasize)); 242 243 /* Program the DMA address */ 244 if (sc->sc_dmasize) { 245 /* 246 * Use dvma mapin routines to map the buffer into DVMA space. 247 */ 248 sc->sc_dvmaaddr = *sc->sc_dmaaddr; 249 sc->sc_dvmakaddr = dvma_mapin(sc->sc_dvmaaddr, 250 sc->sc_dmasize, 0); 251 if (sc->sc_dvmakaddr == NULL) 252 panic("dma: cannot allocate DVMA address"); 253 sc->sc_dmasaddr = dvma_kvtopa(sc->sc_dvmakaddr, BUS_OBIO); 254 DMADDR(sc) = sc->sc_dmasaddr; 255 } else { 256 /* XXX: What is this about? -gwr */ 257 DMADDR(sc) = (u_int32_t) *sc->sc_dmaaddr; 258 } 259 260 /* We never have DMAREV_ESC. */ 261 262 /* Setup DMA control register */ 263 csr = DMACSR(sc); 264 if (datain) 265 csr |= D_WRITE; 266 else 267 csr &= ~D_WRITE; 268 csr |= D_INT_EN; 269 DMACSR(sc) = csr; 270 271 return 0; 272 } 273 274 /* 275 * Pseudo (chained) interrupt from the esp driver to kick the 276 * current running DMA transfer. I am relying on espintr() to 277 * pickup and clean errors for now 278 * 279 * return 1 if it was a DMA continue. 280 */ 281 int 282 espdmaintr(sc) 283 struct dma_softc *sc; 284 { 285 struct ncr53c9x_softc *nsc = sc->sc_esp; 286 char bits[64]; 287 int trans, resid; 288 u_int32_t csr; 289 290 csr = DMACSR(sc); 291 292 NCR_DMA(("%s: intr: addr 0x%x, 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_FLUSH; 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