bzsc.c revision 1.5 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 *, struct cfdata *, 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
77 struct cfdriver bzsccd = {
78 NULL, "bzsc", (cfmatch_t)bzscmatch, bzscattach,
79 DV_DULL, sizeof(struct bzsc_softc), NULL, 0 };
80
81 int bzsc_intr __P((struct sfas_softc *dev));
82 int bzsc_setup_dma __P((struct sfas_softc *sc, void *ptr, int len,
83 int mode));
84 int bzsc_build_dma_chain __P((struct sfas_softc *sc,
85 struct sfas_dma_chain *chain, void *p, int l));
86 int bzsc_need_bump __P((struct sfas_softc *sc, void *ptr, int len));
87 void bzsc_led_dummy __P((struct sfas_softc *sc));
88
89 /*
90 * if we are an Advanced Systems & Software FastlaneZ3
91 */
92 int bzscmatch(struct device *pdp, struct cfdata *cdp, void *auxp)
93 {
94 struct zbus_args *zap;
95
96 if (!is_a1200())
97 return(0);
98
99 zap = auxp;
100 if (zap->manid == 0x2140 && zap->prodid == 11)
101 return(1);
102
103 return(0);
104 }
105
106 void bzscattach(struct device *pdp, struct device *dp, void *auxp)
107 {
108 struct bzsc_softc *sc;
109 struct zbus_args *zap;
110 bzsc_regmap_p rp;
111 u_int *pte, page;
112 vu_char *fas;
113
114 zap = auxp;
115 fas = (vu_char *)(((char *)zap->va)+0x10000);
116
117 sc = (struct bzsc_softc *)dp;
118 rp = &sc->sc_regmap;
119
120 rp->FAS216.sfas_tc_low = &fas[0x00];
121 rp->FAS216.sfas_tc_mid = &fas[0x02];
122 rp->FAS216.sfas_fifo = &fas[0x04];
123 rp->FAS216.sfas_command = &fas[0x06];
124 rp->FAS216.sfas_dest_id = &fas[0x08];
125 rp->FAS216.sfas_timeout = &fas[0x0A];
126 rp->FAS216.sfas_syncper = &fas[0x0C];
127 rp->FAS216.sfas_syncoff = &fas[0x0E];
128 rp->FAS216.sfas_config1 = &fas[0x10];
129 rp->FAS216.sfas_clkconv = &fas[0x12];
130 rp->FAS216.sfas_test = &fas[0x14];
131 rp->FAS216.sfas_config2 = &fas[0x16];
132 rp->FAS216.sfas_config3 = &fas[0x18];
133 rp->FAS216.sfas_tc_high = &fas[0x1C];
134 rp->FAS216.sfas_fifo_bot = &fas[0x1E];
135 rp->cclkaddr = &fas[0x21];
136 rp->epowaddr = &fas[0x31];
137
138 sc->sc_softc.sc_fas = (sfas_regmap_p)rp;
139 sc->sc_softc.sc_spec = 0;
140
141 sc->sc_softc.sc_led = bzsc_led_dummy;
142
143 sc->sc_softc.sc_setup_dma = bzsc_setup_dma;
144 sc->sc_softc.sc_build_dma_chain = bzsc_build_dma_chain;
145 sc->sc_softc.sc_need_bump = bzsc_need_bump;
146
147 sc->sc_softc.sc_clock_freq = 40; /* BlizzardII 1230 runs at 40MHz? */
148 sc->sc_softc.sc_timeout = 250; /* Set default timeout to 250ms */
149 sc->sc_softc.sc_config_flags = 0;
150 sc->sc_softc.sc_host_id = 7;
151
152 sc->sc_softc.sc_bump_sz = NBPG;
153 sc->sc_softc.sc_bump_pa = 0x0;
154
155 sfasinitialize((struct sfas_softc *)sc);
156
157 sc->sc_softc.sc_link.adapter_softc = sc;
158 sc->sc_softc.sc_link.adapter_target = sc->sc_softc.sc_host_id;
159 sc->sc_softc.sc_link.adapter = &bzsc_scsiswitch;
160 sc->sc_softc.sc_link.device = &bzsc_scsidev;
161 sc->sc_softc.sc_link.openings = 1;
162
163 printf("\n");
164
165 sc->sc_softc.sc_isr.isr_intr = bzsc_intr;
166 sc->sc_softc.sc_isr.isr_arg = &sc->sc_softc;
167 sc->sc_softc.sc_isr.isr_ipl = 2;
168 add_isr(&sc->sc_softc.sc_isr);
169
170 /* attach all scsi units on us */
171 config_found(dp, &sc->sc_softc.sc_link, bzscprint);
172 }
173
174 /* print diag if pnp is NULL else just extra */
175 int bzscprint(void *auxp, char *pnp)
176 {
177 if (pnp == NULL)
178 return(UNCONF);
179
180 return(QUIET);
181 }
182
183 int bzsc_intr(struct sfas_softc *dev)
184 {
185 bzsc_regmap_p rp;
186 int quickints;
187
188 rp = (bzsc_regmap_p)dev->sc_fas;
189
190 if (!(*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING))
191 return(0);
192
193 quickints = 16;
194 do {
195 dev->sc_status = *rp->FAS216.sfas_status;
196 dev->sc_interrupt = *rp->FAS216.sfas_interrupt;
197
198 if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
199 dev->sc_resel[0] = *rp->FAS216.sfas_fifo;
200 dev->sc_resel[1] = *rp->FAS216.sfas_fifo;
201 }
202 sfasintr(dev);
203 } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) &&
204 --quickints);
205
206 return(1);
207 }
208
209 /* --------- */
210 void bzsc_set_dma_adr(struct sfas_softc *sc, void *ptr, int mode)
211 {
212 bzsc_regmap_p rp;
213 unsigned long p;
214
215 rp = (bzsc_regmap_p)sc->sc_fas;
216
217 p = ((unsigned long)ptr)>>1;
218
219 if (mode == SFAS_DMA_WRITE)
220 p |= BZSC_DMA_WRITE;
221 else
222 p |= BZSC_DMA_READ;
223
224 *rp->epowaddr = (u_char)(p>>24) & 0xFF;
225 *rp->cclkaddr = (u_char)(p>>16) & 0xFF;
226 *rp->cclkaddr = (u_char)(p>> 8) & 0xFF;
227 *rp->cclkaddr = (u_char)(p ) & 0xFF;
228 }
229
230 /* Set DMA transfer counter */
231 void bzsc_set_dma_tc(struct sfas_softc *sc, unsigned int len)
232 {
233 *sc->sc_fas->sfas_tc_low = len; len >>= 8;
234 *sc->sc_fas->sfas_tc_mid = len; len >>= 8;
235 *sc->sc_fas->sfas_tc_high = len;
236 }
237
238 /* Initialize DMA for transfer */
239 int bzsc_setup_dma(struct sfas_softc *sc, void *ptr, int len, int mode)
240 {
241 int retval;
242
243 retval = 0;
244
245 switch(mode) {
246 case SFAS_DMA_READ:
247 case SFAS_DMA_WRITE:
248 bzsc_set_dma_adr(sc, ptr, mode);
249 bzsc_set_dma_tc(sc, len);
250 break;
251 case SFAS_DMA_CLEAR:
252 default:
253 retval = (*sc->sc_fas->sfas_tc_high << 16) |
254 (*sc->sc_fas->sfas_tc_mid << 8) |
255 *sc->sc_fas->sfas_tc_low;
256
257 bzsc_set_dma_tc(sc, 0);
258 break;
259 }
260
261 return(retval);
262 }
263
264 /* Check if address and len is ok for DMA transfer */
265 int bzsc_need_bump(struct sfas_softc *sc, void *ptr, int len)
266 {
267 int p;
268
269 p = (int)ptr & 0x03;
270
271 if (p) {
272 p = 4-p;
273
274 if (len < 256)
275 p = len;
276 }
277
278 return(p);
279 }
280
281 /* Interrupt driven routines */
282 int bzsc_build_dma_chain(struct sfas_softc *sc, struct sfas_dma_chain *chain,
283 void *p, int l)
284 {
285 int n;
286
287 if (!l)
288 return(0);
289
290 #define set_link(n, p, l, f)\
291 do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0)
292
293 n = 0;
294
295 if (l < 512)
296 set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP);
297 else if (
298 #ifdef M68040
299 ((mmutype == MMU_68040) && ((vm_offset_t)p >= 0xFFFC0000)) &&
300 #endif
301 ((vm_offset_t)p >= 0xFF000000)) {
302 int len;
303
304 while(l) {
305 len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l);
306
307 set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP);
308
309 p += len;
310 l -= len;
311 }
312 } else {
313 char *ptr;
314 vm_offset_t pa, lastpa;
315 int len, prelen, postlen, max_t;
316
317 ptr = p;
318 len = l;
319
320 pa = kvtop(ptr);
321 prelen = ((int)ptr & 0x03);
322
323 if (prelen) {
324 prelen = 4-prelen;
325 set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP);
326 ptr += prelen;
327 len -= prelen;
328 }
329
330 lastpa = 0;
331 while(len > 3) {
332 pa = kvtop(ptr);
333 max_t = NBPG - (pa & PGOFSET);
334 if (max_t > len)
335 max_t = len;
336
337 max_t &= ~3;
338
339 if (lastpa == pa)
340 sc->sc_chain[n-1].len += max_t;
341 else
342 set_link(n, pa, max_t, SFAS_CHAIN_DMA);
343
344 lastpa = pa+max_t;
345
346 ptr += max_t;
347 len -= max_t;
348 }
349
350 if (len)
351 set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP);
352 }
353
354 return(n);
355 }
356
357 /* Turn on led */
358 void bzsc_led_dummy(struct sfas_softc *sc)
359 {
360 }
361