bztzsc.c revision 1.1 1 /* $NetBSD: bztzsc.c,v 1.1 1996/12/16 16:17:29 is 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 *, void *, 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, match, auxp)
97 struct device *pdp;
98 void *match, *auxp;
99 {
100 struct zbus_args *zap;
101 volatile u_int8_t *ta;
102
103 zap = auxp;
104
105 if (zap->manid != 0x2140) /* Phase V ? */
106 return(0);
107
108
109 if (zap->prodid != 24) /* is it B2060? */
110 return 0;
111
112 ta = (vu_char *)(((char *)zap->va) + 0x1ff00 + 0x20);
113
114 if (badbaddr((caddr_t)ta))
115 return(0);
116
117 *ta = 0;
118 *ta = 1;
119 DELAY(5);
120 if (*ta != 1)
121 return(0);
122
123 return(1);
124 }
125
126 u_int32_t bztzsc_flags = 0;
127
128 void
129 bztzscattach(pdp, dp, auxp)
130 struct device *pdp;
131 struct device *dp;
132 void *auxp;
133 {
134 struct bztzsc_softc *sc;
135 struct zbus_args *zap;
136 bztzsc_regmap_p rp;
137 vu_char *fas;
138
139 zap = auxp;
140
141 fas = &((vu_char *)zap->va)[0x1ff00];
142
143 sc = (struct bztzsc_softc *)dp;
144 rp = &sc->sc_regmap;
145
146 rp->FAS216.sfas_tc_low = &fas[0x00];
147 rp->FAS216.sfas_tc_mid = &fas[0x04];
148 rp->FAS216.sfas_fifo = &fas[0x08];
149 rp->FAS216.sfas_command = &fas[0x0C];
150 rp->FAS216.sfas_dest_id = &fas[0x10];
151 rp->FAS216.sfas_timeout = &fas[0x14];
152 rp->FAS216.sfas_syncper = &fas[0x18];
153 rp->FAS216.sfas_syncoff = &fas[0x1C];
154 rp->FAS216.sfas_config1 = &fas[0x20];
155 rp->FAS216.sfas_clkconv = &fas[0x24];
156 rp->FAS216.sfas_test = &fas[0x28];
157 rp->FAS216.sfas_config2 = &fas[0x2C];
158 rp->FAS216.sfas_config3 = &fas[0x30];
159 rp->FAS216.sfas_tc_high = &fas[0x38];
160 rp->FAS216.sfas_fifo_bot = &fas[0x3C];
161
162 rp->hardbits = &fas[0xe0];
163 rp->addrport = &fas[0xf0];
164
165 sc->sc_softc.sc_fas = (sfas_regmap_p)rp;
166
167 sc->sc_softc.sc_led = bztzsc_led;
168
169 sc->sc_softc.sc_setup_dma = bztzsc_setup_dma;
170 sc->sc_softc.sc_build_dma_chain = bztzsc_build_dma_chain;
171 sc->sc_softc.sc_need_bump = bztzsc_need_bump;
172
173 sc->sc_softc.sc_clock_freq = 40; /* Phase5 SCSI all run at 40MHz */
174 sc->sc_softc.sc_timeout = 250; /* Set default timeout to 250ms */
175
176 sc->sc_softc.sc_config_flags = bztzsc_flags; /* for the moment */
177
178 sc->sc_softc.sc_host_id = 7; /* Should check the jumpers */
179
180 sc->sc_softc.sc_bump_sz = NBPG; /* XXX should be the VM pagesize */
181 sc->sc_softc.sc_bump_pa = 0x0;
182
183 sfasinitialize((struct sfas_softc *)sc);
184
185 sc->sc_softc.sc_link.adapter_softc = sc;
186 sc->sc_softc.sc_link.adapter_target = sc->sc_softc.sc_host_id;
187 sc->sc_softc.sc_link.adapter = &bztzsc_scsiswitch;
188 sc->sc_softc.sc_link.device = &bztzsc_scsidev;
189 sc->sc_softc.sc_link.openings = 1;
190
191 sc->sc_softc.sc_isr.isr_intr = bztzsc_intr;
192 sc->sc_softc.sc_isr.isr_arg = &sc->sc_softc;
193 sc->sc_softc.sc_isr.isr_ipl = 2;
194 add_isr(&sc->sc_softc.sc_isr);
195
196 /* We don't want interrupt until we're initialized! */
197
198 printf("\n");
199
200 /* attach all scsi units on us */
201 config_found(dp, &sc->sc_softc.sc_link, scsiprint);
202 }
203
204 int
205 bztzsc_intr(arg)
206 void *arg;
207 {
208 struct sfas_softc *dev = arg;
209 bztzsc_regmap_p rp;
210 int quickints;
211
212 rp = (bztzsc_regmap_p)dev->sc_fas;
213
214 if (*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) {
215 quickints = 16;
216 do {
217 dev->sc_status = *rp->FAS216.sfas_status;
218 dev->sc_interrupt = *rp->FAS216.sfas_interrupt;
219
220 if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
221 dev->sc_resel[0] = *rp->FAS216.sfas_fifo;
222 dev->sc_resel[1] = *rp->FAS216.sfas_fifo;
223 }
224 sfasintr(dev);
225
226 } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING)
227 && --quickints);
228
229 return(1);
230 }
231 return(0);
232 }
233
234 /* Set DMA transfer counter */
235 void
236 bztzsc_set_dma_tc(sc, len)
237 struct sfas_softc *sc;
238 unsigned int len;
239 {
240 *sc->sc_fas->sfas_tc_low = len; len >>= 8;
241 *sc->sc_fas->sfas_tc_mid = len; len >>= 8;
242 *sc->sc_fas->sfas_tc_high = len;
243 }
244
245 /* Initialize DMA for transfer */
246 int
247 bztzsc_setup_dma(sc, ptr, len, mode)
248 struct sfas_softc *sc;
249 vm_offset_t ptr;
250 int len;
251 int mode;
252 {
253 int retval;
254 u_int32_t d;
255 bztzsc_regmap_p rp;
256
257 retval = 0;
258
259 switch(mode) {
260
261 case SFAS_DMA_READ:
262 case SFAS_DMA_WRITE:
263
264 rp = (bztzsc_regmap_p)sc->sc_fas;
265
266 d = (u_int32_t)ptr;
267 d >>= 1;
268
269 if (mode == SFAS_DMA_WRITE)
270 d |= (1L << 31);
271
272 rp->addrport[12] = (u_int8_t)d;
273 __asm __volatile("nop");
274
275 d >>= 8;
276 rp->addrport[8] = (u_int8_t)d;
277 __asm __volatile("nop");
278
279 d >>= 8;
280 rp->addrport[4] = (u_int8_t)d;
281 __asm __volatile("nop");
282
283 d >>= 8;
284 rp->addrport[0] = (u_int8_t)d;
285 __asm __volatile("nop");
286
287 bztzsc_set_dma_tc(sc, len);
288 break;
289
290 case SFAS_DMA_CLEAR:
291 default:
292 retval = (*sc->sc_fas->sfas_tc_high << 16) |
293 (*sc->sc_fas->sfas_tc_mid << 8) |
294 *sc->sc_fas->sfas_tc_low;
295
296 bztzsc_set_dma_tc(sc, 0);
297 break;
298 }
299
300 return(retval);
301 }
302
303 /* Check if address and len is ok for DMA transfer */
304 int
305 bztzsc_need_bump(sc, ptr, len)
306 struct sfas_softc *sc;
307 vm_offset_t ptr;
308 int len;
309 {
310 int p;
311
312 p = (int)ptr & 0x03;
313
314 if (p) {
315 p = 4-p;
316
317 if (len < 256)
318 p = len;
319 }
320 return(p);
321 }
322
323 /* Interrupt driven routines */
324 /* XXX some of this is voodoo might be remnants intended for the Fastlane. */
325 int
326 bztzsc_build_dma_chain(sc, chain, p, l)
327 struct sfas_softc *sc;
328 struct sfas_dma_chain *chain;
329 void *p;
330 int l;
331 {
332 vm_offset_t pa, lastpa;
333 char *ptr;
334 int len, prelen, max_t, n;
335
336 if (l == 0)
337 return(0);
338
339 #define set_link(n, p, l, f)\
340 do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0)
341
342 n = 0;
343
344 if (l < 512)
345 set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP);
346 else if ((p >= (void *)0xFF000000)
347 #if defined(M68040) || defined(M68060)
348 && ((mmutype == MMU_68040) && (p >= (void *)0xFFFC0000))
349 #endif
350 ) {
351 while(l != 0) {
352 len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l);
353
354 set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP);
355
356 p += len;
357 l -= len;
358 }
359 } else {
360 ptr = p;
361 len = l;
362
363 pa = kvtop(ptr);
364 prelen = ((int)ptr & 0x03);
365
366 if (prelen) {
367 prelen = 4-prelen;
368 set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP);
369 ptr += prelen;
370 len -= prelen;
371 }
372
373 lastpa = 0;
374 while(len > 3) {
375 pa = kvtop(ptr);
376 max_t = NBPG - (pa & PGOFSET);
377 if (max_t > len)
378 max_t = len;
379
380 max_t &= ~3;
381
382 if (lastpa == pa)
383 sc->sc_chain[n-1].len += max_t;
384 else
385 set_link(n, pa, max_t, SFAS_CHAIN_DMA);
386
387 lastpa = pa+max_t;
388
389 ptr += max_t;
390 len -= max_t;
391 }
392
393 if (len)
394 set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP);
395 }
396
397 return(n);
398 }
399
400 /* real one for 2060 */
401 void
402 bztzsc_led(sc, mode)
403 struct sfas_softc *sc;
404 int mode;
405 {
406 bztzsc_regmap_p rp;
407
408 rp = (bztzsc_regmap_p)sc->sc_fas;
409
410 if (mode)
411 *rp->hardbits = 0x00; /* Led on, Int on */
412 else
413 *rp->hardbits = 0x02; /* Led off, Int on */
414 }
415