|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)dma.c 7.5 (Berkeley) 5/4/91 ! 34: */ ! 35: ! 36: /* ! 37: * DMA driver ! 38: */ ! 39: ! 40: #include "param.h" ! 41: #include "systm.h" ! 42: #include "time.h" ! 43: #include "kernel.h" ! 44: #include "proc.h" ! 45: ! 46: #include "dmareg.h" ! 47: #include "dmavar.h" ! 48: #include "device.h" ! 49: ! 50: #include "../include/cpu.h" ! 51: #include "../hp300/isr.h" ! 52: ! 53: extern void isrlink(); ! 54: extern void _insque(); ! 55: extern void _remque(); ! 56: extern void timeout(); ! 57: extern u_int kvtop(); ! 58: extern void PCIA(); ! 59: ! 60: /* ! 61: * The largest single request will be MAXPHYS bytes which will require ! 62: * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of ! 63: * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the ! 64: * buffer is not page aligned (+1). ! 65: */ ! 66: #define DMAMAXIO (MAXPHYS/NBPG+1) ! 67: ! 68: struct dma_chain { ! 69: int dc_count; ! 70: char *dc_addr; ! 71: }; ! 72: ! 73: struct dma_softc { ! 74: struct dmadevice *sc_hwaddr; ! 75: struct dmaBdevice *sc_Bhwaddr; ! 76: char sc_type; ! 77: char sc_flags; ! 78: u_short sc_cmd; ! 79: struct dma_chain *sc_cur; ! 80: struct dma_chain *sc_last; ! 81: struct dma_chain sc_chain[DMAMAXIO]; ! 82: } dma_softc[NDMA]; ! 83: ! 84: /* types */ ! 85: #define DMA_B 0 ! 86: #define DMA_C 1 ! 87: ! 88: /* flags */ ! 89: #define DMAF_PCFLUSH 0x01 ! 90: #define DMAF_VCFLUSH 0x02 ! 91: #define DMAF_NOINTR 0x04 ! 92: ! 93: struct devqueue dmachan[NDMA + 1]; ! 94: int dmaintr(); ! 95: ! 96: #ifdef DEBUG ! 97: int dmadebug = 0; ! 98: #define DDB_WORD 0x01 /* same as DMAGO_WORD */ ! 99: #define DDB_LWORD 0x02 /* same as DMAGO_LWORD */ ! 100: #define DDB_FOLLOW 0x04 ! 101: #define DDB_IO 0x08 ! 102: ! 103: void dmatimeout(); ! 104: int dmatimo[NDMA]; ! 105: ! 106: long dmahits[NDMA]; ! 107: long dmamisses[NDMA]; ! 108: long dmabyte[NDMA]; ! 109: long dmaword[NDMA]; ! 110: long dmalword[NDMA]; ! 111: #endif ! 112: ! 113: void ! 114: dmainit() ! 115: { ! 116: register struct dmareg *dma = (struct dmareg *)DMA_BASE; ! 117: register struct dma_softc *dc; ! 118: register int i; ! 119: char rev; ! 120: ! 121: /* ! 122: * Determine the DMA type. ! 123: * Don't know how to easily differentiate the A and B cards, ! 124: * so we just hope nobody has an A card (A cards will work if ! 125: * DMAINTLVL is set to 3). ! 126: */ ! 127: if (!badbaddr((char *)&dma->dma_id[2])) ! 128: rev = dma->dma_id[2]; ! 129: else { ! 130: rev = 'B'; ! 131: #if !defined(HP320) ! 132: panic("dmainit: DMA card requires hp320 support"); ! 133: #endif ! 134: } ! 135: ! 136: dc = &dma_softc[0]; ! 137: for (i = 0; i < NDMA; i++) { ! 138: dc->sc_hwaddr = (i & 1) ? &dma->dma_chan1 : &dma->dma_chan0; ! 139: dc->sc_Bhwaddr = (i & 1) ? &dma->dma_Bchan1 : &dma->dma_Bchan0; ! 140: dc->sc_type = rev == 'B' ? DMA_B : DMA_C; ! 141: dc++; ! 142: dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i]; ! 143: } ! 144: dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i]; ! 145: #ifdef DEBUG ! 146: /* make sure timeout is really not needed */ ! 147: timeout(dmatimeout, 0, 30 * hz); ! 148: #endif ! 149: ! 150: printf("dma: 98620%c with 2 channels, %d bit DMA\n", ! 151: rev, rev == 'B' ? 16 : 32); ! 152: } ! 153: ! 154: int ! 155: dmareq(dq) ! 156: register struct devqueue *dq; ! 157: { ! 158: register int i; ! 159: register int chan; ! 160: register int s = splbio(); ! 161: ! 162: chan = dq->dq_ctlr; ! 163: i = NDMA; ! 164: while (--i >= 0) { ! 165: if ((chan & (1 << i)) == 0) ! 166: continue; ! 167: if (dmachan[i].dq_forw != &dmachan[i]) ! 168: continue; ! 169: insque(dq, &dmachan[i]); ! 170: dq->dq_ctlr = i; ! 171: splx(s); ! 172: return(1); ! 173: } ! 174: insque(dq, dmachan[NDMA].dq_back); ! 175: splx(s); ! 176: return(0); ! 177: } ! 178: ! 179: void ! 180: dmafree(dq) ! 181: register struct devqueue *dq; ! 182: { ! 183: int unit = dq->dq_ctlr; ! 184: register struct dma_softc *dc = &dma_softc[unit]; ! 185: register struct devqueue *dn; ! 186: register int chan, s; ! 187: ! 188: s = splbio(); ! 189: #ifdef DEBUG ! 190: dmatimo[unit] = 0; ! 191: #endif ! 192: DMA_CLEAR(dc); ! 193: /* ! 194: * XXX we may not always go thru the flush code in dmastop() ! 195: */ ! 196: #if defined(HP360) || defined(HP370) ! 197: if (dc->sc_flags & DMAF_PCFLUSH) { ! 198: PCIA(); ! 199: dc->sc_flags &= ~DMAF_PCFLUSH; ! 200: } ! 201: #endif ! 202: #if defined(HP320) || defined(HP350) ! 203: if (dc->sc_flags & DMAF_VCFLUSH) { ! 204: /* ! 205: * 320/350s have VACs that may also need flushing. ! 206: * In our case we only flush the supervisor side ! 207: * because we know that if we are DMAing to user ! 208: * space, the physical pages will also be mapped ! 209: * in kernel space (via vmapbuf) and hence cache- ! 210: * inhibited by the pmap module due to the multiple ! 211: * mapping. ! 212: */ ! 213: DCIS(); ! 214: dc->sc_flags &= ~DMAF_VCFLUSH; ! 215: } ! 216: #endif ! 217: remque(dq); ! 218: chan = 1 << unit; ! 219: for (dn = dmachan[NDMA].dq_forw; ! 220: dn != &dmachan[NDMA]; dn = dn->dq_forw) { ! 221: if (dn->dq_ctlr & chan) { ! 222: remque((caddr_t)dn); ! 223: insque((caddr_t)dn, (caddr_t)dq->dq_back); ! 224: splx(s); ! 225: dn->dq_ctlr = dq->dq_ctlr; ! 226: (dn->dq_driver->d_start)(dn->dq_unit); ! 227: return; ! 228: } ! 229: } ! 230: splx(s); ! 231: } ! 232: ! 233: void ! 234: dmago(unit, addr, count, flags) ! 235: int unit; ! 236: register char *addr; ! 237: register int count; ! 238: register int flags; ! 239: { ! 240: register struct dma_softc *dc = &dma_softc[unit]; ! 241: register struct dma_chain *dcp; ! 242: register char *dmaend = NULL; ! 243: register int tcount; ! 244: ! 245: if (count > MAXPHYS) ! 246: panic("dmago: count > MAXPHYS"); ! 247: #if defined(HP320) ! 248: if (dc->sc_type == DMA_B && (flags & DMAGO_LWORD)) ! 249: panic("dmago: no can do 32-bit DMA"); ! 250: #endif ! 251: #ifdef DEBUG ! 252: if (dmadebug & DDB_FOLLOW) ! 253: printf("dmago(%d, %x, %x, %x)\n", ! 254: unit, addr, count, flags); ! 255: if (flags & DMAGO_LWORD) ! 256: dmalword[unit]++; ! 257: else if (flags & DMAGO_WORD) ! 258: dmaword[unit]++; ! 259: else ! 260: dmabyte[unit]++; ! 261: #endif ! 262: /* ! 263: * Build the DMA chain ! 264: */ ! 265: for (dcp = dc->sc_chain; count > 0; dcp++) { ! 266: dcp->dc_addr = (char *) kvtop(addr); ! 267: if (count < (tcount = NBPG - ((int)addr & PGOFSET))) ! 268: tcount = count; ! 269: dcp->dc_count = tcount; ! 270: addr += tcount; ! 271: count -= tcount; ! 272: if (flags & DMAGO_LWORD) ! 273: tcount >>= 2; ! 274: else if (flags & DMAGO_WORD) ! 275: tcount >>= 1; ! 276: if (dcp->dc_addr == dmaend ! 277: #if defined(HP320) ! 278: /* only 16-bit count on 98620B */ ! 279: && (dc->sc_type != DMA_B || ! 280: (dcp-1)->dc_count + tcount <= 65536) ! 281: #endif ! 282: ) { ! 283: #ifdef DEBUG ! 284: dmahits[unit]++; ! 285: #endif ! 286: dmaend += dcp->dc_count; ! 287: (--dcp)->dc_count += tcount; ! 288: } else { ! 289: #ifdef DEBUG ! 290: dmamisses[unit]++; ! 291: #endif ! 292: dmaend = dcp->dc_addr + dcp->dc_count; ! 293: dcp->dc_count = tcount; ! 294: } ! 295: } ! 296: dc->sc_cur = dc->sc_chain; ! 297: dc->sc_last = --dcp; ! 298: dc->sc_flags = 0; ! 299: /* ! 300: * Set up the command word based on flags ! 301: */ ! 302: dc->sc_cmd = DMA_ENAB | DMA_IPL(DMAINTLVL) | DMA_START; ! 303: if ((flags & DMAGO_READ) == 0) ! 304: dc->sc_cmd |= DMA_WRT; ! 305: if (flags & DMAGO_LWORD) ! 306: dc->sc_cmd |= DMA_LWORD; ! 307: else if (flags & DMAGO_WORD) ! 308: dc->sc_cmd |= DMA_WORD; ! 309: if (flags & DMAGO_PRI) ! 310: dc->sc_cmd |= DMA_PRI; ! 311: #if defined(HP360) || defined(HP370) ! 312: /* ! 313: * Remember if we need to flush external physical cache when ! 314: * DMA is done. We only do this if we are reading (writing memory). ! 315: */ ! 316: if (ectype == EC_PHYS && (flags & DMAGO_READ)) ! 317: dc->sc_flags |= DMAF_PCFLUSH; ! 318: #endif ! 319: #if defined(HP320) || defined(HP350) ! 320: if (ectype == EC_VIRT && (flags & DMAGO_READ)) ! 321: dc->sc_flags |= DMAF_VCFLUSH; ! 322: #endif ! 323: /* ! 324: * Remember if we can skip the dma completion interrupt on ! 325: * the last segment in the chain. ! 326: */ ! 327: if (flags & DMAGO_NOINT) { ! 328: if (dc->sc_cur == dc->sc_last) ! 329: dc->sc_cmd &= ~DMA_ENAB; ! 330: else ! 331: dc->sc_flags |= DMAF_NOINTR; ! 332: } ! 333: #ifdef DEBUG ! 334: if (dmadebug & DDB_IO) ! 335: if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || ! 336: (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) { ! 337: printf("dmago: cmd %x, flags %x\n", ! 338: dc->sc_cmd, dc->sc_flags); ! 339: for (dcp = dc->sc_chain; dcp <= dc->sc_last; dcp++) ! 340: printf(" %d: %d@%x\n", dcp-dc->sc_chain, ! 341: dcp->dc_count, dcp->dc_addr); ! 342: } ! 343: dmatimo[unit] = 1; ! 344: #endif ! 345: DMA_ARM(dc); ! 346: } ! 347: ! 348: void ! 349: dmastop(unit) ! 350: register int unit; ! 351: { ! 352: register struct dma_softc *dc = &dma_softc[unit]; ! 353: register struct devqueue *dq; ! 354: ! 355: #ifdef DEBUG ! 356: if (dmadebug & DDB_FOLLOW) ! 357: printf("dmastop(%d)\n", unit); ! 358: dmatimo[unit] = 0; ! 359: #endif ! 360: DMA_CLEAR(dc); ! 361: #if defined(HP360) || defined(HP370) ! 362: if (dc->sc_flags & DMAF_PCFLUSH) { ! 363: PCIA(); ! 364: dc->sc_flags &= ~DMAF_PCFLUSH; ! 365: } ! 366: #endif ! 367: #if defined(HP320) || defined(HP350) ! 368: if (dc->sc_flags & DMAF_VCFLUSH) { ! 369: /* ! 370: * 320/350s have VACs that may also need flushing. ! 371: * In our case we only flush the supervisor side ! 372: * because we know that if we are DMAing to user ! 373: * space, the physical pages will also be mapped ! 374: * in kernel space (via vmapbuf) and hence cache- ! 375: * inhibited by the pmap module due to the multiple ! 376: * mapping. ! 377: */ ! 378: DCIS(); ! 379: dc->sc_flags &= ~DMAF_VCFLUSH; ! 380: } ! 381: #endif ! 382: /* ! 383: * We may get this interrupt after a device service routine ! 384: * has freed the dma channel. So, ignore the intr if there's ! 385: * nothing on the queue. ! 386: */ ! 387: dq = dmachan[unit].dq_forw; ! 388: if (dq != &dmachan[unit]) ! 389: (dq->dq_driver->d_done)(dq->dq_unit); ! 390: } ! 391: ! 392: int ! 393: dmaintr() ! 394: { ! 395: register struct dma_softc *dc; ! 396: register int i, stat; ! 397: int found = 0; ! 398: ! 399: #ifdef DEBUG ! 400: if (dmadebug & DDB_FOLLOW) ! 401: printf("dmaintr\n"); ! 402: #endif ! 403: for (i = 0, dc = dma_softc; i < NDMA; i++, dc++) { ! 404: stat = DMA_STAT(dc); ! 405: if ((stat & DMA_INTR) == 0) ! 406: continue; ! 407: found++; ! 408: #ifdef DEBUG ! 409: if (dmadebug & DDB_IO) { ! 410: if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || ! 411: (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) ! 412: printf("dmaintr: unit %d stat %x next %d\n", ! 413: i, stat, (dc->sc_cur-dc->sc_chain)+1); ! 414: } ! 415: if (stat & DMA_ARMED) ! 416: printf("dma%d: intr when armed\n", i); ! 417: #endif ! 418: if (++dc->sc_cur <= dc->sc_last) { ! 419: #ifdef DEBUG ! 420: dmatimo[i] = 1; ! 421: #endif ! 422: /* ! 423: * Last chain segment, disable DMA interrupt. ! 424: */ ! 425: if (dc->sc_cur == dc->sc_last && ! 426: (dc->sc_flags & DMAF_NOINTR)) ! 427: dc->sc_cmd &= ~DMA_ENAB; ! 428: DMA_CLEAR(dc); ! 429: DMA_ARM(dc); ! 430: } else ! 431: dmastop(i); ! 432: } ! 433: return(found); ! 434: } ! 435: ! 436: #ifdef DEBUG ! 437: void ! 438: dmatimeout() ! 439: { ! 440: register int i, s; ! 441: ! 442: for (i = 0; i < NDMA; i++) { ! 443: s = splbio(); ! 444: if (dmatimo[i]) { ! 445: if (dmatimo[i] > 1) ! 446: printf("dma%d: timeout #%d\n", ! 447: i, dmatimo[i]-1); ! 448: dmatimo[i]++; ! 449: } ! 450: splx(s); ! 451: } ! 452: timeout(dmatimeout, (caddr_t)0, 30 * hz); ! 453: } ! 454: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.