xref: /netbsd-src/sys/arch/amiga/dev/atzsc.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: atzsc.c,v 1.42 2010/02/09 18:13:10 phx Exp $ */
2 
3 /*
4  * Copyright (c) 1982, 1990 The Regents of the University of California.
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. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *	@(#)dma.c
32  */
33 
34 /*
35  * Copyright (c) 1994 Christian E. Hopps
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. All advertising materials mentioning features or use of this software
46  *    must display the following acknowledgement:
47  *	This product includes software developed by the University of
48  *	California, Berkeley and its contributors.
49  * 4. Neither the name of the University nor the names of its contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  *
65  *	@(#)dma.c
66  */
67 
68 #include <sys/cdefs.h>
69 __KERNEL_RCSID(0, "$NetBSD: atzsc.c,v 1.42 2010/02/09 18:13:10 phx Exp $");
70 
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/kernel.h>
74 #include <sys/device.h>
75 #include <sys/intr.h>
76 #include <machine/cpu.h>
77 #include <dev/scsipi/scsi_all.h>
78 #include <dev/scsipi/scsipi_all.h>
79 #include <dev/scsipi/scsiconf.h>
80 #include <amiga/amiga/custom.h>
81 #include <amiga/amiga/cc.h>
82 #include <amiga/amiga/device.h>
83 #include <amiga/amiga/isr.h>
84 #include <amiga/dev/dmavar.h>
85 #include <amiga/dev/sbicreg.h>
86 #include <amiga/dev/sbicvar.h>
87 #include <amiga/dev/atzscreg.h>
88 #include <amiga/dev/zbusvar.h>
89 
90 void atzscattach(struct device *, struct device *, void *);
91 int atzscmatch(struct device *, struct cfdata *, void *);
92 
93 void atzsc_enintr(struct sbic_softc *);
94 void atzsc_dmastop(struct sbic_softc *);
95 int atzsc_dmanext(struct sbic_softc *);
96 int atzsc_dmaintr(void *);
97 int atzsc_dmago(struct sbic_softc *, char *, int, int);
98 
99 #ifdef DEBUG
100 void atzsc_dump(void);
101 #endif
102 
103 #ifdef DEBUG
104 int	atzsc_dmadebug = 0;
105 #endif
106 
107 CFATTACH_DECL(atzsc, sizeof(struct sbic_softc),
108     atzscmatch, atzscattach, NULL, NULL);
109 
110 /*
111  * if we are a A2091 SCSI
112  */
113 int
114 atzscmatch(struct device *pdp, struct cfdata *cfp, void *auxp)
115 {
116 	struct zbus_args *zap;
117 
118 	zap = auxp;
119 
120 	/*
121 	 * Check manufacturer and product id.
122 	 * I was informed that older boards can be 2 also.
123 	 */
124 	if (zap->manid == 514 && (zap->prodid == 3 || zap->prodid == 2))
125 		return(1);
126 	else
127 		return(0);
128 }
129 
130 void
131 atzscattach(struct device *pdp, struct device *dp, void *auxp)
132 {
133 	volatile struct sdmac *rp;
134 	struct sbic_softc *sc = (struct sbic_softc *)dp;
135 	struct zbus_args *zap;
136 	struct scsipi_adapter *adapt = &sc->sc_adapter;
137 	struct scsipi_channel *chan = &sc->sc_channel;
138 
139 	zap = auxp;
140 
141 	sc->sc_cregs = rp = zap->va;
142 	/*
143 	 * disable ints and reset bank register
144 	 */
145 	rp->CNTR = CNTR_PDMD;
146 	amiga_membarrier();
147 	rp->DAWR = DAWR_ATZSC;
148 	amiga_membarrier();
149 	sc->sc_enintr = atzsc_enintr;
150 	sc->sc_dmago = atzsc_dmago;
151 	sc->sc_dmanext = atzsc_dmanext;
152 	sc->sc_dmastop = atzsc_dmastop;
153 	sc->sc_dmacmd = 0;
154 
155 	/*
156 	 * only 24 bit mem.
157 	 */
158 	sc->sc_flags |= SBICF_BADDMA;
159 	sc->sc_dmamask = ~0x00ffffff;
160 #if 0
161 	/*
162 	 * If the users kva space is not ztwo try and allocate a bounce buffer.
163 	 * XXX this needs to change if we move to multiple memory segments.
164 	 */
165 	if (kvtop(sc) & sc->sc_dmamask) {
166 		sc->sc_dmabuffer = (char *)alloc_z2mem(MAXPHYS * 8); /* XXX */
167 		if (isztwomem(sc->sc_dmabuffer))
168 			printf(" bounce pa 0x%x", kvtop(sc->sc_dmabuffer));
169 		else if (sc->sc_dmabuffer)
170 			printf(" bounce pa 0x%x",
171 			    PREP_DMA_MEM(sc->sc_dmabuffer));
172 	}
173 #endif
174 	sc->sc_sbic.sbic_asr_p = (volatile unsigned char *)rp + 0x91;
175 	sc->sc_sbic.sbic_value_p = (volatile unsigned char *)rp + 0x93;
176 
177 	sc->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 77;
178 
179 	printf(": dmamask 0x%lx\n", ~sc->sc_dmamask);
180 
181 	/*
182 	 * Fill in the scsipi_adapter.
183 	 */
184 	memset(adapt, 0, sizeof(*adapt));
185 	adapt->adapt_dev = &sc->sc_dev;
186 	adapt->adapt_nchannels = 1;
187 	adapt->adapt_openings = 7;
188 	adapt->adapt_max_periph = 1;
189 	adapt->adapt_request = sbic_scsipi_request;
190 	adapt->adapt_minphys = sbic_minphys;
191 
192 	/*
193 	 * Fill in the scsipi_channel.
194 	 */
195 	memset(chan, 0, sizeof(*chan));
196 	chan->chan_adapter = adapt;
197 	chan->chan_bustype = &scsi_bustype;
198 	chan->chan_channel = 0;
199 	chan->chan_ntargets = 8;
200 	chan->chan_nluns = 8;
201 	chan->chan_id = 7;
202 
203 	sbicinit(sc);
204 
205 	sc->sc_isr.isr_intr = atzsc_dmaintr;
206 	sc->sc_isr.isr_arg = sc;
207 	sc->sc_isr.isr_ipl = 2;
208 	add_isr (&sc->sc_isr);
209 
210 	/*
211 	 * attach all scsi units on us
212 	 */
213 	config_found(dp, chan, scsiprint);
214 }
215 
216 void
217 atzsc_enintr(struct sbic_softc *dev)
218 {
219 	volatile struct sdmac *sdp;
220 
221 	sdp = dev->sc_cregs;
222 
223 	dev->sc_flags |= SBICF_INTR;
224 	sdp->CNTR = CNTR_PDMD | CNTR_INTEN;
225 	amiga_membarrier();
226 }
227 
228 int
229 atzsc_dmago(struct sbic_softc *dev, char *addr, int count, int flags)
230 {
231 	volatile struct sdmac *sdp;
232 
233 	sdp = dev->sc_cregs;
234 	/*
235 	 * Set up the command word based on flags
236 	 */
237 	dev->sc_dmacmd = CNTR_PDMD | CNTR_INTEN;
238 	if ((flags & DMAGO_READ) == 0)
239 		dev->sc_dmacmd |= CNTR_DDIR;
240 #ifdef DEBUG
241 	if (atzsc_dmadebug & DDB_IO)
242 		printf("atzsc_dmago: cmd %x\n", dev->sc_dmacmd);
243 #endif
244 
245 	dev->sc_flags |= SBICF_INTR;
246 	sdp->CNTR = dev->sc_dmacmd;
247 	amiga_membarrier();
248 	sdp->ACR = (u_int) dev->sc_cur->dc_addr;
249 	amiga_membarrier();
250 	sdp->ST_DMA = 1;
251 	amiga_membarrier();
252 
253 	return(dev->sc_tcnt);
254 }
255 
256 void
257 atzsc_dmastop(struct sbic_softc *dev)
258 {
259 	volatile struct sdmac *sdp;
260 	int s;
261 	vu_short istr;
262 
263 	sdp = dev->sc_cregs;
264 
265 #ifdef DEBUG
266 	if (atzsc_dmadebug & DDB_FOLLOW)
267 		printf("atzsc_dmastop()\n");
268 #endif
269 	if (dev->sc_dmacmd) {
270 		s = splbio();
271 		if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
272 			/*
273 			 * only FLUSH if terminal count not enabled,
274 			 * and reading from peripheral
275 			 */
276 			sdp->FLUSH = 1;
277 			amiga_membarrier();
278 			do {
279 				istr = sdp->ISTR;
280 				amiga_membarrier();
281 			} while ((istr & ISTR_FE_FLG) == 0);
282 		}
283 		/*
284 		 * clear possible interrupt and stop DMA
285 		 */
286 		sdp->CINT = 1;
287 		amiga_membarrier();
288 		sdp->SP_DMA = 1;
289 		amiga_membarrier();
290 		dev->sc_dmacmd = 0;
291 		splx(s);
292 	}
293 }
294 
295 int
296 atzsc_dmaintr(void *arg)
297 {
298 	struct sbic_softc *dev = arg;
299 	volatile struct sdmac *sdp;
300 	int stat, found;
301 
302 	sdp = dev->sc_cregs;
303 	stat = sdp->ISTR;
304 
305 	if ((stat & (ISTR_INT_F|ISTR_INT_P)) == 0)
306 		return (0);
307 
308 #ifdef DEBUG
309 	if (atzsc_dmadebug & DDB_FOLLOW)
310 		printf("%s: dmaintr 0x%x\n", dev->sc_dev.dv_xname, stat);
311 #endif
312 
313 	/*
314 	 * both, SCSI and DMA interrupts arrive here. I chose
315 	 * arbitrarily that DMA interrupts should have higher
316 	 * precedence than SCSI interrupts.
317 	 */
318 	found = 0;
319 	if (stat & ISTR_E_INT) {
320 		found++;
321 
322 		sdp->CINT = 1;	/* clear possible interrupt */
323 		amiga_membarrier();
324 
325 		/*
326 		 * check for SCSI ints in the same go and
327 		 * eventually save an interrupt
328 		 */
329 	}
330 
331 	if (dev->sc_flags & SBICF_INTR && stat & ISTR_INTS)
332 		found += sbicintr(dev);
333 	return(found);
334 }
335 
336 
337 int
338 atzsc_dmanext(struct sbic_softc *dev)
339 {
340 	volatile struct sdmac *sdp;
341 	vu_short istr;
342 
343 	sdp = dev->sc_cregs;
344 
345 	if (dev->sc_cur > dev->sc_last) {
346 		/* shouldn't happen !! */
347 		printf("atzsc_dmanext at end !!!\n");
348 		atzsc_dmastop(dev);
349 		return(0);
350 	}
351 	if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
352 		  /*
353 		   * only FLUSH if terminal count not enabled,
354 		   * and reading from peripheral
355 		   */
356 		sdp->FLUSH = 1;
357 		amiga_membarrier();
358 		do {
359 			istr = sdp->ISTR;
360 			amiga_membarrier();
361 		} while ((istr & ISTR_FE_FLG) == 0);
362 	}
363 	/*
364 	 * clear possible interrupt and stop DMA
365 	 */
366 	sdp->CINT = 1;	/* clear possible interrupt */
367 	amiga_membarrier();
368 	sdp->SP_DMA = 1;	/* stop DMA */
369 	amiga_membarrier();
370 	sdp->CNTR = dev->sc_dmacmd;
371 	amiga_membarrier();
372 	sdp->ACR = (u_int)dev->sc_cur->dc_addr;
373 	amiga_membarrier();
374 	sdp->ST_DMA = 1;
375 	amiga_membarrier();
376 
377 	dev->sc_tcnt = dev->sc_cur->dc_count << 1;
378 	return(dev->sc_tcnt);
379 }
380 
381 #ifdef DEBUG
382 void
383 atzsc_dump(void)
384 {
385 	extern struct cfdriver atzsc_cd;
386 	struct sbic_softc *sc;
387 	int i;
388 
389 	for (i = 0; i < atzsc_cd.cd_ndevs; ++i) {
390 		sc = device_lookup_private(&atzsc_cd, i);
391 		if (sc != NULL)
392 			sbic_dump(sc);
393 	}
394 }
395 #endif
396