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*53930Shibler * @(#)dma.c 7.6 (Berkeley) 06/05/92 841480Smckusick */ 941480Smckusick 1041480Smckusick /* 1141480Smckusick * DMA driver 1241480Smckusick */ 1341480Smckusick 1449132Skarels #include "param.h" 1549132Skarels #include "systm.h" 1649132Skarels #include "time.h" 1749132Skarels #include "kernel.h" 1849132Skarels #include "proc.h" 1949132Skarels 2041480Smckusick #include "dmareg.h" 2141480Smckusick #include "dmavar.h" 22*53930Shibler #include "hp/dev/device.h" 2341480Smckusick 2445788Sbostic #include "../include/cpu.h" 2545788Sbostic #include "../hp300/isr.h" 2641480Smckusick 2741480Smckusick extern void isrlink(); 2841480Smckusick extern void _insque(); 2941480Smckusick extern void _remque(); 3041480Smckusick extern void timeout(); 3141480Smckusick extern u_int kvtop(); 3241480Smckusick extern void PCIA(); 3341480Smckusick 3441480Smckusick /* 3541480Smckusick * The largest single request will be MAXPHYS bytes which will require 3641480Smckusick * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of 3741480Smckusick * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the 3841480Smckusick * buffer is not page aligned (+1). 3941480Smckusick */ 4041480Smckusick #define DMAMAXIO (MAXPHYS/NBPG+1) 4141480Smckusick 4245750Smckusick struct dma_chain { 4345750Smckusick int dc_count; 4445750Smckusick char *dc_addr; 4545750Smckusick }; 4641480Smckusick 4741480Smckusick struct dma_softc { 4845750Smckusick struct dmadevice *sc_hwaddr; 4945750Smckusick struct dmaBdevice *sc_Bhwaddr; 5045750Smckusick char sc_type; 5145750Smckusick char sc_flags; 5245750Smckusick u_short sc_cmd; 5345750Smckusick struct dma_chain *sc_cur; 5445750Smckusick struct dma_chain *sc_last; 5545750Smckusick struct dma_chain sc_chain[DMAMAXIO]; 5641480Smckusick } dma_softc[NDMA]; 5741480Smckusick 5841480Smckusick /* types */ 5941480Smckusick #define DMA_B 0 6041480Smckusick #define DMA_C 1 6141480Smckusick 6245750Smckusick /* flags */ 6345750Smckusick #define DMAF_PCFLUSH 0x01 6445750Smckusick #define DMAF_VCFLUSH 0x02 6545750Smckusick #define DMAF_NOINTR 0x04 6645750Smckusick 6741480Smckusick struct devqueue dmachan[NDMA + 1]; 6841480Smckusick int dmaintr(); 6941480Smckusick 7041480Smckusick #ifdef DEBUG 7141480Smckusick int dmadebug = 0; 7241480Smckusick #define DDB_WORD 0x01 /* same as DMAGO_WORD */ 7341480Smckusick #define DDB_LWORD 0x02 /* same as DMAGO_LWORD */ 7441480Smckusick #define DDB_FOLLOW 0x04 7541480Smckusick #define DDB_IO 0x08 7641480Smckusick 7745750Smckusick void dmatimeout(); 7845750Smckusick int dmatimo[NDMA]; 7945750Smckusick 8041480Smckusick long dmahits[NDMA]; 8141480Smckusick long dmamisses[NDMA]; 8241480Smckusick long dmabyte[NDMA]; 8341480Smckusick long dmaword[NDMA]; 8441480Smckusick long dmalword[NDMA]; 8541480Smckusick #endif 8641480Smckusick 8741480Smckusick void 8841480Smckusick dmainit() 8941480Smckusick { 9041480Smckusick register struct dmareg *dma = (struct dmareg *)DMA_BASE; 9141480Smckusick register struct dma_softc *dc; 9241480Smckusick register int i; 9341480Smckusick char rev; 9441480Smckusick 9541480Smckusick /* 9641480Smckusick * Determine the DMA type. 9741480Smckusick * Don't know how to easily differentiate the A and B cards, 9841480Smckusick * so we just hope nobody has an A card (A cards will work if 9941480Smckusick * DMAINTLVL is set to 3). 10041480Smckusick */ 10141480Smckusick if (!badbaddr((char *)&dma->dma_id[2])) 10241480Smckusick rev = dma->dma_id[2]; 10341480Smckusick else { 10441480Smckusick rev = 'B'; 10541480Smckusick #if !defined(HP320) 10641480Smckusick panic("dmainit: DMA card requires hp320 support"); 10741480Smckusick #endif 10841480Smckusick } 10941480Smckusick 11041480Smckusick dc = &dma_softc[0]; 11141480Smckusick for (i = 0; i < NDMA; i++) { 11241480Smckusick dc->sc_hwaddr = (i & 1) ? &dma->dma_chan1 : &dma->dma_chan0; 11341480Smckusick dc->sc_Bhwaddr = (i & 1) ? &dma->dma_Bchan1 : &dma->dma_Bchan0; 11441480Smckusick dc->sc_type = rev == 'B' ? DMA_B : DMA_C; 11541480Smckusick dc++; 11641480Smckusick dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i]; 11741480Smckusick } 11841480Smckusick dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i]; 11945750Smckusick #ifdef DEBUG 12045750Smckusick /* make sure timeout is really not needed */ 12145750Smckusick timeout(dmatimeout, 0, 30 * hz); 12245750Smckusick #endif 12341480Smckusick 12441480Smckusick printf("dma: 98620%c with 2 channels, %d bit DMA\n", 12541480Smckusick rev, rev == 'B' ? 16 : 32); 12641480Smckusick } 12741480Smckusick 12841480Smckusick int 12941480Smckusick dmareq(dq) 13041480Smckusick register struct devqueue *dq; 13141480Smckusick { 13241480Smckusick register int i; 13341480Smckusick register int chan; 13441480Smckusick register int s = splbio(); 13541480Smckusick 13641480Smckusick chan = dq->dq_ctlr; 13741480Smckusick i = NDMA; 13841480Smckusick while (--i >= 0) { 13941480Smckusick if ((chan & (1 << i)) == 0) 14041480Smckusick continue; 14141480Smckusick if (dmachan[i].dq_forw != &dmachan[i]) 14241480Smckusick continue; 14341480Smckusick insque(dq, &dmachan[i]); 14441480Smckusick dq->dq_ctlr = i; 14541480Smckusick splx(s); 14641480Smckusick return(1); 14741480Smckusick } 14841480Smckusick insque(dq, dmachan[NDMA].dq_back); 14941480Smckusick splx(s); 15041480Smckusick return(0); 15141480Smckusick } 15241480Smckusick 15341480Smckusick void 15441480Smckusick dmafree(dq) 15541480Smckusick register struct devqueue *dq; 15641480Smckusick { 15741480Smckusick int unit = dq->dq_ctlr; 15841480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 15941480Smckusick register struct devqueue *dn; 16041480Smckusick register int chan, s; 16141480Smckusick 16241480Smckusick s = splbio(); 16345750Smckusick #ifdef DEBUG 16445750Smckusick dmatimo[unit] = 0; 16545750Smckusick #endif 16641480Smckusick DMA_CLEAR(dc); 167*53930Shibler #if defined(HP360) || defined(HP370) || defined(HP380) 16845750Smckusick /* 16945750Smckusick * XXX we may not always go thru the flush code in dmastop() 17045750Smckusick */ 17145750Smckusick if (dc->sc_flags & DMAF_PCFLUSH) { 17245750Smckusick PCIA(); 17345750Smckusick dc->sc_flags &= ~DMAF_PCFLUSH; 17445750Smckusick } 17545750Smckusick #endif 17645750Smckusick #if defined(HP320) || defined(HP350) 17745750Smckusick if (dc->sc_flags & DMAF_VCFLUSH) { 17845750Smckusick /* 17945750Smckusick * 320/350s have VACs that may also need flushing. 18045750Smckusick * In our case we only flush the supervisor side 18145750Smckusick * because we know that if we are DMAing to user 18245750Smckusick * space, the physical pages will also be mapped 18345750Smckusick * in kernel space (via vmapbuf) and hence cache- 18445750Smckusick * inhibited by the pmap module due to the multiple 18545750Smckusick * mapping. 18645750Smckusick */ 18745750Smckusick DCIS(); 18845750Smckusick dc->sc_flags &= ~DMAF_VCFLUSH; 18945750Smckusick } 19045750Smckusick #endif 19141480Smckusick remque(dq); 19241480Smckusick chan = 1 << unit; 19341480Smckusick for (dn = dmachan[NDMA].dq_forw; 19441480Smckusick dn != &dmachan[NDMA]; dn = dn->dq_forw) { 19541480Smckusick if (dn->dq_ctlr & chan) { 19641480Smckusick remque((caddr_t)dn); 19741480Smckusick insque((caddr_t)dn, (caddr_t)dq->dq_back); 19841480Smckusick splx(s); 19941480Smckusick dn->dq_ctlr = dq->dq_ctlr; 20041480Smckusick (dn->dq_driver->d_start)(dn->dq_unit); 20141480Smckusick return; 20241480Smckusick } 20341480Smckusick } 20441480Smckusick splx(s); 20541480Smckusick } 20641480Smckusick 20741480Smckusick void 20841480Smckusick dmago(unit, addr, count, flags) 20941480Smckusick int unit; 21041480Smckusick register char *addr; 21141480Smckusick register int count; 21241480Smckusick register int flags; 21341480Smckusick { 21441480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 21545750Smckusick register struct dma_chain *dcp; 21641480Smckusick register char *dmaend = NULL; 21745750Smckusick register int tcount; 21841480Smckusick 21945750Smckusick if (count > MAXPHYS) 22045750Smckusick panic("dmago: count > MAXPHYS"); 22145750Smckusick #if defined(HP320) 22245750Smckusick if (dc->sc_type == DMA_B && (flags & DMAGO_LWORD)) 22345750Smckusick panic("dmago: no can do 32-bit DMA"); 22445750Smckusick #endif 22541480Smckusick #ifdef DEBUG 22641480Smckusick if (dmadebug & DDB_FOLLOW) 22741480Smckusick printf("dmago(%d, %x, %x, %x)\n", 22841480Smckusick unit, addr, count, flags); 22941480Smckusick if (flags & DMAGO_LWORD) 23041480Smckusick dmalword[unit]++; 23141480Smckusick else if (flags & DMAGO_WORD) 23241480Smckusick dmaword[unit]++; 23341480Smckusick else 23441480Smckusick dmabyte[unit]++; 23541480Smckusick #endif 23641480Smckusick /* 23741480Smckusick * Build the DMA chain 23841480Smckusick */ 23945750Smckusick for (dcp = dc->sc_chain; count > 0; dcp++) { 24045750Smckusick dcp->dc_addr = (char *) kvtop(addr); 241*53930Shibler #if defined(HP380) 242*53930Shibler /* 243*53930Shibler * Push back dirty cache lines 244*53930Shibler */ 245*53930Shibler if (mmutype == MMU_68040) 246*53930Shibler DCFP(dcp->dc_addr); 247*53930Shibler #endif 24845750Smckusick if (count < (tcount = NBPG - ((int)addr & PGOFSET))) 24945750Smckusick tcount = count; 25045750Smckusick dcp->dc_count = tcount; 25145750Smckusick addr += tcount; 25241480Smckusick count -= tcount; 25345750Smckusick if (flags & DMAGO_LWORD) 25445750Smckusick tcount >>= 2; 25545750Smckusick else if (flags & DMAGO_WORD) 25645750Smckusick tcount >>= 1; 25745750Smckusick if (dcp->dc_addr == dmaend 25841480Smckusick #if defined(HP320) 25941480Smckusick /* only 16-bit count on 98620B */ 26041480Smckusick && (dc->sc_type != DMA_B || 26145750Smckusick (dcp-1)->dc_count + tcount <= 65536) 26241480Smckusick #endif 26341480Smckusick ) { 26441480Smckusick #ifdef DEBUG 26541480Smckusick dmahits[unit]++; 26641480Smckusick #endif 26745750Smckusick dmaend += dcp->dc_count; 26845750Smckusick (--dcp)->dc_count += tcount; 26941480Smckusick } else { 27041480Smckusick #ifdef DEBUG 27141480Smckusick dmamisses[unit]++; 27241480Smckusick #endif 27345750Smckusick dmaend = dcp->dc_addr + dcp->dc_count; 27445750Smckusick dcp->dc_count = tcount; 27541480Smckusick } 27641480Smckusick } 27745750Smckusick dc->sc_cur = dc->sc_chain; 27845750Smckusick dc->sc_last = --dcp; 27945750Smckusick dc->sc_flags = 0; 28041480Smckusick /* 28141480Smckusick * Set up the command word based on flags 28241480Smckusick */ 28341480Smckusick dc->sc_cmd = DMA_ENAB | DMA_IPL(DMAINTLVL) | DMA_START; 28441480Smckusick if ((flags & DMAGO_READ) == 0) 28541480Smckusick dc->sc_cmd |= DMA_WRT; 28641480Smckusick if (flags & DMAGO_LWORD) 28741480Smckusick dc->sc_cmd |= DMA_LWORD; 28841480Smckusick else if (flags & DMAGO_WORD) 28941480Smckusick dc->sc_cmd |= DMA_WORD; 29041480Smckusick if (flags & DMAGO_PRI) 29141480Smckusick dc->sc_cmd |= DMA_PRI; 292*53930Shibler #if defined(HP380) 293*53930Shibler /* 294*53930Shibler * On the 68040 we need to flush (push) the data cache before a 295*53930Shibler * DMA (already done above) and flush again after DMA completes. 296*53930Shibler * In theory we should only need to flush prior to a write DMA 297*53930Shibler * and purge after a read DMA but if the entire page is not 298*53930Shibler * involved in the DMA we might purge some valid data. 299*53930Shibler */ 300*53930Shibler if (mmutype == MMU_68040 && (flags & DMAGO_READ)) 301*53930Shibler dc->sc_flags |= DMAF_PCFLUSH; 302*53930Shibler #endif 30345750Smckusick #if defined(HP360) || defined(HP370) 30441480Smckusick /* 30545750Smckusick * Remember if we need to flush external physical cache when 30645750Smckusick * DMA is done. We only do this if we are reading (writing memory). 30741480Smckusick */ 30845750Smckusick if (ectype == EC_PHYS && (flags & DMAGO_READ)) 30945750Smckusick dc->sc_flags |= DMAF_PCFLUSH; 31041480Smckusick #endif 31145750Smckusick #if defined(HP320) || defined(HP350) 31245750Smckusick if (ectype == EC_VIRT && (flags & DMAGO_READ)) 31345750Smckusick dc->sc_flags |= DMAF_VCFLUSH; 31445750Smckusick #endif 31545750Smckusick /* 31645750Smckusick * Remember if we can skip the dma completion interrupt on 31745750Smckusick * the last segment in the chain. 31845750Smckusick */ 31945750Smckusick if (flags & DMAGO_NOINT) { 32045750Smckusick if (dc->sc_cur == dc->sc_last) 32145750Smckusick dc->sc_cmd &= ~DMA_ENAB; 32245750Smckusick else 32345750Smckusick dc->sc_flags |= DMAF_NOINTR; 32445750Smckusick } 32541480Smckusick #ifdef DEBUG 32641480Smckusick if (dmadebug & DDB_IO) 32741480Smckusick if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || 32841480Smckusick (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) { 32945750Smckusick printf("dmago: cmd %x, flags %x\n", 33045750Smckusick dc->sc_cmd, dc->sc_flags); 33145750Smckusick for (dcp = dc->sc_chain; dcp <= dc->sc_last; dcp++) 33245750Smckusick printf(" %d: %d@%x\n", dcp-dc->sc_chain, 33345750Smckusick dcp->dc_count, dcp->dc_addr); 33441480Smckusick } 33545750Smckusick dmatimo[unit] = 1; 33641480Smckusick #endif 33745817Smckusick DMA_ARM(dc); 33841480Smckusick } 33941480Smckusick 34041480Smckusick void 34141480Smckusick dmastop(unit) 34241480Smckusick register int unit; 34341480Smckusick { 34441480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 34541480Smckusick register struct devqueue *dq; 34641480Smckusick 34741480Smckusick #ifdef DEBUG 34841480Smckusick if (dmadebug & DDB_FOLLOW) 34941480Smckusick printf("dmastop(%d)\n", unit); 35045750Smckusick dmatimo[unit] = 0; 35141480Smckusick #endif 35241480Smckusick DMA_CLEAR(dc); 353*53930Shibler #if defined(HP360) || defined(HP370) || defined(HP380) 35445750Smckusick if (dc->sc_flags & DMAF_PCFLUSH) { 35545750Smckusick PCIA(); 35645750Smckusick dc->sc_flags &= ~DMAF_PCFLUSH; 35745750Smckusick } 35845750Smckusick #endif 35945750Smckusick #if defined(HP320) || defined(HP350) 36045750Smckusick if (dc->sc_flags & DMAF_VCFLUSH) { 36145750Smckusick /* 36245750Smckusick * 320/350s have VACs that may also need flushing. 36345750Smckusick * In our case we only flush the supervisor side 36445750Smckusick * because we know that if we are DMAing to user 36545750Smckusick * space, the physical pages will also be mapped 36645750Smckusick * in kernel space (via vmapbuf) and hence cache- 36745750Smckusick * inhibited by the pmap module due to the multiple 36845750Smckusick * mapping. 36945750Smckusick */ 37045750Smckusick DCIS(); 37145750Smckusick dc->sc_flags &= ~DMAF_VCFLUSH; 37245750Smckusick } 37345750Smckusick #endif 37441480Smckusick /* 37541480Smckusick * We may get this interrupt after a device service routine 37641480Smckusick * has freed the dma channel. So, ignore the intr if there's 37741480Smckusick * nothing on the queue. 37841480Smckusick */ 37941480Smckusick dq = dmachan[unit].dq_forw; 38045750Smckusick if (dq != &dmachan[unit]) 38141480Smckusick (dq->dq_driver->d_done)(dq->dq_unit); 38241480Smckusick } 38341480Smckusick 38441480Smckusick int 38541480Smckusick dmaintr() 38641480Smckusick { 38741480Smckusick register struct dma_softc *dc; 38845750Smckusick register int i, stat; 38941480Smckusick int found = 0; 39041480Smckusick 39141480Smckusick #ifdef DEBUG 39241480Smckusick if (dmadebug & DDB_FOLLOW) 39341480Smckusick printf("dmaintr\n"); 39441480Smckusick #endif 39541480Smckusick for (i = 0, dc = dma_softc; i < NDMA; i++, dc++) { 39641480Smckusick stat = DMA_STAT(dc); 39741480Smckusick if ((stat & DMA_INTR) == 0) 39841480Smckusick continue; 39941480Smckusick found++; 40041480Smckusick #ifdef DEBUG 40141480Smckusick if (dmadebug & DDB_IO) { 40241480Smckusick if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || 40341480Smckusick (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) 40441480Smckusick printf("dmaintr: unit %d stat %x next %d\n", 40545750Smckusick i, stat, (dc->sc_cur-dc->sc_chain)+1); 40641480Smckusick } 40741480Smckusick if (stat & DMA_ARMED) 40841480Smckusick printf("dma%d: intr when armed\n", i); 40941480Smckusick #endif 41045750Smckusick if (++dc->sc_cur <= dc->sc_last) { 41145750Smckusick #ifdef DEBUG 41245750Smckusick dmatimo[i] = 1; 41345750Smckusick #endif 41445750Smckusick /* 41545750Smckusick * Last chain segment, disable DMA interrupt. 41645750Smckusick */ 41745750Smckusick if (dc->sc_cur == dc->sc_last && 41845750Smckusick (dc->sc_flags & DMAF_NOINTR)) 41945750Smckusick dc->sc_cmd &= ~DMA_ENAB; 42041480Smckusick DMA_CLEAR(dc); 42145817Smckusick DMA_ARM(dc); 42241480Smckusick } else 42341480Smckusick dmastop(i); 42441480Smckusick } 42541480Smckusick return(found); 42641480Smckusick } 42741480Smckusick 42845750Smckusick #ifdef DEBUG 42941480Smckusick void 43045750Smckusick dmatimeout() 43141480Smckusick { 43241480Smckusick register int i, s; 43341480Smckusick 43445750Smckusick for (i = 0; i < NDMA; i++) { 43541480Smckusick s = splbio(); 43645750Smckusick if (dmatimo[i]) { 43745750Smckusick if (dmatimo[i] > 1) 43845750Smckusick printf("dma%d: timeout #%d\n", 43945750Smckusick i, dmatimo[i]-1); 44045750Smckusick dmatimo[i]++; 44141480Smckusick } 44241480Smckusick splx(s); 44341480Smckusick } 44445750Smckusick timeout(dmatimeout, (caddr_t)0, 30 * hz); 44541480Smckusick } 44645750Smckusick #endif 447