xref: /netbsd-src/sys/arch/atari/dev/dma.c (revision 1f2744e6e4915c9da2a3f980279398c4cf7d5e6d)
1 /*	$NetBSD: dma.c,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $	*/
2 
3 /*
4  * Copyright (c) 1995 Leo Weppelman.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Leo Weppelman.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * This file contains special code dealing with the DMA interface
35  * on the Atari ST.
36  *
37  * The DMA circuitry requires some special treatment for the peripheral
38  * devices which make use of the ST's DMA feature (the hard disk and the
39  * floppy drive).
40  * All devices using DMA need mutually exclusive access and can follow some
41  * standard pattern which will be provided in this file.
42  *
43  * The file contains the following entry points:
44  *
45  *	dmagrab:	ensure exclusive access to the DMA circuitry
46  *	dmafree:	free exclusive access to the DMA circuitry
47  *	dmaint:		DMA interrupt routine, switches to the current driver
48  *	dmaaddr:	specify 24 bit RAM address
49  *	dmardat:	set dma_mode and read word from dma_data
50  *	dmawdat:	set dma_mode and write word to dma_data
51  *	dmacomm:	like dmawdat, but first toggle WRBIT
52  *
53  * FIXME: 	The delay-loops should be done otherwise!
54  */
55 
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/kernel.h>
59 #include <machine/cpu.h>
60 #include <machine/iomap.h>
61 #include <machine/dma.h>
62 
63 #define	NDMA_DEV	10	/* Max 2 floppy's, 8 hard-disks		*/
64 typedef struct {
65 	int	(*call_func)();
66 	int	(*int_func)();
67 	void	*softc;
68 } DMA_DISP;
69 
70 static	DMA_DISP  dispatch[NDMA_DEV];	/* dispatch table		     */
71 static	int	  dma_free = 0;		/* next free entry in dispatch table */
72 static	int	  dma_curr = 0;		/* current entry in dispatch table   */
73 static	int	  dmalock = 0;		/* if != 0, dma is not free	     */
74 static	int	  (*xxxint)();		/* current interrupt function	     */
75 static	void	  *dma_softc;		/* Device currently owning DMA-intr  */
76 static	int	  sched_soft = 0;	/* Software interrupt scheduled	     */
77 
78 static	void	cdmasoft __P((void));
79 
80 dmagrab(int_func, call_func, softc)
81 int 	(*int_func)();
82 int 	(*call_func)();
83 void	*softc;
84 {
85 	int		sps;
86 	DMA_DISP	*disp;
87 
88 	sps = splbio();
89 
90 	if(dmalock) {
91 		disp = &dispatch[dma_free++];
92 		if(dma_free >= NDMA_DEV)
93 			dma_free = 0;
94 		if(disp->call_func != NULL)
95 			panic("dma dispatch table overflow");
96 		disp->call_func = call_func;
97 		disp->int_func  = int_func;
98 		disp->softc     = softc;
99 		splx(sps);
100 		return;
101 	}
102 	dmalock++;
103 	xxxint    = int_func;	/* Grab DMA interrupts			*/
104 	dma_softc = softc;	/* Identify device which got DMA	*/
105 	(*call_func)(softc);	/* Call followup function		*/
106 	splx(sps);
107 
108 }
109 
110 dmafree()
111 {
112 	int		sps;
113 	DMA_DISP	*disp;
114 
115 	sps = splbio();
116 	disp = &dispatch[dma_curr];
117 	if(disp->call_func != NULL) {
118 		xxxint    = disp->int_func;
119 		dma_softc = disp->softc;
120 		(*disp->call_func)(dma_softc);
121 		disp->call_func = NULL;
122 		if(++dma_curr >= NDMA_DEV)
123 			dma_curr = 0;
124 		splx(sps);
125 		return;
126 	}
127 	dmalock = 0;
128 	xxxint = NULL;		/* no more DMA interrupts */
129 	splx(sps);
130 }
131 
132 cdmaint(sr)
133 long	sr;	/* sr at time of interrupt */
134 {
135 	if(xxxint != NULL) {
136 		if(!BASEPRI(sr)) {
137 			if(!sched_soft++)
138 				add_sicallback(cdmasoft, 0, 0);
139 		}
140 		else {
141 			spl1();
142 			cdmasoft();
143 		}
144 	}
145 	else printf("DMA interrupt discarded\r\n");
146 }
147 
148 static void cdmasoft()
149 {
150 	sched_soft = 0;
151 	(*xxxint)(dma_softc);
152 }
153 
154 dmaaddr(address)
155 caddr_t	address;
156 {
157 	register u_long ad = (u_long)address;
158 
159 	DMA->dma_addr[AD_LOW ] = (ad     ) & 0xff;
160 	DMA->dma_addr[AD_MID ] = (ad >> 8) & 0xff;
161 	DMA->dma_addr[AD_HIGH] = (ad >>16) & 0xff;
162 }
163 
164 int
165 dmardat(mode, delay)
166 int	mode, delay;
167 {
168 	while(--delay >= 0);
169 	DMA->dma_mode = mode;
170 	while(--delay >= 0);
171 	return(DMA->dma_data);
172 }
173 
174 dmawdat(mode, data, delay)
175 int	mode, data, delay;
176 {
177 	DMA->dma_mode = mode;
178 	while(--delay >= 0);
179 	DMA->dma_data = data;
180 	while(--delay >= 0);
181 }
182 
183 dmacomm(mode, data, delay)
184 int	mode, data, delay;
185 {
186 	DMA->dma_mode = mode;
187 	DMA->dma_mode = mode ^ WRBIT;
188 	DMA->dma_mode = mode;
189 	while(--delay >= 0);
190 	DMA->dma_data = data;
191 	while(--delay >= 0);
192 }
193 
194 int
195 dmastat(mode, delay)
196 int	mode, delay;
197 {
198 	while(--delay >= 0);
199 	DMA->dma_mode = mode;
200 	while(--delay >= 0);
201 	return(DMA->dma_stat);
202 }
203