lsi64854.c revision 226381
1181111Sdes/*-
2107553Sdes * Copyright (c) 2004 Scott Long
399059Sdes * All rights reserved.
4221420Sdes *
5221420Sdes * Redistribution and use in source and binary forms, with or without
6221420Sdes * modification, are permitted provided that the following conditions
7157020Sdes * are met:
8157020Sdes * 1. Redistributions of source code must retain the above copyright
9157020Sdes *    notice, this list of conditions and the following disclaimer.
10124244Sdes * 2. Redistributions in binary form must reproduce the above copyright
11157020Sdes *    notice, this list of conditions and the following disclaimer in the
12157020Sdes *    documentation and/or other materials provided with the distribution.
1399059Sdes *
14181111Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15181111Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16181111Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17157020Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18157020Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1999059Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20247892Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21247892Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22247892Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23157020Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24157020Sdes * SUCH DAMAGE.
2599059Sdes *
26157020Sdes */
27157020Sdes
28124244Sdes/*	$NetBSD: lsi64854.c,v 1.33 2008/04/28 20:23:50 martin Exp $ */
29157020Sdes
30157020Sdes/*-
31124244Sdes * Copyright (c) 1998 The NetBSD Foundation, Inc.
32181111Sdes * All rights reserved.
33181111Sdes *
34181111Sdes * This code is derived from software contributed to The NetBSD Foundation
3599059Sdes * by Paul Kranenburg.
3699059Sdes *
3799059Sdes * Redistribution and use in source and binary forms, with or without
38157020Sdes * modification, are permitted provided that the following conditions
39157020Sdes * are met:
4099059Sdes * 1. Redistributions of source code must retain the above copyright
41157020Sdes *    notice, this list of conditions and the following disclaimer.
42157020Sdes * 2. Redistributions in binary form must reproduce the above copyright
4399059Sdes *    notice, this list of conditions and the following disclaimer in the
44157020Sdes *    documentation and/or other materials provided with the distribution.
45157020Sdes *
46157020Sdes * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
4799059Sdes * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48181111Sdes * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49181111Sdes * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50181111Sdes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5199059Sdes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5299059Sdes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
5399059Sdes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54157020Sdes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55157020Sdes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
5699059Sdes * POSSIBILITY OF SUCH DAMAGE.
57157020Sdes */
58157020Sdes
5999059Sdes#include <sys/cdefs.h>
60157020Sdes__FBSDID("$FreeBSD: head/sys/sparc64/sbus/lsi64854.c 226381 2011-10-15 09:29:43Z marius $");
61157020Sdes
6299059Sdes#include <sys/param.h>
63157020Sdes#include <sys/systm.h>
64157020Sdes#include <sys/bus.h>
65124244Sdes#include <sys/kernel.h>
66157020Sdes#include <sys/lock.h>
67157020Sdes#include <sys/mutex.h>
68128462Sdes#include <sys/rman.h>
69157020Sdes
70157020Sdes#include <machine/bus.h>
7199059Sdes
72181111Sdes#include <cam/cam.h>
73181111Sdes#include <cam/cam_ccb.h>
74181111Sdes#include <cam/scsi/scsi_all.h>
75157020Sdes
76157020Sdes#include <sparc64/sbus/lsi64854reg.h>
7799059Sdes#include <sparc64/sbus/lsi64854var.h>
78197679Sdes
79197679Sdes#include <dev/esp/ncr53c9xreg.h>
80197679Sdes#include <dev/esp/ncr53c9xvar.h>
81157020Sdes
82157020Sdes#ifdef DEBUG
8399059Sdes#define LDB_SCSI	1
84157020Sdes#define LDB_ENET	2
85157020Sdes#define LDB_PP		4
8699059Sdes#define LDB_ANY		0xff
87157020Sdesint lsi64854debug = 0;
88157020Sdes#define DPRINTF(a,x)							\
8999059Sdes	do {								\
90157020Sdes		if ((lsi64854debug & (a)) != 0)				\
91202213Sed			printf x;					\
9299059Sdes	} while (/* CONSTCOND */0)
93157020Sdes#else
94157020Sdes#define DPRINTF(a,x)
9599059Sdes#endif
96157020Sdes
97202213Sed#define MAX_DMA_SZ	(16*1024*1024)
9899059Sdes
99157020Sdesstatic void	lsi64854_reset(struct lsi64854_softc *);
100157020Sdesstatic void	lsi64854_map_scsi(void *, bus_dma_segment_t *, int, int);
10199059Sdesstatic int	lsi64854_setup(struct lsi64854_softc *, void **, size_t *,
102157020Sdes		    int, size_t *);
103247892Sdesstatic int	lsi64854_scsi_intr(void *);
10499059Sdesstatic int	lsi64854_enet_intr(void *);
10599059Sdesstatic int	lsi64854_setup_pp(struct lsi64854_softc *, void **,
10699059Sdes		    size_t *, int, size_t *);
10799059Sdesstatic int	lsi64854_pp_intr(void *);
10899059Sdes
10999059Sdes/*
11099059Sdes * Finish attaching this DMA device.
11199059Sdes * Front-end must fill in these fields:
11299059Sdes *	sc_res
11399059Sdes *	sc_burst
114157020Sdes *	sc_channel (one of SCSI, ENET, PP)
115157020Sdes *	sc_client (one of SCSI, ENET, PP `soft_c' pointers)
11699059Sdes */
11799059Sdesint
118202213Sedlsi64854_attach(struct lsi64854_softc *sc)
11999059Sdes{
12099059Sdes	bus_dma_lock_t *lockfunc;
121202213Sed	struct ncr53c9x_softc *nsc;
12299059Sdes	void *lockfuncarg;
12399059Sdes	uint32_t csr;
124202213Sed	int error;
12599059Sdes
12699059Sdes	lockfunc = NULL;
12799059Sdes	lockfuncarg = NULL;
12899059Sdes
129204917Sdes	switch (sc->sc_channel) {
130207319Sdes	case L64854_CHANNEL_SCSI:
131204917Sdes		nsc = sc->sc_client;
132221420Sdes		if (NCR_LOCK_INITIALIZED(nsc) == 0) {
133221420Sdes			device_printf(sc->sc_dev, "mutex not initialized\n");
134221420Sdes			return (ENXIO);
135197679Sdes		}
136181111Sdes		lockfunc = busdma_lock_mutex;
137181111Sdes		lockfuncarg = &nsc->sc_lock;
138197679Sdes		sc->intr = lsi64854_scsi_intr;
139197679Sdes		sc->setup = lsi64854_setup;
140197679Sdes		break;
141157020Sdes	case L64854_CHANNEL_ENET:
142157020Sdes		sc->intr = lsi64854_enet_intr;
14399059Sdes		break;
144157020Sdes	case L64854_CHANNEL_PP:
145157020Sdes		sc->intr = lsi64854_pp_intr;
14699059Sdes		sc->setup = lsi64854_setup_pp;
14799059Sdes		break;
148159458Sdes	default:
14999059Sdes		device_printf(sc->sc_dev, "unknown channel\n");
15099059Sdes	}
151159458Sdes	sc->reset = lsi64854_reset;
15299059Sdes
153221420Sdes	if (sc->setup != NULL) {
154221420Sdes		error = bus_dma_tag_create(
155221420Sdes		    sc->sc_parent_dmat,		/* parent */
156157020Sdes		    1, 0,			/* alignment, boundary */
157157020Sdes		    BUS_SPACE_MAXADDR,		/* lowaddr */
15899059Sdes		    BUS_SPACE_MAXADDR,		/* highaddr */
159157020Sdes		    NULL, NULL,			/* filter, filterarg */
160157020Sdes		    MAX_DMA_SZ,			/* maxsize */
161124244Sdes		    1,				/* nsegments */
162157020Sdes		    MAX_DMA_SZ,			/* maxsegsize */
163157020Sdes		    BUS_DMA_ALLOCNOW,		/* flags */
16499059Sdes		    lockfunc, lockfuncarg,	/* lockfunc, lockfuncarg */
165157020Sdes		    &sc->sc_buffer_dmat);
166157020Sdes		if (error != 0) {
16799059Sdes			device_printf(sc->sc_dev,
168157020Sdes			    "cannot allocate buffer DMA tag\n");
169157020Sdes			return (error);
17099059Sdes		}
171157020Sdes
172157020Sdes		error = bus_dmamap_create(sc->sc_buffer_dmat, 0,
17399059Sdes		    &sc->sc_dmamap);
174157020Sdes		if (error != 0) {
175157020Sdes			device_printf(sc->sc_dev, "DMA map create failed\n");
17699059Sdes			bus_dma_tag_destroy(sc->sc_buffer_dmat);
177157020Sdes			return (error);
178157020Sdes		}
17999059Sdes	}
180181111Sdes
181181111Sdes	csr = L64854_GCSR(sc);
182181111Sdes	sc->sc_rev = csr & L64854_DEVID;
183181111Sdes	if (sc->sc_rev == DMAREV_HME)
184181111Sdes		return (0);
185181111Sdes	device_printf(sc->sc_dev, "DMA rev. ");
186157020Sdes	switch (sc->sc_rev) {
187157020Sdes	case DMAREV_0:
18899059Sdes		printf("0");
189157020Sdes		break;
190157020Sdes	case DMAREV_ESC:
19199059Sdes		printf("ESC");
192181111Sdes		break;
193181111Sdes	case DMAREV_1:
194181111Sdes		printf("1");
195149754Sdes		break;
196149754Sdes	case DMAREV_PLUS:
197149754Sdes		printf("1+");
198181111Sdes		break;
199181111Sdes	case DMAREV_2:
200181111Sdes		printf("2");
201107553Sdes		break;
20299059Sdes	default:
20399059Sdes		printf("unknown (0x%x)", sc->sc_rev);
204113912Sdes	}
205113912Sdes
206113912Sdes	DPRINTF(LDB_ANY, (", burst 0x%x, csr 0x%x", sc->sc_burst, csr));
207157020Sdes	printf("\n");
208157020Sdes
209157020Sdes	return (0);
210107553Sdes}
21199059Sdes
21299059Sdesint
213107553Sdeslsi64854_detach(struct lsi64854_softc *sc)
21499059Sdes{
21599059Sdes
216221420Sdes	if (sc->setup != NULL) {
217221420Sdes		bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
218221420Sdes		    (L64854_GCSR(sc) & L64854_WRITE) != 0 ?
219147006Sdes		    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
220147006Sdes		bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
221147006Sdes		bus_dmamap_destroy(sc->sc_buffer_dmat, sc->sc_dmamap);
222107553Sdes		bus_dma_tag_destroy(sc->sc_buffer_dmat);
22399059Sdes	}
22499059Sdes
225107553Sdes	return (0);
22699059Sdes}
22799059Sdes
228157020Sdes/*
229157020Sdes * DMAWAIT waits while condition is true.
230157020Sdes */
231137019Sdes#define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) {		\
232194297Sjhb	int count = 500000;						\
233137019Sdes	while ((COND) && --count > 0) DELAY(1);				\
234124244Sdes	if (count == 0) {						\
235147006Sdes		printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \
236124244Sdes			(u_long)L64854_GCSR(SC));			\
237157020Sdes		if (DONTPANIC)						\
238157020Sdes			printf(MSG);					\
239157020Sdes		else							\
240162860Sdes			panic(MSG);					\
241162860Sdes	}								\
242162860Sdes} while (/* CONSTCOND */0)
243107553Sdes
24499059Sdes#define DMA_DRAIN(sc, dontpanic) do {					\
24599059Sdes	uint32_t csr;							\
246157020Sdes	/*								\
247157020Sdes	 * DMA rev0 & rev1: we are not allowed to touch the DMA "flush"	\
248157020Sdes	 *     and "drain" bits while it is still thinking about a	\
249157020Sdes	 *     request.							\
250157020Sdes	 * other revs: D_ESC_R_PEND bit reads as 0			\
251157020Sdes	 */								\
252147006Sdes	DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
253147006Sdes	if (sc->sc_rev != DMAREV_HME) {                                 \
254147006Sdes	        /*							\
255147006Sdes	         * Select drain bit based on revision			\
256162860Sdes	         * also clears errors and D_TC flag			\
257162860Sdes	         */							\
258162860Sdes	        csr = L64854_GCSR(sc);					\
259162860Sdes	        if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0)	\
260137019Sdes		        csr |= D_ESC_DRAIN;				\
261137019Sdes	        else							\
262137019Sdes		        csr |= L64854_INVALIDATE;			\
263137019Sdes									\
264147006Sdes	        L64854_SCSR(sc,csr);					\
265147006Sdes	}								\
266147006Sdes	/*								\
267147006Sdes	 * Wait for draining to finish					\
268147006Sdes	 * rev0 & rev1 call this PACKCNT				\
269147006Sdes	 */								\
270147006Sdes	DMAWAIT(sc, L64854_GCSR(sc) & L64854_DRAINING, "DRAINING", dontpanic);\
271147006Sdes} while (/* CONSTCOND */0)
272147006Sdes
273147006Sdes#define DMA_FLUSH(sc, dontpanic) do {					\
274147006Sdes	uint32_t csr;							\
275147006Sdes	/*								\
276181111Sdes	 * DMA rev0 & rev1: we are not allowed to touch the DMA "flush"	\
277181111Sdes	 *     and "drain" bits while it is still thinking about a	\
278181111Sdes	 *     request.							\
279181111Sdes	 * other revs: D_ESC_R_PEND bit reads as 0			\
280181111Sdes	 */								\
281181111Sdes	DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
282181111Sdes	csr = L64854_GCSR(sc);					\
283181111Sdes	csr &= ~(L64854_WRITE|L64854_EN_DMA); /* no-ops on ENET */	\
284162860Sdes	csr |= L64854_INVALIDATE;	 	/* XXX FAS ? */		\
285162860Sdes	L64854_SCSR(sc,csr);						\
286162860Sdes} while (/* CONSTCOND */0)
287162860Sdes
288147006Sdesstatic void
289147006Sdeslsi64854_reset(struct lsi64854_softc *sc)
290147006Sdes{
291147006Sdes	uint32_t csr;
292147006Sdes
293147006Sdes	DMA_FLUSH(sc, 1);
294147006Sdes	csr = L64854_GCSR(sc);
295147006Sdes
296162860Sdes	DPRINTF(LDB_ANY, ("%s: csr 0x%x\n", __func__, csr));
297162860Sdes
298162860Sdes	if (sc->sc_dmasize != 0) {
299162860Sdes		bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
300162860Sdes		    (csr & D_WRITE) != 0 ? BUS_DMASYNC_PREREAD :
301162860Sdes		    BUS_DMASYNC_PREWRITE);
302162860Sdes		bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
303162860Sdes	}
304149754Sdes
305149754Sdes	if (sc->sc_rev == DMAREV_HME)
306149754Sdes		L64854_SCSR(sc, csr | D_HW_RESET_FAS366);
307149754Sdes
308149754Sdes	csr |= L64854_RESET;		/* reset DMA */
309149754Sdes	L64854_SCSR(sc, csr);
310149754Sdes	DELAY(200);			/* > 10 Sbus clocks(?) */
311149754Sdes
312157020Sdes	/*DMAWAIT1(sc); why was this here? */
313247892Sdes	csr = L64854_GCSR(sc);
314157020Sdes	csr &= ~L64854_RESET;		/* de-assert reset line */
315157020Sdes	L64854_SCSR(sc, csr);
316157020Sdes	DELAY(5);			/* allow a few ticks to settle */
317157020Sdes
318137019Sdes	csr = L64854_GCSR(sc);
319137019Sdes	csr |= L64854_INT_EN;		/* enable interrupts */
320137019Sdes	if (sc->sc_rev > DMAREV_1 && sc->sc_channel == L64854_CHANNEL_SCSI) {
321137019Sdes		if (sc->sc_rev == DMAREV_HME)
322247892Sdes			csr |= D_TWO_CYCLE;
323137019Sdes		else
324107553Sdes			csr |= D_FASTER;
32599059Sdes	}
32699059Sdes
327221420Sdes	/* Set burst */
328221420Sdes	switch (sc->sc_rev) {
329221420Sdes	case DMAREV_HME:
330107553Sdes	case DMAREV_2:
33199059Sdes		csr &= ~L64854_BURST_SIZE;
33299059Sdes		if (sc->sc_burst == 32)
333107553Sdes			csr |= L64854_BURST_32;
33499319Sdes		else if (sc->sc_burst == 16)
33599059Sdes			csr |= L64854_BURST_16;
336107553Sdes		else
337202213Sed			csr |= L64854_BURST_0;
33899059Sdes		break;
339157020Sdes	case DMAREV_ESC:
340157020Sdes		csr |= D_ESC_AUTODRAIN;	/* Auto-drain */
341157020Sdes		if (sc->sc_burst == 32)
342162860Sdes			csr &= ~D_ESC_BURST;
343162860Sdes		else
344162860Sdes			csr |= D_ESC_BURST;
345157020Sdes		break;
346157020Sdes	default:
347157020Sdes		break;
348107553Sdes	}
34999059Sdes	L64854_SCSR(sc, csr);
35099059Sdes
351107553Sdes	if (sc->sc_rev == DMAREV_HME) {
35299059Sdes		bus_write_4(sc->sc_res, L64854_REG_ADDR, 0);
35399059Sdes		sc->sc_dmactl = csr;
354162860Sdes	}
355162860Sdes	sc->sc_active = 0;
356162860Sdes
357162860Sdes	DPRINTF(LDB_ANY, ("%s: done, csr 0x%x\n", __func__, csr));
358162860Sdes}
359162860Sdes
360124244Sdesstatic void
361124244Sdeslsi64854_map_scsi(void *arg, bus_dma_segment_t *segs, int nseg, int error)
362124244Sdes{
363107553Sdes	struct lsi64854_softc *sc;
36499059Sdes
36599059Sdes	sc = (struct lsi64854_softc *)arg;
366181111Sdes
367181111Sdes	if (nseg != 1)
368181111Sdes		panic("%s: cannot map %d segments\n", __func__, nseg);
369107553Sdes
37099059Sdes	bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
37199059Sdes	    sc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
372181111Sdes	bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
373181111Sdes}
374181111Sdes
375181111Sdes#define	DMAMAX(a)	(MAX_DMA_SZ - ((a) & (MAX_DMA_SZ - 1)))
376181111Sdes/*
377181111Sdes * setup a DMA transfer
378181111Sdes */
379181111Sdesstatic int
380181111Sdeslsi64854_setup(struct lsi64854_softc *sc, void **addr, size_t *len,
381107553Sdes    int datain, size_t *dmasize)
38299059Sdes{
38399059Sdes	long bcnt;
384107553Sdes	uint32_t csr;
38599059Sdes
38699059Sdes	DMA_FLUSH(sc, 0);
387107553Sdes
38899059Sdes#if 0
38999059Sdes	DMACSR(sc) &= ~D_INT_EN;
390147006Sdes#endif
391147006Sdes	sc->sc_dmaaddr = addr;
392147006Sdes	sc->sc_dmalen = len;
393147006Sdes	sc->sc_datain = datain;
394147006Sdes
395147006Sdes	/*
396107553Sdes	 * The rules say we cannot transfer more than the limit
39799059Sdes	 * of this DMA chip (64k for old and 16Mb for new),
39899059Sdes	 * and we cannot cross a 16Mb boundary.
399107553Sdes	 */
40099059Sdes	*dmasize = sc->sc_dmasize =
40199059Sdes	    ulmin(*dmasize, DMAMAX((size_t)*sc->sc_dmaaddr));
402181111Sdes
403181111Sdes	DPRINTF(LDB_ANY, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize));
404181111Sdes
405192595Sdes	/*
406192595Sdes	 * XXX what length?
407192595Sdes	 */
408107553Sdes	if (sc->sc_rev == DMAREV_HME) {
40999059Sdes		L64854_SCSR(sc, sc->sc_dmactl | L64854_RESET);
41099059Sdes		L64854_SCSR(sc, sc->sc_dmactl);
411107553Sdes
41299059Sdes		bus_write_4(sc->sc_res, L64854_REG_CNT, *dmasize);
41399059Sdes	}
414107553Sdes
41599059Sdes	/* Program the DMA address */
41699059Sdes	if (sc->sc_dmasize != 0)
417107553Sdes		if (bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
418107553Sdes		    *sc->sc_dmaaddr, sc->sc_dmasize, lsi64854_map_scsi, sc, 0))
41999059Sdes			panic("%s: cannot allocate DVMA address", __func__);
420157020Sdes
421157020Sdes	if (sc->sc_rev == DMAREV_ESC) {
422157020Sdes		/* DMA ESC chip bug work-around */
423157020Sdes		bcnt = sc->sc_dmasize;
424157020Sdes		if (((bcnt + (long)*sc->sc_dmaaddr) & PAGE_MASK_8K) != 0)
425157020Sdes			bcnt = roundup(bcnt, PAGE_SIZE_8K);
426107553Sdes		bus_write_4(sc->sc_res, L64854_REG_CNT, bcnt);
427107553Sdes	}
428107553Sdes
429181111Sdes	/* Setup DMA control register */
430181111Sdes	csr = L64854_GCSR(sc);
431181111Sdes
432107553Sdes	if (datain)
43399059Sdes		csr |= L64854_WRITE;
43499059Sdes	else
435107553Sdes		csr &= ~L64854_WRITE;
43699059Sdes	csr |= L64854_INT_EN;
43799059Sdes
438157020Sdes	if (sc->sc_rev == DMAREV_HME)
439157020Sdes		csr |= (D_DSBL_SCSI_DRN | D_EN_DMA);
440157020Sdes
441107553Sdes	L64854_SCSR(sc, csr);
442124244Sdes
44399059Sdes	return (0);
444162860Sdes}
445162860Sdes
446162860Sdes/*
447107553Sdes * Pseudo (chained) interrupt from the esp driver to kick the
44899059Sdes * current running DMA transfer. Called from ncr53c9x_intr()
44999059Sdes * for now.
450107553Sdes *
45199059Sdes * return 1 if it was a DMA continue.
45299059Sdes */
453107553Sdesstatic int
45499059Sdeslsi64854_scsi_intr(void *arg)
45599059Sdes{
456107553Sdes	struct lsi64854_softc *sc = arg;
45799059Sdes	struct ncr53c9x_softc *nsc = sc->sc_client;
45899059Sdes	int trans, resid;
459107553Sdes	uint32_t csr;
46099319Sdes
46199059Sdes	csr = L64854_GCSR(sc);
462107553Sdes
463202213Sed	DPRINTF(LDB_SCSI, ("%s: addr 0x%x, csr %b\n", __func__,
46499059Sdes	     bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, DDMACSR_BITS));
465107553Sdes
466202213Sed	if (csr & (D_ERR_PEND|D_SLAVE_ERR)) {
46799059Sdes		device_printf(sc->sc_dev, "error: csr=%b\n", csr, DDMACSR_BITS);
468107553Sdes		csr &= ~D_EN_DMA;	/* Stop DMA */
469202213Sed		/* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
47099059Sdes		csr |= D_INVALIDATE|D_SLAVE_ERR;
471207319Sdes		L64854_SCSR(sc, csr);
472207319Sdes		return (-1);
473207319Sdes	}
474162860Sdes
475162860Sdes	/* This is an "assertion" :) */
476162860Sdes	if (sc->sc_active == 0)
477107553Sdes		panic("%s: DMA wasn't active", __func__);
47899059Sdes
47999059Sdes	DMA_DRAIN(sc, 0);
480107553Sdes
48199059Sdes	/* DMA has stopped */
48299059Sdes	csr &= ~D_EN_DMA;
483204917Sdes	L64854_SCSR(sc, csr);
484204917Sdes	sc->sc_active = 0;
485204917Sdes
486126279Sdes	if (sc->sc_dmasize == 0) {
487126279Sdes		/* A "Transfer Pad" operation completed */
488126279Sdes		DPRINTF(LDB_SCSI, ("%s: discarded %d bytes (tcl=%d, tcm=%d)\n",
489126279Sdes		    __func__, NCR_READ_REG(nsc, NCR_TCL) |
490126279Sdes		    (NCR_READ_REG(nsc, NCR_TCM) << 8),
491126279Sdes		    NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM)));
492126279Sdes		return (0);
493126279Sdes	}
494126279Sdes
495126279Sdes	resid = 0;
496126279Sdes	/*
497126279Sdes	 * If a transfer onto the SCSI bus gets interrupted by the device
498124244Sdes	 * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
499147006Sdes	 * as residual since the NCR53C9X counter registers get decremented
500124244Sdes	 * as bytes are clocked into the FIFO.
501126279Sdes	 */
502126279Sdes	if (!(csr & D_WRITE) &&
503126279Sdes	    (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
504157020Sdes		DPRINTF(LDB_SCSI, ("%s: empty esp FIFO of %d ", __func__,
505157020Sdes		    resid));
506157020Sdes		if (nsc->sc_rev == NCR_VARIANT_FAS366 &&
507247892Sdes		    (NCR_READ_REG(nsc, NCR_CFG3) & NCRFASCFG3_EWIDE))
508247892Sdes			resid <<= 1;
509247892Sdes	}
510157020Sdes
511202213Sed	if ((nsc->sc_espstat & NCRSTAT_TC) == 0) {
512157020Sdes		/*
513157020Sdes		 * `Terminal count' is off, so read the residue
514202213Sed		 * out of the NCR53C9X counter registers.
515157020Sdes		 */
516149754Sdes		resid += (NCR_READ_REG(nsc, NCR_TCL) |
517149754Sdes		    (NCR_READ_REG(nsc, NCR_TCM) << 8) |
518149754Sdes		    ((nsc->sc_cfg2 & NCRCFG2_FE) ?
519107553Sdes		    (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0));
520107553Sdes
521107553Sdes		if (resid == 0 && sc->sc_dmasize == 65536 &&
522157020Sdes		    (nsc->sc_cfg2 & NCRCFG2_FE) == 0)
523157020Sdes			/* A transfer of 64K is encoded as `TCL=TCM=0' */
524157020Sdes			resid = 65536;
525157020Sdes	}
526202213Sed
527157020Sdes	trans = sc->sc_dmasize - resid;
528107553Sdes	if (trans < 0) {			/* transferred < 0? */
52999059Sdes#if 0
53099059Sdes		/*
531107553Sdes		 * This situation can happen in perfectly normal operation
53299059Sdes		 * if the ESP is reselected while using DMA to select
53399059Sdes		 * another target.  As such, don't print the warning.
534107553Sdes		 */
53599059Sdes		device_printf(sc->sc_dev, "xfer (%d) > req (%d)\n", trans,
53699059Sdes		    sc->sc_dmasize);
537107553Sdes#endif
53899059Sdes		trans = sc->sc_dmasize;
53999059Sdes	}
540157020Sdes
541157020Sdes	DPRINTF(LDB_SCSI, ("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
542157020Sdes	    __func__, NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM),
543107553Sdes	    (nsc->sc_cfg2 & NCRCFG2_FE) ? NCR_READ_REG(nsc, NCR_TCH) : 0,
544162953Sdes	    trans, resid));
54599059Sdes
546157020Sdes	if (sc->sc_dmasize != 0) {
547157020Sdes		bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
548157020Sdes		    (csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD :
549147006Sdes		    BUS_DMASYNC_POSTWRITE);
550147006Sdes		bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
551147006Sdes	}
552197679Sdes
553197679Sdes	*sc->sc_dmalen -= trans;
554197679Sdes	*sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans;
555221420Sdes
556221420Sdes#if 0	/* this is not normal operation just yet */
557221420Sdes	if (*sc->sc_dmalen == 0 || nsc->sc_phase != nsc->sc_prevphase)
558107553Sdes		return (0);
55999059Sdes
56099059Sdes	/* and again */
561247892Sdes	dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE);
562247892Sdes	return (1);
563247892Sdes#endif
564221420Sdes	return (0);
565221420Sdes}
566221420Sdes
567147006Sdes/*
568147006Sdes * Pseudo (chained) interrupt to le driver to handle DMA errors.
569147006Sdes */
570107553Sdesstatic int
571107553Sdeslsi64854_enet_intr(void *arg)
572107553Sdes{
573107553Sdes	struct lsi64854_softc *sc = arg;
57499059Sdes	uint32_t csr;
57599059Sdes	int i, rv;
576107553Sdes
57799059Sdes	csr = L64854_GCSR(sc);
57899059Sdes
579181111Sdes	/* If the DMA logic shows an interrupt, claim it */
580149754Sdes	rv = ((csr & E_INT_PEND) != 0) ? 1 : 0;
581149754Sdes
582207319Sdes	if (csr & (E_ERR_PEND|E_SLAVE_ERR)) {
583207319Sdes		device_printf(sc->sc_dev, "error: csr=%b\n", csr, EDMACSR_BITS);
584207319Sdes		csr &= ~L64854_EN_DMA;	/* Stop DMA */
585107553Sdes		/* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
58699059Sdes		csr |= E_INVALIDATE|E_SLAVE_ERR;
58799059Sdes		L64854_SCSR(sc, csr);
588107553Sdes		/* Will be drained with the LE_C0_IDON interrupt. */
58999059Sdes		sc->sc_dodrain = 1;
59099059Sdes		return (-1);
591107553Sdes	}
59299059Sdes
59399059Sdes	/* XXX - is this necessary with E_DSBL_WR_INVAL on? */
594107553Sdes	if (sc->sc_dodrain) {
59599059Sdes		i = 10;
59699059Sdes		csr |= E_DRAIN;
597107553Sdes		L64854_SCSR(sc, csr);
598107553Sdes		while (i-- > 0 && (L64854_GCSR(sc) & E_DRAINING))
599107553Sdes			DELAY(1);
600107553Sdes		sc->sc_dodrain = 0;
60199059Sdes	}
60299059Sdes
603107553Sdes	return (rv);
60499059Sdes}
60599059Sdes
606247892Sdesstatic void
607247892Sdeslsi64854_map_pp(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
608247892Sdes{
609247892Sdes	struct lsi64854_softc *sc;
610247892Sdes
611247892Sdes	sc = (struct lsi64854_softc *)arg;
612157020Sdes
613157020Sdes	if (nsegs != 1)
614157020Sdes		panic("%s: cannot map %d segments\n", __func__, nsegs);
615247892Sdes
616247892Sdes	bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, sc->sc_datain ?
617247892Sdes	    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
618247892Sdes	bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
619202213Sed
620157020Sdes	bus_write_4(sc->sc_res, L64854_REG_CNT, sc->sc_dmasize);
621107553Sdes}
62299059Sdes
62399059Sdes/*
624107553Sdes * setup a DMA transfer
62599059Sdes */
62699059Sdesstatic int
627107553Sdeslsi64854_setup_pp(struct lsi64854_softc *sc, void **addr, size_t *len,
62899059Sdes    int datain, size_t *dmasize)
62999059Sdes{
630107553Sdes	uint32_t csr;
631202213Sed
63299059Sdes	DMA_FLUSH(sc, 0);
633107553Sdes
634202213Sed	sc->sc_dmaaddr = addr;
63599059Sdes	sc->sc_dmalen = len;
636157020Sdes	sc->sc_datain = datain;
637157020Sdes
638157020Sdes	DPRINTF(LDB_PP, ("%s: pp start %ld@%p,%d\n", __func__,
639157020Sdes	    (long)*sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0));
640157020Sdes
641157020Sdes	/*
642107553Sdes	 * the rules say we cannot transfer more than the limit
64399059Sdes	 * of this DMA chip (64k for old and 16Mb for new),
64499059Sdes	 * and we cannot cross a 16Mb boundary.
645107553Sdes	 */
64699059Sdes	*dmasize = sc->sc_dmasize =
64799059Sdes	    ulmin(*dmasize, DMAMAX((size_t)*sc->sc_dmaaddr));
648157020Sdes
649157020Sdes	DPRINTF(LDB_PP, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize));
650157020Sdes
651107553Sdes	/* Program the DMA address */
65299059Sdes	if (sc->sc_dmasize != 0)
65399059Sdes		if (bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
654107553Sdes		    *sc->sc_dmaaddr, sc->sc_dmasize, lsi64854_map_pp, sc, 0))
655162953Sdes			panic("%s: pp cannot allocate DVMA address", __func__);
65699059Sdes
657107553Sdes	/* Setup DMA control register */
65899059Sdes	csr = L64854_GCSR(sc);
65999059Sdes	csr &= ~L64854_BURST_SIZE;
660107553Sdes	if (sc->sc_burst == 32)
66199059Sdes		csr |= L64854_BURST_32;
66299059Sdes	else if (sc->sc_burst == 16)
663157020Sdes		csr |= L64854_BURST_16;
664157020Sdes	else
665157020Sdes		csr |= L64854_BURST_0;
666157020Sdes	csr |= P_EN_DMA|P_INT_EN|P_EN_CNT;
667157020Sdes#if 0
668157020Sdes	/* This bit is read-only in PP csr register */
669137019Sdes	if (datain)
670137019Sdes		csr |= P_WRITE;
671137019Sdes	else
672107553Sdes		csr &= ~P_WRITE;
67399059Sdes#endif
67499059Sdes	L64854_SCSR(sc, csr);
675107553Sdes
67699059Sdes	return (0);
67799059Sdes}
678162860Sdes
679162860Sdes/*
68099059Sdes * Parallel port DMA interrupt.
681157020Sdes */
682157020Sdesstatic int
683157020Sdeslsi64854_pp_intr(void *arg)
684107553Sdes{
68599059Sdes	struct lsi64854_softc *sc = arg;
68699059Sdes	int ret, trans, resid = 0;
687113912Sdes	uint32_t csr;
688113912Sdes
689113912Sdes	csr = L64854_GCSR(sc);
690107553Sdes
69199059Sdes	DPRINTF(LDB_PP, ("%s: addr 0x%x, csr %b\n", __func__,
69299059Sdes	    bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, PDMACSR_BITS));
693157020Sdes
694157020Sdes	if (csr & (P_ERR_PEND|P_SLAVE_ERR)) {
695157020Sdes		resid = bus_read_4(sc->sc_res, L64854_REG_CNT);
696157020Sdes		device_printf(sc->sc_dev, "error: resid %d csr=%b\n", resid,
697124244Sdes		    csr, PDMACSR_BITS);
698124244Sdes		csr &= ~P_EN_DMA;	/* Stop DMA */
699124244Sdes		/* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
700107553Sdes		csr |= P_INVALIDATE|P_SLAVE_ERR;
70199059Sdes		L64854_SCSR(sc, csr);
70299059Sdes		return (-1);
703157020Sdes	}
704157020Sdes
705157020Sdes	ret = (csr & P_INT_PEND) != 0;
706157020Sdes
707157020Sdes	if (sc->sc_active != 0) {
708157020Sdes		DMA_DRAIN(sc, 0);
709107553Sdes		resid = bus_read_4(sc->sc_res, L64854_REG_CNT);
71099059Sdes	}
71199059Sdes
712126279Sdes	/* DMA has stopped */
713126279Sdes	csr &= ~D_EN_DMA;
714126279Sdes	L64854_SCSR(sc, csr);
715124244Sdes	sc->sc_active = 0;
716124244Sdes
717124244Sdes	trans = sc->sc_dmasize - resid;
718107553Sdes	if (trans < 0)				/* transferred < 0? */
71999059Sdes		trans = sc->sc_dmasize;
72099059Sdes	*sc->sc_dmalen -= trans;
721157020Sdes	*sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans;
722157020Sdes
723157020Sdes	if (sc->sc_dmasize != 0) {
724157020Sdes		bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
725157020Sdes		    (csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD :
726157020Sdes		    BUS_DMASYNC_POSTWRITE);
727181111Sdes		bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
728181111Sdes	}
729181111Sdes
730181111Sdes	return (ret != 0);
731181111Sdes}
732181111Sdes