siop.c revision 1.30
1/*	$NetBSD: siop.c,v 1.30 2000/10/06 20:07:10 bouyer Exp $	*/
2
3/*
4 * Copyright (c) 2000 Manuel Bouyer.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by Manuel Bouyer
17 * 4. The name of the author may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33/* SYM53c7/8xx PCI-SCSI I/O Processors driver */
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/device.h>
38#include <sys/malloc.h>
39#include <sys/buf.h>
40#include <sys/kernel.h>
41
42#include <machine/endian.h>
43#include <machine/bus.h>
44
45#include <dev/microcode/siop/siop.out>
46
47#include <dev/scsipi/scsi_all.h>
48#include <dev/scsipi/scsi_message.h>
49#include <dev/scsipi/scsipi_all.h>
50
51#include <dev/scsipi/scsiconf.h>
52
53#include <dev/ic/siopreg.h>
54#include <dev/ic/siopvar.h>
55#include <dev/ic/siopvar_common.h>
56
57#undef DEBUG
58#undef DEBUG_DR
59#undef DEBUG_INTR
60#undef DEBUG_SHED
61#undef DUMP_SCRIPT
62
63#define SIOP_STATS
64
65#ifndef SIOP_DEFAULT_TARGET
66#define SIOP_DEFAULT_TARGET 7
67#endif
68
69/* number of cmd descriptors per block */
70#define SIOP_NCMDPB (NBPG / sizeof(struct siop_xfer))
71
72void	siop_reset __P((struct siop_softc *));
73void	siop_handle_reset __P((struct siop_softc *));
74void	siop_scsicmd_end __P((struct siop_cmd *));
75void	siop_start __P((struct siop_softc *));
76void 	siop_timeout __P((void *));
77int	siop_scsicmd __P((struct scsipi_xfer *));
78void	siop_dump_script __P((struct siop_softc *));
79int	siop_morecbd __P((struct siop_softc *));
80
81struct scsipi_adapter siop_adapter = {
82	0,
83	siop_scsicmd,
84	siop_minphys,
85	siop_ioctl,
86	NULL,
87	NULL,
88};
89
90struct scsipi_device siop_dev = {
91	NULL,
92	NULL,
93	NULL,
94	NULL,
95};
96
97#ifdef SIOP_STATS
98static int siop_stat_intr = 0;
99static int siop_stat_intr_shortxfer = 0;
100static int siop_stat_intr_sdp = 0;
101static int siop_stat_intr_done = 0;
102static int siop_stat_intr_reselect = 0;
103static int siop_stat_intr_xferdisc = 0;
104void siop_printstats __P((void));
105#define INCSTAT(x) x++
106#else
107#define INCSTAT(x)
108#endif
109
110static __inline__ void siop_table_sync __P((struct siop_cmd *, int));
111static __inline__ void
112siop_table_sync(siop_cmd, ops)
113	struct siop_cmd *siop_cmd;
114	int ops;
115{
116	struct siop_softc *sc  = siop_cmd->siop_target->siop_sc;
117	bus_addr_t offset;
118
119	offset = siop_cmd->dsa -
120	    siop_cmd->siop_cbdp->xferdma->dm_segs[0].ds_addr;
121	bus_dmamap_sync(sc->sc_dmat, siop_cmd->siop_cbdp->xferdma, offset,
122	    sizeof(struct siop_xfer), ops);
123}
124
125static __inline__ void siop_sched_sync __P((struct siop_softc *, int));
126static __inline__ void
127siop_sched_sync(sc, ops)
128	struct siop_softc *sc;
129	int ops;
130{
131	bus_dmamap_sync(sc->sc_dmat, sc->sc_scheddma, 0, 2*NBPG, ops);
132}
133
134static __inline__ void siop_resel_sync __P((struct siop_softc *, int));
135static __inline__ void
136siop_resel_sync(sc, ops)
137	struct siop_softc *sc;
138	int ops;
139{
140	bus_dmamap_sync(sc->sc_dmat, sc->sc_scheddma, NBPG, NBPG, ops);
141}
142
143void
144siop_attach(sc)
145	struct siop_softc *sc;
146{
147	int error, i;
148	bus_dma_segment_t seg;
149	int rseg;
150
151	/*
152	 * Allocate DMA-safe memory for the script and script scheduler
153	 * and map it.
154	 */
155	if ((sc->features & SF_CHIP_RAM) == 0) {
156		error = bus_dmamem_alloc(sc->sc_dmat, NBPG,
157		    NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT);
158		if (error) {
159			printf("%s: unable to allocate script DMA memory, "
160			    "error = %d\n", sc->sc_dev.dv_xname, error);
161			return;
162		}
163		error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, NBPG,
164		    (caddr_t *)&sc->sc_script, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
165		if (error) {
166			printf("%s: unable to map script DMA memory, "
167			    "error = %d\n", sc->sc_dev.dv_xname, error);
168			return;
169		}
170		error = bus_dmamap_create(sc->sc_dmat, NBPG, 1,
171		    NBPG, 0, BUS_DMA_NOWAIT, &sc->sc_scriptdma);
172		if (error) {
173			printf("%s: unable to create script DMA map, "
174			    "error = %d\n", sc->sc_dev.dv_xname, error);
175			return;
176		}
177		error = bus_dmamap_load(sc->sc_dmat, sc->sc_scriptdma,
178		    sc->sc_script,
179		    NBPG, NULL, BUS_DMA_NOWAIT);
180		if (error) {
181			printf("%s: unable to load script DMA map, "
182			    "error = %d\n", sc->sc_dev.dv_xname, error);
183			return;
184		}
185		sc->sc_scriptaddr = sc->sc_scriptdma->dm_segs[0].ds_addr;
186	}
187	error = bus_dmamem_alloc(sc->sc_dmat, 2 * NBPG,
188	    2 * NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT);
189	if (error) {
190		printf("%s: unable to allocate scheduler DMA memory, "
191		    "error = %d\n", sc->sc_dev.dv_xname, error);
192		return;
193	}
194	error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, 2 * NBPG,
195	    (caddr_t *)&sc->sc_sched, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
196	if (error) {
197		printf("%s: unable to map scheduler DMA memory, error = %d\n",
198		    sc->sc_dev.dv_xname, error);
199		return;
200	}
201	error = bus_dmamap_create(sc->sc_dmat, 2 * NBPG, 1,
202	    2 * NBPG, 0, BUS_DMA_NOWAIT, &sc->sc_scheddma);
203	if (error) {
204		printf("%s: unable to create scheduler DMA map, error = %d\n",
205		    sc->sc_dev.dv_xname, error);
206		return;
207	}
208	error = bus_dmamap_load(sc->sc_dmat, sc->sc_scheddma, sc->sc_sched,
209	    2 * NBPG, NULL, BUS_DMA_NOWAIT);
210	if (error) {
211		printf("%s: unable to load scheduler DMA map, error = %d\n",
212		    sc->sc_dev.dv_xname, error);
213		return;
214	}
215	sc->sc_resel = &sc->sc_sched[NBPG / sizeof(int32_t)];
216	TAILQ_INIT(&sc->free_list);
217	TAILQ_INIT(&sc->cmds);
218	/* compute number of scheduler slots */
219	sc->sc_nschedslots = (
220	    NBPG /* memory size allocated for scheduler */
221	    - sizeof(endslot_script) /* memory needed at end of scheduler */
222	    ) / (sizeof(slot_script) - 8);
223	sc->sc_currschedslot = 0;
224	/* compute number of reselect slots */
225	sc->sc_nreselslots = (
226	    NBPG /* memory size allocated for reselect script */
227	    - sizeof(reselected_end_script) /* memory needed at end */
228	    ) / (sizeof(reselected_script) - 16);
229#ifdef DEBUG
230	printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p nslots %d "
231	    "nresel %d\n",
232	    sc->sc_dev.dv_xname, (int)sizeof(siop_script),
233	    (u_int32_t)sc->sc_scriptaddr, sc->sc_script, sc->sc_nschedslots,
234	    sc->sc_nreselslots);
235#endif
236
237	sc->sc_link.adapter_softc = sc;
238	sc->sc_link.openings = 1;
239	sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
240	sc->sc_link.scsipi_scsi.max_target  =
241	    (sc->features & SF_BUS_WIDE) ? 15 : 7;
242	sc->sc_link.scsipi_scsi.max_lun = 7;
243	sc->sc_link.scsipi_scsi.adapter_target = bus_space_read_1(sc->sc_rt,
244	    sc->sc_rh, SIOP_SCID);
245	if (sc->sc_link.scsipi_scsi.adapter_target == 0 ||
246	    sc->sc_link.scsipi_scsi.adapter_target >
247	    sc->sc_link.scsipi_scsi.max_target)
248		sc->sc_link.scsipi_scsi.adapter_target = SIOP_DEFAULT_TARGET;
249	sc->sc_link.type = BUS_SCSI;
250	sc->sc_link.adapter = &siop_adapter;
251	sc->sc_link.device = &siop_dev;
252	sc->sc_link.flags  = 0;
253
254	for (i = 0; i < 16; i++)
255		sc->targets[i] = NULL;
256
257	/* find min/max sync period for this chip */
258	sc->maxsync = 0;
259	sc->minsync = 255;
260	for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); i++) {
261		if (sc->clock_period != scf_period[i].clock)
262			continue;
263		if (sc->maxsync < scf_period[i].period)
264			sc->maxsync = scf_period[i].period;
265		if (sc->minsync > scf_period[i].period)
266			sc->minsync = scf_period[i].period;
267	}
268	if (sc->maxsync == 255 || sc->minsync == 0)
269		panic("siop: can't find my sync parameters\n");
270	/* Do a bus reset, so that devices fall back to narrow/async */
271	siop_resetbus(sc);
272	/*
273	 * siop_reset() will reset the chip, thus clearing pending interrupts
274	 */
275	siop_reset(sc);
276#ifdef DUMP_SCRIPT
277	siop_dump_script(sc);
278#endif
279
280	config_found((struct device*)sc, &sc->sc_link, scsiprint);
281}
282
283void
284siop_reset(sc)
285	struct siop_softc *sc;
286{
287	int i, j;
288	u_int32_t *scr;
289	bus_addr_t physaddr;
290
291	siop_common_reset(sc);
292
293	/* copy and patch the script */
294	if (sc->features & SF_CHIP_RAM) {
295		bus_space_write_region_4(sc->sc_ramt, sc->sc_ramh, 0,
296		    siop_script, sizeof(siop_script) / sizeof(siop_script[0]));
297		for (j = 0; j <
298		    (sizeof(E_script_abs_sched_Used) /
299		    sizeof(E_script_abs_sched_Used[0]));
300		    j++) {
301			bus_space_write_4(sc->sc_ramt, sc->sc_ramh,
302			    E_script_abs_sched_Used[j] * 4,
303			    sc->sc_scheddma->dm_segs[0].ds_addr);
304		}
305		for (j = 0; j <
306		    (sizeof(E_abs_find_dsa_Used) /
307		    sizeof(E_abs_find_dsa_Used[0]));
308		    j++) {
309			bus_space_write_4(sc->sc_ramt, sc->sc_ramh,
310			    E_abs_find_dsa_Used[j] * 4,
311			    sc->sc_scheddma->dm_segs[0].ds_addr + NBPG);
312		}
313	} else {
314		for (j = 0;
315		    j < (sizeof(siop_script) / sizeof(siop_script[0])); j++) {
316			sc->sc_script[j] = htole32(siop_script[j]);
317		}
318		for (j = 0; j <
319		    (sizeof(E_script_abs_sched_Used) /
320		    sizeof(E_script_abs_sched_Used[0]));
321		    j++) {
322			sc->sc_script[E_script_abs_sched_Used[j]] =
323			    htole32(sc->sc_scheddma->dm_segs[0].ds_addr);
324		}
325		for (j = 0; j <
326		    (sizeof(E_abs_find_dsa_Used) /
327		    sizeof(E_abs_find_dsa_Used[0]));
328		    j++) {
329			sc->sc_script[E_abs_find_dsa_Used[j]] =
330			    htole32(sc->sc_scheddma->dm_segs[0].ds_addr + NBPG);
331		}
332	}
333	/* copy and init the scheduler slots script */
334	for (i = 0; i < sc->sc_nschedslots; i++) {
335		scr = &sc->sc_sched[(Ent_nextslot / 4) * i];
336		physaddr = sc->sc_scheddma->dm_segs[0].ds_addr +
337		    Ent_nextslot * i;
338		for (j = 0; j < (sizeof(slot_script) / sizeof(slot_script[0]));
339		    j++) {
340			scr[j] = htole32(slot_script[j]);
341		}
342		/*
343		 * save current jump offset and patch MOVE MEMORY operands
344		 * to restore it.
345		 */
346		scr[Ent_slotdata/4 + 1] = scr[Ent_slot/4 + 1];
347		scr[E_slot_nextp_Used[0]] = htole32(physaddr + Ent_slot + 4);
348		scr[E_slot_sched_addrsrc_Used[0]] = htole32(physaddr +
349		    Ent_slotdata + 4);
350		/* JUMP selected, in main script */
351		scr[E_slot_abs_selected_Used[0]] =
352		   htole32(sc->sc_scriptaddr + Ent_selected);
353		/* JUMP addr if SELECT fail */
354		scr[E_slot_abs_reselect_Used[0]] =
355		   htole32(sc->sc_scriptaddr + Ent_reselect);
356	}
357	/* Now the final JUMP */
358	scr = &sc->sc_sched[(Ent_nextslot / 4) * sc->sc_nschedslots];
359	for (j = 0; j < (sizeof(endslot_script) / sizeof(endslot_script[0]));
360	    j++) {
361		scr[j] = htole32(endslot_script[j]);
362	}
363	scr[E_endslot_abs_reselect_Used[0]] =
364	    htole32(sc->sc_scriptaddr + Ent_reselect);
365
366	/* The reselect script */
367	for (i = 0; i < sc->sc_nreselslots; i++) {
368		scr = &sc->sc_resel[(Ent_res_nextld / 4) * i];
369		for (j = 0; j <
370		    (sizeof(reselected_script) / sizeof(reselected_script[0]));
371		    j++) {
372			scr[j] = htole32(reselected_script[j]);
373		}
374		scr[E_resel_abs_selected_Used[0]] =
375		    htole32(sc->sc_scriptaddr + Ent_selected);
376	}
377	/* The final int */
378	scr = &sc->sc_resel[(Ent_res_nextld / 4) * sc->sc_nreselslots];
379	for (j = 0; j <
380	    (sizeof(reselected_end_script) / sizeof(reselected_end_script[0]));
381	    j++) {
382		scr[j] = htole32(reselected_end_script[j]);
383	}
384
385	/* start script */
386	if ((sc->features & SF_CHIP_RAM) == 0) {
387		bus_dmamap_sync(sc->sc_dmat, sc->sc_scriptdma, 0, NBPG,
388		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
389	}
390	siop_sched_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
391	bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
392	    sc->sc_scriptaddr + Ent_reselect);
393}
394
395#if 0
396#define CALL_SCRIPT(ent) do {\
397	printf ("start script DSA 0x%lx DSP 0x%lx\n", \
398	    siop_cmd->dsa, \
399	    sc->sc_scriptaddr + ent); \
400bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, sc->sc_scriptaddr + ent); \
401} while (0)
402#else
403#define CALL_SCRIPT(ent) do {\
404bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, sc->sc_scriptaddr + ent); \
405} while (0)
406#endif
407
408int
409siop_intr(v)
410	void *v;
411{
412	struct siop_softc *sc = v;
413	struct siop_target *siop_target;
414	struct siop_cmd *siop_cmd;
415	struct scsipi_xfer *xs;
416	int istat, sist0, sist1, sstat1, dstat;
417	u_int32_t irqcode;
418	int need_reset = 0;
419	int offset, target, lun;
420	bus_addr_t dsa;
421	struct siop_cbd *cbdp;
422
423	istat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT);
424	if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
425		return 0;
426	INCSTAT(siop_stat_intr);
427	if (istat & ISTAT_INTF) {
428		printf("INTRF\n");
429		bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_INTF);
430	}
431	/* use DSA to find the current siop_cmd */
432	dsa = bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA);
433	for (cbdp = TAILQ_FIRST(&sc->cmds); cbdp != NULL;
434	    cbdp = TAILQ_NEXT(cbdp, next)) {
435		if (dsa >= cbdp->xferdma->dm_segs[0].ds_addr &&
436	    	    dsa < cbdp->xferdma->dm_segs[0].ds_addr + NBPG) {
437			dsa -= cbdp->xferdma->dm_segs[0].ds_addr;
438			siop_cmd = &cbdp->cmds[dsa / sizeof(struct siop_xfer)];
439			siop_table_sync(siop_cmd,
440			    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
441			break;
442		}
443	}
444	if (cbdp == NULL) {
445		siop_cmd = NULL;
446	}
447	if (istat & ISTAT_DIP) {
448		u_int32_t *p;
449		dstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DSTAT);
450		if (dstat & DSTAT_SSI) {
451			printf("single step dsp 0x%08x dsa 0x08%x\n",
452			    (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
453			    sc->sc_scriptaddr),
454			    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
455			if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
456			    (istat & ISTAT_SIP) == 0) {
457				bus_space_write_1(sc->sc_rt, sc->sc_rh,
458				    SIOP_DCNTL, bus_space_read_1(sc->sc_rt,
459				    sc->sc_rh, SIOP_DCNTL) | DCNTL_STD);
460			}
461			return 1;
462		}
463		if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
464		printf("DMA IRQ:");
465		if (dstat & DSTAT_IID)
466			printf(" Illegal instruction");
467		if (dstat & DSTAT_ABRT)
468			printf(" abort");
469		if (dstat & DSTAT_BF)
470			printf(" bus fault");
471		if (dstat & DSTAT_MDPE)
472			printf(" parity");
473		if (dstat & DSTAT_DFE)
474			printf(" dma fifo empty");
475		printf(", DSP=0x%x DSA=0x%x: ",
476		    (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
477		    sc->sc_scriptaddr),
478		    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
479		p = sc->sc_script +
480		    (bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
481		    sc->sc_scriptaddr - 8) / 4;
482		printf("0x%x 0x%x 0x%x 0x%x\n", le32toh(p[0]), le32toh(p[1]),
483		    le32toh(p[2]), le32toh(p[3]));
484		if (siop_cmd)
485			printf("last msg_in=0x%x status=0x%x\n",
486			    siop_cmd->siop_table->msg_in[0],
487			    le32toh(siop_cmd->siop_table->status));
488		else
489			printf("%s: current DSA invalid\n",
490			    sc->sc_dev.dv_xname);
491		need_reset = 1;
492		}
493	}
494	if (istat & ISTAT_SIP) {
495		/*
496		 * SCSI interrupt. If current command is not active,
497		 * we don't need siop_cmd
498		 */
499		if (siop_cmd && siop_cmd->status != CMDST_ACTIVE &&
500		    siop_cmd->status != CMDST_SENSE_ACTIVE) {
501			siop_cmd = NULL;
502		}
503		if (istat & ISTAT_DIP)
504			delay(10);
505		sist0 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST0);
506			delay(10);
507		sist1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST1);
508		sstat1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1);
509#ifdef DEBUG_INTR
510		printf("scsi interrupt, sist0=0x%x sist1=0x%x sstat1=0x%x "
511		    "DSA=0x%x DSP=0x%lx\n", sist0, sist1,
512		    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),
513		    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),
514		    (u_long)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
515		    sc->sc_scriptaddr));
516#endif
517		if (siop_cmd) {
518			xs = siop_cmd->xs;
519			siop_target = siop_cmd->siop_target;
520		}
521		if (sist0 & SIST0_RST) {
522			siop_handle_reset(sc);
523			siop_start(sc);
524			/* no table to flush here */
525			return 1;
526		}
527		if (sist0 & SIST0_SGE) {
528			if (siop_cmd)
529				scsi_print_addr(xs->sc_link);
530			else
531				printf("%s:", sc->sc_dev.dv_xname);
532			printf("scsi gross error\n");
533			goto reset;
534		}
535		if ((sist0 & SIST0_MA) && need_reset == 0) {
536			if (siop_cmd) {
537				int scratcha0;
538				dstat = bus_space_read_1(sc->sc_rt, sc->sc_rh,
539				    SIOP_DSTAT);
540				/*
541				 * first restore DSA, in case we were in a S/G
542				 * operation.
543				 */
544				bus_space_write_4(sc->sc_rt, sc->sc_rh,
545				    SIOP_DSA, siop_cmd->dsa);
546				scratcha0 = bus_space_read_1(sc->sc_rt,
547				    sc->sc_rh, SIOP_SCRATCHA);
548				switch (sstat1 & SSTAT1_PHASE_MASK) {
549				case SSTAT1_PHASE_STATUS:
550				/*
551				 * previous phase may be aborted for any reason
552				 * ( for example, the target has less data to
553				 * transfer than requested). Just go to status
554				 * and the command should terminate.
555				 */
556					INCSTAT(siop_stat_intr_shortxfer);
557					CALL_SCRIPT(Ent_status);
558					if ((dstat & DSTAT_DFE) == 0)
559						siop_clearfifo(sc);
560					/* no table to flush here */
561					return 1;
562				case SSTAT1_PHASE_MSGIN:
563					/*
564					 * target may be ready to disconnect
565					 * Save data pointers just in case.
566					 */
567					INCSTAT(siop_stat_intr_xferdisc);
568					if (scratcha0 & A_flag_data)
569						siop_sdp(siop_cmd);
570					else if ((dstat & DSTAT_DFE) == 0)
571						siop_clearfifo(sc);
572					bus_space_write_1(sc->sc_rt, sc->sc_rh,
573					    SIOP_SCRATCHA,
574					    scratcha0 & ~A_flag_data);
575					siop_table_sync(siop_cmd,
576					    BUS_DMASYNC_PREREAD |
577					    BUS_DMASYNC_PREWRITE);
578					CALL_SCRIPT(Ent_msgin);
579					return 1;
580				}
581				printf("%s: unexpected phase mismatch %d\n",
582				    sc->sc_dev.dv_xname,
583				    sstat1 & SSTAT1_PHASE_MASK);
584			} else {
585				printf("%s: phase mismatch without command\n",
586				    sc->sc_dev.dv_xname);
587			}
588			need_reset = 1;
589		}
590		if (sist0 & SIST0_PAR) {
591			/* parity error, reset */
592			if (siop_cmd)
593				scsi_print_addr(xs->sc_link);
594			else
595				printf("%s:", sc->sc_dev.dv_xname);
596			printf("parity error\n");
597			goto reset;
598		}
599		if ((sist1 & SIST1_STO) && need_reset == 0) {
600			/* selection time out, assume there's no device here */
601			if (siop_cmd) {
602				siop_cmd->status = CMDST_DONE;
603				xs->error = XS_SELTIMEOUT;
604				goto end;
605			} else {
606				printf("%s: selection timeout without "
607				    "command\n", sc->sc_dev.dv_xname);
608				need_reset = 1;
609			}
610		}
611		if (sist0 & SIST0_UDC) {
612			/*
613			 * unexpected disconnect. Usually the target signals
614			 * a fatal condition this way. Attempt to get sense.
615			 */
616			 if (siop_cmd)
617				goto check_sense;
618			printf("%s: unexpected disconnect without "
619			    "command\n", sc->sc_dev.dv_xname);
620			goto reset;
621		}
622		if (sist1 & SIST1_SBMC) {
623			/* SCSI bus mode change */
624			if (siop_modechange(sc) == 0 || need_reset == 1)
625				goto reset;
626			if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
627				/*
628				 * we have a script interrupt, it will
629				 * restart the script.
630				 */
631				goto scintr;
632			}
633			/*
634			 * else we have to restart it ourselve, at the
635			 * interrupted instruction.
636			 */
637			bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
638			    bus_space_read_4(sc->sc_rt, sc->sc_rh,
639			    SIOP_DSP) - 8);
640			return 1;
641		}
642		/* Else it's an unhandled exeption (for now). */
643		printf("%s: unhandled scsi interrupt, sist0=0x%x sist1=0x%x "
644		    "sstat1=0x%x DSA=0x%x DSP=0x%x\n", sc->sc_dev.dv_xname,
645		    sist0, sist1,
646		    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),
647		    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),
648		    (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
649		    sc->sc_scriptaddr));
650		if (siop_cmd) {
651			siop_cmd->status = CMDST_DONE;
652			xs->error = XS_SELTIMEOUT;
653			goto end;
654		}
655		need_reset = 1;
656	}
657	if (need_reset) {
658reset:
659		/* fatal error, reset the bus */
660		siop_resetbus(sc);
661		/* no table to flush here */
662		return 1;
663	}
664
665scintr:
666	if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
667		irqcode = bus_space_read_4(sc->sc_rt, sc->sc_rh,
668		    SIOP_DSPS);
669#ifdef DEBUG_INTR
670		printf("script interrupt 0x%x\n", irqcode);
671#endif
672		if (siop_cmd == NULL) {
673			printf("%s: script interrupt (0x%x) with invalid "
674			    "DSA !!!\n", sc->sc_dev.dv_xname, irqcode);
675			goto reset;
676		}
677		/*
678		 * an inactive command is only valid if it's a reselect
679		 * interrupt: we'll change siop_cmd to point to the rigth one
680		 * just here
681		 */
682		if (irqcode != A_int_resel && irqcode != A_int_reseltag &&
683		    siop_cmd->status != CMDST_ACTIVE &&
684		    siop_cmd->status != CMDST_SENSE_ACTIVE) {
685			printf("%s: Aie, no command (IRQ code 0x%x current "
686			    "status %d) !\n", sc->sc_dev.dv_xname,
687			    irqcode, siop_cmd->status);
688			xs = NULL;
689		} else {
690			xs = siop_cmd->xs;
691			siop_target = siop_cmd->siop_target;
692		}
693		switch(irqcode) {
694		case A_int_err:
695			printf("error, DSP=0x%x\n",
696			    (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh,
697			    SIOP_DSP) - sc->sc_scriptaddr));
698			if (xs) {
699				xs->error = XS_SELTIMEOUT;
700				goto end;
701			} else {
702				goto reset;
703			}
704		case A_int_msgin:
705			if (siop_cmd->siop_table->msg_in[0] ==
706			    MSG_MESSAGE_REJECT) {
707				int msg, extmsg;
708				if (siop_cmd->siop_table->msg_out[0] & 0x80) {
709					/*
710					 * message was part of a identify +
711					 * something else. Identify shoudl't
712					 * have been rejected.
713					 */
714					msg = siop_cmd->siop_table->msg_out[1];
715					extmsg =
716					    siop_cmd->siop_table->msg_out[3];
717				} else {
718					msg = siop_cmd->siop_table->msg_out[0];
719					extmsg =
720					    siop_cmd->siop_table->msg_out[2];
721				}
722				if (msg == MSG_MESSAGE_REJECT) {
723					/* MSG_REJECT  for a MSG_REJECT  !*/
724					if (xs)
725						scsi_print_addr(xs->sc_link);
726					else
727						printf("%s: ",
728						   sc->sc_dev.dv_xname);
729					printf("our reject message was "
730					    "rejected\n");
731					goto reset;
732				}
733				if (msg == MSG_EXTENDED &&
734				    extmsg == MSG_EXT_WDTR) {
735					/* WDTR rejected, initiate sync */
736					printf("%s: target %d using 8bit "
737					    "transfers\n", sc->sc_dev.dv_xname,
738					    xs->sc_link->scsipi_scsi.target);
739					if (xs->sc_link->quirks & SDEV_NOSYNC) {
740						siop_cmd->siop_target->status =
741						    TARST_OK;
742						/* no table to flush here */
743						CALL_SCRIPT(Ent_msgin_ack);
744						return 1;
745					}
746					siop_target->status = TARST_SYNC_NEG;
747					siop_cmd->siop_table->msg_out[0] =
748					    MSG_EXTENDED;
749					siop_cmd->siop_table->msg_out[1] =
750					    MSG_EXT_SDTR_LEN;
751					siop_cmd->siop_table->msg_out[2] =
752					    MSG_EXT_SDTR;
753					siop_cmd->siop_table->msg_out[3] =
754					    sc->minsync;
755					siop_cmd->siop_table->msg_out[4] =
756					    sc->maxoff;
757					siop_cmd->siop_table->t_msgout.count =
758					    htole32(MSG_EXT_SDTR_LEN + 2);
759					siop_cmd->siop_table->t_msgout.addr =
760					    htole32(siop_cmd->dsa);
761					siop_table_sync(siop_cmd,
762					    BUS_DMASYNC_PREREAD |
763					    BUS_DMASYNC_PREWRITE);
764					CALL_SCRIPT(Ent_send_msgout);
765					return 1;
766				} else if (msg == MSG_EXTENDED &&
767				    extmsg == MSG_EXT_SDTR) {
768					/* sync rejected */
769					printf("%s: target %d asynchronous\n",
770					    sc->sc_dev.dv_xname,
771					    xs->sc_link->scsipi_scsi.target);
772					siop_cmd->siop_target->status =
773					    TARST_OK;
774					/* no table to flush here */
775					CALL_SCRIPT(Ent_msgin_ack);
776					return 1;
777				}
778				if (xs)
779					scsi_print_addr(xs->sc_link);
780				else
781					printf("%s: ", sc->sc_dev.dv_xname);
782				if (msg == MSG_EXTENDED) {
783					printf("scsi message reject, extended "
784					    "message sent was 0x%x\n", extmsg);
785				} else {
786					printf("scsi message reject, message "
787					    "sent was 0x%x\n", msg);
788				}
789				/* no table to flush here */
790				CALL_SCRIPT(Ent_msgin_ack);
791				return 1;
792			}
793			if (xs)
794				scsi_print_addr(xs->sc_link);
795			else
796				printf("%s: ", sc->sc_dev.dv_xname);
797			printf("unhandled message 0x%x\n",
798			    siop_cmd->siop_table->msg_in[0]);
799			siop_cmd->siop_table->t_msgout.count= htole32(1);
800			siop_cmd->siop_table->t_msgout.addr =
801			    htole32(siop_cmd->dsa);
802			siop_cmd->siop_table->msg_out[0] = MSG_MESSAGE_REJECT;
803			siop_table_sync(siop_cmd,
804			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
805			CALL_SCRIPT(Ent_send_msgout);
806			return 1;
807		case A_int_extmsgin:
808#ifdef DEBUG_INTR
809			printf("extended message: msg 0x%x len %d\n",
810			    siop_cmd->siop_table->msg_in[2],
811			    siop_cmd->siop_table->msg_in[1]);
812#endif
813			if (siop_cmd->siop_table->msg_in[1] > 6)
814				printf("%s: extended message too big (%d)\n",
815				    sc->sc_dev.dv_xname,
816				    siop_cmd->siop_table->msg_in[1]);
817			siop_cmd->siop_table->t_extmsgdata.count =
818			    htole32(siop_cmd->siop_table->msg_in[1] - 1);
819			siop_cmd->siop_table->t_extmsgdata.addr =
820			    htole32(
821			    le32toh(siop_cmd->siop_table->t_extmsgin.addr)
822			    + 2);
823			siop_table_sync(siop_cmd,
824			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
825			CALL_SCRIPT(Ent_get_extmsgdata);
826			return 1;
827		case A_int_extmsgdata:
828#ifdef DEBUG_INTR
829			{
830			int i;
831			printf("extended message: 0x%x, data:",
832			    siop_cmd->siop_table->msg_in[2]);
833			for (i = 3; i < 2 + siop_cmd->siop_table->msg_in[1];
834			    i++)
835				printf(" 0x%x",
836				    siop_cmd->siop_table->msg_in[i]);
837			printf("\n");
838			}
839#endif
840			if (siop_cmd->siop_table->msg_in[2] == MSG_EXT_WDTR) {
841				switch (siop_wdtr_neg(siop_cmd)) {
842				case SIOP_NEG_NOP:
843					break;
844				case SIOP_NEG_MSGOUT:
845					siop_table_sync(siop_cmd,
846					    BUS_DMASYNC_PREREAD |
847					    BUS_DMASYNC_PREWRITE);
848					CALL_SCRIPT(Ent_send_msgout);
849					break;
850				case SIOP_NEG_ACK:
851					CALL_SCRIPT(Ent_msgin_ack);
852				default:
853					panic("invalid retval from "
854					    "siop_wdtr_neg()");
855				}
856				return(1);
857			}
858			if (siop_cmd->siop_table->msg_in[2] == MSG_EXT_SDTR) {
859				switch (siop_sdtr_neg(siop_cmd)) {
860				case SIOP_NEG_NOP:
861					break;
862				case SIOP_NEG_MSGOUT:
863					siop_table_sync(siop_cmd,
864					    BUS_DMASYNC_PREREAD |
865					    BUS_DMASYNC_PREWRITE);
866					CALL_SCRIPT(Ent_send_msgout);
867					break;
868				case SIOP_NEG_ACK:
869					CALL_SCRIPT(Ent_msgin_ack);
870					break;
871				default:
872					panic("invalid retval from "
873					    "siop_wdtr_neg()");
874				}
875				return(1);
876			}
877			/* send a message reject */
878			siop_cmd->siop_table->t_msgout.count =
879			    htole32(1);
880			siop_cmd->siop_table->t_msgout.addr =
881			    htole32(siop_cmd->dsa);
882			siop_cmd->siop_table->msg_out[0] =
883			    MSG_MESSAGE_REJECT;
884			siop_table_sync(siop_cmd,
885			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
886			CALL_SCRIPT(Ent_send_msgout);
887			return 1;
888		case A_int_resel: /* reselected */
889		case A_int_reseltag: /* reselected  with tag */
890			INCSTAT(siop_stat_intr_reselect);
891			if ((siop_cmd->siop_table->msg_in[0] & 0x80) == 0) {
892				printf("%s: reselect without identify (%d)\n",
893				    sc->sc_dev.dv_xname,
894				    siop_cmd->siop_table->msg_in[0]);
895				goto reset;
896			}
897			target = bus_space_read_1(sc->sc_rt,
898			    sc->sc_rh, SIOP_SCRATCHA);
899			if ((target & 0x80) == 0) {
900				printf("reselect without id (%d)\n", target);
901				goto reset;
902			}
903			target &= 0x0f;
904			lun = siop_cmd->siop_table->msg_in[0] & 0x07;
905#ifdef DEBUG_DR
906			printf("reselected by target %d lun %d\n",
907			    target, lun);
908#endif
909			siop_cmd =
910			    sc->targets[target]->active_list[lun].tqh_first;
911			if (siop_cmd == NULL) {
912				printf("%s: reselected without cmd\n",
913				    sc->sc_dev.dv_xname);
914				goto reset;
915			}
916			bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSA,
917			    siop_cmd->dsa);
918			bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
919			    (sc->targets[target]->id >> 24) & 0xff);
920			bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,
921			    (sc->targets[target]->id >> 8) & 0xff);
922			/* no table to flush */
923			CALL_SCRIPT(Ent_selected);
924			return 1;
925		case A_int_disc:
926			INCSTAT(siop_stat_intr_sdp);
927			offset = bus_space_read_1(sc->sc_rt, sc->sc_rh,
928			    SIOP_SCRATCHA + 1);
929#ifdef DEBUG_DR
930			printf("disconnect offset %d\n", offset);
931#endif
932			if (offset > SIOP_NSG) {
933				printf("%s: bad offset for disconnect (%d)\n",
934				    sc->sc_dev.dv_xname, offset);
935				goto reset;
936			}
937			/*
938			 * offset == SIOP_NSG may be a valid condition if
939			 * we get a sdp when the xfer is done.
940			 * Don't call memmove in this case.
941			 */
942			if (offset < SIOP_NSG) {
943				memmove(&siop_cmd->siop_table->data[0],
944				    &siop_cmd->siop_table->data[offset],
945				    (SIOP_NSG - offset) * sizeof(scr_table_t));
946				siop_table_sync(siop_cmd,
947				    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
948			}
949			bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
950			    sc->sc_scheddma->dm_segs[0].ds_addr);
951			return 1;
952		case A_int_resfail:
953			printf("reselect failed\n");
954			bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
955			    sc->sc_scheddma->dm_segs[0].ds_addr);
956			return  1;
957		case A_int_done:
958			if (xs == NULL) {
959				printf("%s: done without command, DSA=0x%lx\n",
960				    sc->sc_dev.dv_xname, (u_long)siop_cmd->dsa);
961				siop_cmd->status = CMDST_FREE;
962				bus_space_write_4(sc->sc_rt, sc->sc_rh,
963				    SIOP_DSP,
964				    sc->sc_scheddma->dm_segs[0].ds_addr);
965				siop_start(sc);
966				return 1;
967			}
968			if (siop_target->status == TARST_PROBING &&
969			    xs->sc_link->device_softc != NULL)
970				siop_target->status = TARST_ASYNC;
971#ifdef DEBUG_INTR
972			printf("done, DSA=0x%lx target id 0x%x last msg "
973			    "in=0x%x status=0x%x\n", (u_long)siop_cmd->dsa,
974			    le32toh(siop_cmd->siop_table->id),
975			    siop_cmd->siop_table->msg_in[0],
976			    le32toh(siop_cmd->siop_table->status));
977#endif
978			INCSTAT(siop_stat_intr_done);
979			if (siop_cmd->status == CMDST_SENSE_ACTIVE)
980				siop_cmd->status = CMDST_SENSE_DONE;
981			else
982				siop_cmd->status = CMDST_DONE;
983			switch(le32toh(siop_cmd->siop_table->status)) {
984			case SCSI_OK:
985				xs->error = (siop_cmd->status == CMDST_DONE) ?
986				    XS_NOERROR : XS_SENSE;
987				break;
988			case SCSI_BUSY:
989				xs->error = XS_BUSY;
990				break;
991			case SCSI_CHECK:
992check_sense:
993				if (siop_cmd->status == CMDST_SENSE_DONE) {
994					/* request sense on a request sense ? */
995					printf("request sense failed\n");
996					xs->error = XS_DRIVER_STUFFUP;
997				} else {
998					siop_cmd->status = CMDST_SENSE;
999				}
1000				break;
1001			case 0xff:
1002				/*
1003				 * the status byte was not updated, cmd was
1004				 * aborted
1005				 */
1006				xs->error = XS_SELTIMEOUT;
1007				break;
1008			default:
1009				xs->error = XS_DRIVER_STUFFUP;
1010			}
1011			goto end;
1012		default:
1013			printf("unknown irqcode %x\n", irqcode);
1014			xs->error = XS_SELTIMEOUT;
1015			goto end;
1016		}
1017		return 1;
1018	}
1019	/* We just should't get there */
1020	panic("siop_intr: I shouldn't be there !");
1021	return 1;
1022end:
1023	bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
1024	    sc->sc_scheddma->dm_segs[0].ds_addr);
1025	lun = siop_cmd->xs->sc_link->scsipi_scsi.lun;
1026	siop_scsicmd_end(siop_cmd);
1027	if (siop_cmd->status == CMDST_FREE) {
1028		TAILQ_REMOVE(&siop_target->active_list[lun],
1029		    siop_cmd, next);
1030		TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
1031	}
1032	siop_start(sc);
1033	return 1;
1034}
1035
1036void
1037siop_scsicmd_end(siop_cmd)
1038	struct siop_cmd *siop_cmd;
1039{
1040	struct scsipi_xfer *xs = siop_cmd->xs;
1041	struct siop_softc *sc = siop_cmd->siop_target->siop_sc;
1042	u_int32_t *scr;
1043
1044	/* remove from reselect slot */
1045	siop_resel_sync(sc, BUS_DMASYNC_POSTWRITE);
1046#ifdef DEBUG_SHED
1047	printf("freeing resel %d\n", siop_cmd->reselslot);
1048#endif
1049	scr = &sc->sc_resel[(Ent_res_nextld / 4) * siop_cmd->reselslot];
1050	scr[Ent_rtarget / 4] = htole32(0x808400ff);
1051	siop_resel_sync(sc, BUS_DMASYNC_PREWRITE);
1052	if (siop_cmd->status != CMDST_SENSE_DONE &&
1053	    xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
1054		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
1055		    siop_cmd->dmamap_data->dm_mapsize,
1056		    (xs->xs_control & XS_CTL_DATA_IN) ?
1057		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1058		bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_data);
1059	}
1060	bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
1061	if (siop_cmd->status == CMDST_SENSE) {
1062		/* issue a request sense for this target */
1063		int error, i;
1064		siop_cmd->rs_cmd.opcode = REQUEST_SENSE;
1065		siop_cmd->rs_cmd.byte2 = xs->sc_link->scsipi_scsi.lun << 5;
1066		siop_cmd->rs_cmd.unused[0] = siop_cmd->rs_cmd.unused[1] = 0;
1067		siop_cmd->rs_cmd.length = sizeof(struct scsipi_sense_data);
1068		siop_cmd->rs_cmd.control = 0;
1069		siop_cmd->siop_table->status = htole32(0xff); /*invalid status*/
1070		siop_cmd->siop_table->t_msgout.count= htole32(1);
1071		siop_cmd->siop_table->t_msgout.addr = htole32(siop_cmd->dsa);
1072		siop_cmd->siop_table->msg_out[0] =
1073		    MSG_IDENTIFY(xs->sc_link->scsipi_scsi.lun, 1);
1074		error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,
1075		    &siop_cmd->rs_cmd, sizeof(struct scsipi_sense),
1076		    NULL, BUS_DMA_NOWAIT);
1077		if (error) {
1078			printf("%s: unable to load cmd DMA map: %d",
1079			    sc->sc_dev.dv_xname, error);
1080			xs->error = XS_DRIVER_STUFFUP;
1081			goto out;
1082		}
1083		siop_cmd->siop_table->cmd.count =
1084		    htole32(siop_cmd->dmamap_cmd->dm_segs[0].ds_len);
1085		siop_cmd->siop_table->cmd.addr =
1086		    htole32(siop_cmd->dmamap_cmd->dm_segs[0].ds_addr);
1087		error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_data,
1088		    &xs->sense.scsi_sense, sizeof(struct  scsipi_sense_data),
1089		    NULL, BUS_DMA_NOWAIT);
1090		if (error) {
1091			printf("%s: unable to load sense DMA map: %d",
1092			    sc->sc_dev.dv_xname, error);
1093			xs->error = XS_DRIVER_STUFFUP;
1094			bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
1095			goto out;
1096		}
1097		for (i = 0; i < siop_cmd->dmamap_data->dm_nsegs; i++) {
1098			siop_cmd->siop_table->data[i].count =
1099			    htole32(siop_cmd->dmamap_data->dm_segs[i].ds_len);
1100			siop_cmd->siop_table->data[i].addr =
1101			    htole32(siop_cmd->dmamap_data->dm_segs[i].ds_addr);
1102		}
1103		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
1104		    siop_cmd->dmamap_data->dm_mapsize, BUS_DMASYNC_PREREAD);
1105		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd, 0,
1106		    siop_cmd->dmamap_cmd->dm_mapsize, BUS_DMASYNC_PREWRITE);
1107		siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
1108		return;
1109	} else if (siop_cmd->status == CMDST_SENSE_DONE) {
1110		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
1111		    siop_cmd->dmamap_data->dm_mapsize, BUS_DMASYNC_POSTREAD);
1112		bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_data);
1113	}
1114out:
1115	callout_stop(&siop_cmd->xs->xs_callout);
1116	siop_cmd->status = CMDST_FREE;
1117	xs->xs_status |= XS_STS_DONE;
1118	xs->resid = 0;
1119	if ((xs->xs_control & XS_CTL_POLL) == 0)
1120		scsipi_done (xs);
1121}
1122
1123/*
1124 * handle a bus reset: reset chip, unqueue all active commands and report
1125 * loosage to upper layer.
1126 * As the upper layer may requeue immediatly we have to first store
1127 * all active commands in a temporary queue.
1128 */
1129void
1130siop_handle_reset(sc)
1131	struct siop_softc *sc;
1132{
1133	struct cmd_list reset_list;
1134	struct siop_cmd *siop_cmd, *next_siop_cmd;
1135	int target, lun;
1136	/*
1137	 * scsi bus reset. reset the chip and restart
1138	 * the queue. Need to clean up all active commands
1139	 */
1140	printf("%s: scsi bus reset\n", sc->sc_dev.dv_xname);
1141	/* stop, reset and restart the chip */
1142	siop_reset(sc);
1143	TAILQ_INIT(&reset_list);
1144	/* find all active commands */
1145	for (target = 0; target <= sc->sc_link.scsipi_scsi.max_target;
1146	    target++) {
1147		if (sc->targets[target] == NULL)
1148			continue;
1149		for (lun = 0; lun < 8; lun++) {
1150			for (siop_cmd =
1151			    TAILQ_FIRST(&sc->targets[target]->active_list[lun]);
1152			    siop_cmd != NULL; siop_cmd = next_siop_cmd) {
1153				next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1154				if (siop_cmd->status < CMDST_ACTIVE)
1155					continue;
1156				printf("cmd %p (target %d) in reset list\n",
1157				    siop_cmd, target);
1158				TAILQ_REMOVE(
1159				    &sc->targets[target]->active_list[lun],
1160				    siop_cmd, next);
1161				TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1162			}
1163		}
1164		sc->targets[target]->status = TARST_ASYNC;
1165		sc->targets[target]->flags = ~(TARF_SYNC | TARF_WIDE);
1166	}
1167	for (siop_cmd = TAILQ_FIRST(&reset_list); siop_cmd != NULL;
1168	    siop_cmd = next_siop_cmd) {
1169		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1170		siop_cmd->xs->error = (siop_cmd->flags & CMDFL_TIMEOUT) ?
1171		    XS_TIMEOUT : XS_RESET;
1172		printf("cmd %p about to be processed\n", siop_cmd);
1173		if (siop_cmd->status == CMDST_SENSE ||
1174		    siop_cmd->status == CMDST_SENSE_ACTIVE)
1175			siop_cmd->status = CMDST_SENSE_DONE;
1176		else
1177			siop_cmd->status = CMDST_DONE;
1178		TAILQ_REMOVE(&reset_list, siop_cmd, next);
1179		siop_scsicmd_end(siop_cmd);
1180		TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
1181	}
1182}
1183
1184int
1185siop_scsicmd(xs)
1186	struct scsipi_xfer *xs;
1187{
1188	struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc;
1189	struct siop_cmd *siop_cmd;
1190	int s, error, i;
1191	int target = xs->sc_link->scsipi_scsi.target;
1192	int lun = xs->sc_link->scsipi_scsi.lun;
1193
1194	s = splbio();
1195#ifdef DEBUG_SHED
1196	printf("starting cmd for %d:%d\n", target, lun);
1197#endif
1198	siop_cmd = sc->free_list.tqh_first;
1199	if (siop_cmd) {
1200		TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
1201	} else {
1202		if (siop_morecbd(sc) == 0) {
1203			siop_cmd = sc->free_list.tqh_first;
1204#ifdef DIAGNOSTIC
1205			if (siop_cmd == NULL)
1206				panic("siop_morecbd succeed and does nothing");
1207#endif
1208			TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
1209		}
1210	}
1211	splx(s);
1212	if (siop_cmd == NULL) {
1213		xs->error = XS_DRIVER_STUFFUP;
1214		return(TRY_AGAIN_LATER);
1215	}
1216#ifdef DIAGNOSTIC
1217	if (siop_cmd->status != CMDST_FREE)
1218		panic("siop_scsicmd: new cmd not free");
1219#endif
1220	if (sc->targets[target] == NULL) {
1221		sc->targets[target] =
1222		    malloc(sizeof(struct siop_target), M_DEVBUF, M_NOWAIT);
1223		if (sc->targets[target] == NULL) {
1224			printf("%s: can't malloc memory for target %d\n",
1225			    sc->sc_dev.dv_xname, target);
1226			xs->error = XS_DRIVER_STUFFUP;
1227			return(TRY_AGAIN_LATER);
1228		}
1229		sc->targets[target]->siop_sc = sc;
1230		sc->targets[target]->status = TARST_PROBING;
1231		sc->targets[target]->flags = 0;
1232		sc->targets[target]->id = sc->clock_div << 24; /* scntl3 */
1233		sc->targets[target]->id |=  target << 16; /* id */
1234		/* sc->targets[target]->id |= 0x0 << 8; scxfer is 0 */
1235		for (i = 0; i < 8; i++)
1236			TAILQ_INIT(&sc->targets[target]->active_list[i]);
1237	}
1238	siop_cmd->siop_target = sc->targets[target];
1239	siop_cmd->xs = xs;
1240	siop_cmd->siop_table->id = htole32(sc->targets[target]->id);
1241	siop_cmd->siop_table->t_msgout.count= htole32(1);
1242	siop_cmd->siop_table->t_msgout.addr = htole32(siop_cmd->dsa);
1243	memset(siop_cmd->siop_table->msg_out, 0, 8);
1244	siop_cmd->siop_table->msg_out[0] = MSG_IDENTIFY(lun, 1);
1245#if 0
1246	siop_cmd->siop_table->msg_out[1] = MSG_SIMPLE_Q_TAG;
1247	siop_cmd->siop_table->msg_out[2] = 0;
1248#endif
1249	if (sc->targets[target]->status == TARST_ASYNC) {
1250		if (sc->features & SF_BUS_WIDE &&
1251		    (xs->sc_link->quirks & SDEV_NOWIDE) == 0) {
1252			sc->targets[target]->status = TARST_WIDE_NEG;
1253			siop_cmd->siop_table->msg_out[1] = MSG_EXTENDED;
1254			siop_cmd->siop_table->msg_out[2] = MSG_EXT_WDTR_LEN;
1255			siop_cmd->siop_table->msg_out[3] = MSG_EXT_WDTR;
1256			siop_cmd->siop_table->msg_out[4] =
1257			    MSG_EXT_WDTR_BUS_16_BIT;
1258			siop_cmd->siop_table->t_msgout.count=
1259			    htole32(MSG_EXT_WDTR_LEN + 2 + 1);
1260		} else if ((xs->sc_link->quirks & SDEV_NOSYNC) == 0) {
1261			sc->targets[target]->status = TARST_SYNC_NEG;
1262			siop_cmd->siop_table->msg_out[1] = MSG_EXTENDED;
1263			siop_cmd->siop_table->msg_out[2] = MSG_EXT_SDTR_LEN;
1264			siop_cmd->siop_table->msg_out[3] = MSG_EXT_SDTR;
1265			siop_cmd->siop_table->msg_out[4] = sc->minsync;
1266			siop_cmd->siop_table->msg_out[5] = sc->maxoff;
1267			siop_cmd->siop_table->t_msgout.count=
1268			    htole32(MSG_EXT_SDTR_LEN + 2 +1);
1269		} else {
1270			sc->targets[target]->status = TARST_OK;
1271		}
1272	}
1273	siop_cmd->siop_table->status = htole32(0xff); /* set invalid status */
1274
1275	/* load the DMA maps */
1276	error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,
1277	    xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT);
1278	if (error) {
1279		printf("%s: unable to load cmd DMA map: %d",
1280		    sc->sc_dev.dv_xname, error);
1281		xs->error = XS_DRIVER_STUFFUP;
1282		return(TRY_AGAIN_LATER);
1283	}
1284	siop_cmd->siop_table->cmd.count =
1285	    htole32(siop_cmd->dmamap_cmd->dm_segs[0].ds_len);
1286	siop_cmd->siop_table->cmd.addr =
1287	    htole32(siop_cmd->dmamap_cmd->dm_segs[0].ds_addr);
1288	if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
1289		error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_data,
1290		    xs->data, xs->datalen, NULL, BUS_DMA_NOWAIT);
1291		if (error) {
1292			printf("%s: unable to load cmd DMA map: %d",
1293			    sc->sc_dev.dv_xname, error);
1294			xs->error = XS_DRIVER_STUFFUP;
1295			return(TRY_AGAIN_LATER);
1296			bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
1297		}
1298		for (i = 0; i < siop_cmd->dmamap_data->dm_nsegs; i++) {
1299			siop_cmd->siop_table->data[i].count =
1300			    htole32(siop_cmd->dmamap_data->dm_segs[i].ds_len);
1301			siop_cmd->siop_table->data[i].addr =
1302			    htole32(siop_cmd->dmamap_data->dm_segs[i].ds_addr);
1303		}
1304		bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
1305		    siop_cmd->dmamap_data->dm_mapsize,
1306		    (xs->xs_control & XS_CTL_DATA_IN) ?
1307		    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
1308	}
1309	bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd, 0,
1310	    siop_cmd->dmamap_cmd->dm_mapsize, BUS_DMASYNC_PREWRITE);
1311	siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1312
1313	siop_cmd->status = CMDST_READY;
1314	s = splbio();
1315	TAILQ_INSERT_TAIL(&sc->targets[target]->active_list[lun],
1316	    siop_cmd, next);
1317	siop_start(sc);
1318	if (xs->xs_control & XS_CTL_POLL) {
1319		/* poll for command completion */
1320		while ((xs->xs_status & XS_STS_DONE) == 0)
1321			siop_intr(sc);
1322		splx(s);
1323		return (COMPLETE);
1324	}
1325	splx(s);
1326	return (SUCCESSFULLY_QUEUED);
1327}
1328
1329void
1330siop_start(sc)
1331	struct siop_softc *sc;
1332{
1333	struct siop_cmd *siop_cmd;
1334	u_int32_t *scr, *rscr;
1335	u_int32_t dsa;
1336	int timeout;
1337	int target, lun, slot, resel;
1338	int newcmd = 0;
1339
1340	/*
1341	 * first make sure to read valid data
1342	 */
1343	siop_sched_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1344
1345	/*
1346	 * The queue management here is a bit tricky: the script always looks
1347	 * at the slot from first to last, so if we always use the first
1348	 * free slot commands can stay at the tail of the queue ~forever.
1349	 * The algorithm used here is to restart from the head when we know
1350	 * that the queue is empty, and only add commands after the last one.
1351	 * When we're at the end of the queue wait for the script to clear it.
1352	 * The best thing to do here would be to implement a circular queue,
1353	 * but using only 53c720 features this can be "interesting".
1354	 * A mid-way solution could be to implement 2 queues and swap orders.
1355	 */
1356	slot = sc->sc_currschedslot;
1357	scr = &sc->sc_sched[(Ent_nextslot / 4) * slot];
1358	/*
1359	 * if relative addr of first jump is not 0 the slot is free. As this is
1360	 * the last used slot, all previous slots are free, we can restart
1361	 * from 0.
1362	 */
1363	if (scr[Ent_slot / 4 + 1] != 0) {
1364		slot = sc->sc_currschedslot = 0;
1365	} else {
1366		slot++;
1367	}
1368
1369	for (target = 0; target <= sc->sc_link.scsipi_scsi.max_target;
1370	    target++) {
1371		if (sc->targets[target] == NULL)
1372			continue;
1373		for (lun = 0; lun < 8; lun++) {
1374			siop_cmd =
1375			    sc->targets[target]->active_list[lun].tqh_first;
1376			if (siop_cmd == NULL)
1377				continue;
1378			if (siop_cmd->status != CMDST_READY &&
1379			    siop_cmd->status != CMDST_SENSE)
1380				continue;
1381			/* find a reselect slot */
1382			for (resel = 0; resel < sc->sc_nreselslots; resel++) {
1383				/* if target is 0xff the slot is free */
1384				rscr = &sc->sc_resel[
1385				    (Ent_res_nextld / 4) * resel];
1386				if ((htole32(rscr[Ent_rtarget / 4]) & 0xff)
1387				    == 0xff)
1388					break;
1389			}
1390			if (resel == sc->sc_nreselslots) {
1391#ifdef DEBUG
1392				printf("%s: out of reselect slot\n",
1393					sc->sc_dev.dv_xname);
1394#endif
1395				goto end; /* no free slot */
1396			}
1397			/* find a free scheduler slot and load it */
1398			for (; slot < sc->sc_nschedslots; slot++) {
1399				scr = &sc->sc_sched[(Ent_nextslot / 4) * slot];
1400				/*
1401				 * if relative addr of first jump is 0 the
1402				 * slot isn't free
1403				 */
1404				if (scr[Ent_slot / 4 + 1] == 0)
1405					continue;
1406#ifdef DEBUG_SHED
1407				printf("using slot %d resel %d for DSA 0x%lx\n", slot, resel, (u_long)siop_cmd->dsa);
1408#endif
1409				/* note that we started a new command */
1410				newcmd = 1;
1411				/* mark command as active */
1412				if (siop_cmd->status == CMDST_READY)
1413					siop_cmd->status = CMDST_ACTIVE;
1414				else if (siop_cmd->status == CMDST_SENSE)
1415					siop_cmd->status = CMDST_SENSE_ACTIVE;
1416				else
1417					panic("siop_start: bad status");
1418				/* patch scripts with DSA addr */
1419				dsa = siop_cmd->dsa;
1420				/*
1421				 * first reselect script
1422				 * 0x808400xx is 'JUMP foo if not 0xxx'
1423				 * we need target | 0x80 for the IDENTIFY cmd.
1424				 */
1425				rscr[Ent_rtarget / 4] =
1426				    htole32(0x80840080 | target);
1427				rscr[Ent_rlun / 4] =
1428				    htole32(0x80840000 | lun);
1429				/*
1430				 * 0x78000000 is a 'move data8 to reg'. data8
1431				 * is the second octet, reg offset is the third.
1432				 */
1433				rscr[Ent_rdsa0 / 4] =
1434				    htole32(0x78100000 |
1435				    ((dsa & 0x000000ff) <<  8));
1436				rscr[Ent_rdsa1 / 4] =
1437				    htole32(0x78110000 |
1438				    ( dsa & 0x0000ff00       ));
1439				rscr[Ent_rdsa2 / 4] =
1440				    htole32(0x78120000 |
1441				    ((dsa & 0x00ff0000) >>  8));
1442				rscr[Ent_rdsa3 / 4] =
1443				    htole32(0x78130000 |
1444				    ((dsa & 0xff000000) >> 16));
1445				siop_cmd->reselslot = resel;
1446				/* now scheduler slot */
1447				scr[Ent_idsa0 / 4] =
1448				    htole32(0x78100000 |
1449				    ((dsa & 0x000000ff) <<  8));
1450				scr[Ent_idsa1 / 4] =
1451				    htole32(0x78110000 |
1452				    ( dsa & 0x0000ff00       ));
1453				scr[Ent_idsa2 / 4] =
1454				    htole32(0x78120000 |
1455				    ((dsa & 0x00ff0000) >>  8));
1456				scr[Ent_idsa3 / 4] =
1457				    htole32(0x78130000 |
1458				    ((dsa & 0xff000000) >> 16));
1459				/* handle timeout */
1460				if (siop_cmd->status == CMDST_ACTIVE) {
1461					if ((siop_cmd->xs->xs_control &
1462					    XS_CTL_POLL) == 0) {
1463						/* start exire timer */
1464						timeout = (u_int64_t)
1465						    siop_cmd->xs->timeout *
1466						    (u_int64_t)hz / 1000;
1467						if (timeout == 0)
1468							timeout = 1;
1469						callout_reset(
1470						    &siop_cmd->xs->xs_callout,
1471						    timeout, siop_timeout,
1472						    siop_cmd);
1473					}
1474				}
1475				/*
1476				 * Change jump offset so that this slot will be
1477				 * handled
1478				 */
1479				scr[Ent_slot / 4 + 1] = 0;
1480				break;
1481			}
1482			/* no more free slot, no need to continue */
1483			if (slot == sc->sc_nschedslots) {
1484				goto end;
1485			}
1486			sc->sc_currschedslot = slot;
1487		}
1488	}
1489end:
1490	/* if nothing changed no need to flush cache and wakeup script */
1491	if (newcmd == 0)
1492		return;
1493	/* make sure SCRIPT processor will read valid data */
1494	siop_sched_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1495	/* Signal script it has some work to do */
1496	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_SIGP);
1497	/* and wait for IRQ */
1498	return;
1499}
1500
1501void
1502siop_timeout(v)
1503	void *v;
1504{
1505	struct siop_cmd *siop_cmd = v;
1506	struct siop_softc *sc = siop_cmd->siop_target->siop_sc;
1507	int s;
1508
1509	scsi_print_addr(siop_cmd->xs->sc_link);
1510	printf("command timeout\n");
1511
1512	s = splbio();
1513	/* reset the scsi bus */
1514	siop_resetbus(sc);
1515
1516	/* deactivate callout */
1517	callout_stop(&siop_cmd->xs->xs_callout);
1518	/* mark command has being timed out; siop_intr will handle it */
1519	/*
1520	 * mark command has being timed out and just return;
1521	 * the bus reset will generate an interrupt,
1522	 * it will be handled in siop_intr()
1523	 */
1524	siop_cmd->flags |= CMDFL_TIMEOUT;
1525	splx(s);
1526	return;
1527
1528}
1529
1530void
1531siop_dump_script(sc)
1532	struct siop_softc *sc;
1533{
1534	int i;
1535	siop_sched_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1536	for (i = 0; i < NBPG / 4; i += 2) {
1537		printf("0x%04x: 0x%08x 0x%08x", i * 4,
1538		    le32toh(sc->sc_script[i]), le32toh(sc->sc_script[i+1]));
1539		if ((le32toh(sc->sc_script[i]) & 0xe0000000) == 0xc0000000) {
1540			i++;
1541			printf(" 0x%08x", le32toh(sc->sc_script[i+1]));
1542		}
1543		printf("\n");
1544	}
1545}
1546
1547int
1548siop_morecbd(sc)
1549	struct siop_softc *sc;
1550{
1551	int error, i;
1552	bus_dma_segment_t seg;
1553	int rseg;
1554	struct siop_cbd *newcbd;
1555
1556	/* allocate a new list head */
1557	newcbd = malloc(sizeof(struct siop_cbd), M_DEVBUF, M_NOWAIT);
1558	if (newcbd == NULL) {
1559		printf("%s: can't allocate memory for command descriptors "
1560		    "head\n", sc->sc_dev.dv_xname);
1561		return ENOMEM;
1562	}
1563
1564	/* allocate cmd list */
1565	newcbd->cmds =
1566	    malloc(sizeof(struct siop_cmd) * SIOP_NCMDPB, M_DEVBUF, M_NOWAIT);
1567	if (newcbd->cmds == NULL) {
1568		printf("%s: can't allocate memory for command descriptors\n",
1569		    sc->sc_dev.dv_xname);
1570		error = ENOMEM;
1571		goto bad3;
1572	}
1573	error = bus_dmamem_alloc(sc->sc_dmat, NBPG, NBPG, 0, &seg, 1, &rseg,
1574	    BUS_DMA_NOWAIT);
1575	if (error) {
1576		printf("%s: unable to allocate cbd DMA memory, error = %d\n",
1577		    sc->sc_dev.dv_xname, error);
1578		goto bad2;
1579	}
1580	error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, NBPG,
1581	    (caddr_t *)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1582	if (error) {
1583		printf("%s: unable to map cbd DMA memory, error = %d\n",
1584		    sc->sc_dev.dv_xname, error);
1585		goto bad2;
1586	}
1587	error = bus_dmamap_create(sc->sc_dmat, NBPG, 1, NBPG, 0,
1588	    BUS_DMA_NOWAIT, &newcbd->xferdma);
1589	if (error) {
1590		printf("%s: unable to create cbd DMA map, error = %d\n",
1591		    sc->sc_dev.dv_xname, error);
1592		goto bad1;
1593	}
1594	error = bus_dmamap_load(sc->sc_dmat, newcbd->xferdma, newcbd->xfers,
1595	    NBPG, NULL, BUS_DMA_NOWAIT);
1596	if (error) {
1597		printf("%s: unable to load cbd DMA map, error = %d\n",
1598		    sc->sc_dev.dv_xname, error);
1599		goto bad0;
1600	}
1601
1602	for (i = 0; i < SIOP_NCMDPB; i++) {
1603		error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, SIOP_NSG,
1604		    MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1605		    &newcbd->cmds[i].dmamap_data);
1606		if (error) {
1607			printf("%s: unable to create data DMA map for cbd: "
1608			    "error %d\n",
1609			    sc->sc_dev.dv_xname, error);
1610			goto bad0;
1611		}
1612		error = bus_dmamap_create(sc->sc_dmat,
1613		    sizeof(struct scsipi_generic), 1,
1614		    sizeof(struct scsipi_generic), 0,
1615		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1616		    &newcbd->cmds[i].dmamap_cmd);
1617		if (error) {
1618			printf("%s: unable to create cmd DMA map for cbd %d\n",
1619			    sc->sc_dev.dv_xname, error);
1620			goto bad0;
1621		}
1622		newcbd->cmds[i].siop_cbdp = newcbd;
1623		newcbd->cmds[i].siop_table = &newcbd->xfers[i];
1624		memset(newcbd->cmds[i].siop_table, 0, sizeof(struct siop_xfer));
1625		newcbd->cmds[i].dsa = newcbd->xferdma->dm_segs[0].ds_addr +
1626		    i * sizeof(struct siop_xfer);
1627		newcbd->cmds[i].status = CMDST_FREE;
1628		newcbd->cmds[i].siop_table->t_msgout.count= htole32(1);
1629		newcbd->cmds[i].siop_table->t_msgout.addr =
1630		    htole32(newcbd->cmds[i].dsa);
1631		newcbd->cmds[i].siop_table->t_msgin.count= htole32(1);
1632		newcbd->cmds[i].siop_table->t_msgin.addr =
1633		    htole32(newcbd->cmds[i].dsa + 8);
1634		newcbd->cmds[i].siop_table->t_extmsgin.count= htole32(2);
1635		newcbd->cmds[i].siop_table->t_extmsgin.addr = htole32(
1636		    le32toh(newcbd->cmds[i].siop_table->t_msgin.addr) + 1);
1637		newcbd->cmds[i].siop_table->t_msgtag.count= htole32(2);
1638		newcbd->cmds[i].siop_table->t_msgtag.addr = htole32(
1639		    le32toh(newcbd->cmds[i].siop_table->t_msgin.addr) + 1);
1640		newcbd->cmds[i].siop_table->t_status.count= htole32(1);
1641		newcbd->cmds[i].siop_table->t_status.addr = htole32(
1642		    le32toh(newcbd->cmds[i].siop_table->t_msgin.addr) + 8);
1643		TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
1644#ifdef DEBUG
1645		printf("tables[%d]: out=0x%x in=0x%x status=0x%x\n", i,
1646		    le32toh(newcbd->cmds[i].siop_table->t_msgin.addr),
1647		    le32toh(newcbd->cmds[i].siop_table->t_msgout.addr),
1648		    le32toh(newcbd->cmds[i].siop_table->t_status.addr));
1649#endif
1650	}
1651	TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
1652	return 0;
1653bad0:
1654	bus_dmamap_destroy(sc->sc_dmat, newcbd->xferdma);
1655bad1:
1656	bus_dmamem_free(sc->sc_dmat, &seg, rseg);
1657bad2:
1658	free(newcbd->cmds, M_DEVBUF);
1659bad3:
1660	free(newcbd, M_DEVBUF);
1661	return error;
1662}
1663
1664#ifdef SIOP_STATS
1665void
1666siop_printstats()
1667{
1668	printf("siop_stat_intr %d\n", siop_stat_intr);
1669	printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer);
1670	printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc);
1671	printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp);
1672	printf("siop_stat_intr_reselect %d\n", siop_stat_intr_reselect);
1673	printf("siop_stat_intr_done %d\n", siop_stat_intr_done);
1674}
1675#endif
1676