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*49132Skarels * @(#)dma.c 7.5 (Berkeley) 05/04/91 841480Smckusick */ 941480Smckusick 1041480Smckusick /* 1141480Smckusick * DMA driver 1241480Smckusick */ 1341480Smckusick 14*49132Skarels #include "param.h" 15*49132Skarels #include "systm.h" 16*49132Skarels #include "time.h" 17*49132Skarels #include "kernel.h" 18*49132Skarels #include "proc.h" 19*49132Skarels 2041480Smckusick #include "dmareg.h" 2141480Smckusick #include "dmavar.h" 2241480Smckusick #include "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); 16745750Smckusick /* 16845750Smckusick * XXX we may not always go thru the flush code in dmastop() 16945750Smckusick */ 17045750Smckusick #if defined(HP360) || defined(HP370) 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); 24145750Smckusick if (count < (tcount = NBPG - ((int)addr & PGOFSET))) 24245750Smckusick tcount = count; 24345750Smckusick dcp->dc_count = tcount; 24445750Smckusick addr += tcount; 24541480Smckusick count -= tcount; 24645750Smckusick if (flags & DMAGO_LWORD) 24745750Smckusick tcount >>= 2; 24845750Smckusick else if (flags & DMAGO_WORD) 24945750Smckusick tcount >>= 1; 25045750Smckusick if (dcp->dc_addr == dmaend 25141480Smckusick #if defined(HP320) 25241480Smckusick /* only 16-bit count on 98620B */ 25341480Smckusick && (dc->sc_type != DMA_B || 25445750Smckusick (dcp-1)->dc_count + tcount <= 65536) 25541480Smckusick #endif 25641480Smckusick ) { 25741480Smckusick #ifdef DEBUG 25841480Smckusick dmahits[unit]++; 25941480Smckusick #endif 26045750Smckusick dmaend += dcp->dc_count; 26145750Smckusick (--dcp)->dc_count += tcount; 26241480Smckusick } else { 26341480Smckusick #ifdef DEBUG 26441480Smckusick dmamisses[unit]++; 26541480Smckusick #endif 26645750Smckusick dmaend = dcp->dc_addr + dcp->dc_count; 26745750Smckusick dcp->dc_count = tcount; 26841480Smckusick } 26941480Smckusick } 27045750Smckusick dc->sc_cur = dc->sc_chain; 27145750Smckusick dc->sc_last = --dcp; 27245750Smckusick dc->sc_flags = 0; 27341480Smckusick /* 27441480Smckusick * Set up the command word based on flags 27541480Smckusick */ 27641480Smckusick dc->sc_cmd = DMA_ENAB | DMA_IPL(DMAINTLVL) | DMA_START; 27741480Smckusick if ((flags & DMAGO_READ) == 0) 27841480Smckusick dc->sc_cmd |= DMA_WRT; 27941480Smckusick if (flags & DMAGO_LWORD) 28041480Smckusick dc->sc_cmd |= DMA_LWORD; 28141480Smckusick else if (flags & DMAGO_WORD) 28241480Smckusick dc->sc_cmd |= DMA_WORD; 28341480Smckusick if (flags & DMAGO_PRI) 28441480Smckusick dc->sc_cmd |= DMA_PRI; 28545750Smckusick #if defined(HP360) || defined(HP370) 28641480Smckusick /* 28745750Smckusick * Remember if we need to flush external physical cache when 28845750Smckusick * DMA is done. We only do this if we are reading (writing memory). 28941480Smckusick */ 29045750Smckusick if (ectype == EC_PHYS && (flags & DMAGO_READ)) 29145750Smckusick dc->sc_flags |= DMAF_PCFLUSH; 29241480Smckusick #endif 29345750Smckusick #if defined(HP320) || defined(HP350) 29445750Smckusick if (ectype == EC_VIRT && (flags & DMAGO_READ)) 29545750Smckusick dc->sc_flags |= DMAF_VCFLUSH; 29645750Smckusick #endif 29745750Smckusick /* 29845750Smckusick * Remember if we can skip the dma completion interrupt on 29945750Smckusick * the last segment in the chain. 30045750Smckusick */ 30145750Smckusick if (flags & DMAGO_NOINT) { 30245750Smckusick if (dc->sc_cur == dc->sc_last) 30345750Smckusick dc->sc_cmd &= ~DMA_ENAB; 30445750Smckusick else 30545750Smckusick dc->sc_flags |= DMAF_NOINTR; 30645750Smckusick } 30741480Smckusick #ifdef DEBUG 30841480Smckusick if (dmadebug & DDB_IO) 30941480Smckusick if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || 31041480Smckusick (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) { 31145750Smckusick printf("dmago: cmd %x, flags %x\n", 31245750Smckusick dc->sc_cmd, dc->sc_flags); 31345750Smckusick for (dcp = dc->sc_chain; dcp <= dc->sc_last; dcp++) 31445750Smckusick printf(" %d: %d@%x\n", dcp-dc->sc_chain, 31545750Smckusick dcp->dc_count, dcp->dc_addr); 31641480Smckusick } 31745750Smckusick dmatimo[unit] = 1; 31841480Smckusick #endif 31945817Smckusick DMA_ARM(dc); 32041480Smckusick } 32141480Smckusick 32241480Smckusick void 32341480Smckusick dmastop(unit) 32441480Smckusick register int unit; 32541480Smckusick { 32641480Smckusick register struct dma_softc *dc = &dma_softc[unit]; 32741480Smckusick register struct devqueue *dq; 32841480Smckusick 32941480Smckusick #ifdef DEBUG 33041480Smckusick if (dmadebug & DDB_FOLLOW) 33141480Smckusick printf("dmastop(%d)\n", unit); 33245750Smckusick dmatimo[unit] = 0; 33341480Smckusick #endif 33441480Smckusick DMA_CLEAR(dc); 33545750Smckusick #if defined(HP360) || defined(HP370) 33645750Smckusick if (dc->sc_flags & DMAF_PCFLUSH) { 33745750Smckusick PCIA(); 33845750Smckusick dc->sc_flags &= ~DMAF_PCFLUSH; 33945750Smckusick } 34045750Smckusick #endif 34145750Smckusick #if defined(HP320) || defined(HP350) 34245750Smckusick if (dc->sc_flags & DMAF_VCFLUSH) { 34345750Smckusick /* 34445750Smckusick * 320/350s have VACs that may also need flushing. 34545750Smckusick * In our case we only flush the supervisor side 34645750Smckusick * because we know that if we are DMAing to user 34745750Smckusick * space, the physical pages will also be mapped 34845750Smckusick * in kernel space (via vmapbuf) and hence cache- 34945750Smckusick * inhibited by the pmap module due to the multiple 35045750Smckusick * mapping. 35145750Smckusick */ 35245750Smckusick DCIS(); 35345750Smckusick dc->sc_flags &= ~DMAF_VCFLUSH; 35445750Smckusick } 35545750Smckusick #endif 35641480Smckusick /* 35741480Smckusick * We may get this interrupt after a device service routine 35841480Smckusick * has freed the dma channel. So, ignore the intr if there's 35941480Smckusick * nothing on the queue. 36041480Smckusick */ 36141480Smckusick dq = dmachan[unit].dq_forw; 36245750Smckusick if (dq != &dmachan[unit]) 36341480Smckusick (dq->dq_driver->d_done)(dq->dq_unit); 36441480Smckusick } 36541480Smckusick 36641480Smckusick int 36741480Smckusick dmaintr() 36841480Smckusick { 36941480Smckusick register struct dma_softc *dc; 37045750Smckusick register int i, stat; 37141480Smckusick int found = 0; 37241480Smckusick 37341480Smckusick #ifdef DEBUG 37441480Smckusick if (dmadebug & DDB_FOLLOW) 37541480Smckusick printf("dmaintr\n"); 37641480Smckusick #endif 37741480Smckusick for (i = 0, dc = dma_softc; i < NDMA; i++, dc++) { 37841480Smckusick stat = DMA_STAT(dc); 37941480Smckusick if ((stat & DMA_INTR) == 0) 38041480Smckusick continue; 38141480Smckusick found++; 38241480Smckusick #ifdef DEBUG 38341480Smckusick if (dmadebug & DDB_IO) { 38441480Smckusick if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) || 38541480Smckusick (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) 38641480Smckusick printf("dmaintr: unit %d stat %x next %d\n", 38745750Smckusick i, stat, (dc->sc_cur-dc->sc_chain)+1); 38841480Smckusick } 38941480Smckusick if (stat & DMA_ARMED) 39041480Smckusick printf("dma%d: intr when armed\n", i); 39141480Smckusick #endif 39245750Smckusick if (++dc->sc_cur <= dc->sc_last) { 39345750Smckusick #ifdef DEBUG 39445750Smckusick dmatimo[i] = 1; 39545750Smckusick #endif 39645750Smckusick /* 39745750Smckusick * Last chain segment, disable DMA interrupt. 39845750Smckusick */ 39945750Smckusick if (dc->sc_cur == dc->sc_last && 40045750Smckusick (dc->sc_flags & DMAF_NOINTR)) 40145750Smckusick dc->sc_cmd &= ~DMA_ENAB; 40241480Smckusick DMA_CLEAR(dc); 40345817Smckusick DMA_ARM(dc); 40441480Smckusick } else 40541480Smckusick dmastop(i); 40641480Smckusick } 40741480Smckusick return(found); 40841480Smckusick } 40941480Smckusick 41045750Smckusick #ifdef DEBUG 41141480Smckusick void 41245750Smckusick dmatimeout() 41341480Smckusick { 41441480Smckusick register int i, s; 41541480Smckusick 41645750Smckusick for (i = 0; i < NDMA; i++) { 41741480Smckusick s = splbio(); 41845750Smckusick if (dmatimo[i]) { 41945750Smckusick if (dmatimo[i] > 1) 42045750Smckusick printf("dma%d: timeout #%d\n", 42145750Smckusick i, dmatimo[i]-1); 42245750Smckusick dmatimo[i]++; 42341480Smckusick } 42441480Smckusick splx(s); 42541480Smckusick } 42645750Smckusick timeout(dmatimeout, (caddr_t)0, 30 * hz); 42741480Smckusick } 42845750Smckusick #endif 429