atzsc.c revision 1.42 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