xref: /csrg-svn/sys/hp300/dev/dma.c (revision 49132)
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