1/*	$NetBSD: si.c,v 1.25 2024/02/13 05:35:13 thorpej Exp $	*/
2
3/*-
4 * Copyright (c) 1996,2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Adam Glass, David Jones, Gordon W. Ross, Jason R. Thorpe and
9 * Paul Kranenburg.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * This file contains VME bus-dependent of the `si' SCSI adapter.
35 * This hardware is frequently found on Sun 3 and Sun 4 machines.
36 *
37 * The SCSI machinery on this adapter is implemented by an NCR5380,
38 * which is taken care of by the chipset driver in /sys/dev/ic/ncr5380sbc.c
39 *
40 * The logic has a bit to enable or disable the DMA engine,
41 * but that bit also gates the interrupt line from the NCR5380!
42 * Therefore, in order to get any interrupt from the 5380, (i.e.
43 * for reselect) one must clear the DMA engine transfer count and
44 * then enable DMA.  This has the further complication that you
45 * CAN NOT touch the NCR5380 while the DMA enable bit is set, so
46 * we have to turn DMA back off before we even look at the 5380.
47 *
48 * What wonderfully whacky hardware this is!
49 *
50 */
51
52/*
53 * This driver originated as an MD implementation for the sun3 and sun4
54 * ports. The notes pertaining to that history are included below.
55 *
56 * David Jones wrote the initial version of this module for NetBSD/sun3,
57 * which included support for the VME adapter only. (no reselection).
58 *
59 * Gordon Ross added support for the Sun 3 OBIO adapter, and re-worked
60 * both the VME and OBIO code to support disconnect/reselect.
61 * (Required figuring out the hardware "features" noted above.)
62 *
63 * The autoconfiguration boilerplate came from Adam Glass.
64 *
65 * Jason R. Thorpe ported the autoconfiguration and VME portions to
66 * NetBSD/sparc, and added initial support for the 4/100 "SCSI Weird",
67 * a wacky OBIO variant of the VME SCSI-3.  Many thanks to Chuck Cranor
68 * for lots of helpful tips and suggestions.  Thanks also to Paul Kranenburg
69 * and Chris Torek for bits of insight needed along the way.  Thanks to
70 * David Gilbert and Andrew Gillham who risked filesystem life-and-limb
71 * for the sake of testing.  Andrew Gillham helped work out the bugs
72 * the 4/100 DMA code.
73 */
74
75#include <sys/cdefs.h>
76__KERNEL_RCSID(0, "$NetBSD: si.c,v 1.25 2024/02/13 05:35:13 thorpej Exp $");
77
78#include "opt_ddb.h"
79
80#include <sys/param.h>
81#include <sys/systm.h>
82#include <sys/kernel.h>
83#include <sys/malloc.h>
84#include <sys/errno.h>
85#include <sys/device.h>
86#include <sys/buf.h>
87
88#include <sys/bus.h>
89#include <sys/intr.h>
90
91#include <dev/vme/vmereg.h>
92#include <dev/vme/vmevar.h>
93
94#include <dev/scsipi/scsi_all.h>
95#include <dev/scsipi/scsipi_all.h>
96#include <dev/scsipi/scsipi_debug.h>
97#include <dev/scsipi/scsiconf.h>
98
99#ifndef Debugger
100#define	Debugger()
101#endif
102
103#ifndef DEBUG
104#define DEBUG XXX
105#endif
106
107#include <dev/ic/ncr5380reg.h>
108#include <dev/ic/ncr5380var.h>
109
110#include <dev/sun/sireg.h>
111
112/*
113 * Transfers smaller than this are done using PIO
114 * (on assumption they're not worth DMA overhead)
115 */
116#define	MIN_DMA_LEN 128
117
118#ifdef	DEBUG
119int si_debug = 0;
120#endif
121
122/*
123 * This structure is used to keep track of mapped DMA requests.
124 */
125struct si_dma_handle {
126	int 		dh_flags;
127#define	SIDH_BUSY	0x01		/* This DH is in use */
128#define	SIDH_OUT	0x02		/* DMA does data out (write) */
129	int 		dh_maplen;	/* Original data length */
130	bus_dmamap_t	dh_dmamap;
131#define dh_dvma	dh_dmamap->dm_segs[0].ds_addr /* VA of buffer in DVMA space */
132};
133
134/*
135 * The first structure member has to be the ncr5380_softc
136 * so we can just cast to go back and fourth between them.
137 */
138struct si_softc {
139	struct ncr5380_softc	ncr_sc;
140	bus_space_tag_t		sc_bustag;	/* bus tags */
141	bus_dma_tag_t		sc_dmatag;
142	vme_chipset_tag_t	sc_vctag;
143
144	int		sc_adapter_iv_am; /* int. vec + address modifier */
145	struct si_dma_handle *sc_dma;
146	int		sc_xlen;	/* length of current DMA segment. */
147	int		sc_options;	/* options for this instance. */
148};
149
150/*
151 * Options.  By default, DMA is enabled and DMA completion interrupts
152 * and reselect are disabled.  You may enable additional features
153 * the `flags' directive in your kernel's configuration file.
154 *
155 * Alternatively, you can patch your kernel with DDB or some other
156 * mechanism.  The sc_options member of the softc is OR'd with
157 * the value in si_options.
158 *
159 * Note, there's a separate sw_options to make life easier.
160 */
161#define	SI_ENABLE_DMA	0x01	/* Use DMA (maybe polled) */
162#define	SI_DMA_INTR	0x02	/* DMA completion interrupts */
163#define	SI_DO_RESELECT	0x04	/* Allow disconnect/reselect */
164#define	SI_OPTIONS_MASK	(SI_ENABLE_DMA|SI_DMA_INTR|SI_DO_RESELECT)
165#define SI_OPTIONS_BITS	"\10\3RESELECT\2DMA_INTR\1DMA"
166int si_options = SI_ENABLE_DMA|SI_DMA_INTR|SI_DO_RESELECT;
167
168static int	si_match(device_t, cfdata_t, void *);
169static void	si_attach(device_t, device_t, void *);
170static int	si_intr(void *);
171static void	si_reset_adapter(struct ncr5380_softc *);
172
173void	si_dma_alloc(struct ncr5380_softc *);
174void	si_dma_free(struct ncr5380_softc *);
175void	si_dma_poll(struct ncr5380_softc *);
176
177void	si_dma_setup(struct ncr5380_softc *);
178void	si_dma_start(struct ncr5380_softc *);
179void	si_dma_eop(struct ncr5380_softc *);
180void	si_dma_stop(struct ncr5380_softc *);
181
182void	si_intr_on (struct ncr5380_softc *);
183void	si_intr_off(struct ncr5380_softc *);
184
185/*
186 * Shorthand bus space access
187 * XXX - must look into endian issues here.
188 */
189#define SIREG_READ(sc, index) \
190	bus_space_read_2((sc)->sc_regt, (sc)->sc_regh, index)
191#define SIREG_WRITE(sc, index, v) \
192	bus_space_write_2((sc)->sc_regt, (sc)->sc_regh, index, v)
193
194
195/* Auto-configuration glue. */
196CFATTACH_DECL_NEW(si, sizeof(struct si_softc),
197    si_match, si_attach, NULL, NULL);
198
199static int
200si_match(device_t parent, cfdata_t cf, void *aux)
201{
202	struct vme_attach_args	*va = aux;
203	vme_chipset_tag_t	ct = va->va_vct;
204        vme_am_t		mod;
205        vme_addr_t		vme_addr;
206
207	/* Make sure there is something there... */
208	mod = VME_AM_A24 | VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA;
209	vme_addr = va->r[0].offset;
210
211	if (vme_probe(ct, vme_addr, 1, mod, VME_D8, NULL, 0) != 0)
212		return 0;
213
214	/*
215	 * If this is a VME SCSI board, we have to determine whether
216	 * it is an "sc" (Sun2) or "si" (Sun3) SCSI board.  This can
217	 * be determined using the fact that the "sc" board occupies
218	 * 4K bytes in VME space but the "si" board occupies 2K bytes.
219	 */
220	return vme_probe(ct, vme_addr + 0x801, 1, mod, VME_D8, NULL, 0) != 0;
221}
222
223static void
224si_attach(device_t parent, device_t self, void *aux)
225{
226	struct si_softc		*sc = device_private(self);
227	struct ncr5380_softc *ncr_sc = &sc->ncr_sc;
228	struct vme_attach_args	*va = aux;
229	vme_chipset_tag_t	ct = va->va_vct;
230	bus_space_tag_t		bt;
231	bus_space_handle_t	bh;
232	vme_mapresc_t resc;
233	vme_intr_handle_t	ih;
234	vme_am_t		mod;
235	char bits[64];
236	int i;
237
238	ncr_sc->sc_dev = self;
239	sc->sc_dmatag = va->va_bdt;
240	sc->sc_vctag = ct;
241
242	mod = VME_AM_A24 | VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA;
243
244	if (vme_space_map(ct, va->r[0].offset, SIREG_BANK_SZ,
245			  mod, VME_D8, 0, &bt, &bh, &resc) != 0)
246		panic("%s: vme_space_map", device_xname(self));
247
248	ncr_sc->sc_regt = bt;
249	ncr_sc->sc_regh = bh;
250
251	sc->sc_options = si_options;
252
253	ncr_sc->sc_dma_setup = si_dma_setup;
254	ncr_sc->sc_dma_start = si_dma_start;
255	ncr_sc->sc_dma_eop   = si_dma_stop;
256	ncr_sc->sc_dma_stop  = si_dma_stop;
257
258	vme_intr_map(ct, va->ilevel, va->ivector, &ih);
259	vme_intr_establish(ct, ih, IPL_BIO, si_intr, sc);
260
261	aprint_normal("\n");
262
263	sc->sc_adapter_iv_am = (mod << 8) | (va->ivector & 0xFF);
264
265	/*
266	 * Pull in the options flags.  Allow the user to completely
267	 * override the default values.
268	 */
269	if ((device_cfdata(self)->cf_flags & SI_OPTIONS_MASK) != 0)
270		sc->sc_options =
271		    device_cfdata(self)->cf_flags & SI_OPTIONS_MASK;
272
273	/*
274	 * Initialize fields used by the MI code
275	 */
276
277	/* NCR5380 register bank offsets */
278	ncr_sc->sci_r0 = 0;
279	ncr_sc->sci_r1 = 1;
280	ncr_sc->sci_r2 = 2;
281	ncr_sc->sci_r3 = 3;
282	ncr_sc->sci_r4 = 4;
283	ncr_sc->sci_r5 = 5;
284	ncr_sc->sci_r6 = 6;
285	ncr_sc->sci_r7 = 7;
286
287	ncr_sc->sc_rev = NCR_VARIANT_NCR5380;
288
289	/*
290	 * MD function pointers used by the MI code.
291	 */
292	ncr_sc->sc_pio_out = ncr5380_pio_out;
293	ncr_sc->sc_pio_in =  ncr5380_pio_in;
294	ncr_sc->sc_dma_alloc = si_dma_alloc;
295	ncr_sc->sc_dma_free  = si_dma_free;
296	ncr_sc->sc_dma_poll  = si_dma_poll;
297
298	ncr_sc->sc_flags = 0;
299	if ((sc->sc_options & SI_DO_RESELECT) == 0)
300		ncr_sc->sc_no_disconnect = 0xFF;
301	if ((sc->sc_options & SI_DMA_INTR) == 0)
302		ncr_sc->sc_flags |= NCR5380_FORCE_POLLING;
303	ncr_sc->sc_min_dma_len = MIN_DMA_LEN;
304
305	/*
306	 * Allocate DMA handles.
307	 */
308	i = SCI_OPENINGS * sizeof(struct si_dma_handle);
309	sc->sc_dma = malloc(i, M_DEVBUF, M_WAITOK);
310	for (i = 0; i < SCI_OPENINGS; i++) {
311		sc->sc_dma[i].dh_flags = 0;
312
313		/* Allocate a DMA handle */
314		if (vme_dmamap_create(
315				sc->sc_vctag,	/* VME chip tag */
316				MAXPHYS,	/* size */
317				VME_AM_A24,	/* address modifier */
318				VME_D16,	/* data size */
319				0,		/* swap */
320				1,		/* nsegments */
321				MAXPHYS,	/* maxsegsz */
322				0,		/* boundary */
323				BUS_DMA_NOWAIT,
324				&sc->sc_dma[i].dh_dmamap) != 0) {
325
326			aprint_error_dev(self, "DMA buffer map create error\n");
327			return;
328		}
329	}
330
331	if (sc->sc_options) {
332		snprintb(bits, sizeof(bits), SI_OPTIONS_BITS, sc->sc_options);
333		aprint_normal_dev(self, "options=%s\n", bits);
334	}
335
336	ncr_sc->sc_channel.chan_id = 7;
337	ncr_sc->sc_adapter.adapt_minphys = minphys;
338
339	/*
340	 *  Initialize si board itself.
341	 */
342	si_reset_adapter(ncr_sc);
343	ncr5380_attach(ncr_sc);
344
345	if (sc->sc_options & SI_DO_RESELECT) {
346		/*
347		 * Need to enable interrupts (and DMA!)
348		 * on this H/W for reselect to work.
349		 */
350		ncr_sc->sc_intr_on   = si_intr_on;
351		ncr_sc->sc_intr_off  = si_intr_off;
352	}
353}
354
355#define CSR_WANT (SI_CSR_SBC_IP | SI_CSR_DMA_IP | \
356	SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR )
357
358static int
359si_intr(void *arg)
360{
361	struct si_softc *sc = arg;
362	struct ncr5380_softc *ncr_sc = &sc->ncr_sc;
363	int dma_error, claimed;
364	uint16_t csr;
365
366	claimed = 0;
367	dma_error = 0;
368
369	/* SBC interrupt? DMA interrupt? */
370	csr = SIREG_READ(ncr_sc, SIREG_CSR);
371
372	NCR_TRACE("si_intr: csr=0x%x\n", csr);
373
374	if (csr & SI_CSR_DMA_CONFLICT) {
375		dma_error |= SI_CSR_DMA_CONFLICT;
376		printf("%s: DMA conflict\n", __func__);
377	}
378	if (csr & SI_CSR_DMA_BUS_ERR) {
379		dma_error |= SI_CSR_DMA_BUS_ERR;
380		printf("%s: DMA bus error\n", __func__);
381	}
382	if (dma_error) {
383		if (sc->ncr_sc.sc_state & NCR_DOINGDMA)
384			sc->ncr_sc.sc_state |= NCR_ABORTING;
385		/* Make sure we will call the main isr. */
386		csr |= SI_CSR_DMA_IP;
387	}
388
389	if (csr & (SI_CSR_SBC_IP | SI_CSR_DMA_IP)) {
390		claimed = ncr5380_intr(&sc->ncr_sc);
391#ifdef DEBUG
392		if (!claimed) {
393			printf("%s: spurious from SBC\n", __func__);
394			if (si_debug & 4) {
395				Debugger();	/* XXX */
396			}
397		}
398#endif
399	}
400
401	return claimed;
402}
403
404
405static void
406si_reset_adapter(struct ncr5380_softc *ncr_sc)
407{
408	struct si_softc *sc = (struct si_softc *)ncr_sc;
409
410#ifdef	DEBUG
411	if (si_debug) {
412		printf("%s\n", __func__);
413	}
414#endif
415
416	/*
417	 * The SCSI3 controller has an 8K FIFO to buffer data between the
418	 * 5380 and the DMA.  Make sure it starts out empty.
419	 *
420	 * The reset bits in the CSR are active low.
421	 */
422	SIREG_WRITE(ncr_sc, SIREG_CSR, 0);
423	delay(10);
424	SIREG_WRITE(ncr_sc, SIREG_CSR,
425	    SI_CSR_FIFO_RES | SI_CSR_SCSI_RES | SI_CSR_INTR_EN);
426	delay(10);
427
428	SIREG_WRITE(ncr_sc, SIREG_FIFO_CNT, 0);
429	SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRH, 0);
430	SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRL, 0);
431	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, 0);
432	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, 0);
433	SIREG_WRITE(ncr_sc, SIREG_IV_AM, sc->sc_adapter_iv_am);
434	SIREG_WRITE(ncr_sc, SIREG_FIFO_CNTH, 0);
435
436	SCI_CLR_INTR(ncr_sc);
437}
438
439/*****************************************************************
440 * Common functions for DMA
441 ****************************************************************/
442
443/*
444 * Allocate a DMA handle and put it in sc->sc_dma.  Prepare
445 * for DMA transfer.
446 */
447void
448si_dma_alloc(struct ncr5380_softc *ncr_sc)
449{
450	struct si_softc *sc = (struct si_softc *)ncr_sc;
451	struct sci_req *sr = ncr_sc->sc_current;
452	struct scsipi_xfer *xs = sr->sr_xs;
453	struct si_dma_handle *dh;
454	int i, xlen;
455	u_long addr;
456
457#ifdef DIAGNOSTIC
458	if (sr->sr_dma_hand != NULL)
459		panic("%s: already have DMA handle", __func__);
460#endif
461
462#if 1	/* XXX - Temporary */
463	/* XXX - In case we think DMA is completely broken... */
464	if ((sc->sc_options & SI_ENABLE_DMA) == 0)
465		return;
466#endif
467
468	addr = (u_long)ncr_sc->sc_dataptr;
469	xlen = ncr_sc->sc_datalen;
470
471	/* If the DMA start addr is misaligned then do PIO */
472	if ((addr & 1) || (xlen & 1)) {
473		printf("%s: misaligned.\n", __func__);
474		return;
475	}
476
477	/* Make sure our caller checked sc_min_dma_len. */
478	if (xlen < MIN_DMA_LEN)
479		panic("%s: xlen=0x%x", __func__, xlen);
480
481	/* Find free DMA handle.  Guaranteed to find one since we have
482	   as many DMA handles as the driver has processes. */
483	for (i = 0; i < SCI_OPENINGS; i++) {
484		if ((sc->sc_dma[i].dh_flags & SIDH_BUSY) == 0)
485			goto found;
486	}
487	panic("si: no free DMA handles.");
488
489found:
490	dh = &sc->sc_dma[i];
491	dh->dh_flags = SIDH_BUSY;
492	dh->dh_maplen  = xlen;
493
494	/* Copy the "write" flag for convenience. */
495	if ((xs->xs_control & XS_CTL_DATA_OUT) != 0)
496		dh->dh_flags |= SIDH_OUT;
497
498	/*
499	 * Double-map the buffer into DVMA space.  If we can't re-map
500	 * the buffer, we print a warning and fall back to PIO mode.
501	 *
502	 * NOTE: it is not safe to sleep here!
503	 */
504	if (bus_dmamap_load(sc->sc_dmatag, dh->dh_dmamap,
505			    (void *)addr, xlen, NULL, BUS_DMA_NOWAIT) != 0) {
506		/* Can't remap segment */
507		printf("%s: can't remap 0x%lx/0x%x, doing PIO\n",
508		    __func__, addr, dh->dh_maplen);
509		dh->dh_flags = 0;
510		return;
511	}
512	bus_dmamap_sync(sc->sc_dmatag, dh->dh_dmamap, addr, xlen,
513			(dh->dh_flags & SIDH_OUT)
514				? BUS_DMASYNC_PREWRITE
515				: BUS_DMASYNC_PREREAD);
516
517	/* success */
518	sr->sr_dma_hand = dh;
519}
520
521
522void
523si_dma_free(struct ncr5380_softc *ncr_sc)
524{
525	struct si_softc *sc = (struct si_softc *)ncr_sc;
526	struct sci_req *sr = ncr_sc->sc_current;
527	struct si_dma_handle *dh = sr->sr_dma_hand;
528
529#ifdef DIAGNOSTIC
530	if (dh == NULL)
531		panic("%s: no DMA handle", __func__);
532#endif
533
534	if (ncr_sc->sc_state & NCR_DOINGDMA)
535		panic("%s: free while in progress", __func__);
536
537	if (dh->dh_flags & SIDH_BUSY) {
538		/* Give back the DVMA space. */
539		bus_dmamap_sync(sc->sc_dmatag, dh->dh_dmamap,
540				dh->dh_dvma, dh->dh_maplen,
541				(dh->dh_flags & SIDH_OUT)
542					? BUS_DMASYNC_POSTWRITE
543					: BUS_DMASYNC_POSTREAD);
544		bus_dmamap_unload(sc->sc_dmatag, dh->dh_dmamap);
545		dh->dh_flags = 0;
546	}
547	sr->sr_dma_hand = NULL;
548}
549
550
551/*
552 * Poll (spin-wait) for DMA completion.
553 * Called right after xx_dma_start(), and
554 * xx_dma_stop() will be called next.
555 * Same for either VME or OBIO.
556 */
557void
558si_dma_poll(struct ncr5380_softc *ncr_sc)
559{
560	struct sci_req *sr = ncr_sc->sc_current;
561	int tmo, csr_mask, csr;
562
563	/* Make sure DMA started successfully. */
564	if (ncr_sc->sc_state & NCR_ABORTING)
565		return;
566
567	csr_mask = SI_CSR_SBC_IP | SI_CSR_DMA_IP |
568		SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR;
569
570	tmo = 50000;	/* X100 = 5 sec. */
571	for (;;) {
572		csr = SIREG_READ(ncr_sc, SIREG_CSR);
573		if (csr & csr_mask)
574			break;
575		if (--tmo <= 0) {
576			printf("%s: DMA timeout (while polling)\n",
577			    device_xname(ncr_sc->sc_dev));
578			/* Indicate timeout as MI code would. */
579			sr->sr_flags |= SR_OVERDUE;
580			break;
581		}
582		delay(100);
583	}
584
585#ifdef	DEBUG
586	if (si_debug) {
587		printf("%s: done, csr=0x%x\n", __func__, csr);
588	}
589#endif
590}
591
592
593/*****************************************************************
594 * VME functions for DMA
595 ****************************************************************/
596
597
598/*
599 * This is called when the bus is going idle,
600 * so we want to enable the SBC interrupts.
601 * That is controlled by the DMA enable!
602 * Who would have guessed!
603 * What a NASTY trick!
604 */
605void
606si_intr_on(struct ncr5380_softc *ncr_sc)
607{
608	uint16_t csr;
609
610	/* Clear DMA start address and counters */
611	SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRH, 0);
612	SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRL, 0);
613	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, 0);
614	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, 0);
615
616	/* Enter receive mode (for safety) and enable DMA engine */
617	csr = SIREG_READ(ncr_sc, SIREG_CSR);
618	csr &= ~SI_CSR_SEND;
619	csr |= SI_CSR_DMA_EN;
620	SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
621}
622
623/*
624 * This is called when the bus is idle and we are
625 * about to start playing with the SBC chip.
626 */
627void
628si_intr_off(struct ncr5380_softc *ncr_sc)
629{
630	uint16_t csr;
631
632	csr = SIREG_READ(ncr_sc, SIREG_CSR);
633	csr &= ~SI_CSR_DMA_EN;
634	SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
635}
636
637/*
638 * This function is called during the COMMAND or MSG_IN phase
639 * that precedes a DATA_IN or DATA_OUT phase, in case we need
640 * to setup the DMA engine before the bus enters a DATA phase.
641 *
642 * XXX: The VME adapter appears to suppress SBC interrupts
643 * when the FIFO is not empty or the FIFO count is non-zero!
644 *
645 * On the VME version we just clear the DMA count and address
646 * here (to make sure it stays idle) and do the real setup
647 * later, in dma_start.
648 */
649void
650si_dma_setup(struct ncr5380_softc *ncr_sc)
651{
652	struct si_softc *sc = (struct si_softc *)ncr_sc;
653	struct sci_req *sr = ncr_sc->sc_current;
654	struct si_dma_handle *dh = sr->sr_dma_hand;
655	uint16_t csr;
656	u_long dva;
657	int xlen;
658
659	/*
660	 * Set up the DMA controller.
661	 * Note that (dh->dh_len < sc_datalen)
662	 */
663
664	csr = SIREG_READ(ncr_sc, SIREG_CSR);
665
666	/* Disable DMA while we're setting up the transfer */
667	csr &= ~SI_CSR_DMA_EN;
668
669	/* Reset the FIFO */
670	csr &= ~SI_CSR_FIFO_RES;		/* active low */
671	SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
672	csr |= SI_CSR_FIFO_RES;
673	SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
674
675	/*
676	 * Get the DVMA mapping for this segment.
677	 */
678	dva = (u_long)(dh->dh_dvma);
679	if (dva & 1)
680		panic("%s: bad dmaaddr=0x%lx", __func__, dva);
681	xlen = ncr_sc->sc_datalen;
682	xlen &= ~1;
683	sc->sc_xlen = xlen;	/* XXX: or less... */
684
685#ifdef	DEBUG
686	if (si_debug & 2) {
687		printf("%s: dh=%p, dmaaddr=0x%lx, xlen=%d\n",
688		    __func__, dh, dva, xlen);
689	}
690#endif
691	/* Set direction (send/recv) */
692	if (dh->dh_flags & SIDH_OUT) {
693		csr |= SI_CSR_SEND;
694	} else {
695		csr &= ~SI_CSR_SEND;
696	}
697
698	/* Set byte-packing control */
699	if (dva & 2) {
700		csr |= SI_CSR_BPCON;
701	} else {
702		csr &= ~SI_CSR_BPCON;
703	}
704
705	SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
706
707	/* Load start address */
708	SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRH, (uint16_t)(dva >> 16));
709	SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRL, (uint16_t)(dva & 0xFFFF));
710
711	/* Clear DMA counters; these will be set in si_dma_start() */
712	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, 0);
713	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, 0);
714
715	/* Clear FIFO counter. (also hits dma_count) */
716	SIREG_WRITE(ncr_sc, SIREG_FIFO_CNTH, 0);
717	SIREG_WRITE(ncr_sc, SIREG_FIFO_CNT, 0);
718}
719
720
721void
722si_dma_start(struct ncr5380_softc *ncr_sc)
723{
724	struct si_softc *sc = (struct si_softc *)ncr_sc;
725	struct sci_req *sr = ncr_sc->sc_current;
726	struct si_dma_handle *dh = sr->sr_dma_hand;
727	int xlen;
728	u_int mode;
729	uint16_t csr;
730
731	xlen = sc->sc_xlen;
732
733	/* Load transfer length */
734	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, (uint16_t)(xlen >> 16));
735	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, (uint16_t)(xlen & 0xFFFF));
736	SIREG_WRITE(ncr_sc, SIREG_FIFO_CNTH, (uint16_t)(xlen >> 16));
737	SIREG_WRITE(ncr_sc, SIREG_FIFO_CNT, (uint16_t)(xlen & 0xFFFF));
738
739	/*
740	 * Acknowledge the phase change.  (After DMA setup!)
741	 * Put the SBIC into DMA mode, and start the transfer.
742	 */
743	if (dh->dh_flags & SIDH_OUT) {
744		NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_OUT);
745		SCI_CLR_INTR(ncr_sc);
746		NCR5380_WRITE(ncr_sc, sci_icmd, SCI_ICMD_DATA);
747
748		mode = NCR5380_READ(ncr_sc, sci_mode);
749		mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
750		NCR5380_WRITE(ncr_sc, sci_mode, mode);
751
752		NCR5380_WRITE(ncr_sc, sci_dma_send, 0); /* start it */
753	} else {
754		NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_IN);
755		SCI_CLR_INTR(ncr_sc);
756		NCR5380_WRITE(ncr_sc, sci_icmd, 0);
757
758		mode = NCR5380_READ(ncr_sc, sci_mode);
759		mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
760		NCR5380_WRITE(ncr_sc, sci_mode, mode);
761
762		NCR5380_WRITE(ncr_sc, sci_irecv, 0); /* start it */
763	}
764
765	ncr_sc->sc_state |= NCR_DOINGDMA;
766
767	/* Enable DMA engine */
768	csr = SIREG_READ(ncr_sc, SIREG_CSR);
769	csr |= SI_CSR_DMA_EN;
770	SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
771
772#ifdef	DEBUG
773	if (si_debug & 2) {
774		printf("%s: started, flags=0x%x\n",
775		    __func__, ncr_sc->sc_state);
776	}
777#endif
778}
779
780
781void
782si_dma_eop(struct ncr5380_softc *ncr_sc)
783{
784
785	/* Not needed - DMA was stopped prior to examining sci_csr */
786}
787
788
789void
790si_dma_stop(struct ncr5380_softc *ncr_sc)
791{
792	struct si_softc *sc = (struct si_softc *)ncr_sc;
793	struct sci_req *sr = ncr_sc->sc_current;
794	struct si_dma_handle *dh = sr->sr_dma_hand;
795	int resid, ntrans;
796	uint16_t csr;
797	u_int mode;
798
799	if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
800#ifdef	DEBUG
801		printf("%s: DMA not running\n", __func__);
802#endif
803		return;
804	}
805
806	ncr_sc->sc_state &= ~NCR_DOINGDMA;
807
808	csr = SIREG_READ(ncr_sc, SIREG_CSR);
809
810	/* First, halt the DMA engine. */
811	csr &= ~SI_CSR_DMA_EN;
812	SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
813
814	if (csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) {
815		printf("si: DMA error, csr=0x%x, reset\n", csr);
816		sr->sr_xs->error = XS_DRIVER_STUFFUP;
817		ncr_sc->sc_state |= NCR_ABORTING;
818		si_reset_adapter(ncr_sc);
819	}
820
821	/* Note that timeout may have set the error flag. */
822	if (ncr_sc->sc_state & NCR_ABORTING)
823		goto out;
824
825	/*
826	 * Now try to figure out how much actually transferred
827	 *
828	 * The fifo_count does not reflect how many bytes were
829	 * actually transferred for VME.
830	 *
831	 * SCSI-3 VME interface is a little funny on writes:
832	 * if we have a disconnect, the DMA has overshot by
833	 * one byte and the resid needs to be incremented.
834	 * Only happens for partial transfers.
835	 * (Thanks to Matt Jacob)
836	 */
837
838	resid = SIREG_READ(ncr_sc, SIREG_FIFO_CNTH) << 16;
839	resid |= SIREG_READ(ncr_sc, SIREG_FIFO_CNT) & 0xFFFF;
840	if (dh->dh_flags & SIDH_OUT)
841		if ((resid > 0) && (resid < sc->sc_xlen))
842			resid++;
843	ntrans = sc->sc_xlen - resid;
844
845#ifdef	DEBUG
846	if (si_debug & 2) {
847		printf("%s: resid=0x%x ntrans=0x%x\n",
848		    __func__, resid, ntrans);
849	}
850#endif
851
852	if (ntrans > ncr_sc->sc_datalen)
853		panic("%s: excess transfer", __func__);
854
855	/* Adjust data pointer */
856	ncr_sc->sc_dataptr += ntrans;
857	ncr_sc->sc_datalen -= ntrans;
858
859#ifdef	DEBUG
860	if (si_debug & 2) {
861		printf("%s: ntrans=0x%x\n", __func__, ntrans);
862	}
863#endif
864
865	/*
866	 * After a read, we may need to clean-up
867	 * "Left-over bytes" (yuck!)
868	 */
869	if (((dh->dh_flags & SIDH_OUT) == 0) &&
870		((csr & SI_CSR_LOB) != 0)) {
871		uint8_t *cp = ncr_sc->sc_dataptr;
872		uint16_t bprh, bprl;
873
874		bprh = SIREG_READ(ncr_sc, SIREG_BPRH);
875		bprl = SIREG_READ(ncr_sc, SIREG_BPRL);
876
877#ifdef DEBUG
878		printf("si: got left-over bytes: bprh=%x, bprl=%x, csr=%x\n",
879			bprh, bprl, csr);
880#endif
881
882		if (csr & SI_CSR_BPCON) {
883			/* have SI_CSR_BPCON */
884			cp[-1] = (bprl & 0xff00) >> 8;
885		} else {
886			switch (csr & SI_CSR_LOB) {
887			case SI_CSR_LOB_THREE:
888				cp[-3] = (bprh & 0xff00) >> 8;
889				cp[-2] = (bprh & 0x00ff);
890				cp[-1] = (bprl & 0xff00) >> 8;
891				break;
892			case SI_CSR_LOB_TWO:
893				cp[-2] = (bprh & 0xff00) >> 8;
894				cp[-1] = (bprh & 0x00ff);
895				break;
896			case SI_CSR_LOB_ONE:
897				cp[-1] = (bprh & 0xff00) >> 8;
898				break;
899			}
900		}
901	}
902
903out:
904	SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRH, 0);
905	SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRL, 0);
906
907	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, 0);
908	SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, 0);
909
910	SIREG_WRITE(ncr_sc, SIREG_FIFO_CNTH, 0);
911	SIREG_WRITE(ncr_sc, SIREG_FIFO_CNT, 0);
912
913	mode = NCR5380_READ(ncr_sc, sci_mode);
914	/* Put SBIC back in PIO mode. */
915	mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);
916	NCR5380_WRITE(ncr_sc, sci_mode, mode);
917	NCR5380_WRITE(ncr_sc, sci_icmd, 0);
918}
919