wstsc.c revision 1.26 1 /* $NetBSD: wstsc.c,v 1.26 2002/01/28 09:57:04 aymeric Exp $ */
2
3 /*
4 * Copyright (c) 1994 Michael L. Hitch
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 includes software developed by the University of
19 * California, Berkeley and its contributors.
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 * @(#)supradma.c
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: wstsc.c,v 1.26 2002/01/28 09:57:04 aymeric Exp $");
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/device.h>
46 #include <dev/scsipi/scsi_all.h>
47 #include <dev/scsipi/scsipi_all.h>
48 #include <dev/scsipi/scsiconf.h>
49 #include <amiga/amiga/device.h>
50 #include <amiga/amiga/isr.h>
51 #include <amiga/dev/scireg.h>
52 #include <amiga/dev/scivar.h>
53 #include <amiga/dev/zbusvar.h>
54
55 void wstscattach(struct device *, struct device *, void *);
56 int wstscmatch(struct device *, struct cfdata *, void *);
57
58 int wstsc_dma_xfer_in(struct sci_softc *dev, int len,
59 register u_char *buf, int phase);
60 int wstsc_dma_xfer_out(struct sci_softc *dev, int len,
61 register u_char *buf, int phase);
62 int wstsc_dma_xfer_in2(struct sci_softc *dev, int len,
63 register u_short *buf, int phase);
64 int wstsc_dma_xfer_out2(struct sci_softc *dev, int len,
65 register u_short *buf, int phase);
66 int wstsc_intr(void *);
67
68 #ifdef DEBUG
69 extern int sci_debug;
70 #define QPRINTF(a) if (sci_debug > 1) printf a
71 #else
72 #define QPRINTF(a)
73 #endif
74
75 extern int sci_data_wait;
76
77 int supradma_pseudo = 0; /* 0=none, 1=byte, 2=word */
78
79 struct cfattach wstsc_ca = {
80 sizeof(struct sci_softc), wstscmatch, wstscattach
81 };
82
83 /*
84 * if this a Supra WordSync board
85 */
86 int
87 wstscmatch(struct device *pdp, struct cfdata *cfp, void *auxp)
88 {
89 struct zbus_args *zap;
90
91 zap = auxp;
92
93 /*
94 * Check manufacturer and product id.
95 */
96 if (zap->manid == 1056 && (
97 zap->prodid == 12 || /* WordSync */
98 zap->prodid == 13)) /* ByteSync */
99 return(1);
100 else
101 return(0);
102 }
103
104 void
105 wstscattach(struct device *pdp, struct device *dp, void *auxp)
106 {
107 volatile u_char *rp;
108 struct sci_softc *sc = (struct sci_softc *)dp;
109 struct zbus_args *zap;
110 struct scsipi_adapter *adapt = &sc->sc_adapter;
111 struct scsipi_channel *chan = &sc->sc_channel;
112
113 printf("\n");
114
115 zap = auxp;
116
117 rp = zap->va;
118 /*
119 * set up 5380 register pointers
120 * (Needs check on which Supra board this is - for now,
121 * just do the WordSync)
122 */
123 sc->sci_data = rp + 0;
124 sc->sci_odata = rp + 0;
125 sc->sci_icmd = rp + 2;
126 sc->sci_mode = rp + 4;
127 sc->sci_tcmd = rp + 6;
128 sc->sci_bus_csr = rp + 8;
129 sc->sci_sel_enb = rp + 8;
130 sc->sci_csr = rp + 10;
131 sc->sci_dma_send = rp + 10;
132 sc->sci_idata = rp + 12;
133 sc->sci_trecv = rp + 12;
134 sc->sci_iack = rp + 14;
135 sc->sci_irecv = rp + 14;
136
137 if (supradma_pseudo == 2) {
138 sc->dma_xfer_in = (int(*)(struct sci_softc *, int, u_char *, int))wstsc_dma_xfer_in2;
139 sc->dma_xfer_out = (int(*)(struct sci_softc *, int, u_char *, int))wstsc_dma_xfer_out2;
140 }
141 else if (supradma_pseudo == 1) {
142 sc->dma_xfer_in = wstsc_dma_xfer_in;
143 sc->dma_xfer_out = wstsc_dma_xfer_out;
144 }
145
146 sc->sc_isr.isr_intr = wstsc_intr;
147 sc->sc_isr.isr_arg = sc;
148 sc->sc_isr.isr_ipl = 2;
149 add_isr(&sc->sc_isr);
150
151 scireset(sc);
152
153 /*
154 * Fill in the scsipi_adapter.
155 */
156 memset(adapt, 0, sizeof(*adapt));
157 adapt->adapt_dev = &sc->sc_dev;
158 adapt->adapt_nchannels = 1;
159 adapt->adapt_openings = 7;
160 adapt->adapt_max_periph = 1;
161 adapt->adapt_request = sci_scsipi_request;
162 adapt->adapt_minphys = sci_minphys;
163
164 /*
165 * Fill in the scsipi_channel.
166 */
167 memset(chan, 0, sizeof(*chan));
168 chan->chan_adapter = adapt;
169 chan->chan_bustype = &scsi_bustype;
170 chan->chan_channel = 0;
171 chan->chan_ntargets = 8;
172 chan->chan_nluns = 8;
173 chan->chan_id = 7;
174
175 /*
176 * attach all scsi units on us
177 */
178 config_found(dp, chan, scsiprint);
179 }
180
181 int
182 wstsc_dma_xfer_in(struct sci_softc *dev, int len, register u_char *buf,
183 int phase)
184 {
185 int wait = sci_data_wait;
186 volatile register u_char *sci_dma = dev->sci_idata;
187 volatile register u_char *sci_csr = dev->sci_csr;
188 #ifdef DEBUG
189 u_char *obp = (u_char *) buf;
190 #endif
191
192 QPRINTF(("supradma_in %d, csr=%02x\n", len, *dev->sci_bus_csr));
193
194 *dev->sci_tcmd = phase;
195 *dev->sci_icmd = 0;
196 *dev->sci_mode = SCI_MODE_DMA;
197 *dev->sci_irecv = 0;
198
199 while (len >= 128) {
200 wait = sci_data_wait;
201 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
202 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
203 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
204 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
205 || --wait < 0) {
206 #ifdef DEBUG
207 if (sci_debug | 1)
208 printf("supradma2_in fail: l%d i%x w%d\n",
209 len, *dev->sci_bus_csr, wait);
210 #endif
211 *dev->sci_mode = 0;
212 return 0;
213 }
214 }
215
216 #define R1 (*buf++ = *sci_dma)
217 R1; R1; R1; R1; R1; R1; R1; R1;
218 R1; R1; R1; R1; R1; R1; R1; R1;
219 R1; R1; R1; R1; R1; R1; R1; R1;
220 R1; R1; R1; R1; R1; R1; R1; R1;
221 R1; R1; R1; R1; R1; R1; R1; R1;
222 R1; R1; R1; R1; R1; R1; R1; R1;
223 R1; R1; R1; R1; R1; R1; R1; R1;
224 R1; R1; R1; R1; R1; R1; R1; R1;
225 R1; R1; R1; R1; R1; R1; R1; R1;
226 R1; R1; R1; R1; R1; R1; R1; R1;
227 R1; R1; R1; R1; R1; R1; R1; R1;
228 R1; R1; R1; R1; R1; R1; R1; R1;
229 R1; R1; R1; R1; R1; R1; R1; R1;
230 R1; R1; R1; R1; R1; R1; R1; R1;
231 R1; R1; R1; R1; R1; R1; R1; R1;
232 R1; R1; R1; R1; R1; R1; R1; R1;
233 len -= 128;
234 }
235
236 while (len > 0) {
237 wait = sci_data_wait;
238 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
239 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
240 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
241 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
242 || --wait < 0) {
243 #ifdef DEBUG
244 if (sci_debug | 1)
245 printf("supradma1_in fail: l%d i%x w%d\n",
246 len, *dev->sci_bus_csr, wait);
247 #endif
248 *dev->sci_mode = 0;
249 return 0;
250 }
251 }
252
253 *buf++ = *sci_dma;
254 len--;
255 }
256
257 QPRINTF(("supradma_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
258 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
259 obp[6], obp[7], obp[8], obp[9]));
260
261 *dev->sci_mode = 0;
262 return 0;
263 }
264
265 int
266 wstsc_dma_xfer_out(struct sci_softc *dev, int len, register u_char *buf,
267 int phase)
268 {
269 int wait = sci_data_wait;
270 volatile register u_char *sci_dma = dev->sci_data;
271 volatile register u_char *sci_csr = dev->sci_csr;
272
273 QPRINTF(("supradma_out %d, csr=%02x\n", len, *dev->sci_bus_csr));
274
275 QPRINTF(("supradma_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
276 len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
277 buf[6], buf[7], buf[8], buf[9]));
278
279 *dev->sci_tcmd = phase;
280 *dev->sci_mode = SCI_MODE_DMA;
281 *dev->sci_icmd = SCI_ICMD_DATA;
282 *dev->sci_dma_send = 0;
283 while (len > 0) {
284 wait = sci_data_wait;
285 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
286 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
287 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
288 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
289 || --wait < 0) {
290 #ifdef DEBUG
291 if (sci_debug)
292 printf("supradma_out fail: l%d i%x w%d\n",
293 len, *dev->sci_bus_csr, wait);
294 #endif
295 *dev->sci_mode = 0;
296 return 0;
297 }
298 }
299
300 *sci_dma = *buf++;
301 len--;
302 }
303
304 wait = sci_data_wait;
305 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) ==
306 SCI_CSR_PHASE_MATCH && --wait);
307
308
309 *dev->sci_mode = 0;
310 *dev->sci_icmd = 0;
311 return 0;
312 }
313
314
315 int
316 wstsc_dma_xfer_in2(struct sci_softc *dev, int len, register u_short *buf,
317 int phase)
318 {
319 volatile register u_short *sci_dma = (u_short *)(dev->sci_idata + 0x10);
320 volatile register u_char *sci_csr = dev->sci_csr + 0x10;
321 #ifdef DEBUG
322 u_char *obp = (u_char *) buf;
323 #endif
324 #if 0
325 int wait = sci_data_wait;
326 #endif
327
328 QPRINTF(("supradma_in2 %d, csr=%02x\n", len, *dev->sci_bus_csr));
329
330 *dev->sci_tcmd = phase;
331 *dev->sci_mode = SCI_MODE_DMA;
332 *dev->sci_icmd = 0;
333 *(dev->sci_irecv + 16) = 0;
334 while (len >= 128) {
335 #if 0
336 wait = sci_data_wait;
337 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
338 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
339 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
340 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
341 || --wait < 0) {
342 #ifdef DEBUG
343 if (sci_debug | 1)
344 printf("supradma2_in2 fail: l%d i%x w%d\n",
345 len, *dev->sci_bus_csr, wait);
346 #endif
347 *dev->sci_mode &= ~SCI_MODE_DMA;
348 return 0;
349 }
350 }
351 #else
352 while (!(*sci_csr & SCI_CSR_DREQ))
353 ;
354 #endif
355
356 #define R2 (*buf++ = *sci_dma)
357 R2; R2; R2; R2; R2; R2; R2; R2;
358 R2; R2; R2; R2; R2; R2; R2; R2;
359 R2; R2; R2; R2; R2; R2; R2; R2;
360 R2; R2; R2; R2; R2; R2; R2; R2;
361 R2; R2; R2; R2; R2; R2; R2; R2;
362 R2; R2; R2; R2; R2; R2; R2; R2;
363 R2; R2; R2; R2; R2; R2; R2; R2;
364 R2; R2; R2; R2; R2; R2; R2; R2;
365 len -= 128;
366 }
367 while (len > 0) {
368 #if 0
369 wait = sci_data_wait;
370 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
371 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
372 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
373 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
374 || --wait < 0) {
375 #ifdef DEBUG
376 if (sci_debug | 1)
377 printf("supradma1_in2 fail: l%d i%x w%d\n",
378 len, *dev->sci_bus_csr, wait);
379 #endif
380 *dev->sci_mode &= ~SCI_MODE_DMA;
381 return 0;
382 }
383 }
384 #else
385 while (!(*sci_csr * SCI_CSR_DREQ))
386 ;
387 #endif
388
389 *buf++ = *sci_dma;
390 len -= 2;
391 }
392
393 QPRINTF(("supradma_in2 {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
394 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
395 obp[6], obp[7], obp[8], obp[9]));
396
397 *dev->sci_irecv = 0;
398 *dev->sci_mode = 0;
399 return 0;
400 }
401
402 int
403 wstsc_dma_xfer_out2(struct sci_softc *dev, int len, register u_short *buf,
404 int phase)
405 {
406 volatile register u_short *sci_dma = (ushort *)(dev->sci_data + 0x10);
407 volatile register u_char *sci_bus_csr = dev->sci_bus_csr;
408 #ifdef DEBUG
409 u_char *obp = (u_char *) buf;
410 #endif
411 #if 0
412 int wait = sci_data_wait;
413 #endif
414
415 QPRINTF(("supradma_out2 %d, csr=%02x\n", len, *dev->sci_bus_csr));
416
417 QPRINTF(("supradma_out2 {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
418 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
419 obp[6], obp[7], obp[8], obp[9]));
420
421 *dev->sci_tcmd = phase;
422 *dev->sci_mode = SCI_MODE_DMA;
423 *dev->sci_icmd = SCI_ICMD_DATA;
424 *dev->sci_dma_send = 0;
425 while (len > 64) {
426 #if 0
427 wait = sci_data_wait;
428 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
429 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
430 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
431 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
432 || --wait < 0) {
433 #ifdef DEBUG
434 if (sci_debug)
435 printf("supradma_out2 fail: l%d i%x w%d\n",
436 len, csr, wait);
437 #endif
438 *dev->sci_mode = 0;
439 return 0;
440 }
441 }
442 #else
443 *dev->sci_mode = 0;
444 *dev->sci_icmd &= ~SCI_ICMD_ACK;
445 while (!(*sci_bus_csr & SCI_BUS_REQ))
446 ;
447 *dev->sci_mode = SCI_MODE_DMA;
448 *dev->sci_dma_send = 0;
449 #endif
450
451 #define W2 (*sci_dma = *buf++)
452 W2; W2; W2; W2; W2; W2; W2; W2;
453 W2; W2; W2; W2; W2; W2; W2; W2;
454 if (*(sci_bus_csr + 0x10) & SCI_BUS_REQ)
455 ;
456 len -= 64;
457 }
458
459 while (len > 0) {
460 #if 0
461 wait = sci_data_wait;
462 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
463 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
464 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
465 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
466 || --wait < 0) {
467 #ifdef DEBUG
468 if (sci_debug)
469 printf("supradma_out2 fail: l%d i%x w%d\n",
470 len, csr, wait);
471 #endif
472 *dev->sci_mode = 0;
473 return 0;
474 }
475 }
476 #else
477 *dev->sci_mode = 0;
478 *dev->sci_icmd &= ~SCI_ICMD_ACK;
479 while (!(*sci_bus_csr & SCI_BUS_REQ))
480 ;
481 *dev->sci_mode = SCI_MODE_DMA;
482 *dev->sci_dma_send = 0;
483 #endif
484
485 *sci_dma = *buf++;
486 if (*(sci_bus_csr + 0x10) & SCI_BUS_REQ)
487 ;
488 len -= 2;
489 }
490
491 #if 0
492 wait = sci_data_wait;
493 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) ==
494 SCI_CSR_PHASE_MATCH && --wait);
495 #endif
496
497
498 *dev->sci_irecv = 0;
499 *dev->sci_icmd &= ~SCI_ICMD_ACK;
500 *dev->sci_mode = 0;
501 *dev->sci_icmd = 0;
502 return 0;
503 }
504
505 int
506 wstsc_intr(void *arg)
507 {
508 struct sci_softc *dev = arg;
509 u_char stat;
510
511 if ((*(dev->sci_csr + 0x10) & SCI_CSR_INT) == 0)
512 return (0);
513 stat = *(dev->sci_iack + 0x10);
514 return (1);
515 }
516