bzsc.c revision 1.6 1 /*
2 * Copyright (c) 1995 Daniel Widenfalk
3 * Copyright (c) 1994 Christian E. Hopps
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. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)dma.c
36 */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/device.h>
42 #include <scsi/scsi_all.h>
43 #include <scsi/scsiconf.h>
44 #include <vm/vm.h>
45 #include <vm/vm_kern.h>
46 #include <vm/vm_page.h>
47 #include <machine/pmap.h>
48 #include <amiga/amiga/custom.h>
49 #include <amiga/amiga/cc.h>
50 #include <amiga/amiga/device.h>
51 #include <amiga/amiga/isr.h>
52 #include <amiga/dev/sfasreg.h>
53 #include <amiga/dev/sfasvar.h>
54 #include <amiga/dev/zbusvar.h>
55 #include <amiga/dev/bzscreg.h>
56 #include <amiga/dev/bzscvar.h>
57
58 int bzscprint __P((void *auxp, char *));
59 void bzscattach __P((struct device *, struct device *, void *));
60 int bzscmatch __P((struct device *, void *, void *));
61
62 struct scsi_adapter bzsc_scsiswitch = {
63 sfas_scsicmd,
64 sfas_minphys,
65 0, /* no lun support */
66 0, /* no lun support */
67 };
68
69 struct scsi_device bzsc_scsidev = {
70 NULL, /* use default error handler */
71 NULL, /* do not have a start functio */
72 NULL, /* have no async handler */
73 NULL, /* Use default done routine */
74 };
75
76 struct cfattach bzsc_ca = {
77 sizeof(struct bzsc_softc), bzscmatch, bzscattach
78 };
79
80 struct cfdriver bzsc_cd = {
81 NULL, "bzsc", DV_DULL, NULL, 0
82 };
83
84 int bzsc_intr __P((struct sfas_softc *dev));
85 int bzsc_setup_dma __P((struct sfas_softc *sc, void *ptr, int len,
86 int mode));
87 int bzsc_build_dma_chain __P((struct sfas_softc *sc,
88 struct sfas_dma_chain *chain, void *p, int l));
89 int bzsc_need_bump __P((struct sfas_softc *sc, void *ptr, int len));
90 void bzsc_led_dummy __P((struct sfas_softc *sc));
91
92 /*
93 * if we are an Advanced Systems & Software FastlaneZ3
94 */
95 int bzscmatch(struct device *pdp, void *match, void *auxp)
96 {
97 struct zbus_args *zap;
98
99 if (!is_a1200())
100 return(0);
101
102 zap = auxp;
103 if (zap->manid == 0x2140 && zap->prodid == 11)
104 return(1);
105
106 return(0);
107 }
108
109 void bzscattach(struct device *pdp, struct device *dp, void *auxp)
110 {
111 struct bzsc_softc *sc;
112 struct zbus_args *zap;
113 bzsc_regmap_p rp;
114 u_int *pte, page;
115 vu_char *fas;
116
117 zap = auxp;
118 fas = (vu_char *)(((char *)zap->va)+0x10000);
119
120 sc = (struct bzsc_softc *)dp;
121 rp = &sc->sc_regmap;
122
123 rp->FAS216.sfas_tc_low = &fas[0x00];
124 rp->FAS216.sfas_tc_mid = &fas[0x02];
125 rp->FAS216.sfas_fifo = &fas[0x04];
126 rp->FAS216.sfas_command = &fas[0x06];
127 rp->FAS216.sfas_dest_id = &fas[0x08];
128 rp->FAS216.sfas_timeout = &fas[0x0A];
129 rp->FAS216.sfas_syncper = &fas[0x0C];
130 rp->FAS216.sfas_syncoff = &fas[0x0E];
131 rp->FAS216.sfas_config1 = &fas[0x10];
132 rp->FAS216.sfas_clkconv = &fas[0x12];
133 rp->FAS216.sfas_test = &fas[0x14];
134 rp->FAS216.sfas_config2 = &fas[0x16];
135 rp->FAS216.sfas_config3 = &fas[0x18];
136 rp->FAS216.sfas_tc_high = &fas[0x1C];
137 rp->FAS216.sfas_fifo_bot = &fas[0x1E];
138 rp->cclkaddr = &fas[0x21];
139 rp->epowaddr = &fas[0x31];
140
141 sc->sc_softc.sc_fas = (sfas_regmap_p)rp;
142 sc->sc_softc.sc_spec = 0;
143
144 sc->sc_softc.sc_led = bzsc_led_dummy;
145
146 sc->sc_softc.sc_setup_dma = bzsc_setup_dma;
147 sc->sc_softc.sc_build_dma_chain = bzsc_build_dma_chain;
148 sc->sc_softc.sc_need_bump = bzsc_need_bump;
149
150 sc->sc_softc.sc_clock_freq = 40; /* BlizzardII 1230 runs at 40MHz? */
151 sc->sc_softc.sc_timeout = 250; /* Set default timeout to 250ms */
152 sc->sc_softc.sc_config_flags = 0;
153 sc->sc_softc.sc_host_id = 7;
154
155 sc->sc_softc.sc_bump_sz = NBPG;
156 sc->sc_softc.sc_bump_pa = 0x0;
157
158 sfasinitialize((struct sfas_softc *)sc);
159
160 sc->sc_softc.sc_link.adapter_softc = sc;
161 sc->sc_softc.sc_link.adapter_target = sc->sc_softc.sc_host_id;
162 sc->sc_softc.sc_link.adapter = &bzsc_scsiswitch;
163 sc->sc_softc.sc_link.device = &bzsc_scsidev;
164 sc->sc_softc.sc_link.openings = 1;
165
166 printf("\n");
167
168 sc->sc_softc.sc_isr.isr_intr = bzsc_intr;
169 sc->sc_softc.sc_isr.isr_arg = &sc->sc_softc;
170 sc->sc_softc.sc_isr.isr_ipl = 2;
171 add_isr(&sc->sc_softc.sc_isr);
172
173 /* attach all scsi units on us */
174 config_found(dp, &sc->sc_softc.sc_link, bzscprint);
175 }
176
177 /* print diag if pnp is NULL else just extra */
178 int bzscprint(void *auxp, char *pnp)
179 {
180 if (pnp == NULL)
181 return(UNCONF);
182
183 return(QUIET);
184 }
185
186 int bzsc_intr(struct sfas_softc *dev)
187 {
188 bzsc_regmap_p rp;
189 int quickints;
190
191 rp = (bzsc_regmap_p)dev->sc_fas;
192
193 if (!(*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING))
194 return(0);
195
196 quickints = 16;
197 do {
198 dev->sc_status = *rp->FAS216.sfas_status;
199 dev->sc_interrupt = *rp->FAS216.sfas_interrupt;
200
201 if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
202 dev->sc_resel[0] = *rp->FAS216.sfas_fifo;
203 dev->sc_resel[1] = *rp->FAS216.sfas_fifo;
204 }
205 sfasintr(dev);
206 } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) &&
207 --quickints);
208
209 return(1);
210 }
211
212 /* --------- */
213 void bzsc_set_dma_adr(struct sfas_softc *sc, void *ptr, int mode)
214 {
215 bzsc_regmap_p rp;
216 unsigned long p;
217
218 rp = (bzsc_regmap_p)sc->sc_fas;
219
220 p = ((unsigned long)ptr)>>1;
221
222 if (mode == SFAS_DMA_WRITE)
223 p |= BZSC_DMA_WRITE;
224 else
225 p |= BZSC_DMA_READ;
226
227 *rp->epowaddr = (u_char)(p>>24) & 0xFF;
228 *rp->cclkaddr = (u_char)(p>>16) & 0xFF;
229 *rp->cclkaddr = (u_char)(p>> 8) & 0xFF;
230 *rp->cclkaddr = (u_char)(p ) & 0xFF;
231 }
232
233 /* Set DMA transfer counter */
234 void bzsc_set_dma_tc(struct sfas_softc *sc, unsigned int len)
235 {
236 *sc->sc_fas->sfas_tc_low = len; len >>= 8;
237 *sc->sc_fas->sfas_tc_mid = len; len >>= 8;
238 *sc->sc_fas->sfas_tc_high = len;
239 }
240
241 /* Initialize DMA for transfer */
242 int bzsc_setup_dma(struct sfas_softc *sc, void *ptr, int len, int mode)
243 {
244 int retval;
245
246 retval = 0;
247
248 switch(mode) {
249 case SFAS_DMA_READ:
250 case SFAS_DMA_WRITE:
251 bzsc_set_dma_adr(sc, ptr, mode);
252 bzsc_set_dma_tc(sc, len);
253 break;
254 case SFAS_DMA_CLEAR:
255 default:
256 retval = (*sc->sc_fas->sfas_tc_high << 16) |
257 (*sc->sc_fas->sfas_tc_mid << 8) |
258 *sc->sc_fas->sfas_tc_low;
259
260 bzsc_set_dma_tc(sc, 0);
261 break;
262 }
263
264 return(retval);
265 }
266
267 /* Check if address and len is ok for DMA transfer */
268 int bzsc_need_bump(struct sfas_softc *sc, void *ptr, int len)
269 {
270 int p;
271
272 p = (int)ptr & 0x03;
273
274 if (p) {
275 p = 4-p;
276
277 if (len < 256)
278 p = len;
279 }
280
281 return(p);
282 }
283
284 /* Interrupt driven routines */
285 int bzsc_build_dma_chain(struct sfas_softc *sc, struct sfas_dma_chain *chain,
286 void *p, int l)
287 {
288 int n;
289
290 if (!l)
291 return(0);
292
293 #define set_link(n, p, l, f)\
294 do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0)
295
296 n = 0;
297
298 if (l < 512)
299 set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP);
300 else if (
301 #ifdef M68040
302 ((mmutype == MMU_68040) && ((vm_offset_t)p >= 0xFFFC0000)) &&
303 #endif
304 ((vm_offset_t)p >= 0xFF000000)) {
305 int len;
306
307 while(l) {
308 len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l);
309
310 set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP);
311
312 p += len;
313 l -= len;
314 }
315 } else {
316 char *ptr;
317 vm_offset_t pa, lastpa;
318 int len, prelen, postlen, max_t;
319
320 ptr = p;
321 len = l;
322
323 pa = kvtop(ptr);
324 prelen = ((int)ptr & 0x03);
325
326 if (prelen) {
327 prelen = 4-prelen;
328 set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP);
329 ptr += prelen;
330 len -= prelen;
331 }
332
333 lastpa = 0;
334 while(len > 3) {
335 pa = kvtop(ptr);
336 max_t = NBPG - (pa & PGOFSET);
337 if (max_t > len)
338 max_t = len;
339
340 max_t &= ~3;
341
342 if (lastpa == pa)
343 sc->sc_chain[n-1].len += max_t;
344 else
345 set_link(n, pa, max_t, SFAS_CHAIN_DMA);
346
347 lastpa = pa+max_t;
348
349 ptr += max_t;
350 len -= max_t;
351 }
352
353 if (len)
354 set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP);
355 }
356
357 return(n);
358 }
359
360 /* Turn on led */
361 void bzsc_led_dummy(struct sfas_softc *sc)
362 {
363 }
364