1 /* $NetBSD: atzsc.c,v 1.45 2021/08/07 16:18:41 thorpej 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.45 2021/08/07 16:18:41 thorpej 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(device_t, device_t, void *);
91 int atzscmatch(device_t, cfdata_t, 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_NEW(atzsc, sizeof(struct sbic_softc),
108 atzscmatch, atzscattach, NULL, NULL);
109
110 /*
111 * if we are a A2091 SCSI
112 */
113 int
114 atzscmatch(device_t parent, cfdata_t cf, void *aux)
115 {
116 struct zbus_args *zap;
117
118 zap = aux;
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(device_t parent, device_t self, void *aux)
132 {
133 volatile struct sdmac *rp;
134 struct sbic_softc *sc = device_private(self);
135 struct zbus_args *zap;
136 struct scsipi_adapter *adapt = &sc->sc_adapter;
137 struct scsipi_channel *chan = &sc->sc_channel;
138
139 zap = aux;
140
141 sc->sc_dev = self;
142 sc->sc_cregs = rp = zap->va;
143 /*
144 * disable ints and reset bank register
145 */
146 rp->CNTR = CNTR_PDMD;
147 amiga_membarrier();
148 rp->DAWR = DAWR_ATZSC;
149 amiga_membarrier();
150 sc->sc_enintr = atzsc_enintr;
151 sc->sc_dmago = atzsc_dmago;
152 sc->sc_dmanext = atzsc_dmanext;
153 sc->sc_dmastop = atzsc_dmastop;
154 sc->sc_dmacmd = 0;
155
156 /*
157 * only 24 bit mem.
158 */
159 sc->sc_flags |= SBICF_BADDMA;
160 sc->sc_dmamask = ~0x00ffffff;
161 #if 0
162 /*
163 * If the users kva space is not ztwo try and allocate a bounce buffer.
164 * XXX this needs to change if we move to multiple memory segments.
165 */
166 if (kvtop(sc) & sc->sc_dmamask) {
167 sc->sc_dmabuffer = (char *)alloc_z2mem(MAXPHYS * 8); /* XXX */
168 if (isztwomem(sc->sc_dmabuffer))
169 printf(" bounce pa 0x%x", kvtop(sc->sc_dmabuffer));
170 else if (sc->sc_dmabuffer)
171 printf(" bounce pa 0x%x",
172 PREP_DMA_MEM(sc->sc_dmabuffer));
173 }
174 #endif
175 sc->sc_sbic.sbic_asr_p = (volatile unsigned char *)rp + 0x91;
176 sc->sc_sbic.sbic_value_p = (volatile unsigned char *)rp + 0x93;
177
178 sc->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 77;
179
180 printf(": dmamask 0x%lx\n", ~sc->sc_dmamask);
181
182 /*
183 * Fill in the scsipi_adapter.
184 */
185 memset(adapt, 0, sizeof(*adapt));
186 adapt->adapt_dev = self;
187 adapt->adapt_nchannels = 1;
188 adapt->adapt_openings = 7;
189 adapt->adapt_max_periph = 1;
190 adapt->adapt_request = sbic_scsipi_request;
191 adapt->adapt_minphys = sbic_minphys;
192
193 /*
194 * Fill in the scsipi_channel.
195 */
196 memset(chan, 0, sizeof(*chan));
197 chan->chan_adapter = adapt;
198 chan->chan_bustype = &scsi_bustype;
199 chan->chan_channel = 0;
200 chan->chan_ntargets = 8;
201 chan->chan_nluns = 8;
202 chan->chan_id = 7;
203
204 sbicinit(sc);
205
206 sc->sc_isr.isr_intr = atzsc_dmaintr;
207 sc->sc_isr.isr_arg = sc;
208 sc->sc_isr.isr_ipl = 2;
209 add_isr (&sc->sc_isr);
210
211 /*
212 * attach all scsi units on us
213 */
214 config_found(self, chan, scsiprint, CFARGS_NONE);
215 }
216
217 void
218 atzsc_enintr(struct sbic_softc *dev)
219 {
220 volatile struct sdmac *sdp;
221
222 sdp = dev->sc_cregs;
223
224 dev->sc_flags |= SBICF_INTR;
225 sdp->CNTR = CNTR_PDMD | CNTR_INTEN;
226 amiga_membarrier();
227 }
228
229 int
230 atzsc_dmago(struct sbic_softc *dev, char *addr, int count, int flags)
231 {
232 volatile struct sdmac *sdp;
233
234 sdp = dev->sc_cregs;
235 /*
236 * Set up the command word based on flags
237 */
238 dev->sc_dmacmd = CNTR_PDMD | CNTR_INTEN;
239 if ((flags & DMAGO_READ) == 0)
240 dev->sc_dmacmd |= CNTR_DDIR;
241 #ifdef DEBUG
242 if (atzsc_dmadebug & DDB_IO)
243 printf("atzsc_dmago: cmd %x\n", dev->sc_dmacmd);
244 #endif
245
246 dev->sc_flags |= SBICF_INTR;
247 sdp->CNTR = dev->sc_dmacmd;
248 amiga_membarrier();
249 sdp->ACR = (u_int) dev->sc_cur->dc_addr;
250 amiga_membarrier();
251 sdp->ST_DMA = 1;
252 amiga_membarrier();
253
254 return(dev->sc_tcnt);
255 }
256
257 void
258 atzsc_dmastop(struct sbic_softc *dev)
259 {
260 volatile struct sdmac *sdp;
261 int s;
262 vu_short istr;
263
264 sdp = dev->sc_cregs;
265
266 #ifdef DEBUG
267 if (atzsc_dmadebug & DDB_FOLLOW)
268 printf("atzsc_dmastop()\n");
269 #endif
270 if (dev->sc_dmacmd) {
271 s = splbio();
272 if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
273 /*
274 * only FLUSH if terminal count not enabled,
275 * and reading from peripheral
276 */
277 sdp->FLUSH = 1;
278 amiga_membarrier();
279 do {
280 istr = sdp->ISTR;
281 amiga_membarrier();
282 } while ((istr & ISTR_FE_FLG) == 0);
283 }
284 /*
285 * clear possible interrupt and stop DMA
286 */
287 sdp->CINT = 1;
288 amiga_membarrier();
289 sdp->SP_DMA = 1;
290 amiga_membarrier();
291 dev->sc_dmacmd = 0;
292 splx(s);
293 }
294 }
295
296 int
297 atzsc_dmaintr(void *arg)
298 {
299 struct sbic_softc *dev = arg;
300 volatile struct sdmac *sdp;
301 int stat, found;
302
303 sdp = dev->sc_cregs;
304 stat = sdp->ISTR;
305
306 if ((stat & (ISTR_INT_F|ISTR_INT_P)) == 0)
307 return (0);
308
309 #ifdef DEBUG
310 if (atzsc_dmadebug & DDB_FOLLOW)
311 printf("%s: dmaintr 0x%x\n", device_xname(dev->sc_dev), stat);
312 #endif
313
314 /*
315 * both, SCSI and DMA interrupts arrive here. I chose
316 * arbitrarily that DMA interrupts should have higher
317 * precedence than SCSI interrupts.
318 */
319 found = 0;
320 if (stat & ISTR_E_INT) {
321 found++;
322
323 sdp->CINT = 1; /* clear possible interrupt */
324 amiga_membarrier();
325
326 /*
327 * check for SCSI ints in the same go and
328 * eventually save an interrupt
329 */
330 }
331
332 if (dev->sc_flags & SBICF_INTR && stat & ISTR_INTS)
333 found += sbicintr(dev);
334 return(found);
335 }
336
337
338 int
339 atzsc_dmanext(struct sbic_softc *dev)
340 {
341 volatile struct sdmac *sdp;
342 vu_short istr;
343
344 sdp = dev->sc_cregs;
345
346 if (dev->sc_cur > dev->sc_last) {
347 /* shouldn't happen !! */
348 printf("atzsc_dmanext at end !!!\n");
349 atzsc_dmastop(dev);
350 return(0);
351 }
352 if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
353 /*
354 * only FLUSH if terminal count not enabled,
355 * and reading from peripheral
356 */
357 sdp->FLUSH = 1;
358 amiga_membarrier();
359 do {
360 istr = sdp->ISTR;
361 amiga_membarrier();
362 } while ((istr & ISTR_FE_FLG) == 0);
363 }
364 /*
365 * clear possible interrupt and stop DMA
366 */
367 sdp->CINT = 1; /* clear possible interrupt */
368 amiga_membarrier();
369 sdp->SP_DMA = 1; /* stop DMA */
370 amiga_membarrier();
371 sdp->CNTR = dev->sc_dmacmd;
372 amiga_membarrier();
373 sdp->ACR = (u_int)dev->sc_cur->dc_addr;
374 amiga_membarrier();
375 sdp->ST_DMA = 1;
376 amiga_membarrier();
377
378 dev->sc_tcnt = dev->sc_cur->dc_count << 1;
379 return(dev->sc_tcnt);
380 }
381
382 #ifdef DEBUG
383 void
384 atzsc_dump(void)
385 {
386 extern struct cfdriver atzsc_cd;
387 struct sbic_softc *sc;
388 int i;
389
390 for (i = 0; i < atzsc_cd.cd_ndevs; ++i) {
391 sc = device_lookup_private(&atzsc_cd, i);
392 if (sc != NULL)
393 sbic_dump(sc);
394 }
395 }
396 #endif
Cache object: 1569c7228cd00c01b45dc2a4f748b234
|