xref: /illumos-gate/usr/src/uts/common/io/dma_engine.c (revision 2d6eb4a5)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
28*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
29*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /*
32*7c478bd9Sstevel@tonic-gate  * This is the implementation of the kernel DMA interface for the
33*7c478bd9Sstevel@tonic-gate  * AT Class machines using Intel 8237A DMAC.
34*7c478bd9Sstevel@tonic-gate  *
35*7c478bd9Sstevel@tonic-gate  * The following routines in the interface are implemented:
36*7c478bd9Sstevel@tonic-gate  *	i_dmae_init()
37*7c478bd9Sstevel@tonic-gate  *	_dmae_nxcookie()
38*7c478bd9Sstevel@tonic-gate  *	i_dmae_acquire()
39*7c478bd9Sstevel@tonic-gate  *	i_dmae_free()
40*7c478bd9Sstevel@tonic-gate  *	i_dmae_prog()
41*7c478bd9Sstevel@tonic-gate  *	i_dmae_swsetup()
42*7c478bd9Sstevel@tonic-gate  *	i_dmae_swstart()
43*7c478bd9Sstevel@tonic-gate  *	i_dmae_stop()
44*7c478bd9Sstevel@tonic-gate  *	i_dmae_enable()
45*7c478bd9Sstevel@tonic-gate  *	i_dmae_disable()
46*7c478bd9Sstevel@tonic-gate  *	i_dmae_get_best_mode()
47*7c478bd9Sstevel@tonic-gate  *	i_dmae_get_chan_stat()
48*7c478bd9Sstevel@tonic-gate  *
49*7c478bd9Sstevel@tonic-gate  */
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/buf.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/dma_engine.h>
58*7c478bd9Sstevel@tonic-gate #include <sys/dma_i8237A.h>
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
61*7c478bd9Sstevel@tonic-gate #include <sys/promif.h>
62*7c478bd9Sstevel@tonic-gate static int dmaedebug = 0;
63*7c478bd9Sstevel@tonic-gate #define	dprintf(x)	if (dmaedebug) prom_printf x
64*7c478bd9Sstevel@tonic-gate #else
65*7c478bd9Sstevel@tonic-gate #define	dprintf(x)
66*7c478bd9Sstevel@tonic-gate #endif
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate static struct dmae_chnl dmae_stat[NCHANS];
70*7c478bd9Sstevel@tonic-gate static uintptr_t dmae_call_list[NCHANS] = {0, 0, 0, 0, 0, 0, 0, 0};
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate /*
73*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_init()
74*7c478bd9Sstevel@tonic-gate  *  purpose: called to initialize the dma interface, the DMAC, and any
75*7c478bd9Sstevel@tonic-gate  *           dma data structures. Called during system initialization.
76*7c478bd9Sstevel@tonic-gate  *  caller:  main()
77*7c478bd9Sstevel@tonic-gate  *  calls:   d37A_init()
78*7c478bd9Sstevel@tonic-gate  */
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate int
i_dmae_init(dev_info_t * dip)81*7c478bd9Sstevel@tonic-gate i_dmae_init(dev_info_t *dip)
82*7c478bd9Sstevel@tonic-gate {
83*7c478bd9Sstevel@tonic-gate 	int chnl;
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate 	dprintf(("i_dmae_init: initializing dma.\n"));
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	/* initialize semaphore map */
88*7c478bd9Sstevel@tonic-gate 	for (chnl = 0; chnl < NCHANS; chnl++) {
89*7c478bd9Sstevel@tonic-gate 		sema_init(&dmae_stat[chnl].dch_lock, 1, NULL, SEMA_DRIVER,
90*7c478bd9Sstevel@tonic-gate 		    (void *)NULL);
91*7c478bd9Sstevel@tonic-gate 	}
92*7c478bd9Sstevel@tonic-gate 	return (d37A_init(dip));
93*7c478bd9Sstevel@tonic-gate }
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate /*
97*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_acquire()
98*7c478bd9Sstevel@tonic-gate  *  purpose: Request the semaphore for the indicated channel.
99*7c478bd9Sstevel@tonic-gate  *           A call_back function can be passed if caller does/cannot
100*7c478bd9Sstevel@tonic-gate  *           wait for the semaphore.
101*7c478bd9Sstevel@tonic-gate  *  caller:  drivers
102*7c478bd9Sstevel@tonic-gate  *  calls:   sema_p(), sema_tryp(), ddi_set_callback()
103*7c478bd9Sstevel@tonic-gate  */
104*7c478bd9Sstevel@tonic-gate int
i_dmae_acquire(dev_info_t * dip,int chnl,int (* dmae_waitfp)(),caddr_t arg)105*7c478bd9Sstevel@tonic-gate i_dmae_acquire(dev_info_t *dip, int chnl, int (*dmae_waitfp)(), caddr_t arg)
106*7c478bd9Sstevel@tonic-gate {
107*7c478bd9Sstevel@tonic-gate #if defined(lint)
108*7c478bd9Sstevel@tonic-gate 	dip = dip;
109*7c478bd9Sstevel@tonic-gate #endif
110*7c478bd9Sstevel@tonic-gate 	dprintf(("i_dmae_acquire: channel %d, waitfp %p\n",
111*7c478bd9Sstevel@tonic-gate 	    chnl, (void *)dmae_waitfp));
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	if (!d37A_dma_valid(chnl))
114*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	if (dmae_waitfp == DDI_DMA_SLEEP) {
117*7c478bd9Sstevel@tonic-gate 		sema_p(&dmae_stat[chnl].dch_lock);
118*7c478bd9Sstevel@tonic-gate 	} else if (sema_tryp(&dmae_stat[chnl].dch_lock) == 0) {
119*7c478bd9Sstevel@tonic-gate 		if (dmae_waitfp == DDI_DMA_DONTWAIT) {
120*7c478bd9Sstevel@tonic-gate 			dprintf(("_dma_acquire: channel %d is busy.\n", chnl));
121*7c478bd9Sstevel@tonic-gate 		} else {
122*7c478bd9Sstevel@tonic-gate 			ddi_set_callback(dmae_waitfp, arg,
123*7c478bd9Sstevel@tonic-gate 			    &dmae_call_list[chnl]);
124*7c478bd9Sstevel@tonic-gate 		}
125*7c478bd9Sstevel@tonic-gate 		return (DDI_DMA_NORESOURCES);
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	/*
129*7c478bd9Sstevel@tonic-gate 	 * XXX -  save dip for authentication later ??
130*7c478bd9Sstevel@tonic-gate 	 */
131*7c478bd9Sstevel@tonic-gate 	dprintf(("_dma_acquire: channel %d now allocated.\n", chnl));
132*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
133*7c478bd9Sstevel@tonic-gate }
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate /*
137*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_free()
138*7c478bd9Sstevel@tonic-gate  *  purpose: Release the channel semaphore on chnl. Assumes caller actually
139*7c478bd9Sstevel@tonic-gate  *           owns the semaphore (no check made for this).
140*7c478bd9Sstevel@tonic-gate  *  caller:  drivers
141*7c478bd9Sstevel@tonic-gate  *  calls:   none
142*7c478bd9Sstevel@tonic-gate  */
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate int
i_dmae_free(dev_info_t * dip,int chnl)145*7c478bd9Sstevel@tonic-gate i_dmae_free(dev_info_t *dip, int chnl)
146*7c478bd9Sstevel@tonic-gate {
147*7c478bd9Sstevel@tonic-gate #if defined(lint)
148*7c478bd9Sstevel@tonic-gate 	dip = dip;
149*7c478bd9Sstevel@tonic-gate #endif
150*7c478bd9Sstevel@tonic-gate 	dprintf(("i_dmae_free: channel %d\n", chnl));
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate 	d37A_dma_release(chnl);
153*7c478bd9Sstevel@tonic-gate 	/*
154*7c478bd9Sstevel@tonic-gate 	 * XXX - should dip be authenticated as the one that did acquire?
155*7c478bd9Sstevel@tonic-gate 	 */
156*7c478bd9Sstevel@tonic-gate 	sema_v(&dmae_stat[chnl].dch_lock);
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	if (dmae_call_list[chnl])
159*7c478bd9Sstevel@tonic-gate 		ddi_run_callback(&dmae_call_list[chnl]);
160*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
161*7c478bd9Sstevel@tonic-gate }
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate /*
164*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_get_best_mode()
165*7c478bd9Sstevel@tonic-gate  *  purpose: confirm that data is aligned for efficient flyby mode
166*7c478bd9Sstevel@tonic-gate  *  caller:  driver routines.
167*7c478bd9Sstevel@tonic-gate  *  calls:   d37A_get_best_mode.
168*7c478bd9Sstevel@tonic-gate  */
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate uchar_t
i_dmae_get_best_mode(dev_info_t * dip,struct ddi_dmae_req * dmaereqp)171*7c478bd9Sstevel@tonic-gate i_dmae_get_best_mode(dev_info_t *dip, struct ddi_dmae_req *dmaereqp)
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate #if defined(lint)
174*7c478bd9Sstevel@tonic-gate 	dip = dip;
175*7c478bd9Sstevel@tonic-gate #endif
176*7c478bd9Sstevel@tonic-gate 	return (d37A_get_best_mode(dmaereqp));
177*7c478bd9Sstevel@tonic-gate }
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate /*
180*7c478bd9Sstevel@tonic-gate  *  routine: _dmae_nxcookie()
181*7c478bd9Sstevel@tonic-gate  *  purpose: service the interrupt by calling device driver routine for next
182*7c478bd9Sstevel@tonic-gate  *		DMA cookie.
183*7c478bd9Sstevel@tonic-gate  *  caller:  d37A_intr()
184*7c478bd9Sstevel@tonic-gate  *  calls:   routine provided in request structure
185*7c478bd9Sstevel@tonic-gate  */
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate ddi_dma_cookie_t *
_dmae_nxcookie(int chnl)188*7c478bd9Sstevel@tonic-gate _dmae_nxcookie(int chnl)
189*7c478bd9Sstevel@tonic-gate {
190*7c478bd9Sstevel@tonic-gate 	ddi_dma_cookie_t *cookiep = NULL;
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 	dprintf(("_dmae_nxcookie: chnl %d\n", chnl));
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	if (dmae_stat[chnl].proc) {
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 		cookiep = dmae_stat[chnl].proc(dmae_stat[chnl].procparms);
197*7c478bd9Sstevel@tonic-gate 		/*
198*7c478bd9Sstevel@tonic-gate 		 * expect a cookie pointer from user's routine;
199*7c478bd9Sstevel@tonic-gate 		 * null cookie pointer will terminate chaining
200*7c478bd9Sstevel@tonic-gate 		 */
201*7c478bd9Sstevel@tonic-gate 	}
202*7c478bd9Sstevel@tonic-gate 	return (cookiep);
203*7c478bd9Sstevel@tonic-gate }
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate /*
207*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_prog()
208*7c478bd9Sstevel@tonic-gate  *  purpose: Program channel for the to_be_initiated_by_hardware operation.
209*7c478bd9Sstevel@tonic-gate  *           _dma_acquire is called to request the channel semaphore and
210*7c478bd9Sstevel@tonic-gate  *	     mode is passed as the sleep parameter.
211*7c478bd9Sstevel@tonic-gate  *	     The channel is enabled after it is setup.
212*7c478bd9Sstevel@tonic-gate  *	     Note that the ddi_dmae_req pointer can be to NULL if the mode
213*7c478bd9Sstevel@tonic-gate  *	     registers have already been setup by a prior call; this implements
214*7c478bd9Sstevel@tonic-gate  *	     a prog_next() to update the address and count registers.
215*7c478bd9Sstevel@tonic-gate  *  caller:  driver routines
216*7c478bd9Sstevel@tonic-gate  *  calls:   d37A_prog_chan()
217*7c478bd9Sstevel@tonic-gate  */
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate int
i_dmae_prog(dev_info_t * dip,struct ddi_dmae_req * dmaereqp,ddi_dma_cookie_t * cp,int chnl)220*7c478bd9Sstevel@tonic-gate i_dmae_prog(dev_info_t *dip, struct ddi_dmae_req *dmaereqp,
221*7c478bd9Sstevel@tonic-gate     ddi_dma_cookie_t *cp, int chnl)
222*7c478bd9Sstevel@tonic-gate {
223*7c478bd9Sstevel@tonic-gate 	struct dmae_chnl *dcp;
224*7c478bd9Sstevel@tonic-gate 	int rval;
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate #if defined(lint)
227*7c478bd9Sstevel@tonic-gate 	dip = dip;
228*7c478bd9Sstevel@tonic-gate #endif
229*7c478bd9Sstevel@tonic-gate 	rval = d37A_prog_chan(dmaereqp, cp, chnl);
230*7c478bd9Sstevel@tonic-gate 	if (rval != DDI_SUCCESS) {
231*7c478bd9Sstevel@tonic-gate 		dprintf(("i_dmae_prog: failure on channel %d dmaereq=%p\n",
232*7c478bd9Sstevel@tonic-gate 		    chnl, (void *)dmaereqp));
233*7c478bd9Sstevel@tonic-gate 	} else {
234*7c478bd9Sstevel@tonic-gate 		dprintf(("i_dmae_prog: channel %d dmaereq=%p\n",
235*7c478bd9Sstevel@tonic-gate 		    chnl, (void *)dmaereqp));
236*7c478bd9Sstevel@tonic-gate 		dcp = &dmae_stat[chnl];
237*7c478bd9Sstevel@tonic-gate 		dcp->dch_cookiep = cp;
238*7c478bd9Sstevel@tonic-gate 		if (dmaereqp) {
239*7c478bd9Sstevel@tonic-gate 			dcp->proc = dmaereqp->proc;
240*7c478bd9Sstevel@tonic-gate 			dcp->procparms = dmaereqp->procparms;
241*7c478bd9Sstevel@tonic-gate 		}
242*7c478bd9Sstevel@tonic-gate 		d37A_dma_enable(chnl);
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate 	return (rval);
245*7c478bd9Sstevel@tonic-gate }
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate /*
249*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_swsetup()
250*7c478bd9Sstevel@tonic-gate  *  purpose: Setup chan for the operation given in dmacbptr.
251*7c478bd9Sstevel@tonic-gate  *           _dma_acquire is first called
252*7c478bd9Sstevel@tonic-gate  *           to request the channel semaphore for chnl; mode is
253*7c478bd9Sstevel@tonic-gate  *           passed to _dma_acquire().
254*7c478bd9Sstevel@tonic-gate  *  caller:  driver routines
255*7c478bd9Sstevel@tonic-gate  *  calls:   d37A_dma_swsetup()
256*7c478bd9Sstevel@tonic-gate  */
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate int
i_dmae_swsetup(dev_info_t * dip,struct ddi_dmae_req * dmaereqp,ddi_dma_cookie_t * cp,int chnl)259*7c478bd9Sstevel@tonic-gate i_dmae_swsetup(dev_info_t *dip, struct ddi_dmae_req *dmaereqp,
260*7c478bd9Sstevel@tonic-gate     ddi_dma_cookie_t *cp, int chnl)
261*7c478bd9Sstevel@tonic-gate {
262*7c478bd9Sstevel@tonic-gate 	struct dmae_chnl *dcp;
263*7c478bd9Sstevel@tonic-gate 	int rval;
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate #if defined(lint)
266*7c478bd9Sstevel@tonic-gate 	dip = dip;
267*7c478bd9Sstevel@tonic-gate #endif
268*7c478bd9Sstevel@tonic-gate 	rval = d37A_dma_swsetup(dmaereqp, cp, chnl);
269*7c478bd9Sstevel@tonic-gate 	if (rval != DDI_SUCCESS) {
270*7c478bd9Sstevel@tonic-gate 		dprintf(("i_dmae_swsetup: failure on channel %d dmaereq=%p\n",
271*7c478bd9Sstevel@tonic-gate 		    chnl, (void *)dmaereqp));
272*7c478bd9Sstevel@tonic-gate 	} else {
273*7c478bd9Sstevel@tonic-gate 		dprintf(("i_dmae_swsetup: channel %d: dmaereq=%p\n",
274*7c478bd9Sstevel@tonic-gate 		    chnl, (void *)dmaereqp));
275*7c478bd9Sstevel@tonic-gate 		dcp = &dmae_stat[chnl];
276*7c478bd9Sstevel@tonic-gate 		dcp->dch_cookiep = cp;
277*7c478bd9Sstevel@tonic-gate 		dcp->proc = dmaereqp->proc;
278*7c478bd9Sstevel@tonic-gate 		dcp->procparms = dmaereqp->procparms;
279*7c478bd9Sstevel@tonic-gate 	}
280*7c478bd9Sstevel@tonic-gate 	return (rval);
281*7c478bd9Sstevel@tonic-gate }
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate /*
285*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_swstart()
286*7c478bd9Sstevel@tonic-gate  *  purpose: Start the operation setup by i_dmae_swsetup().
287*7c478bd9Sstevel@tonic-gate  *  caller:  driver routines
288*7c478bd9Sstevel@tonic-gate  *  calls:   d37A_dma_swstart().
289*7c478bd9Sstevel@tonic-gate  */
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate void
i_dmae_swstart(dev_info_t * dip,int chnl)292*7c478bd9Sstevel@tonic-gate i_dmae_swstart(dev_info_t *dip, int chnl)
293*7c478bd9Sstevel@tonic-gate {
294*7c478bd9Sstevel@tonic-gate #if defined(lint)
295*7c478bd9Sstevel@tonic-gate 	dip = dip;
296*7c478bd9Sstevel@tonic-gate #endif
297*7c478bd9Sstevel@tonic-gate 	dprintf(("i_dmae_swstart: channel %d.\n", chnl));
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	d37A_dma_swstart(chnl);
300*7c478bd9Sstevel@tonic-gate }
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate /*
304*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_stop()
305*7c478bd9Sstevel@tonic-gate  *  purpose: stop DMA activity on chnl.
306*7c478bd9Sstevel@tonic-gate  *  caller:  driver routines
307*7c478bd9Sstevel@tonic-gate  *  calls:   splhi(), _dma_relse(), splx(),
308*7c478bd9Sstevel@tonic-gate  *           d37A_dma_stop().
309*7c478bd9Sstevel@tonic-gate  */
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate void
i_dmae_stop(dev_info_t * dip,int chnl)312*7c478bd9Sstevel@tonic-gate i_dmae_stop(dev_info_t *dip, int chnl)
313*7c478bd9Sstevel@tonic-gate {
314*7c478bd9Sstevel@tonic-gate #if defined(lint)
315*7c478bd9Sstevel@tonic-gate 	dip = dip;
316*7c478bd9Sstevel@tonic-gate #endif
317*7c478bd9Sstevel@tonic-gate 	dprintf(("i_dmae_stop: channel %d\n", chnl));
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	/* call d37A the stop the channel */
320*7c478bd9Sstevel@tonic-gate 	d37A_dma_stop(chnl);
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	dmae_stat[chnl].dch_cookiep = NULL;
323*7c478bd9Sstevel@tonic-gate }
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate /*
327*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_enable()
328*7c478bd9Sstevel@tonic-gate  *  purpose: Allow the hardware tied to channel chnl to request service
329*7c478bd9Sstevel@tonic-gate  *           from the DMAC. i_dmae_prog() should have been called prior
330*7c478bd9Sstevel@tonic-gate  *           to this.
331*7c478bd9Sstevel@tonic-gate  *  caller:  driver routines.
332*7c478bd9Sstevel@tonic-gate  *  calls:   d37A_dma_enable()
333*7c478bd9Sstevel@tonic-gate  */
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate void
i_dmae_enable(dev_info_t * dip,int chnl)336*7c478bd9Sstevel@tonic-gate i_dmae_enable(dev_info_t *dip, int chnl)
337*7c478bd9Sstevel@tonic-gate {
338*7c478bd9Sstevel@tonic-gate #if defined(lint)
339*7c478bd9Sstevel@tonic-gate 	dip = dip;
340*7c478bd9Sstevel@tonic-gate #endif
341*7c478bd9Sstevel@tonic-gate 	dprintf(("i_dmae_enable: channel %d\n", chnl));
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	d37A_dma_enable(chnl);
344*7c478bd9Sstevel@tonic-gate }
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate /*
348*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_disable()
349*7c478bd9Sstevel@tonic-gate  *  purpose: Called to mask off hardware requests on channel chnl. Assumes
350*7c478bd9Sstevel@tonic-gate  *           the caller owns the channel.
351*7c478bd9Sstevel@tonic-gate  *  caller:  driver routines.
352*7c478bd9Sstevel@tonic-gate  *  calls:   d37A_dma_disable()
353*7c478bd9Sstevel@tonic-gate  */
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate void
i_dmae_disable(dev_info_t * dip,int chnl)356*7c478bd9Sstevel@tonic-gate i_dmae_disable(dev_info_t *dip, int chnl)
357*7c478bd9Sstevel@tonic-gate {
358*7c478bd9Sstevel@tonic-gate #if defined(lint)
359*7c478bd9Sstevel@tonic-gate 	dip = dip;
360*7c478bd9Sstevel@tonic-gate #endif
361*7c478bd9Sstevel@tonic-gate 	/* dprintf(("i_dmae_disable: disable channel %d.\n", chnl)); */
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	d37A_dma_disable(chnl);
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	dmae_stat[chnl].dch_cookiep = NULL;
366*7c478bd9Sstevel@tonic-gate }
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate /*
370*7c478bd9Sstevel@tonic-gate  *  routine: i_dmae_get_chan_stat()
371*7c478bd9Sstevel@tonic-gate  *  purpose: Obtain the current channel status from the DMAC
372*7c478bd9Sstevel@tonic-gate  *  caller:  driver routines.
373*7c478bd9Sstevel@tonic-gate  *  calls:   d37A_get_chan_stat()
374*7c478bd9Sstevel@tonic-gate  */
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate void
i_dmae_get_chan_stat(dev_info_t * dip,int chnl,ulong_t * addressp,int * countp)377*7c478bd9Sstevel@tonic-gate i_dmae_get_chan_stat(dev_info_t *dip, int chnl, ulong_t *addressp, int *countp)
378*7c478bd9Sstevel@tonic-gate {
379*7c478bd9Sstevel@tonic-gate #if defined(lint)
380*7c478bd9Sstevel@tonic-gate 	dip = dip;
381*7c478bd9Sstevel@tonic-gate #endif
382*7c478bd9Sstevel@tonic-gate 	dprintf(("i_dmae_get_chan_stat: channel %d", chnl));
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	d37A_get_chan_stat(chnl, addressp, countp);
385*7c478bd9Sstevel@tonic-gate }
386