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