141480Smckusick /* 241480Smckusick * Copyright (c) 1982, 1990 The Regents of the University of California. 341480Smckusick * All rights reserved. 441480Smckusick * 541480Smckusick * %sccs.include.redist.c% 641480Smckusick * 7*45750Smckusick * @(#)dma.c 7.2 (Berkeley) 12/05/90 841480Smckusick */ 941480Smckusick 1041480Smckusick /* 1141480Smckusick * DMA driver 1241480Smckusick */ 1341480Smckusick 1441480Smckusick #include "param.h" 1541480Smckusick #include "systm.h" 1641480Smckusick #include "time.h" 1741480Smckusick #include "kernel.h" 1841480Smckusick #include "proc.h" 1941480Smckusick #include "dmareg.h" 2041480Smckusick #include "dmavar.h" 2141480Smckusick #include "device.h" 2241480Smckusick 2341480Smckusick #include "machine/cpu.h" 2441480Smckusick #include "machine/isr.h" 2541480Smckusick 2641480Smckusick extern void isrlink(); 2741480Smckusick extern void printf(); 2841480Smckusick extern void panic(); 2941480Smckusick extern void _insque(); 3041480Smckusick extern void _remque(); 3141480Smckusick extern void timeout(); 3241480Smckusick extern int splbio(); 3341480Smckusick extern void splx(); 3441480Smckusick extern u_int kvtop(); 3541480Smckusick extern void PCIA(); 3641480Smckusick 3741480Smckusick /* 3841480Smckusick * The largest single request will be MAXPHYS bytes which will require 3941480Smckusick * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of 4041480Smckusick * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the 4141480Smckusick * buffer is not page aligned (+1). 4241480Smckusick */ 4341480Smckusick #define DMAMAXIO (MAXPHYS/NBPG+1) 4441480Smckusick 45*45750Smckusick struct dma_chain { 46*45750Smckusick int dc_count; 47*45750Smckusick char *dc_addr; 48*45750Smckusick }; 4941480Smckusick 5041480Smckusick struct dma_softc { 51*45750Smckusick struct dmadevice *sc_hwaddr; 52*45750Smckusick struct dmaBdevice *sc_Bhwaddr; 53*45750Smckusick char sc_type; 54*45750Smckusick char sc_flags; 55*45750Smckusick u_short sc_cmd; 56*45750Smckusick struct dma_chain *sc_cur; 57*45750Smckusick struct dma_chain *sc_last; 58*45750Smckusick struct dma_chain sc_chain[DMAMAXIO]; 5941480Smckusick } dma_softc[NDMA]; 6041480Smckusick 6141480Smckusick /* types */ 6241480Smckusick #define DMA_B 0 6341480Smckusick #define DMA_C 1 6441480Smckusick 65*45750Smckusick /* flags */ 66*45750Smckusick #define DMAF_PCFLUSH 0x01 67*45750Smckusick #define DMAF_VCFLUSH 0x02 68*45750Smckusick #define DMAF_NOINTR 0x04 69*45750Smckusick 7041480Smckusick struct devqueue dmachan[NDMA + 1]; 7141480Smckusick int dmaintr(); 7241480Smckusick 7341480Smckusick #ifdef DEBUG 7441480Smckusick int dmadebug = 0; 7541480Smckusick #define DDB_WORD 0x01 /* same as DMAGO_WORD */ 7641480Smckusick #define DDB_LWORD 0x02 /* same as DMAGO_LWORD */ 7741480Smckusick #define DDB_FOLLOW 0x04 7841480Smckusick #define DDB_IO 0x08 7941480Smckusick 80*45750Smckusick void dmatimeout(); 81*45750Smckusick int dmatimo[NDMA]; 82*45750Smckusick 8341480Smckusick long dmahits[NDMA]; 8441480Smckusick long dmamisses[NDMA]; 8541480Smckusick long dmabyte[NDMA]; 8641480Smckusick long dmaword[NDMA]; 8741480Smckusick long dmalword[NDMA]; 8841480Smckusick #endif 8941480Smckusick 9041480Smckusick void 9141480Smckusick dmainit() 9241480Smckusick { 9341480Smckusick register struct dmareg *dma = (struct dmareg *)DMA_BASE; 9441480Smckusick register struct dma_softc *dc; 9541480Smckusick register int i; 9641480Smckusick char rev; 9741480Smckusick 9841480Smckusick /* 9941480Smckusick * Determine the DMA type. 10041480Smckusick * Don't know how to easily differentiate the A and B cards, 10141480Smckusick * so we just hope nobody has an A card (A cards will work if 10241480Smckusick * DMAINTLVL is set to 3). 10341480Smckusick */ 10441480Smckusick if (!badbaddr((char *)&dma->dma_id[2])) 10541480Smckusick rev = dma->dma_id[2]; 10641480Smckusick else { 10741480Smckusick rev = 'B'; 10841480Smckusick #if !defined(HP320) 10941480Smckusick panic("dmainit: DMA card requires hp320 support"); 11041480Smckusick #endif 11141480Smckusick } 11241480Smckusick 11341480Smckusick dc = &dma_softc[0]; 11441480Smckusick for (i = 0; i < NDMA; i++) { 11541480Smckusick dc->sc_hwaddr = (i & 1) ? &dma->dma_chan1 : &dma->dma_chan0; 11641480Smckusick dc->sc_Bhwaddr = (i & 1) ? &dma->dma_Bchan1 : &dma->dma_Bchan0; 11741480Smckusick dc->sc_type = rev == 'B' ? DMA_B : DMA_C; 11841480Smckusick dc++; 11941480Smckusick dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i]; 12041480Smckusick } 12141480Smckusick dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i]; 122*45750Smckusick #ifdef DEBUG 123*45750Smckusick /* make sure timeout is really not needed */ 124*45750Smckusick timeout(dmatimeout, 0, 30 * hz); 125*45750Smckusick #endif 12641480Smckusick 12741480Smckusick printf("dma: 98620%c with 2 channels, %d bit DMA\n", 12841480Smckusick rev, rev == 'B' ? 16 : 32); 12941480Smckusick } 13041480Smckusick 13141480Smckusick int 13241480Smckusick dmareq(dq) 13341480Smckusick register struct devqueue *dq; 13441480Smckusick { 13541480Smckusick register int i; 13641480Smckusick register int chan; 13741480Smckusick register int s = splbio(); 13841480Smckusick 13941480Smckusick chan = dq->dq_ctlr; 14041480Smckusick i = NDMA; 14141480Smckusick while (--i >= 0) { 14241480Smckusick if ((chan & (1 << i)) == 0) 14341480Smckusick continue; 14441480Smckusick if (dmachan[i].dq_forw != &dmachan[i]) 14541480Smckusick continue; 14641480Smckusick insque(dq, &dmachan[i]); 14741480Smckusick dq->dq_ctlr = i; 14841480Smckusick splx(s); 14941480Smckusick return(1); 15041480Smckusick } 15141480Smckusick insque(dq, dmachan[NDMA].dq_back); 15241480Smckusick splx(s); 15341480Smckusick return(0); 15441480Smckusick } 15541480Smckusick 15641480Smckusick void 15741480Smckusick dmafree(dq) 15841480Smckusick register struct devqueue *dq; 15941480Smckusick { 16041480Smckusick int unit = dq->dq_ctlr; 16141480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 16241480Smckusick register struct devqueue *dn; 16341480Smckusick register int chan, s; 16441480Smckusick 16541480Smckusick s = splbio(); 166*45750Smckusick #ifdef DEBUG 167*45750Smckusick dmatimo[unit] = 0; 168*45750Smckusick #endif 16941480Smckusick DMA_CLEAR(dc); 170*45750Smckusick /* 171*45750Smckusick * XXX we may not always go thru the flush code in dmastop() 172*45750Smckusick */ 173*45750Smckusick #if defined(HP360) || defined(HP370) 174*45750Smckusick if (dc->sc_flags & DMAF_PCFLUSH) { 175*45750Smckusick PCIA(); 176*45750Smckusick dc->sc_flags &= ~DMAF_PCFLUSH; 177*45750Smckusick } 178*45750Smckusick #endif 179*45750Smckusick #if defined(HP320) || defined(HP350) 180*45750Smckusick if (dc->sc_flags & DMAF_VCFLUSH) { 181*45750Smckusick /* 182*45750Smckusick * 320/350s have VACs that may also need flushing. 183*45750Smckusick * In our case we only flush the supervisor side 184*45750Smckusick * because we know that if we are DMAing to user 185*45750Smckusick * space, the physical pages will also be mapped 186*45750Smckusick * in kernel space (via vmapbuf) and hence cache- 187*45750Smckusick * inhibited by the pmap module due to the multiple 188*45750Smckusick * mapping. 189*45750Smckusick */ 190*45750Smckusick DCIS(); 191*45750Smckusick dc->sc_flags &= ~DMAF_VCFLUSH; 192*45750Smckusick } 193*45750Smckusick #endif 19441480Smckusick remque(dq); 19541480Smckusick chan = 1 << unit; 19641480Smckusick for (dn = dmachan[NDMA].dq_forw; 19741480Smckusick dn != &dmachan[NDMA]; dn = dn->dq_forw) { 19841480Smckusick if (dn->dq_ctlr & chan) { 19941480Smckusick remque((caddr_t)dn); 20041480Smckusick insque((caddr_t)dn, (caddr_t)dq->dq_back); 20141480Smckusick splx(s); 20241480Smckusick dn->dq_ctlr = dq->dq_ctlr; 20341480Smckusick (dn->dq_driver->d_start)(dn->dq_unit); 20441480Smckusick return; 20541480Smckusick } 20641480Smckusick } 20741480Smckusick splx(s); 20841480Smckusick } 20941480Smckusick 21041480Smckusick void 21141480Smckusick dmago(unit, addr, count, flags) 21241480Smckusick int unit; 21341480Smckusick register char *addr; 21441480Smckusick register int count; 21541480Smckusick register int flags; 21641480Smckusick { 21741480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 218*45750Smckusick register struct dma_chain *dcp; 21941480Smckusick register char *dmaend = NULL; 220*45750Smckusick register int tcount; 22141480Smckusick 222*45750Smckusick if (count > MAXPHYS) 223*45750Smckusick panic("dmago: count > MAXPHYS"); 224*45750Smckusick #if defined(HP320) 225*45750Smckusick if (dc->sc_type == DMA_B && (flags & DMAGO_LWORD)) 226*45750Smckusick panic("dmago: no can do 32-bit DMA"); 227*45750Smckusick #endif 22841480Smckusick #ifdef DEBUG 22941480Smckusick if (dmadebug & DDB_FOLLOW) 23041480Smckusick printf("dmago(%d, %x, %x, %x)\n", 23141480Smckusick unit, addr, count, flags); 23241480Smckusick if (flags & DMAGO_LWORD) 23341480Smckusick dmalword[unit]++; 23441480Smckusick else if (flags & DMAGO_WORD) 23541480Smckusick dmaword[unit]++; 23641480Smckusick else 23741480Smckusick dmabyte[unit]++; 23841480Smckusick #endif 23941480Smckusick /* 24041480Smckusick * Build the DMA chain 24141480Smckusick */ 242*45750Smckusick for (dcp = dc->sc_chain; count > 0; dcp++) { 243*45750Smckusick dcp->dc_addr = (char *) kvtop(addr); 244*45750Smckusick if (count < (tcount = NBPG - ((int)addr & PGOFSET))) 245*45750Smckusick tcount = count; 246*45750Smckusick dcp->dc_count = tcount; 247*45750Smckusick addr += tcount; 24841480Smckusick count -= tcount; 249*45750Smckusick if (flags & DMAGO_LWORD) 250*45750Smckusick tcount >>= 2; 251*45750Smckusick else if (flags & DMAGO_WORD) 252*45750Smckusick tcount >>= 1; 253*45750Smckusick if (dcp->dc_addr == dmaend 25441480Smckusick #if defined(HP320) 25541480Smckusick /* only 16-bit count on 98620B */ 25641480Smckusick && (dc->sc_type != DMA_B || 257*45750Smckusick (dcp-1)->dc_count + tcount <= 65536) 25841480Smckusick #endif 25941480Smckusick ) { 26041480Smckusick #ifdef DEBUG 26141480Smckusick dmahits[unit]++; 26241480Smckusick #endif 263*45750Smckusick dmaend += dcp->dc_count; 264*45750Smckusick (--dcp)->dc_count += tcount; 26541480Smckusick } else { 26641480Smckusick #ifdef DEBUG 26741480Smckusick dmamisses[unit]++; 26841480Smckusick #endif 269*45750Smckusick dmaend = dcp->dc_addr + dcp->dc_count; 270*45750Smckusick dcp->dc_count = tcount; 27141480Smckusick } 27241480Smckusick } 273*45750Smckusick dc->sc_cur = dc->sc_chain; 274*45750Smckusick dc->sc_last = --dcp; 275*45750Smckusick dc->sc_flags = 0; 27641480Smckusick /* 27741480Smckusick * Set up the command word based on flags 27841480Smckusick */ 27941480Smckusick dc->sc_cmd = DMA_ENAB | DMA_IPL(DMAINTLVL) | DMA_START; 28041480Smckusick if ((flags & DMAGO_READ) == 0) 28141480Smckusick dc->sc_cmd |= DMA_WRT; 28241480Smckusick if (flags & DMAGO_LWORD) 28341480Smckusick dc->sc_cmd |= DMA_LWORD; 28441480Smckusick else if (flags & DMAGO_WORD) 28541480Smckusick dc->sc_cmd |= DMA_WORD; 28641480Smckusick if (flags & DMAGO_PRI) 28741480Smckusick dc->sc_cmd |= DMA_PRI; 288*45750Smckusick #if defined(HP360) || defined(HP370) 28941480Smckusick /* 290*45750Smckusick * Remember if we need to flush external physical cache when 291*45750Smckusick * DMA is done. We only do this if we are reading (writing memory). 29241480Smckusick */ 293*45750Smckusick if (ectype == EC_PHYS && (flags & DMAGO_READ)) 294*45750Smckusick dc->sc_flags |= DMAF_PCFLUSH; 29541480Smckusick #endif 296*45750Smckusick #if defined(HP320) || defined(HP350) 297*45750Smckusick if (ectype == EC_VIRT && (flags & DMAGO_READ)) 298*45750Smckusick dc->sc_flags |= DMAF_VCFLUSH; 299*45750Smckusick #endif 300*45750Smckusick /* 301*45750Smckusick * Remember if we can skip the dma completion interrupt on 302*45750Smckusick * the last segment in the chain. 303*45750Smckusick */ 304*45750Smckusick if (flags & DMAGO_NOINT) { 305*45750Smckusick if (dc->sc_cur == dc->sc_last) 306*45750Smckusick dc->sc_cmd &= ~DMA_ENAB; 307*45750Smckusick else 308*45750Smckusick dc->sc_flags |= DMAF_NOINTR; 309*45750Smckusick } 31041480Smckusick #ifdef DEBUG 31141480Smckusick if (dmadebug & DDB_IO) 31241480Smckusick if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || 31341480Smckusick (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) { 314*45750Smckusick printf("dmago: cmd %x, flags %x\n", 315*45750Smckusick dc->sc_cmd, dc->sc_flags); 316*45750Smckusick for (dcp = dc->sc_chain; dcp <= dc->sc_last; dcp++) 317*45750Smckusick printf(" %d: %d@%x\n", dcp-dc->sc_chain, 318*45750Smckusick dcp->dc_count, dcp->dc_addr); 31941480Smckusick } 320*45750Smckusick dmatimo[unit] = 1; 32141480Smckusick #endif 322*45750Smckusick DMA_ARM(dc); 32341480Smckusick } 32441480Smckusick 32541480Smckusick void 32641480Smckusick dmastop(unit) 32741480Smckusick register int unit; 32841480Smckusick { 32941480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 33041480Smckusick register struct devqueue *dq; 33141480Smckusick 33241480Smckusick #ifdef DEBUG 33341480Smckusick if (dmadebug & DDB_FOLLOW) 33441480Smckusick printf("dmastop(%d)\n", unit); 335*45750Smckusick dmatimo[unit] = 0; 33641480Smckusick #endif 33741480Smckusick DMA_CLEAR(dc); 338*45750Smckusick #if defined(HP360) || defined(HP370) 339*45750Smckusick if (dc->sc_flags & DMAF_PCFLUSH) { 340*45750Smckusick PCIA(); 341*45750Smckusick dc->sc_flags &= ~DMAF_PCFLUSH; 342*45750Smckusick } 343*45750Smckusick #endif 344*45750Smckusick #if defined(HP320) || defined(HP350) 345*45750Smckusick if (dc->sc_flags & DMAF_VCFLUSH) { 346*45750Smckusick /* 347*45750Smckusick * 320/350s have VACs that may also need flushing. 348*45750Smckusick * In our case we only flush the supervisor side 349*45750Smckusick * because we know that if we are DMAing to user 350*45750Smckusick * space, the physical pages will also be mapped 351*45750Smckusick * in kernel space (via vmapbuf) and hence cache- 352*45750Smckusick * inhibited by the pmap module due to the multiple 353*45750Smckusick * mapping. 354*45750Smckusick */ 355*45750Smckusick DCIS(); 356*45750Smckusick dc->sc_flags &= ~DMAF_VCFLUSH; 357*45750Smckusick } 358*45750Smckusick #endif 35941480Smckusick /* 36041480Smckusick * We may get this interrupt after a device service routine 36141480Smckusick * has freed the dma channel. So, ignore the intr if there's 36241480Smckusick * nothing on the queue. 36341480Smckusick */ 36441480Smckusick dq = dmachan[unit].dq_forw; 365*45750Smckusick if (dq != &dmachan[unit]) 36641480Smckusick (dq->dq_driver->d_done)(dq->dq_unit); 36741480Smckusick } 36841480Smckusick 36941480Smckusick int 37041480Smckusick dmaintr() 37141480Smckusick { 37241480Smckusick register struct dma_softc *dc; 373*45750Smckusick register int i, stat; 37441480Smckusick int found = 0; 37541480Smckusick 37641480Smckusick #ifdef DEBUG 37741480Smckusick if (dmadebug & DDB_FOLLOW) 37841480Smckusick printf("dmaintr\n"); 37941480Smckusick #endif 38041480Smckusick for (i = 0, dc = dma_softc; i < NDMA; i++, dc++) { 38141480Smckusick stat = DMA_STAT(dc); 38241480Smckusick if ((stat & DMA_INTR) == 0) 38341480Smckusick continue; 38441480Smckusick found++; 38541480Smckusick #ifdef DEBUG 38641480Smckusick if (dmadebug & DDB_IO) { 38741480Smckusick if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || 38841480Smckusick (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) 38941480Smckusick printf("dmaintr: unit %d stat %x next %d\n", 390*45750Smckusick i, stat, (dc->sc_cur-dc->sc_chain)+1); 39141480Smckusick } 39241480Smckusick if (stat & DMA_ARMED) 39341480Smckusick printf("dma%d: intr when armed\n", i); 39441480Smckusick #endif 395*45750Smckusick if (++dc->sc_cur <= dc->sc_last) { 396*45750Smckusick #ifdef DEBUG 397*45750Smckusick dmatimo[i] = 1; 398*45750Smckusick #endif 399*45750Smckusick /* 400*45750Smckusick * Last chain segment, disable DMA interrupt. 401*45750Smckusick */ 402*45750Smckusick if (dc->sc_cur == dc->sc_last && 403*45750Smckusick (dc->sc_flags & DMAF_NOINTR)) 404*45750Smckusick dc->sc_cmd &= ~DMA_ENAB; 40541480Smckusick DMA_CLEAR(dc); 406*45750Smckusick DMA_ARM(dc); 40741480Smckusick } else 40841480Smckusick dmastop(i); 40941480Smckusick } 41041480Smckusick return(found); 41141480Smckusick } 41241480Smckusick 413*45750Smckusick #ifdef DEBUG 41441480Smckusick void 415*45750Smckusick dmatimeout() 41641480Smckusick { 41741480Smckusick register int i, s; 41841480Smckusick 419*45750Smckusick for (i = 0; i < NDMA; i++) { 42041480Smckusick s = splbio(); 421*45750Smckusick if (dmatimo[i]) { 422*45750Smckusick if (dmatimo[i] > 1) 423*45750Smckusick printf("dma%d: timeout #%d\n", 424*45750Smckusick i, dmatimo[i]-1); 425*45750Smckusick dmatimo[i]++; 42641480Smckusick } 42741480Smckusick splx(s); 42841480Smckusick } 429*45750Smckusick timeout(dmatimeout, (caddr_t)0, 30 * hz); 43041480Smckusick } 431*45750Smckusick #endif 432