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