bztzsc.c revision 1.2 1 /* $NetBSD: bztzsc.c,v 1.2 1996/12/23 09:09:54 veego Exp $ */
2
3 /*
4 * Copyright (c) 1996 Ignatios Souvatzis
5 * Copyright (c) 1982, 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product contains software written by Ignatios Souvatzis for
19 * the NetBSD project.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
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/bztzscreg.h>
56 #include <amiga/dev/bztzscvar.h>
57
58 void bztzscattach __P((struct device *, struct device *, void *));
59 int bztzscmatch __P((struct device *, struct cfdata *, void *));
60
61 struct scsi_adapter bztzsc_scsiswitch = {
62 sfas_scsicmd,
63 sfas_minphys,
64 0, /* no lun support */
65 0, /* no lun support */
66 };
67
68 struct scsi_device bztzsc_scsidev = {
69 NULL, /* use default error handler */
70 NULL, /* do not have a start functio */
71 NULL, /* have no async handler */
72 NULL, /* Use default done routine */
73 };
74
75 struct cfattach bztzsc_ca = {
76 sizeof(struct bztzsc_softc), bztzscmatch, bztzscattach
77 };
78
79 struct cfdriver bztzsc_cd = {
80 NULL, "bztzsc", DV_DULL, NULL, 0
81 };
82
83 int bztzsc_intr __P((void *));
84 void bztzsc_set_dma_tc __P((struct sfas_softc *sc, unsigned int len));
85 int bztzsc_setup_dma __P((struct sfas_softc *sc, vm_offset_t ptr, int len,
86 int mode));
87 int bztzsc_build_dma_chain __P((struct sfas_softc *sc,
88 struct sfas_dma_chain *chain, void *p, int l));
89 int bztzsc_need_bump __P((struct sfas_softc *sc, vm_offset_t ptr, int len));
90 void bztzsc_led __P((struct sfas_softc *sc, int mode));
91
92 /*
93 * If we are an Phase 5 Devices Blizzard-2060 SCSI option:
94 */
95 int
96 bztzscmatch(pdp, cfp, auxp)
97 struct device *pdp;
98 struct cfdata *cfp;
99 void *auxp;
100 {
101 struct zbus_args *zap;
102 volatile u_int8_t *ta;
103
104 zap = auxp;
105
106 if (zap->manid != 0x2140) /* Phase V ? */
107 return(0);
108
109
110 if (zap->prodid != 24) /* is it B2060? */
111 return 0;
112
113 ta = (vu_char *)(((char *)zap->va) + 0x1ff00 + 0x20);
114
115 if (badbaddr((caddr_t)ta))
116 return(0);
117
118 *ta = 0;
119 *ta = 1;
120 DELAY(5);
121 if (*ta != 1)
122 return(0);
123
124 return(1);
125 }
126
127 u_int32_t bztzsc_flags = 0;
128
129 void
130 bztzscattach(pdp, dp, auxp)
131 struct device *pdp;
132 struct device *dp;
133 void *auxp;
134 {
135 struct bztzsc_softc *sc;
136 struct zbus_args *zap;
137 bztzsc_regmap_p rp;
138 vu_char *fas;
139
140 zap = auxp;
141
142 fas = &((vu_char *)zap->va)[0x1ff00];
143
144 sc = (struct bztzsc_softc *)dp;
145 rp = &sc->sc_regmap;
146
147 rp->FAS216.sfas_tc_low = &fas[0x00];
148 rp->FAS216.sfas_tc_mid = &fas[0x04];
149 rp->FAS216.sfas_fifo = &fas[0x08];
150 rp->FAS216.sfas_command = &fas[0x0C];
151 rp->FAS216.sfas_dest_id = &fas[0x10];
152 rp->FAS216.sfas_timeout = &fas[0x14];
153 rp->FAS216.sfas_syncper = &fas[0x18];
154 rp->FAS216.sfas_syncoff = &fas[0x1C];
155 rp->FAS216.sfas_config1 = &fas[0x20];
156 rp->FAS216.sfas_clkconv = &fas[0x24];
157 rp->FAS216.sfas_test = &fas[0x28];
158 rp->FAS216.sfas_config2 = &fas[0x2C];
159 rp->FAS216.sfas_config3 = &fas[0x30];
160 rp->FAS216.sfas_tc_high = &fas[0x38];
161 rp->FAS216.sfas_fifo_bot = &fas[0x3C];
162
163 rp->hardbits = &fas[0xe0];
164 rp->addrport = &fas[0xf0];
165
166 sc->sc_softc.sc_fas = (sfas_regmap_p)rp;
167
168 sc->sc_softc.sc_led = bztzsc_led;
169
170 sc->sc_softc.sc_setup_dma = bztzsc_setup_dma;
171 sc->sc_softc.sc_build_dma_chain = bztzsc_build_dma_chain;
172 sc->sc_softc.sc_need_bump = bztzsc_need_bump;
173
174 sc->sc_softc.sc_clock_freq = 40; /* Phase5 SCSI all run at 40MHz */
175 sc->sc_softc.sc_timeout = 250; /* Set default timeout to 250ms */
176
177 sc->sc_softc.sc_config_flags = bztzsc_flags; /* for the moment */
178
179 sc->sc_softc.sc_host_id = 7; /* Should check the jumpers */
180
181 sc->sc_softc.sc_bump_sz = NBPG; /* XXX should be the VM pagesize */
182 sc->sc_softc.sc_bump_pa = 0x0;
183
184 sfasinitialize((struct sfas_softc *)sc);
185
186 sc->sc_softc.sc_link.adapter_softc = sc;
187 sc->sc_softc.sc_link.adapter_target = sc->sc_softc.sc_host_id;
188 sc->sc_softc.sc_link.adapter = &bztzsc_scsiswitch;
189 sc->sc_softc.sc_link.device = &bztzsc_scsidev;
190 sc->sc_softc.sc_link.openings = 1;
191
192 sc->sc_softc.sc_isr.isr_intr = bztzsc_intr;
193 sc->sc_softc.sc_isr.isr_arg = &sc->sc_softc;
194 sc->sc_softc.sc_isr.isr_ipl = 2;
195 add_isr(&sc->sc_softc.sc_isr);
196
197 /* We don't want interrupt until we're initialized! */
198
199 printf("\n");
200
201 /* attach all scsi units on us */
202 config_found(dp, &sc->sc_softc.sc_link, scsiprint);
203 }
204
205 int
206 bztzsc_intr(arg)
207 void *arg;
208 {
209 struct sfas_softc *dev = arg;
210 bztzsc_regmap_p rp;
211 int quickints;
212
213 rp = (bztzsc_regmap_p)dev->sc_fas;
214
215 if (*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) {
216 quickints = 16;
217 do {
218 dev->sc_status = *rp->FAS216.sfas_status;
219 dev->sc_interrupt = *rp->FAS216.sfas_interrupt;
220
221 if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
222 dev->sc_resel[0] = *rp->FAS216.sfas_fifo;
223 dev->sc_resel[1] = *rp->FAS216.sfas_fifo;
224 }
225 sfasintr(dev);
226
227 } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING)
228 && --quickints);
229
230 return(1);
231 }
232 return(0);
233 }
234
235 /* Set DMA transfer counter */
236 void
237 bztzsc_set_dma_tc(sc, len)
238 struct sfas_softc *sc;
239 unsigned int len;
240 {
241 *sc->sc_fas->sfas_tc_low = len; len >>= 8;
242 *sc->sc_fas->sfas_tc_mid = len; len >>= 8;
243 *sc->sc_fas->sfas_tc_high = len;
244 }
245
246 /* Initialize DMA for transfer */
247 int
248 bztzsc_setup_dma(sc, ptr, len, mode)
249 struct sfas_softc *sc;
250 vm_offset_t ptr;
251 int len;
252 int mode;
253 {
254 int retval;
255 u_int32_t d;
256 bztzsc_regmap_p rp;
257
258 retval = 0;
259
260 switch(mode) {
261
262 case SFAS_DMA_READ:
263 case SFAS_DMA_WRITE:
264
265 rp = (bztzsc_regmap_p)sc->sc_fas;
266
267 d = (u_int32_t)ptr;
268 d >>= 1;
269
270 if (mode == SFAS_DMA_WRITE)
271 d |= (1L << 31);
272
273 rp->addrport[12] = (u_int8_t)d;
274 __asm __volatile("nop");
275
276 d >>= 8;
277 rp->addrport[8] = (u_int8_t)d;
278 __asm __volatile("nop");
279
280 d >>= 8;
281 rp->addrport[4] = (u_int8_t)d;
282 __asm __volatile("nop");
283
284 d >>= 8;
285 rp->addrport[0] = (u_int8_t)d;
286 __asm __volatile("nop");
287
288 bztzsc_set_dma_tc(sc, len);
289 break;
290
291 case SFAS_DMA_CLEAR:
292 default:
293 retval = (*sc->sc_fas->sfas_tc_high << 16) |
294 (*sc->sc_fas->sfas_tc_mid << 8) |
295 *sc->sc_fas->sfas_tc_low;
296
297 bztzsc_set_dma_tc(sc, 0);
298 break;
299 }
300
301 return(retval);
302 }
303
304 /* Check if address and len is ok for DMA transfer */
305 int
306 bztzsc_need_bump(sc, ptr, len)
307 struct sfas_softc *sc;
308 vm_offset_t ptr;
309 int len;
310 {
311 int p;
312
313 p = (int)ptr & 0x03;
314
315 if (p) {
316 p = 4-p;
317
318 if (len < 256)
319 p = len;
320 }
321 return(p);
322 }
323
324 /* Interrupt driven routines */
325 /* XXX some of this is voodoo might be remnants intended for the Fastlane. */
326 int
327 bztzsc_build_dma_chain(sc, chain, p, l)
328 struct sfas_softc *sc;
329 struct sfas_dma_chain *chain;
330 void *p;
331 int l;
332 {
333 vm_offset_t pa, lastpa;
334 char *ptr;
335 int len, prelen, max_t, n;
336
337 if (l == 0)
338 return(0);
339
340 #define set_link(n, p, l, f)\
341 do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0)
342
343 n = 0;
344
345 if (l < 512)
346 set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP);
347 else if ((p >= (void *)0xFF000000)
348 #if defined(M68040) || defined(M68060)
349 && ((mmutype == MMU_68040) && (p >= (void *)0xFFFC0000))
350 #endif
351 ) {
352 while(l != 0) {
353 len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l);
354
355 set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP);
356
357 p += len;
358 l -= len;
359 }
360 } else {
361 ptr = p;
362 len = l;
363
364 pa = kvtop(ptr);
365 prelen = ((int)ptr & 0x03);
366
367 if (prelen) {
368 prelen = 4-prelen;
369 set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP);
370 ptr += prelen;
371 len -= prelen;
372 }
373
374 lastpa = 0;
375 while(len > 3) {
376 pa = kvtop(ptr);
377 max_t = NBPG - (pa & PGOFSET);
378 if (max_t > len)
379 max_t = len;
380
381 max_t &= ~3;
382
383 if (lastpa == pa)
384 sc->sc_chain[n-1].len += max_t;
385 else
386 set_link(n, pa, max_t, SFAS_CHAIN_DMA);
387
388 lastpa = pa+max_t;
389
390 ptr += max_t;
391 len -= max_t;
392 }
393
394 if (len)
395 set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP);
396 }
397
398 return(n);
399 }
400
401 /* real one for 2060 */
402 void
403 bztzsc_led(sc, mode)
404 struct sfas_softc *sc;
405 int mode;
406 {
407 bztzsc_regmap_p rp;
408
409 rp = (bztzsc_regmap_p)sc->sc_fas;
410
411 if (mode)
412 *rp->hardbits = 0x00; /* Led on, Int on */
413 else
414 *rp->hardbits = 0x02; /* Led off, Int on */
415 }
416