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