isp_sbus.c revision 203444
1/*-
2 * Copyright (c) 1997-2006 by Matthew Jacob
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice immediately at the beginning of the file, without modification,
10 *    this list of conditions, and the following disclaimer.
11 * 2. The name of the author may not be used to endorse or promote products
12 *    derived from this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26/*
27 * SBus specific probe and attach routines for Qlogic ISP SCSI adapters.
28 * FreeBSD Version.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/isp/isp_sbus.c 203444 2010-02-03 21:09:32Z mjacob $");
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/linker.h>
37#include <sys/firmware.h>
38#include <sys/bus.h>
39#include <sys/kernel.h>
40#include <sys/module.h>
41#include <sys/resource.h>
42
43#include <dev/ofw/ofw_bus.h>
44
45#include <machine/bus.h>
46#include <machine/resource.h>
47#include <sys/rman.h>
48#include <sparc64/sbus/sbusvar.h>
49
50#include <dev/isp/isp_freebsd.h>
51
52static uint32_t isp_sbus_rd_reg(ispsoftc_t *, int);
53static void isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t);
54static int isp_sbus_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
55static int isp_sbus_mbxdma(ispsoftc_t *);
56static int isp_sbus_dmasetup(ispsoftc_t *, XS_T *, void *);
57
58
59static void isp_sbus_reset0(ispsoftc_t *);
60static void isp_sbus_reset1(ispsoftc_t *);
61static void isp_sbus_dumpregs(ispsoftc_t *, const char *);
62
63static struct ispmdvec mdvec = {
64	isp_sbus_rd_isr,
65	isp_sbus_rd_reg,
66	isp_sbus_wr_reg,
67	isp_sbus_mbxdma,
68	isp_sbus_dmasetup,
69	isp_common_dmateardown,
70	isp_sbus_reset0,
71	isp_sbus_reset1,
72	isp_sbus_dumpregs,
73	NULL,
74	BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
75};
76
77static int isp_sbus_probe (device_t);
78static int isp_sbus_attach (device_t);
79
80
81#define	ISP_SBD(isp)	((struct isp_sbussoftc *)isp)->sbus_dev
82struct isp_sbussoftc {
83	ispsoftc_t			sbus_isp;
84	device_t			sbus_dev;
85	struct resource *		sbus_reg;
86	void *				ih;
87	int16_t				sbus_poff[_NREG_BLKS];
88	sdparam				sbus_param;
89	struct isp_spi			sbus_spi;
90	struct ispmdvec			sbus_mdvec;
91	struct resource *		sbus_ires;
92};
93
94
95static device_method_t isp_sbus_methods[] = {
96	/* Device interface */
97	DEVMETHOD(device_probe,		isp_sbus_probe),
98	DEVMETHOD(device_attach,	isp_sbus_attach),
99	{ 0, 0 }
100};
101
102static driver_t isp_sbus_driver = {
103	"isp", isp_sbus_methods, sizeof (struct isp_sbussoftc)
104};
105static devclass_t isp_devclass;
106DRIVER_MODULE(isp, sbus, isp_sbus_driver, isp_devclass, 0, 0);
107
108static int
109isp_sbus_probe(device_t dev)
110{
111	int found = 0;
112	const char *name = ofw_bus_get_name(dev);
113	if (strcmp(name, "SUNW,isp") == 0 ||
114	    strcmp(name, "QLGC,isp") == 0 ||
115	    strcmp(name, "ptisp") == 0 ||
116	    strcmp(name, "PTI,ptisp") == 0) {
117		found++;
118	}
119	if (!found)
120		return (ENXIO);
121
122	if (isp_announced == 0 && bootverbose) {
123		printf("Qlogic ISP Driver, FreeBSD Version %d.%d, "
124		    "Core Version %d.%d\n",
125		    ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
126		    ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
127		isp_announced++;
128	}
129	return (0);
130}
131
132static int
133isp_sbus_attach(device_t dev)
134{
135	struct resource *regs;
136	int tval, iqd, isp_debug, role, rid, ispburst, default_id;
137	struct isp_sbussoftc *sbs;
138	ispsoftc_t *isp = NULL;
139	int locksetup = 0;
140	int ints_setup = 0;
141
142	/*
143	 * Figure out if we're supposed to skip this one.
144	 * If we are, we actually go to ISP_ROLE_NONE.
145	 */
146
147	tval = 0;
148	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
149	    "disable", &tval) == 0 && tval) {
150		device_printf(dev, "device is disabled\n");
151		/* but return 0 so the !$)$)*!$*) unit isn't reused */
152		return (0);
153	}
154
155	role = 0;
156	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
157	    "role", &role) == 0 &&
158	    ((role & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) == 0)) {
159		device_printf(dev, "setting role to 0x%x\n", role);
160	} else {
161		role = ISP_DEFAULT_ROLES;
162	}
163
164	sbs = malloc(sizeof (*sbs), M_DEVBUF, M_NOWAIT | M_ZERO);
165	if (sbs == NULL) {
166		device_printf(dev, "cannot allocate softc\n");
167		return (ENOMEM);
168	}
169
170	regs = NULL;
171	iqd = 0;
172	rid = 0;
173	regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
174	if (regs == 0) {
175		device_printf(dev, "unable to map registers\n");
176		goto bad;
177	}
178	sbs->sbus_dev = dev;
179	sbs->sbus_reg = regs;
180	sbs->sbus_mdvec = mdvec;
181
182	sbs->sbus_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
183	sbs->sbus_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = SBUS_MBOX_REGS_OFF;
184	sbs->sbus_poff[SXP_BLOCK >> _BLK_REG_SHFT] = SBUS_SXP_REGS_OFF;
185	sbs->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF;
186	sbs->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
187	isp = &sbs->sbus_isp;
188	isp->isp_bus_tag = rman_get_bustag(regs);
189	isp->isp_bus_handle = rman_get_bushandle(regs);
190	isp->isp_mdvec = &sbs->sbus_mdvec;
191	isp->isp_bustype = ISP_BT_SBUS;
192	isp->isp_type = ISP_HA_SCSI_UNKNOWN;
193	isp->isp_param = &sbs->sbus_param;
194	isp->isp_osinfo.pc.ptr = &sbs->sbus_spi;
195	isp->isp_revision = 0;	/* XXX */
196	isp->isp_dev = dev;
197	isp->isp_nchan = 1;
198	ISP_SET_PC(isp, 0, role, role);
199
200	/*
201	 * Get the clock frequency and convert it from HZ to MHz,
202	 * rounding up. This defaults to 25MHz if there isn't a
203	 * device specific one in the OFW device tree.
204	 */
205	sbs->sbus_mdvec.dv_clock = (sbus_get_clockfreq(dev) + 500000)/1000000;
206
207	/*
208	 * Now figure out what the proper burst sizes, etc., to use.
209	 * Unfortunately, there is no ddi_dma_burstsizes here which
210	 * walks up the tree finding the limiting burst size node (if
211	 * any). We just use what's here for isp.
212	 */
213	ispburst = sbus_get_burstsz(dev);
214	if (ispburst == 0) {
215		ispburst = SBUS_BURST_32 - 1;
216	}
217	sbs->sbus_mdvec.dv_conf1 =  0;
218	if (ispburst & (1 << 5)) {
219		sbs->sbus_mdvec.dv_conf1 = BIU_SBUS_CONF1_FIFO_32;
220	} else if (ispburst & (1 << 4)) {
221		sbs->sbus_mdvec.dv_conf1 = BIU_SBUS_CONF1_FIFO_16;
222	} else if (ispburst & (1 << 3)) {
223		sbs->sbus_mdvec.dv_conf1 =
224		    BIU_SBUS_CONF1_BURST8 | BIU_SBUS_CONF1_FIFO_8;
225	}
226	if (sbs->sbus_mdvec.dv_conf1) {
227		sbs->sbus_mdvec.dv_conf1 |= BIU_BURST_ENABLE;
228	}
229
230	/*
231	 * We don't trust NVRAM on SBus cards
232	 */
233	isp->isp_confopts |= ISP_CFG_NONVRAM;
234
235	/*
236	 * Mark things if we're a PTI SBus adapter.
237	 */
238	if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 ||
239	    strcmp("ptisp", ofw_bus_get_name(dev)) == 0) {
240		SDPARAM(isp, 0)->isp_ptisp = 1;
241	}
242
243
244	isp->isp_osinfo.fw = firmware_get("isp_1000");
245	if (isp->isp_osinfo.fw) {
246		union {
247			const void *cp;
248			uint16_t *sp;
249		} stupid;
250		stupid.cp = isp->isp_osinfo.fw->data;
251		isp->isp_mdvec->dv_ispfw = stupid.sp;
252	}
253
254	tval = 0;
255        if (resource_int_value(device_get_name(dev), device_get_unit(dev),
256            "fwload_disable", &tval) == 0 && tval != 0) {
257		isp->isp_confopts |= ISP_CFG_NORELOAD;
258	}
259
260	default_id = -1;
261	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
262            "iid", &tval) == 0) {
263		default_id = tval;
264		isp->isp_confopts |= ISP_CFG_OWNLOOPID;
265	}
266	if (default_id == -1) {
267		/*
268		 * XXX: should be a way to get properties w/o having
269		 * XXX: to call OF_xxx functions
270		 */
271		default_id = 7;
272	}
273	ISP_SPI_PC(isp, 0)->iid = default_id;
274
275	isp_debug = 0;
276        (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
277            "debug", &isp_debug);
278
279	/* Make sure the lock is set up. */
280	mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
281	locksetup++;
282
283	iqd = 0;
284	sbs->sbus_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
285	    RF_ACTIVE | RF_SHAREABLE);
286	if (sbs->sbus_ires == NULL) {
287		device_printf(dev, "could not allocate interrupt\n");
288		goto bad;
289	}
290
291	if (isp_setup_intr(dev, sbs->sbus_ires, ISP_IFLAGS, NULL,
292	    isp_platform_intr, isp, &sbs->ih)) {
293		device_printf(dev, "could not setup interrupt\n");
294		goto bad;
295	}
296	ints_setup++;
297
298	/*
299	 * Set up logging levels.
300	 */
301	if (isp_debug) {
302		isp->isp_dblev = isp_debug;
303	} else {
304		isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
305	}
306	if (bootverbose) {
307		isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
308	}
309
310	/*
311	 * Make sure we're in reset state.
312	 */
313	ISP_LOCK(isp);
314	isp_reset(isp, 1);
315	if (isp->isp_state != ISP_RESETSTATE) {
316		isp_uninit(isp);
317		ISP_UNLOCK(isp);
318		goto bad;
319	}
320	isp_init(isp);
321	if (isp->isp_state == ISP_INITSTATE) {
322		isp->isp_state = ISP_RUNSTATE;
323	}
324	ISP_UNLOCK(isp);
325	if (isp_attach(isp)) {
326		ISP_LOCK(isp);
327		isp_uninit(isp);
328		ISP_UNLOCK(isp);
329		goto bad;
330	}
331	return (0);
332
333bad:
334
335	if (sbs && ints_setup) {
336		(void) bus_teardown_intr(dev, sbs->sbus_ires, sbs->ih);
337	}
338
339	if (sbs && sbs->sbus_ires) {
340		bus_release_resource(dev, SYS_RES_IRQ, iqd, sbs->sbus_ires);
341	}
342
343	if (locksetup && isp) {
344		mtx_destroy(&isp->isp_osinfo.lock);
345	}
346
347	if (regs) {
348		(void) bus_release_resource(dev, SYS_RES_MEMORY, 0, regs);
349	}
350
351	if (sbs) {
352		free(sbs, M_DEVBUF);
353	}
354	return (ENXIO);
355}
356
357#define	IspVirt2Off(a, x)	\
358	(((struct isp_sbussoftc *)a)->sbus_poff[((x) & _BLK_REG_MASK) >> \
359	_BLK_REG_SHFT] + ((x) & 0xff))
360
361#define	BXR2(sbc, off)		\
362	bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, off)
363
364static int
365isp_sbus_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp)
366{
367	uint16_t isr, sema;
368
369	isr = BXR2(sbc, IspVirt2Off(isp, BIU_ISR));
370	sema = BXR2(sbc, IspVirt2Off(isp, BIU_SEMA));
371	isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema);
372	isr &= INT_PENDING_MASK(isp);
373	sema &= BIU_SEMA_LOCK;
374	if (isr == 0 && sema == 0) {
375		return (0);
376	}
377	*isrp = isr;
378	if ((*semap = sema) != 0) {
379		*mbp = BXR2(sbc, IspVirt2Off(isp, OUTMAILBOX0));
380	}
381	return (1);
382}
383
384static uint32_t
385isp_sbus_rd_reg(ispsoftc_t *isp, int regoff)
386{
387	uint16_t rval;
388	struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp;
389	int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
390	offset += (regoff & 0xff);
391	rval = bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, offset);
392	isp_prt(isp, ISP_LOGDEBUG3,
393	    "isp_sbus_rd_reg(off %x) = %x", regoff, rval);
394	return (rval);
395}
396
397static void
398isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val)
399{
400	struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp;
401	int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
402	offset += (regoff & 0xff);
403	isp_prt(isp, ISP_LOGDEBUG3,
404	    "isp_sbus_wr_reg(off %x) = %x", regoff, val);
405	bus_space_write_2(isp->isp_bus_tag, isp->isp_bus_handle, offset, val);
406	MEMORYBARRIER(isp, SYNC_REG, offset, 2);
407}
408
409struct imush {
410	ispsoftc_t *isp;
411	int error;
412};
413
414static void imc(void *, bus_dma_segment_t *, int, int);
415
416static void
417imc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
418{
419	struct imush *imushp = (struct imush *) arg;
420	if (error) {
421		imushp->error = error;
422	} else {
423		ispsoftc_t *isp =imushp->isp;
424		bus_addr_t addr = segs->ds_addr;
425
426		isp->isp_rquest_dma = addr;
427		addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
428		isp->isp_result_dma = addr;
429	}
430}
431
432static int
433isp_sbus_mbxdma(ispsoftc_t *isp)
434{
435	caddr_t base;
436	uint32_t len;
437	int i, error, ns;
438	struct imush im;
439
440	/*
441	 * Already been here? If so, leave...
442	 */
443	if (isp->isp_rquest) {
444		return (0);
445	}
446
447	ISP_UNLOCK(isp);
448
449	len = sizeof (struct isp_pcmd) * isp->isp_maxcmds;
450	isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *)
451	    malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
452	if (isp->isp_osinfo.pcmd_pool == NULL) {
453		isp_prt(isp, ISP_LOGERR, "cannot alloc pcmd pool");
454		ISP_LOCK(isp);
455		return (1);
456	}
457
458	len = sizeof (isp_hdl_t *) * isp->isp_maxcmds;
459	isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
460	if (isp->isp_xflist == NULL) {
461		isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
462		ISP_LOCK(isp);
463		return (1);
464	}
465	for (len = 0; len < isp->isp_maxcmds - 1; len++) {
466		isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1];
467	}
468	isp->isp_xffree = isp->isp_xflist;
469	len = sizeof (bus_dmamap_t) * isp->isp_maxcmds;
470
471	if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_SBD(isp)), 1,
472	    BUS_SPACE_MAXADDR_24BIT+1, BUS_SPACE_MAXADDR_32BIT,
473	    BUS_SPACE_MAXADDR_32BIT, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT,
474	    ISP_NSEGS, BUS_SPACE_MAXADDR_24BIT, 0, &isp->isp_osinfo.dmat)) {
475		isp_prt(isp, ISP_LOGERR, "could not create master dma tag");
476		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
477		free(isp->isp_xflist, M_DEVBUF);
478		ISP_LOCK(isp);
479		return(1);
480	}
481
482	/*
483	 * Allocate and map the request, result queues, plus FC scratch area.
484	 */
485	len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
486	len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
487
488	ns = (len / PAGE_SIZE) + 1;
489	if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN,
490	    BUS_SPACE_MAXADDR_24BIT+1, BUS_SPACE_MAXADDR_32BIT,
491	    BUS_SPACE_MAXADDR_32BIT, NULL, NULL, len, ns,
492	    BUS_SPACE_MAXADDR_24BIT, 0, &isp->isp_osinfo.cdmat)) {
493		isp_prt(isp, ISP_LOGERR,
494		    "cannot create a dma tag for control spaces");
495		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
496		free(isp->isp_xflist, M_DEVBUF);
497		ISP_LOCK(isp);
498		return (1);
499	}
500
501	if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT,
502	    &isp->isp_osinfo.cdmap) != 0) {
503		isp_prt(isp, ISP_LOGERR,
504		    "cannot allocate %d bytes of CCB memory", len);
505		bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
506		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
507		free(isp->isp_xflist, M_DEVBUF);
508		ISP_LOCK(isp);
509		return (1);
510	}
511
512	for (i = 0; i < isp->isp_maxcmds; i++) {
513		struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i];
514		error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap);
515		if (error) {
516			isp_prt(isp, ISP_LOGERR,
517			    "error %d creating per-cmd DMA maps", error);
518			while (--i >= 0) {
519				bus_dmamap_destroy(isp->isp_osinfo.dmat,
520				    isp->isp_osinfo.pcmd_pool[i].dmap);
521			}
522			goto bad;
523		}
524		callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0);
525		if (i == isp->isp_maxcmds-1) {
526			pcmd->next = NULL;
527		} else {
528			pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1];
529		}
530	}
531	isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0];
532
533	im.isp = isp;
534	im.error = 0;
535	bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0);
536	if (im.error) {
537		isp_prt(isp, ISP_LOGERR,
538		    "error %d loading dma map for control areas", im.error);
539		goto bad;
540	}
541
542	isp->isp_rquest = base;
543	base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
544	isp->isp_result = base;
545	ISP_LOCK(isp);
546	return (0);
547
548bad:
549	bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap);
550	bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
551	free(isp->isp_xflist, M_DEVBUF);
552	free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
553	isp->isp_rquest = NULL;
554	ISP_LOCK(isp);
555	return (1);
556}
557
558typedef struct {
559	ispsoftc_t *isp;
560	void *cmd_token;
561	void *rq;	/* original request */
562	int error;
563	bus_size_t mapsize;
564} mush_t;
565
566#define	MUSHERR_NOQENTRIES	-2
567
568static void dma2(void *, bus_dma_segment_t *, int, int);
569
570static void
571dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
572{
573	mush_t *mp;
574	ispsoftc_t *isp;
575	struct ccb_scsiio *csio;
576	isp_ddir_t ddir;
577	ispreq_t *rq;
578
579	mp = (mush_t *) arg;
580	if (error) {
581		mp->error = error;
582		return;
583	}
584	csio = mp->cmd_token;
585	isp = mp->isp;
586	rq = mp->rq;
587	if (nseg) {
588		if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
589			bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
590			ddir = ISP_FROM_DEVICE;
591		} else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
592			bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
593			ddir = ISP_TO_DEVICE;
594		} else {
595			ddir = ISP_NOXFR;
596		}
597	} else {
598		dm_segs = NULL;
599		nseg = 0;
600		ddir = ISP_NOXFR;
601	}
602
603	if (isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir) != CMD_QUEUED) {
604		mp->error = MUSHERR_NOQENTRIES;
605	}
606}
607
608static int
609isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff)
610{
611	mush_t mush, *mp;
612	void (*eptr)(void *, bus_dma_segment_t *, int, int);
613
614	mp = &mush;
615	mp->isp = isp;
616	mp->cmd_token = csio;
617	mp->rq = ff;
618	mp->error = 0;
619	mp->mapsize = 0;
620
621	eptr = dma2;
622
623	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || (csio->dxfer_len == 0)) {
624		(*eptr)(mp, NULL, 0, 0);
625	} else if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
626		if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) {
627			int error;
628			error = bus_dmamap_load(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, csio->data_ptr, csio->dxfer_len, eptr, mp, 0);
629#if 0
630			xpt_print(csio->ccb_h.path, "%s: bus_dmamap_load " "ptr %p len %d returned %d\n", __func__, csio->data_ptr, csio->dxfer_len, error);
631#endif
632
633			if (error == EINPROGRESS) {
634				bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap);
635				mp->error = EINVAL;
636				isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported");
637			} else if (error && mp->error == 0) {
638#ifdef	DIAGNOSTIC
639				isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error);
640#endif
641				mp->error = error;
642			}
643		} else {
644			/* Pointer to physical buffer */
645			struct bus_dma_segment seg;
646			seg.ds_addr = (bus_addr_t)(vm_offset_t)csio->data_ptr;
647			seg.ds_len = csio->dxfer_len;
648			(*eptr)(mp, &seg, 1, 0);
649		}
650	} else {
651		struct bus_dma_segment *segs;
652
653		if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) {
654			isp_prt(isp, ISP_LOGERR, "Physical segment pointers unsupported");
655			mp->error = EINVAL;
656		} else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) {
657			isp_prt(isp, ISP_LOGERR, "Physical SG/LIST Phys segment pointers unsupported");
658			mp->error = EINVAL;
659		} else {
660			/* Just use the segments provided */
661			segs = (struct bus_dma_segment *) csio->data_ptr;
662			(*eptr)(mp, segs, csio->sglist_cnt, 0);
663		}
664	}
665	if (mp->error) {
666		int retval = CMD_COMPLETE;
667		if (mp->error == MUSHERR_NOQENTRIES) {
668			retval = CMD_EAGAIN;
669		} else if (mp->error == EFBIG) {
670			XS_SETERR(csio, CAM_REQ_TOO_BIG);
671		} else if (mp->error == EINVAL) {
672			XS_SETERR(csio, CAM_REQ_INVALID);
673		} else {
674			XS_SETERR(csio, CAM_UNREC_HBA_ERROR);
675		}
676		return (retval);
677	}
678	return (CMD_QUEUED);
679}
680
681static void
682isp_sbus_reset0(ispsoftc_t *isp)
683{
684	ISP_DISABLE_INTS(isp);
685}
686
687static void
688isp_sbus_reset1(ispsoftc_t *isp)
689{
690	ISP_ENABLE_INTS(isp);
691}
692
693static void
694isp_sbus_dumpregs(ispsoftc_t *isp, const char *msg)
695{
696	if (msg)
697		printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg);
698	else
699		printf("%s:\n", device_get_nameunit(isp->isp_dev));
700	printf("    biu_conf1=%x", ISP_READ(isp, BIU_CONF1));
701	printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR),
702	    ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA));
703	printf("risc_hccr=%x\n", ISP_READ(isp, HCCR));
704
705
706	ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
707	printf("    cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n",
708		ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS),
709		ISP_READ(isp, CDMA_FIFO_STS));
710	printf("    ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n",
711		ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS),
712		ISP_READ(isp, DDMA_FIFO_STS));
713	printf("    sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n",
714		ISP_READ(isp, SXP_INTERRUPT),
715		ISP_READ(isp, SXP_GROSS_ERR),
716		ISP_READ(isp, SXP_PINS_CTRL));
717	ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
718	printf("    mbox regs: %x %x %x %x %x\n",
719	    ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1),
720	    ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3),
721	    ISP_READ(isp, OUTMAILBOX4));
722}
723