wstsc.c revision 1.30
1/*	$NetBSD: wstsc.c,v 1.30 2004/03/28 18:59:39 mhitch Exp $ */
2
3/*
4 * Copyright (c) 1982, 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *	@(#)supradma.c
32 */
33
34/*
35 * Copyright (c) 1994 Michael L. Hitch
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 *
57 *	@(#)supradma.c
58 */
59
60#include <sys/cdefs.h>
61__KERNEL_RCSID(0, "$NetBSD: wstsc.c,v 1.30 2004/03/28 18:59:39 mhitch Exp $");
62
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/kernel.h>
66#include <sys/device.h>
67#include <dev/scsipi/scsi_all.h>
68#include <dev/scsipi/scsipi_all.h>
69#include <dev/scsipi/scsiconf.h>
70#include <amiga/amiga/device.h>
71#include <amiga/amiga/isr.h>
72#include <amiga/dev/scireg.h>
73#include <amiga/dev/scivar.h>
74#include <amiga/dev/zbusvar.h>
75
76void wstscattach(struct device *, struct device *, void *);
77int wstscmatch(struct device *, struct cfdata *, void *);
78
79int wstsc_dma_xfer_in(struct sci_softc *dev, int len,
80    register u_char *buf, int phase);
81int wstsc_dma_xfer_out(struct sci_softc *dev, int len,
82    register u_char *buf, int phase);
83int wstsc_dma_xfer_in2(struct sci_softc *dev, int len,
84    register u_short *buf, int phase);
85int wstsc_dma_xfer_out2(struct sci_softc *dev, int len,
86    register u_short *buf, int phase);
87int wstsc_intr(void *);
88
89#ifdef DEBUG
90extern int sci_debug;
91#define QPRINTF(a) if (sci_debug > 1) printf a
92#else
93#define QPRINTF(a)
94#endif
95
96extern int sci_data_wait;
97
98int supradma_pseudo = 0;	/* 0=none, 1=byte, 2=word */
99
100CFATTACH_DECL(wstsc, sizeof(struct sci_softc),
101    wstscmatch, wstscattach, NULL, NULL);
102
103/*
104 * if this a Supra WordSync board
105 */
106int
107wstscmatch(struct device *pdp, struct cfdata *cfp, void *auxp)
108{
109	struct zbus_args *zap;
110
111	zap = auxp;
112
113	/*
114	 * Check manufacturer and product id.
115	 */
116	if (zap->manid == 1056 && (
117	    zap->prodid == 12 ||	/* WordSync */
118	    zap->prodid == 13))		/* ByteSync */
119		return(1);
120	else
121		return(0);
122}
123
124void
125wstscattach(struct device *pdp, struct device *dp, void *auxp)
126{
127	volatile u_char *rp;
128	struct sci_softc *sc = (struct sci_softc *)dp;
129	struct zbus_args *zap;
130	struct scsipi_adapter *adapt = &sc->sc_adapter;
131	struct scsipi_channel *chan = &sc->sc_channel;
132
133	printf("\n");
134
135	zap = auxp;
136
137	rp = zap->va;
138	/*
139	 * set up 5380 register pointers
140	 * (Needs check on which Supra board this is - for now,
141	 *  just do the WordSync)
142	 */
143	sc->sci_data = rp + 0;
144	sc->sci_odata = rp + 0;
145	sc->sci_icmd = rp + 2;
146	sc->sci_mode = rp + 4;
147	sc->sci_tcmd = rp + 6;
148	sc->sci_bus_csr = rp + 8;
149	sc->sci_sel_enb = rp + 8;
150	sc->sci_csr = rp + 10;
151	sc->sci_dma_send = rp + 10;
152	sc->sci_idata = rp + 12;
153	sc->sci_trecv = rp + 12;
154	sc->sci_iack = rp + 14;
155	sc->sci_irecv = rp + 14;
156
157	if (supradma_pseudo == 2) {
158		sc->dma_xfer_in = (int(*)(struct sci_softc *, int, u_char *, int))wstsc_dma_xfer_in2;
159		sc->dma_xfer_out = (int(*)(struct sci_softc *, int, u_char *, int))wstsc_dma_xfer_out2;
160	}
161	else if (supradma_pseudo == 1) {
162		sc->dma_xfer_in = wstsc_dma_xfer_in;
163		sc->dma_xfer_out = wstsc_dma_xfer_out;
164	}
165
166	sc->sc_isr.isr_intr = wstsc_intr;
167	sc->sc_isr.isr_arg = sc;
168	sc->sc_isr.isr_ipl = 2;
169	add_isr(&sc->sc_isr);
170
171	scireset(sc);
172
173	/*
174	 * Fill in the scsipi_adapter.
175	 */
176	memset(adapt, 0, sizeof(*adapt));
177	adapt->adapt_dev = &sc->sc_dev;
178	adapt->adapt_nchannels = 1;
179	adapt->adapt_openings = 7;
180	adapt->adapt_max_periph = 1;
181	adapt->adapt_request = sci_scsipi_request;
182	adapt->adapt_minphys = sci_minphys;
183
184	/*
185	 * Fill in the scsipi_channel.
186	 */
187	memset(chan, 0, sizeof(*chan));
188	chan->chan_adapter = adapt;
189	chan->chan_bustype = &scsi_bustype;
190	chan->chan_channel = 0;
191	chan->chan_ntargets = 8;
192	chan->chan_nluns = 8;
193	chan->chan_id = 7;
194
195	/*
196	 * attach all scsi units on us
197	 */
198	config_found(dp, chan, scsiprint);
199}
200
201int
202wstsc_dma_xfer_in(struct sci_softc *dev, int len, register u_char *buf,
203                  int phase)
204{
205	int wait = sci_data_wait;
206	volatile register u_char *sci_dma = dev->sci_idata;
207	volatile register u_char *sci_csr = dev->sci_csr;
208#ifdef DEBUG
209	u_char *obp = (u_char *) buf;
210#endif
211
212	QPRINTF(("supradma_in %d, csr=%02x\n", len, *dev->sci_bus_csr));
213
214	*dev->sci_tcmd = phase;
215	*dev->sci_icmd = 0;
216	*dev->sci_mode = SCI_MODE_DMA;
217	*dev->sci_irecv = 0;
218
219	while (len >= 128) {
220		wait = sci_data_wait;
221		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
222		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
223			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
224			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
225			  || --wait < 0) {
226#ifdef DEBUG
227				if (sci_debug | 1)
228					printf("supradma2_in fail: l%d i%x w%d\n",
229					len, *dev->sci_bus_csr, wait);
230#endif
231				*dev->sci_mode = 0;
232				return 0;
233			}
234		}
235
236#define R1	(*buf++ = *sci_dma)
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		R1; R1; R1; R1; R1; R1; R1; R1;
241		R1; R1; R1; R1; R1; R1; R1; R1;
242		R1; R1; R1; R1; R1; R1; R1; R1;
243		R1; R1; R1; R1; R1; R1; R1; R1;
244		R1; R1; R1; R1; R1; R1; R1; R1;
245		R1; R1; R1; R1; R1; R1; R1; R1;
246		R1; R1; R1; R1; R1; R1; R1; R1;
247		R1; R1; R1; R1; R1; R1; R1; R1;
248		R1; R1; R1; R1; R1; R1; R1; R1;
249		R1; R1; R1; R1; R1; R1; R1; R1;
250		R1; R1; R1; R1; R1; R1; R1; R1;
251		R1; R1; R1; R1; R1; R1; R1; R1;
252		R1; R1; R1; R1; R1; R1; R1; R1;
253		len -= 128;
254	}
255
256	while (len > 0) {
257		wait = sci_data_wait;
258		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
259		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
260			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
261			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
262			  || --wait < 0) {
263#ifdef DEBUG
264				if (sci_debug | 1)
265					printf("supradma1_in fail: l%d i%x w%d\n",
266					len, *dev->sci_bus_csr, wait);
267#endif
268				*dev->sci_mode = 0;
269				return 0;
270			}
271		}
272
273		*buf++ = *sci_dma;
274		len--;
275	}
276
277	QPRINTF(("supradma_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
278	  len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
279	  obp[6], obp[7], obp[8], obp[9]));
280
281	*dev->sci_mode = 0;
282	return 0;
283}
284
285int
286wstsc_dma_xfer_out(struct sci_softc *dev, int len, register u_char *buf,
287                   int phase)
288{
289	int wait = sci_data_wait;
290	volatile register u_char *sci_dma = dev->sci_data;
291	volatile register u_char *sci_csr = dev->sci_csr;
292
293	QPRINTF(("supradma_out %d, csr=%02x\n", len, *dev->sci_bus_csr));
294
295	QPRINTF(("supradma_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
296  	 len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
297	 buf[6], buf[7], buf[8], buf[9]));
298
299	*dev->sci_tcmd = phase;
300	*dev->sci_mode = SCI_MODE_DMA;
301	*dev->sci_icmd = SCI_ICMD_DATA;
302	*dev->sci_dma_send = 0;
303	while (len > 0) {
304		wait = sci_data_wait;
305		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
306		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
307			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
308			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
309			  || --wait < 0) {
310#ifdef DEBUG
311				if (sci_debug)
312					printf("supradma_out fail: l%d i%x w%d\n",
313					len, *dev->sci_bus_csr, wait);
314#endif
315				*dev->sci_mode = 0;
316				return 0;
317			}
318		}
319
320		*sci_dma = *buf++;
321		len--;
322	}
323
324	wait = sci_data_wait;
325	while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) ==
326	  SCI_CSR_PHASE_MATCH && --wait);
327
328
329	*dev->sci_mode = 0;
330	*dev->sci_icmd = 0;
331	return 0;
332}
333
334
335int
336wstsc_dma_xfer_in2(struct sci_softc *dev, int len, register u_short *buf,
337                   int phase)
338{
339	volatile register u_short *sci_dma = (u_short *)(dev->sci_idata + 0x10);
340	volatile register u_char *sci_csr = dev->sci_csr + 0x10;
341#ifdef DEBUG
342	u_char *obp = (u_char *) buf;
343#endif
344#if 0
345	int wait = sci_data_wait;
346#endif
347
348	QPRINTF(("supradma_in2 %d, csr=%02x\n", len, *dev->sci_bus_csr));
349
350	*dev->sci_tcmd = phase;
351	*dev->sci_mode = SCI_MODE_DMA;
352	*dev->sci_icmd = 0;
353	*(dev->sci_irecv + 16) = 0;
354	while (len >= 128) {
355#if 0
356		wait = sci_data_wait;
357		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
358		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
359			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
360			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
361			  || --wait < 0) {
362#ifdef DEBUG
363				if (sci_debug | 1)
364					printf("supradma2_in2 fail: l%d i%x w%d\n",
365					len, *dev->sci_bus_csr, wait);
366#endif
367				*dev->sci_mode &= ~SCI_MODE_DMA;
368				return 0;
369			}
370		}
371#else
372		while (!(*sci_csr & SCI_CSR_DREQ))
373			;
374#endif
375
376#define R2	(*buf++ = *sci_dma)
377		R2; R2; R2; R2; R2; R2; R2; R2;
378		R2; R2; R2; R2; R2; R2; R2; R2;
379		R2; R2; R2; R2; R2; R2; R2; R2;
380		R2; R2; R2; R2; R2; R2; R2; R2;
381		R2; R2; R2; R2; R2; R2; R2; R2;
382		R2; R2; R2; R2; R2; R2; R2; R2;
383		R2; R2; R2; R2; R2; R2; R2; R2;
384		R2; R2; R2; R2; R2; R2; R2; R2;
385		len -= 128;
386	}
387	while (len > 0) {
388#if 0
389		wait = sci_data_wait;
390		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
391		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
392			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
393			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
394			  || --wait < 0) {
395#ifdef DEBUG
396				if (sci_debug | 1)
397					printf("supradma1_in2 fail: l%d i%x w%d\n",
398					len, *dev->sci_bus_csr, wait);
399#endif
400				*dev->sci_mode &= ~SCI_MODE_DMA;
401				return 0;
402			}
403		}
404#else
405		while (!(*sci_csr * SCI_CSR_DREQ))
406			;
407#endif
408
409		*buf++ = *sci_dma;
410		len -= 2;
411	}
412
413	QPRINTF(("supradma_in2 {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
414	  len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
415	  obp[6], obp[7], obp[8], obp[9]));
416
417	*dev->sci_irecv = 0;
418	*dev->sci_mode = 0;
419	return 0;
420}
421
422int
423wstsc_dma_xfer_out2(struct sci_softc *dev, int len, register u_short *buf,
424                    int phase)
425{
426	volatile register u_short *sci_dma = (ushort *)(dev->sci_data + 0x10);
427	volatile register u_char *sci_bus_csr = dev->sci_bus_csr;
428#ifdef DEBUG
429	u_char *obp = (u_char *) buf;
430#endif
431#if 0
432	int wait = sci_data_wait;
433#endif
434
435	QPRINTF(("supradma_out2 %d, csr=%02x\n", len, *dev->sci_bus_csr));
436
437	QPRINTF(("supradma_out2 {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
438  	 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
439	 obp[6], obp[7], obp[8], obp[9]));
440
441	*dev->sci_tcmd = phase;
442	*dev->sci_mode = SCI_MODE_DMA;
443	*dev->sci_icmd = SCI_ICMD_DATA;
444	*dev->sci_dma_send = 0;
445	while (len > 64) {
446#if 0
447		wait = sci_data_wait;
448		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
449		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
450			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
451			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
452			  || --wait < 0) {
453#ifdef DEBUG
454				if (sci_debug)
455					printf("supradma_out2 fail: l%d i%x w%d\n",
456					len, csr, wait);
457#endif
458				*dev->sci_mode = 0;
459				return 0;
460			}
461		}
462#else
463		*dev->sci_mode = 0;
464		*dev->sci_icmd &= ~SCI_ICMD_ACK;
465		while (!(*sci_bus_csr & SCI_BUS_REQ))
466			;
467		*dev->sci_mode = SCI_MODE_DMA;
468		*dev->sci_dma_send = 0;
469#endif
470
471#define W2	(*sci_dma = *buf++)
472		W2; W2; W2; W2; W2; W2; W2; W2;
473		W2; W2; W2; W2; W2; W2; W2; W2;
474		if (*(sci_bus_csr + 0x10) & SCI_BUS_REQ)
475			;
476		len -= 64;
477	}
478
479	while (len > 0) {
480#if 0
481		wait = sci_data_wait;
482		while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
483		  (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
484			if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
485			  || !(*dev->sci_bus_csr & SCI_BUS_BSY)
486			  || --wait < 0) {
487#ifdef DEBUG
488				if (sci_debug)
489					printf("supradma_out2 fail: l%d i%x w%d\n",
490					len, csr, wait);
491#endif
492				*dev->sci_mode = 0;
493				return 0;
494			}
495		}
496#else
497		*dev->sci_mode = 0;
498		*dev->sci_icmd &= ~SCI_ICMD_ACK;
499		while (!(*sci_bus_csr & SCI_BUS_REQ))
500			;
501		*dev->sci_mode = SCI_MODE_DMA;
502		*dev->sci_dma_send = 0;
503#endif
504
505		*sci_dma = *buf++;
506		if (*(sci_bus_csr + 0x10) & SCI_BUS_REQ)
507			;
508		len -= 2;
509	}
510
511#if 0
512	wait = sci_data_wait;
513	while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) ==
514	  SCI_CSR_PHASE_MATCH && --wait);
515#endif
516
517
518	*dev->sci_irecv = 0;
519	*dev->sci_icmd &= ~SCI_ICMD_ACK;
520	*dev->sci_mode = 0;
521	*dev->sci_icmd = 0;
522	return 0;
523}
524
525int
526wstsc_intr(void *arg)
527{
528	struct sci_softc *dev = arg;
529	u_char stat;
530
531	if ((*(dev->sci_csr + 0x10) & SCI_CSR_INT) == 0)
532		return (0);
533	stat = *(dev->sci_iack + 0x10);
534	return (1);
535}
536