1/*	$OpenBSD: siop.c,v 1.90 2024/04/13 23:44:11 jsg Exp $ */
2/*	$NetBSD: siop.c,v 1.79 2005/11/18 23:10:32 bouyer Exp $	*/
3
4/*
5 * Copyright (c) 2000 Manuel Bouyer.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29/* SYM53c7/8xx PCI-SCSI I/O Processors driver */
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/device.h>
34#include <sys/malloc.h>
35#include <sys/kernel.h>
36#include <sys/endian.h>
37
38#include <machine/bus.h>
39
40#include <dev/microcode/siop/siop.out>
41
42#include <scsi/scsi_all.h>
43#include <scsi/scsi_message.h>
44#include <scsi/scsiconf.h>
45
46#include <dev/ic/siopreg.h>
47#include <dev/ic/siopvar_common.h>
48#include <dev/ic/siopvar.h>
49
50#ifndef SIOP_DEBUG
51#undef SIOP_DEBUG_DR
52#undef SIOP_DEBUG_INTR
53#undef SIOP_DEBUG_SCHED
54#undef DUMP_SCRIPT
55#else
56#define SIOP_DEBUG_DR
57#define SIOP_DEBUG_INTR
58#define SIOP_DEBUG_SCHED
59#define DUMP_SCRIPT
60#endif
61
62
63#undef 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 (PAGE_SIZE / sizeof(struct siop_xfer))
71
72/* Number of scheduler slot (needs to match script) */
73#define SIOP_NSLOTS 40
74
75void	siop_table_sync(struct siop_cmd *, int);
76void	siop_script_sync(struct siop_softc *, int);
77u_int32_t siop_script_read(struct siop_softc *, u_int);
78void	siop_script_write(struct siop_softc *, u_int, u_int32_t);
79void	siop_reset(struct siop_softc *);
80void	siop_handle_reset(struct siop_softc *);
81int	siop_handle_qtag_reject(struct siop_cmd *);
82void	siop_scsicmd_end(struct siop_cmd *);
83void	siop_start(struct siop_softc *);
84void 	siop_timeout(void *);
85void	siop_scsicmd(struct scsi_xfer *);
86void *	siop_cmd_get(void *);
87void	siop_cmd_put(void *, void *);
88int	siop_scsiprobe(struct scsi_link *);
89void	siop_scsifree(struct scsi_link *);
90#ifdef DUMP_SCRIPT
91void	siop_dump_script(struct siop_softc *);
92#endif
93void	siop_morecbd(struct siop_softc *);
94struct siop_lunsw *siop_get_lunsw(struct siop_softc *);
95void	siop_add_reselsw(struct siop_softc *, int);
96void	siop_update_scntl3(struct siop_softc *, struct siop_common_target *);
97
98struct siop_dmamem *siop_dmamem_alloc(struct siop_softc *, size_t);
99void	siop_dmamem_free(struct siop_softc *, struct siop_dmamem *);
100
101struct cfdriver siop_cd = {
102	NULL, "siop", DV_DULL
103};
104
105const struct scsi_adapter siop_switch = {
106	siop_scsicmd, NULL, siop_scsiprobe, siop_scsifree, NULL
107};
108
109#ifdef SIOP_STATS
110static int siop_stat_intr = 0;
111static int siop_stat_intr_shortxfer = 0;
112static int siop_stat_intr_sdp = 0;
113static int siop_stat_intr_saveoffset = 0;
114static int siop_stat_intr_done = 0;
115static int siop_stat_intr_xferdisc = 0;
116static int siop_stat_intr_lunresel = 0;
117static int siop_stat_intr_qfull = 0;
118void siop_printstats(void);
119#define INCSTAT(x) x++
120#else
121#define INCSTAT(x)
122#endif
123
124void
125siop_table_sync(struct siop_cmd *siop_cmd, int ops)
126{
127	struct siop_common_softc *sc  = siop_cmd->cmd_c.siop_sc;
128	bus_addr_t offset;
129
130	offset = siop_cmd->cmd_c.dsa -
131	    SIOP_DMA_DVA(siop_cmd->siop_cbdp->xfers);
132	bus_dmamap_sync(sc->sc_dmat,
133	    SIOP_DMA_MAP(siop_cmd->siop_cbdp->xfers), offset,
134	    sizeof(struct siop_xfer), ops);
135}
136
137void
138siop_script_sync(struct siop_softc *sc, int ops)
139{
140	if ((sc->sc_c.features & SF_CHIP_RAM) == 0)
141		bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
142		    PAGE_SIZE, ops);
143}
144
145u_int32_t
146siop_script_read(struct siop_softc *sc, u_int offset)
147{
148	if (sc->sc_c.features & SF_CHIP_RAM) {
149		return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
150		    offset * 4);
151	} else {
152		return siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[offset]);
153	}
154}
155
156void
157siop_script_write(struct siop_softc *sc, u_int offset, u_int32_t val)
158{
159	if (sc->sc_c.features & SF_CHIP_RAM) {
160		bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
161		    offset * 4, val);
162	} else {
163		sc->sc_c.sc_script[offset] = siop_htoc32(&sc->sc_c, val);
164	}
165}
166
167void
168siop_attach(struct siop_softc *sc)
169{
170	struct scsibus_attach_args saa;
171
172	if (siop_common_attach(&sc->sc_c) != 0)
173		return;
174
175	TAILQ_INIT(&sc->free_list);
176	TAILQ_INIT(&sc->ready_list);
177	TAILQ_INIT(&sc->urgent_list);
178	TAILQ_INIT(&sc->cmds);
179	TAILQ_INIT(&sc->lunsw_list);
180	scsi_iopool_init(&sc->iopool, sc, siop_cmd_get, siop_cmd_put);
181	sc->sc_currschedslot = 0;
182
183	/* Start with one page worth of commands */
184	siop_morecbd(sc);
185
186#ifdef SIOP_DEBUG
187	printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
188	    sc->sc_c.sc_dev.dv_xname, (int)sizeof(siop_script),
189	    (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script);
190#endif
191
192	/* Do a bus reset, so that devices fall back to narrow/async */
193	siop_resetbus(&sc->sc_c);
194	/*
195	 * siop_reset() will reset the chip, thus clearing pending interrupts
196	 */
197	siop_reset(sc);
198#ifdef DUMP_SCRIPT
199	siop_dump_script(sc);
200#endif
201
202	saa.saa_adapter_softc = sc;
203	saa.saa_adapter = &siop_switch;
204	saa.saa_adapter_target = sc->sc_c.sc_id;
205	saa.saa_adapter_buswidth = (sc->sc_c.features & SF_BUS_WIDE) ? 16 : 8;
206	saa.saa_luns = 8;
207	saa.saa_openings = SIOP_NTAG;
208	saa.saa_pool = &sc->iopool;
209	saa.saa_quirks = saa.saa_flags = 0;
210	saa.saa_wwpn = saa.saa_wwnn = 0;
211
212	config_found((struct device*)sc, &saa, scsiprint);
213}
214
215void
216siop_reset(struct siop_softc *sc)
217{
218	int i, j, buswidth;
219	struct siop_lunsw *lunsw;
220
221	siop_common_reset(&sc->sc_c);
222
223	/* copy and patch the script */
224	if (sc->sc_c.features & SF_CHIP_RAM) {
225		bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0,
226		    siop_script, sizeof(siop_script) / sizeof(siop_script[0]));
227		for (j = 0; j <
228		    (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
229		    j++) {
230			bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
231			    E_abs_msgin_Used[j] * 4,
232			    sc->sc_c.sc_scriptaddr + Ent_msgin_space);
233		}
234		if (sc->sc_c.features & SF_CHIP_LED0) {
235			bus_space_write_region_4(sc->sc_c.sc_ramt,
236			    sc->sc_c.sc_ramh,
237			    Ent_led_on1, siop_led_on,
238			    sizeof(siop_led_on) / sizeof(siop_led_on[0]));
239			bus_space_write_region_4(sc->sc_c.sc_ramt,
240			    sc->sc_c.sc_ramh,
241			    Ent_led_on2, siop_led_on,
242			    sizeof(siop_led_on) / sizeof(siop_led_on[0]));
243			bus_space_write_region_4(sc->sc_c.sc_ramt,
244			    sc->sc_c.sc_ramh,
245			    Ent_led_off, siop_led_off,
246			    sizeof(siop_led_off) / sizeof(siop_led_off[0]));
247		}
248	} else {
249		for (j = 0;
250		    j < (sizeof(siop_script) / sizeof(siop_script[0])); j++) {
251			sc->sc_c.sc_script[j] =
252			    siop_htoc32(&sc->sc_c, siop_script[j]);
253		}
254		for (j = 0; j <
255		    (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
256		    j++) {
257			sc->sc_c.sc_script[E_abs_msgin_Used[j]] =
258			    siop_htoc32(&sc->sc_c,
259				sc->sc_c.sc_scriptaddr + Ent_msgin_space);
260		}
261		if (sc->sc_c.features & SF_CHIP_LED0) {
262			for (j = 0; j < (sizeof(siop_led_on) /
263			    sizeof(siop_led_on[0])); j++)
264				sc->sc_c.sc_script[
265				    Ent_led_on1 / sizeof(siop_led_on[0]) + j
266				    ] = siop_htoc32(&sc->sc_c, siop_led_on[j]);
267			for (j = 0; j < (sizeof(siop_led_on) /
268			    sizeof(siop_led_on[0])); j++)
269				sc->sc_c.sc_script[
270				    Ent_led_on2 / sizeof(siop_led_on[0]) + j
271				    ] = siop_htoc32(&sc->sc_c, siop_led_on[j]);
272			for (j = 0; j < (sizeof(siop_led_off) /
273			    sizeof(siop_led_off[0])); j++)
274				sc->sc_c.sc_script[
275				   Ent_led_off / sizeof(siop_led_off[0]) + j
276				   ] = siop_htoc32(&sc->sc_c, siop_led_off[j]);
277		}
278	}
279	sc->script_free_lo = sizeof(siop_script) / sizeof(siop_script[0]);
280	sc->script_free_hi = sc->sc_c.ram_size / 4;
281	sc->sc_ntargets = 0;
282
283	/* free used and unused lun switches */
284	while((lunsw = TAILQ_FIRST(&sc->lunsw_list)) != NULL) {
285#ifdef SIOP_DEBUG
286		printf("%s: free lunsw at offset %d\n",
287				sc->sc_c.sc_dev.dv_xname, lunsw->lunsw_off);
288#endif
289		TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
290		free(lunsw, M_DEVBUF, 0);
291	}
292	TAILQ_INIT(&sc->lunsw_list);
293	/* restore reselect switch */
294	buswidth = (sc->sc_c.features & SF_BUS_WIDE) ? 16 : 8;
295	for (i = 0; i < buswidth; i++) {
296		struct siop_target *target;
297		if (sc->sc_c.targets[i] == NULL)
298			continue;
299#ifdef SIOP_DEBUG
300		printf("%s: restore sw for target %d\n",
301				sc->sc_c.sc_dev.dv_xname, i);
302#endif
303		target = (struct siop_target *)sc->sc_c.targets[i];
304		free(target->lunsw, M_DEVBUF, 0);
305		target->lunsw = siop_get_lunsw(sc);
306		if (target->lunsw == NULL) {
307			printf("%s: can't alloc lunsw for target %d\n",
308			    sc->sc_c.sc_dev.dv_xname, i);
309			break;
310		}
311		siop_add_reselsw(sc, i);
312	}
313
314	/* start script */
315	if ((sc->sc_c.features & SF_CHIP_RAM) == 0) {
316		bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
317		    PAGE_SIZE, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
318	}
319	bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP,
320	    sc->sc_c.sc_scriptaddr + Ent_reselect);
321}
322
323#if 0
324#define CALL_SCRIPT(ent) do {\
325	printf ("start script DSA 0x%lx DSP 0x%lx\n", \
326	    siop_cmd->cmd_c.dsa, \
327	    sc->sc_c.sc_scriptaddr + ent); \
328bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
329} while (0)
330#else
331#define CALL_SCRIPT(ent) do {\
332bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
333} while (0)
334#endif
335
336int
337siop_intr(void *v)
338{
339	struct siop_softc *sc = v;
340	struct siop_target *siop_target;
341	struct siop_cmd *siop_cmd;
342	struct siop_lun *siop_lun;
343	struct scsi_xfer *xs;
344	int istat, sist, sstat1, dstat = 0;
345	u_int32_t irqcode;
346	int need_reset = 0;
347	int offset, target, lun, tag;
348	bus_addr_t dsa;
349	struct siop_cbd *cbdp;
350	int restart = 0;
351
352	istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT);
353	if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
354		return 0;
355	INCSTAT(siop_stat_intr);
356	if (istat & ISTAT_INTF) {
357		printf("INTRF\n");
358		bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
359		    SIOP_ISTAT, ISTAT_INTF);
360	}
361	if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
362	    (ISTAT_DIP | ISTAT_ABRT)) {
363		/* clear abort */
364		bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
365		    SIOP_ISTAT, 0);
366	}
367	/* use DSA to find the current siop_cmd */
368	siop_cmd = NULL;
369	dsa = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA);
370	TAILQ_FOREACH(cbdp, &sc->cmds, next) {
371		if (dsa >= SIOP_DMA_DVA(cbdp->xfers) &&
372	    	    dsa < SIOP_DMA_DVA(cbdp->xfers) + PAGE_SIZE) {
373			dsa -= SIOP_DMA_DVA(cbdp->xfers);
374			siop_cmd = &cbdp->cmds[dsa / sizeof(struct siop_xfer)];
375			siop_table_sync(siop_cmd,
376			    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
377			break;
378		}
379	}
380	if (siop_cmd) {
381		xs = siop_cmd->cmd_c.xs;
382		siop_target = (struct siop_target *)siop_cmd->cmd_c.siop_target;
383		target = siop_cmd->cmd_c.xs->sc_link->target;
384		lun = siop_cmd->cmd_c.xs->sc_link->lun;
385		tag = siop_cmd->cmd_c.tag;
386		siop_lun = siop_target->siop_lun[lun];
387#ifdef DIAGNOSTIC
388		if (siop_cmd->cmd_c.status != CMDST_ACTIVE &&
389		    siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE) {
390 			printf("siop_cmd (lun %d) for DSA 0x%x "
391			    "not active (%d)\n", lun, (u_int)dsa,
392			    siop_cmd->cmd_c.status);
393			xs = NULL;
394			siop_target = NULL;
395			target = -1;
396			lun = -1;
397			tag = -1;
398			siop_lun = NULL;
399			siop_cmd = NULL;
400		} else if (siop_lun->siop_tag[tag].active != siop_cmd) {
401			printf("siop_cmd (lun %d tag %d) not in siop_lun "
402			    "active (%p != %p)\n", lun, tag, siop_cmd,
403			    siop_lun->siop_tag[tag].active);
404		}
405#endif
406	} else {
407		xs = NULL;
408		siop_target = NULL;
409		target = -1;
410		lun = -1;
411		tag = -1;
412		siop_lun = NULL;
413	}
414	if (istat & ISTAT_DIP) {
415		dstat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
416		    SIOP_DSTAT);
417		if (dstat & DSTAT_ABRT) {
418			/* was probably generated by a bus reset IOCTL */
419			if ((dstat & DSTAT_DFE) == 0)
420				siop_clearfifo(&sc->sc_c);
421			goto reset;
422		}
423		if (dstat & DSTAT_SSI) {
424			printf("single step dsp 0x%08x dsa 0x08%x\n",
425			    (int)(bus_space_read_4(sc->sc_c.sc_rt,
426			    sc->sc_c.sc_rh, SIOP_DSP) -
427			    sc->sc_c.sc_scriptaddr),
428			    bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
429				SIOP_DSA));
430			if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
431			    (istat & ISTAT_SIP) == 0) {
432				bus_space_write_1(sc->sc_c.sc_rt,
433				    sc->sc_c.sc_rh, SIOP_DCNTL,
434				    bus_space_read_1(sc->sc_c.sc_rt,
435				    sc->sc_c.sc_rh, SIOP_DCNTL) | DCNTL_STD);
436			}
437			return 1;
438		}
439
440		if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
441			printf("%s: DMA IRQ:", sc->sc_c.sc_dev.dv_xname);
442			if (dstat & DSTAT_IID)
443				printf(" illegal instruction");
444			if (dstat & DSTAT_BF)
445				printf(" bus fault");
446			if (dstat & DSTAT_MDPE)
447				printf(" parity");
448			if (dstat & DSTAT_DFE)
449				printf(" DMA fifo empty");
450			else
451				siop_clearfifo(&sc->sc_c);
452			printf(", DSP=0x%x DSA=0x%x: ",
453			    (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
454				SIOP_DSP) - sc->sc_c.sc_scriptaddr),
455			    bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
456			if (siop_cmd)
457				printf("last msg_in=0x%x status=0x%x\n",
458				    siop_cmd->cmd_tables->msg_in[0],
459				    siop_ctoh32(&sc->sc_c,
460					siop_cmd->cmd_tables->status));
461			else
462				printf("current DSA invalid\n");
463			need_reset = 1;
464		}
465	}
466	if (istat & ISTAT_SIP) {
467		if (istat & ISTAT_DIP)
468			delay(10);
469		/*
470		 * Can't read sist0 & sist1 independently, or we have to
471		 * insert delay
472		 */
473		sist = bus_space_read_2(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
474		    SIOP_SIST0);
475		sstat1 = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
476		    SIOP_SSTAT1);
477#ifdef SIOP_DEBUG_INTR
478		printf("scsi interrupt, sist=0x%x sstat1=0x%x "
479		    "DSA=0x%x DSP=0x%lx\n", sist, sstat1,
480		    bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
481		    (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
482			SIOP_DSP) -
483		    sc->sc_c.sc_scriptaddr));
484#endif
485		if (sist & SIST0_RST) {
486			siop_handle_reset(sc);
487			siop_start(sc);
488			/* no table to flush here */
489			return 1;
490		}
491		if (sist & SIST0_SGE) {
492			if (siop_cmd)
493				sc_print_addr(xs->sc_link);
494			else
495				printf("%s: ", sc->sc_c.sc_dev.dv_xname);
496			printf("scsi gross error\n");
497			goto reset;
498		}
499		if ((sist & SIST0_MA) && need_reset == 0) {
500			if (siop_cmd) {
501				int scratcha0;
502				/* XXX Why read DSTAT again? */
503				dstat = bus_space_read_1(sc->sc_c.sc_rt,
504				    sc->sc_c.sc_rh, SIOP_DSTAT);
505				/*
506				 * first restore DSA, in case we were in a S/G
507				 * operation.
508				 */
509				bus_space_write_4(sc->sc_c.sc_rt,
510				    sc->sc_c.sc_rh,
511				    SIOP_DSA, siop_cmd->cmd_c.dsa);
512				scratcha0 = bus_space_read_1(sc->sc_c.sc_rt,
513				    sc->sc_c.sc_rh, SIOP_SCRATCHA);
514				switch (sstat1 & SSTAT1_PHASE_MASK) {
515				case SSTAT1_PHASE_STATUS:
516				/*
517				 * previous phase may be aborted for any reason
518				 * ( for example, the target has less data to
519				 * transfer than requested). Compute resid and
520				 * just go to status, the command should
521				 * terminate.
522				 */
523					INCSTAT(siop_stat_intr_shortxfer);
524					if (scratcha0 & A_flag_data)
525						siop_ma(&siop_cmd->cmd_c);
526					else if ((dstat & DSTAT_DFE) == 0)
527						siop_clearfifo(&sc->sc_c);
528					CALL_SCRIPT(Ent_status);
529					return 1;
530				case SSTAT1_PHASE_MSGIN:
531				/*
532				 * target may be ready to disconnect
533				 * Compute resid which would be used later
534				 * if a save data pointer is needed.
535				 */
536					INCSTAT(siop_stat_intr_xferdisc);
537					if (scratcha0 & A_flag_data)
538						siop_ma(&siop_cmd->cmd_c);
539					else if ((dstat & DSTAT_DFE) == 0)
540						siop_clearfifo(&sc->sc_c);
541					bus_space_write_1(sc->sc_c.sc_rt,
542					    sc->sc_c.sc_rh, SIOP_SCRATCHA,
543					    scratcha0 & ~A_flag_data);
544					CALL_SCRIPT(Ent_msgin);
545					return 1;
546				}
547				printf("%s: unexpected phase mismatch %d\n",
548				    sc->sc_c.sc_dev.dv_xname,
549				    sstat1 & SSTAT1_PHASE_MASK);
550			} else {
551				printf("%s: phase mismatch without command\n",
552				    sc->sc_c.sc_dev.dv_xname);
553			}
554			need_reset = 1;
555		}
556		if (sist & SIST0_PAR) {
557			/* parity error, reset */
558			if (siop_cmd)
559				sc_print_addr(xs->sc_link);
560			else
561				printf("%s: ", sc->sc_c.sc_dev.dv_xname);
562			printf("parity error\n");
563			goto reset;
564		}
565		if ((sist & (SIST1_STO << 8)) && need_reset == 0) {
566			/* selection time out, assume there's no device here */
567			if (siop_cmd) {
568				siop_cmd->cmd_c.status = CMDST_DONE;
569				xs->error = XS_SELTIMEOUT;
570				goto end;
571			} else {
572				printf("%s: selection timeout without "
573				    "command\n", sc->sc_c.sc_dev.dv_xname);
574				need_reset = 1;
575			}
576		}
577		if (sist & SIST0_UDC) {
578			/*
579			 * unexpected disconnect. Usually the target signals
580			 * a fatal condition this way. Attempt to get sense.
581			 */
582			if (siop_cmd) {
583				siop_cmd->cmd_tables->status =
584				    siop_htoc32(&sc->sc_c, SCSI_CHECK);
585				goto end;
586			}
587			printf("%s: unexpected disconnect without "
588			    "command\n", sc->sc_c.sc_dev.dv_xname);
589			goto reset;
590		}
591		if (sist & (SIST1_SBMC << 8)) {
592			/* SCSI bus mode change */
593			if (siop_modechange(&sc->sc_c) == 0 || need_reset == 1)
594				goto reset;
595			if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
596				/*
597				 * we have a script interrupt, it will
598				 * restart the script.
599				 */
600				goto scintr;
601			}
602			/*
603			 * else we have to restart it ourselves, at the
604			 * interrupted instruction.
605			 */
606			bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
607			    SIOP_DSP,
608			    bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
609			    SIOP_DSP) - 8);
610			return 1;
611		}
612		/* Else it's an unhandled exception (for now). */
613		printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x "
614		    "DSA=0x%x DSP=0x%x\n", sc->sc_c.sc_dev.dv_xname,
615		    sist, sstat1,
616		    bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
617		    (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
618			SIOP_DSP) - sc->sc_c.sc_scriptaddr));
619		if (siop_cmd) {
620			siop_cmd->cmd_c.status = CMDST_DONE;
621			xs->error = XS_SELTIMEOUT;
622			goto end;
623		}
624		need_reset = 1;
625	} else {
626		sist = sstat1 = 0;
627	}
628	if (need_reset) {
629reset:
630		/* fatal error, reset the bus */
631		siop_resetbus(&sc->sc_c);
632		/* no table to flush here */
633		return 1;
634	}
635
636scintr:
637	if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
638		irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
639		    SIOP_DSPS);
640#ifdef SIOP_DEBUG_INTR
641		printf("script interrupt 0x%x\n", irqcode);
642#endif
643		/*
644		 * no command, or an inactive command is only valid for a
645		 * reselect interrupt
646		 */
647		if ((irqcode & 0x80) == 0) {
648			if (siop_cmd == NULL) {
649				printf(
650			"%s: script interrupt (0x%x) with invalid DSA !!!\n",
651				    sc->sc_c.sc_dev.dv_xname, irqcode);
652				goto reset;
653			}
654			if (siop_cmd->cmd_c.status != CMDST_ACTIVE &&
655			    siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE) {
656				printf("%s: command with invalid status "
657				    "(IRQ code 0x%x current status %d) !\n",
658				    sc->sc_c.sc_dev.dv_xname,
659				    irqcode, siop_cmd->cmd_c.status);
660				xs = NULL;
661			}
662		}
663		switch(irqcode) {
664		case A_int_err:
665			printf("error, DSP=0x%x\n",
666			    (int)(bus_space_read_4(sc->sc_c.sc_rt,
667			    sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
668			if (xs) {
669				xs->error = XS_SELTIMEOUT;
670				goto end;
671			} else {
672				goto reset;
673			}
674		case A_int_reseltarg:
675			printf("%s: reselect with invalid target\n",
676				    sc->sc_c.sc_dev.dv_xname);
677			goto reset;
678		case A_int_resellun:
679			INCSTAT(siop_stat_intr_lunresel);
680			target = bus_space_read_1(sc->sc_c.sc_rt,
681			    sc->sc_c.sc_rh, SIOP_SCRATCHA) & 0xf;
682			lun = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
683			    SIOP_SCRATCHA + 1);
684			tag = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
685			    SIOP_SCRATCHA + 2);
686			siop_target =
687			    (struct siop_target *)sc->sc_c.targets[target];
688			if (siop_target == NULL) {
689				printf("%s: reselect with invalid target %d\n",
690				    sc->sc_c.sc_dev.dv_xname, target);
691				goto reset;
692			}
693			siop_lun = siop_target->siop_lun[lun];
694			if (siop_lun == NULL) {
695				printf("%s: target %d reselect with invalid "
696				    "lun %d\n", sc->sc_c.sc_dev.dv_xname,
697				    target, lun);
698				goto reset;
699			}
700			if (siop_lun->siop_tag[tag].active == NULL) {
701				printf("%s: target %d lun %d tag %d reselect "
702				    "without command\n",
703				    sc->sc_c.sc_dev.dv_xname,
704				    target, lun, tag);
705				goto reset;
706			}
707			siop_cmd = siop_lun->siop_tag[tag].active;
708			bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
709			    SIOP_DSP, siop_cmd->cmd_c.dsa +
710			    sizeof(struct siop_common_xfer) +
711			    Ent_ldsa_reload_dsa);
712			siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
713			return 1;
714		case A_int_reseltag:
715			printf("%s: reselect with invalid tag\n",
716				    sc->sc_c.sc_dev.dv_xname);
717			goto reset;
718		case A_int_msgin:
719		{
720			int msgin = bus_space_read_1(sc->sc_c.sc_rt,
721			    sc->sc_c.sc_rh, SIOP_SFBR);
722			if (msgin == MSG_MESSAGE_REJECT) {
723				int msg, extmsg;
724				if (siop_cmd->cmd_tables->msg_out[0] & 0x80) {
725					/*
726					 * message was part of a identify +
727					 * something else. Identify shouldn't
728					 * have been rejected.
729					 */
730					msg =
731					    siop_cmd->cmd_tables->msg_out[1];
732					extmsg =
733					    siop_cmd->cmd_tables->msg_out[3];
734				} else {
735					msg = siop_cmd->cmd_tables->msg_out[0];
736					extmsg =
737					    siop_cmd->cmd_tables->msg_out[2];
738				}
739				if (msg == MSG_MESSAGE_REJECT) {
740					/* MSG_REJECT  for a MSG_REJECT  !*/
741					if (xs)
742						sc_print_addr(xs->sc_link);
743					else
744						printf("%s: ",
745						   sc->sc_c.sc_dev.dv_xname);
746					printf("our reject message was "
747					    "rejected\n");
748					goto reset;
749				}
750				if (msg == MSG_EXTENDED &&
751				    extmsg == MSG_EXT_WDTR) {
752					/* WDTR rejected, initiate sync */
753					if ((siop_target->target_c.flags &
754					   TARF_SYNC) == 0) {
755						siop_target->target_c.status =
756						    TARST_OK;
757						siop_update_xfer_mode(&sc->sc_c,
758						    target);
759						/* no table to flush here */
760						CALL_SCRIPT(Ent_msgin_ack);
761						return 1;
762					}
763					siop_target->target_c.status =
764					    TARST_SYNC_NEG;
765					siop_sdtr_msg(&siop_cmd->cmd_c, 0,
766					    sc->sc_c.st_minsync,
767					    sc->sc_c.maxoff);
768					siop_table_sync(siop_cmd,
769					    BUS_DMASYNC_PREREAD |
770					    BUS_DMASYNC_PREWRITE);
771					CALL_SCRIPT(Ent_send_msgout);
772					return 1;
773				} else if (msg == MSG_EXTENDED &&
774				    extmsg == MSG_EXT_SDTR) {
775					/* sync rejected */
776					siop_target->target_c.offset = 0;
777					siop_target->target_c.period = 0;
778					siop_target->target_c.status = TARST_OK;
779					siop_update_xfer_mode(&sc->sc_c,
780					    target);
781					/* no table to flush here */
782					CALL_SCRIPT(Ent_msgin_ack);
783					return 1;
784				} else if (msg == MSG_EXTENDED &&
785				    extmsg == MSG_EXT_PPR) {
786					/* PPR negotiation rejected */
787					siop_target->target_c.offset = 0;
788					siop_target->target_c.period = 0;
789					siop_target->target_c.status = TARST_ASYNC;
790					siop_target->target_c.flags &= ~(TARF_DT | TARF_ISDT);
791					CALL_SCRIPT(Ent_msgin_ack);
792					return 1;
793				} else if (msg == MSG_SIMPLE_Q_TAG ||
794				    msg == MSG_HEAD_OF_Q_TAG ||
795				    msg == MSG_ORDERED_Q_TAG) {
796					if (siop_handle_qtag_reject(
797					    siop_cmd) == -1)
798						goto reset;
799					CALL_SCRIPT(Ent_msgin_ack);
800					return 1;
801				}
802				if (xs)
803					sc_print_addr(xs->sc_link);
804				else
805					printf("%s: ",
806					    sc->sc_c.sc_dev.dv_xname);
807				if (msg == MSG_EXTENDED) {
808					printf("scsi message reject, extended "
809					    "message sent was 0x%x\n", extmsg);
810				} else {
811					printf("scsi message reject, message "
812					    "sent was 0x%x\n", msg);
813				}
814				/* no table to flush here */
815				CALL_SCRIPT(Ent_msgin_ack);
816				return 1;
817			}
818			if (msgin == MSG_IGN_WIDE_RESIDUE) {
819			/* use the extmsgdata table to get the second byte */
820				siop_cmd->cmd_tables->t_extmsgdata.count =
821				    siop_htoc32(&sc->sc_c, 1);
822				siop_table_sync(siop_cmd,
823				    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
824				CALL_SCRIPT(Ent_get_extmsgdata);
825				return 1;
826			}
827			if (xs)
828				sc_print_addr(xs->sc_link);
829			else
830				printf("%s: ", sc->sc_c.sc_dev.dv_xname);
831			printf("unhandled message 0x%x\n",
832			    siop_cmd->cmd_tables->msg_in[0]);
833			siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
834			siop_cmd->cmd_tables->t_msgout.count =
835			    siop_htoc32(&sc->sc_c, 1);
836			siop_table_sync(siop_cmd,
837			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
838			CALL_SCRIPT(Ent_send_msgout);
839			return 1;
840		}
841		case A_int_extmsgin:
842#ifdef SIOP_DEBUG_INTR
843			printf("extended message: msg 0x%x len %d\n",
844			    siop_cmd->cmd_tables->msg_in[2],
845			    siop_cmd->cmd_tables->msg_in[1]);
846#endif
847			if (siop_cmd->cmd_tables->msg_in[1] >
848			    sizeof(siop_cmd->cmd_tables->msg_in) - 2)
849				printf("%s: extended message too big (%d)\n",
850				    sc->sc_c.sc_dev.dv_xname,
851				    siop_cmd->cmd_tables->msg_in[1]);
852			siop_cmd->cmd_tables->t_extmsgdata.count =
853			    siop_htoc32(&sc->sc_c,
854			        siop_cmd->cmd_tables->msg_in[1] - 1);
855			siop_table_sync(siop_cmd,
856			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
857			CALL_SCRIPT(Ent_get_extmsgdata);
858			return 1;
859		case A_int_extmsgdata:
860#ifdef SIOP_DEBUG_INTR
861			{
862			int i;
863			printf("extended message: 0x%x, data:",
864			    siop_cmd->cmd_tables->msg_in[2]);
865			for (i = 3; i < 2 + siop_cmd->cmd_tables->msg_in[1];
866			    i++)
867				printf(" 0x%x",
868				    siop_cmd->cmd_tables->msg_in[i]);
869			printf("\n");
870			}
871#endif
872			if (siop_cmd->cmd_tables->msg_in[0] ==
873			    MSG_IGN_WIDE_RESIDUE) {
874			/* we got the second byte of MSG_IGN_WIDE_RESIDUE */
875				if (siop_cmd->cmd_tables->msg_in[3] != 1)
876					printf("MSG_IGN_WIDE_RESIDUE: "
877					    "bad len %d\n",
878					    siop_cmd->cmd_tables->msg_in[3]);
879				switch (siop_iwr(&siop_cmd->cmd_c)) {
880				case SIOP_NEG_MSGOUT:
881					siop_table_sync(siop_cmd,
882					    BUS_DMASYNC_PREREAD |
883					    BUS_DMASYNC_PREWRITE);
884					CALL_SCRIPT(Ent_send_msgout);
885					return(1);
886				case SIOP_NEG_ACK:
887					CALL_SCRIPT(Ent_msgin_ack);
888					return(1);
889				default:
890					panic("invalid retval from "
891					    "siop_iwr()");
892				}
893				return(1);
894			}
895			if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
896				switch (siop_wdtr_neg(&siop_cmd->cmd_c)) {
897				case SIOP_NEG_MSGOUT:
898					siop_update_scntl3(sc,
899					    siop_cmd->cmd_c.siop_target);
900					siop_table_sync(siop_cmd,
901					    BUS_DMASYNC_PREREAD |
902					    BUS_DMASYNC_PREWRITE);
903					CALL_SCRIPT(Ent_send_msgout);
904					return(1);
905				case SIOP_NEG_ACK:
906					siop_update_scntl3(sc,
907					    siop_cmd->cmd_c.siop_target);
908					CALL_SCRIPT(Ent_msgin_ack);
909					return(1);
910				default:
911					panic("invalid retval from "
912					    "siop_wdtr_neg()");
913				}
914				return(1);
915			}
916			if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) {
917				switch (siop_sdtr_neg(&siop_cmd->cmd_c)) {
918				case SIOP_NEG_MSGOUT:
919					siop_update_scntl3(sc,
920					    siop_cmd->cmd_c.siop_target);
921					siop_table_sync(siop_cmd,
922					    BUS_DMASYNC_PREREAD |
923					    BUS_DMASYNC_PREWRITE);
924					CALL_SCRIPT(Ent_send_msgout);
925					return(1);
926				case SIOP_NEG_ACK:
927					siop_update_scntl3(sc,
928					    siop_cmd->cmd_c.siop_target);
929					CALL_SCRIPT(Ent_msgin_ack);
930					return(1);
931				default:
932					panic("invalid retval from "
933					    "siop_sdtr_neg()");
934				}
935				return(1);
936			}
937			if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) {
938				switch (siop_ppr_neg(&siop_cmd->cmd_c)) {
939				case SIOP_NEG_MSGOUT:
940					siop_update_scntl3(sc,
941					    siop_cmd->cmd_c.siop_target);
942					siop_table_sync(siop_cmd,
943					    BUS_DMASYNC_PREREAD |
944					    BUS_DMASYNC_PREWRITE);
945					CALL_SCRIPT(Ent_send_msgout);
946					return(1);
947				case SIOP_NEG_ACK:
948					siop_update_scntl3(sc,
949					    siop_cmd->cmd_c.siop_target);
950					CALL_SCRIPT(Ent_msgin_ack);
951					return(1);
952				default:
953					panic("invalid retval from "
954					    "siop_wdtr_neg()");
955				}
956				return(1);
957			}
958			/* send a message reject */
959			siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
960			siop_cmd->cmd_tables->t_msgout.count =
961			    siop_htoc32(&sc->sc_c, 1);
962			siop_table_sync(siop_cmd,
963			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
964			CALL_SCRIPT(Ent_send_msgout);
965			return 1;
966		case A_int_disc:
967			INCSTAT(siop_stat_intr_sdp);
968			offset = bus_space_read_1(sc->sc_c.sc_rt,
969			    sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
970#ifdef SIOP_DEBUG_DR
971			printf("disconnect offset %d\n", offset);
972#endif
973			siop_sdp(&siop_cmd->cmd_c, offset);
974			/* we start again with no offset */
975			siop_cmd->saved_offset = SIOP_NOOFFSET;
976			siop_table_sync(siop_cmd,
977			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
978			CALL_SCRIPT(Ent_script_sched);
979			return 1;
980		case A_int_saveoffset:
981			INCSTAT(siop_stat_intr_saveoffset);
982			offset = bus_space_read_1(sc->sc_c.sc_rt,
983			    sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
984#ifdef SIOP_DEBUG_DR
985			printf("saveoffset offset %d\n", offset);
986#endif
987			siop_cmd->saved_offset = offset;
988			CALL_SCRIPT(Ent_script_sched);
989			return 1;
990		case A_int_resfail:
991			printf("reselect failed\n");
992			/* check if we can put some command in scheduler */
993			siop_start(sc);
994			CALL_SCRIPT(Ent_script_sched);
995			return  1;
996		case A_int_done:
997			if (xs == NULL) {
998				printf("%s: done without command, DSA=0x%lx\n",
999				    sc->sc_c.sc_dev.dv_xname,
1000				    (u_long)siop_cmd->cmd_c.dsa);
1001				siop_cmd->cmd_c.status = CMDST_FREE;
1002				siop_start(sc);
1003				CALL_SCRIPT(Ent_script_sched);
1004				return 1;
1005			}
1006#ifdef SIOP_DEBUG_INTR
1007			printf("done, DSA=0x%lx target id 0x%x last msg "
1008			    "in=0x%x status=0x%x\n", (u_long)siop_cmd->cmd_c.dsa,
1009			    siop_ctoh32(&sc->sc_c, siop_cmd->cmd_tables->id),
1010			    siop_cmd->cmd_tables->msg_in[0],
1011			    siop_ctoh32(&sc->sc_c,
1012				siop_cmd->cmd_tables->status));
1013#endif
1014			INCSTAT(siop_stat_intr_done);
1015			/* update resid.  */
1016			offset = bus_space_read_1(sc->sc_c.sc_rt,
1017			    sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
1018			/*
1019			 * if we got a disconnect between the last data phase
1020			 * and the status phase, offset will be 0. In this
1021			 * case, siop_cmd->saved_offset will have the proper
1022			 * value if it got updated by the controller
1023			 */
1024			if (offset == 0 &&
1025			    siop_cmd->saved_offset != SIOP_NOOFFSET)
1026				offset = siop_cmd->saved_offset;
1027			siop_update_resid(&siop_cmd->cmd_c, offset);
1028			if (siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE)
1029				siop_cmd->cmd_c.status = CMDST_SENSE_DONE;
1030			else
1031				siop_cmd->cmd_c.status = CMDST_DONE;
1032			goto end;
1033		default:
1034			printf("unknown irqcode %x\n", irqcode);
1035			if (xs) {
1036				xs->error = XS_SELTIMEOUT;
1037				goto end;
1038			}
1039			goto reset;
1040		}
1041		return 1;
1042	} else
1043		irqcode = 0;
1044	/* We can get here if ISTAT_DIP and DSTAT_DFE are the only bits set. */
1045	/* But that *SHOULDN'T* happen. It does on powerpc (at least).	     */
1046	printf("%s: siop_intr() - we should not be here!\n"
1047	    "   istat = 0x%x, dstat = 0x%x, sist = 0x%x, sstat1 = 0x%x\n"
1048	    "   need_reset = %x, irqcode = %x, siop_cmd %s\n",
1049	    sc->sc_c.sc_dev.dv_xname,
1050	    istat, dstat, sist, sstat1, need_reset, irqcode,
1051	    (siop_cmd == NULL) ? "== NULL" : "!= NULL");
1052	goto reset; /* Where we should have gone in the first place! */
1053end:
1054	/*
1055	 * restart the script now if command completed properly
1056	 * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
1057	 * queue
1058	 */
1059	xs->status = siop_ctoh32(&sc->sc_c, siop_cmd->cmd_tables->status);
1060	if (xs->status == SCSI_OK)
1061		CALL_SCRIPT(Ent_script_sched);
1062	else
1063		restart = 1;
1064	siop_lun->siop_tag[tag].active = NULL;
1065	siop_scsicmd_end(siop_cmd);
1066	siop_start(sc);
1067	if (restart)
1068		CALL_SCRIPT(Ent_script_sched);
1069	return 1;
1070}
1071
1072void
1073siop_scsicmd_end(struct siop_cmd *siop_cmd)
1074{
1075	struct scsi_xfer *xs = siop_cmd->cmd_c.xs;
1076	struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
1077	struct siop_lun *siop_lun =
1078	    ((struct siop_target*)sc->sc_c.targets[xs->sc_link->target])->siop_lun[xs->sc_link->lun];
1079
1080	/*
1081	 * If the command is re-queued (SENSE, QUEUE_FULL) it
1082	 * must get a new timeout, so delete existing timeout now.
1083	 */
1084	timeout_del(&siop_cmd->cmd_c.xs->stimeout);
1085
1086	switch(xs->status) {
1087	case SCSI_OK:
1088		xs->error = (siop_cmd->cmd_c.status == CMDST_DONE) ?
1089		    XS_NOERROR : XS_SENSE;
1090		break;
1091	case SCSI_BUSY:
1092		xs->error = XS_BUSY;
1093		break;
1094	case SCSI_CHECK:
1095		if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) {
1096			/* request sense on a request sense ? */
1097			printf("%s: request sense failed\n",
1098			    sc->sc_c.sc_dev.dv_xname);
1099			xs->error = XS_DRIVER_STUFFUP;
1100		} else {
1101			siop_cmd->cmd_c.status = CMDST_SENSE;
1102		}
1103		break;
1104	case SCSI_QUEUE_FULL:
1105		/*
1106		 * Device didn't queue the command. We have to retry
1107		 * it.  We insert it into the urgent list, hoping to
1108		 * preserve order.  But unfortunately, commands already
1109		 * in the scheduler may be accepted before this one.
1110		 * Also remember the condition, to avoid starting new
1111		 * commands for this device before one is done.
1112		 */
1113		INCSTAT(siop_stat_intr_qfull);
1114#ifdef SIOP_DEBUG
1115		printf("%s:%d:%d: queue full (tag %d)\n", sc->sc_c.sc_dev.dv_xname,
1116		    xs->sc_link->target,
1117		    xs->sc_link->lun, siop_cmd->cmd_c.tag);
1118#endif
1119		siop_lun->lun_flags |= SIOP_LUNF_FULL;
1120		siop_cmd->cmd_c.status = CMDST_READY;
1121		siop_setuptables(&siop_cmd->cmd_c);
1122		siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1123		TAILQ_INSERT_TAIL(&sc->urgent_list, siop_cmd, next);
1124		return;
1125	case SCSI_SIOP_NOCHECK:
1126		/*
1127		 * don't check status, xs->error is already valid
1128		 */
1129		break;
1130	case SCSI_SIOP_NOSTATUS:
1131		/*
1132		 * the status byte was not updated, cmd was
1133		 * aborted
1134		 */
1135		xs->error = XS_SELTIMEOUT;
1136		break;
1137	default:
1138		xs->error = XS_DRIVER_STUFFUP;
1139	}
1140	if (siop_cmd->cmd_c.status != CMDST_SENSE_DONE &&
1141	    xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1142		bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data, 0,
1143		    siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1144		    (xs->flags & SCSI_DATA_IN) ?
1145		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1146		bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data);
1147	}
1148	if (siop_cmd->cmd_c.status == CMDST_SENSE) {
1149		/* issue a request sense for this target */
1150		struct scsi_sense *cmd = (struct scsi_sense *)&siop_cmd->cmd_c.siop_tables->xscmd;
1151		int error;
1152		bzero(cmd, sizeof(*cmd));
1153		siop_cmd->cmd_c.siop_tables->cmd.count =
1154		   siop_htoc32(&sc->sc_c, sizeof(struct scsi_sense));
1155		cmd->opcode = REQUEST_SENSE;
1156		cmd->byte2 = xs->sc_link->lun << 5;
1157		cmd->unused[0] = cmd->unused[1] = 0;
1158		cmd->length = sizeof(struct scsi_sense_data);
1159		cmd->control = 0;
1160		siop_cmd->cmd_c.flags &= ~CMDFL_TAG;
1161		error = bus_dmamap_load(sc->sc_c.sc_dmat,
1162		    siop_cmd->cmd_c.dmamap_data,
1163		    siop_cmd->cmd_c.sense, sizeof(struct scsi_sense_data),
1164		    NULL, BUS_DMA_NOWAIT);
1165		if (error) {
1166			printf("%s: unable to load data DMA map "
1167			    "(for SENSE): %d\n",
1168			    sc->sc_c.sc_dev.dv_xname, error);
1169			xs->error = XS_DRIVER_STUFFUP;
1170			goto out;
1171		}
1172		bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
1173		    0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1174		    BUS_DMASYNC_PREREAD);
1175
1176		siop_setuptables(&siop_cmd->cmd_c);
1177		siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1178		/* arrange for the cmd to be handled now */
1179		TAILQ_INSERT_HEAD(&sc->urgent_list, siop_cmd, next);
1180		return;
1181	} else if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) {
1182		bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
1183		    0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1184		    BUS_DMASYNC_POSTREAD);
1185		bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data);
1186		bcopy(siop_cmd->cmd_c.sense, &xs->sense, sizeof(xs->sense));
1187	}
1188out:
1189	siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
1190#if 0
1191	if (xs->resid != 0)
1192		printf("resid %d datalen %d\n", xs->resid, xs->datalen);
1193#endif
1194	scsi_done(xs);
1195}
1196
1197/*
1198 * handle a rejected queue tag message: the command will run untagged,
1199 * has to adjust the reselect script.
1200 */
1201int
1202siop_handle_qtag_reject(struct siop_cmd *siop_cmd)
1203{
1204	struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
1205	int target = siop_cmd->cmd_c.xs->sc_link->target;
1206	int lun = siop_cmd->cmd_c.xs->sc_link->lun;
1207	int tag = siop_cmd->cmd_tables->msg_out[2];
1208	struct siop_lun *siop_lun =
1209	    ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
1210
1211#ifdef SIOP_DEBUG
1212	printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",
1213	    sc->sc_c.sc_dev.dv_xname, target, lun, tag, siop_cmd->cmd_c.tag,
1214	    siop_cmd->cmd_c.status);
1215#endif
1216
1217	if (siop_lun->siop_tag[0].active != NULL) {
1218		printf("%s: untagged command already running for target %d "
1219		    "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname,
1220		    target, lun, siop_lun->siop_tag[0].active->cmd_c.status);
1221		return -1;
1222	}
1223	/* clear tag slot */
1224	siop_lun->siop_tag[tag].active = NULL;
1225	/* add command to non-tagged slot */
1226	siop_lun->siop_tag[0].active = siop_cmd;
1227	siop_cmd->cmd_c.tag = 0;
1228	/* adjust reselect script if there is one */
1229	if (siop_lun->siop_tag[0].reseloff > 0) {
1230		siop_script_write(sc,
1231		    siop_lun->siop_tag[0].reseloff + 1,
1232		    siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) +
1233		    Ent_ldsa_reload_dsa);
1234		siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
1235	}
1236	return 0;
1237}
1238
1239/*
1240 * handle a bus reset: reset chip, unqueue all active commands, free all
1241 * target struct and report lossage to upper layer.
1242 * As the upper layer may requeue immediately we have to first store
1243 * all active commands in a temporary queue.
1244 */
1245void
1246siop_handle_reset(struct siop_softc *sc)
1247{
1248	struct cmd_list reset_list;
1249	struct siop_cmd *siop_cmd, *next_siop_cmd;
1250	struct siop_lun *siop_lun;
1251	int target, lun, tag, buswidth;
1252	/*
1253	 * scsi bus reset. reset the chip and restart
1254	 * the queue. Need to clean up all active commands
1255	 */
1256	printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname);
1257	/* stop, reset and restart the chip */
1258	siop_reset(sc);
1259	TAILQ_INIT(&reset_list);
1260	/*
1261	 * Process all commands: first commands being executed
1262	 */
1263	buswidth = (sc->sc_c.features & SF_BUS_WIDE) ? 16 : 8;
1264	for (target = 0; target < buswidth; target++) {
1265		if (sc->sc_c.targets[target] == NULL)
1266			continue;
1267		for (lun = 0; lun < 8; lun++) {
1268			struct siop_target *siop_target =
1269			    (struct siop_target *)sc->sc_c.targets[target];
1270			siop_lun = siop_target->siop_lun[lun];
1271			if (siop_lun == NULL)
1272				continue;
1273			siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
1274			for (tag = 0; tag <
1275			    ((sc->sc_c.targets[target]->flags & TARF_TAG) ?
1276			    SIOP_NTAG : 1);
1277			    tag++) {
1278				siop_cmd = siop_lun->siop_tag[tag].active;
1279				if (siop_cmd == NULL)
1280					continue;
1281				siop_lun->siop_tag[tag].active = NULL;
1282				TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1283				sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1284				printf("cmd %p (tag %d) added to reset list\n",
1285				    siop_cmd, tag);
1286			}
1287		}
1288		if (sc->sc_c.targets[target]->status != TARST_PROBING) {
1289			sc->sc_c.targets[target]->status = TARST_ASYNC;
1290			sc->sc_c.targets[target]->flags &= ~TARF_ISWIDE;
1291			sc->sc_c.targets[target]->period =
1292			    sc->sc_c.targets[target]->offset = 0;
1293			siop_update_xfer_mode(&sc->sc_c, target);
1294		}
1295	}
1296	/* Next commands from the urgent list */
1297	for (siop_cmd = TAILQ_FIRST(&sc->urgent_list); siop_cmd != NULL;
1298	    siop_cmd = next_siop_cmd) {
1299		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1300		TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
1301		TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1302		sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1303		printf("cmd %p added to reset list from urgent list\n",
1304		    siop_cmd);
1305	}
1306	/* Then commands waiting in the input list. */
1307	for (siop_cmd = TAILQ_FIRST(&sc->ready_list); siop_cmd != NULL;
1308	    siop_cmd = next_siop_cmd) {
1309		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1310		TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
1311		TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1312		sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1313		printf("cmd %p added to reset list from ready list\n",
1314		    siop_cmd);
1315	}
1316
1317	for (siop_cmd = TAILQ_FIRST(&reset_list); siop_cmd != NULL;
1318	    siop_cmd = next_siop_cmd) {
1319		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1320		siop_cmd->cmd_c.flags &= ~CMDFL_TAG;
1321		siop_cmd->cmd_c.xs->error =
1322		    (siop_cmd->cmd_c.flags & CMDFL_TIMEOUT)
1323		    ? XS_TIMEOUT : XS_RESET;
1324		siop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
1325		sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1326		printf("cmd %p (status %d) reset",
1327		    siop_cmd, siop_cmd->cmd_c.status);
1328		if (siop_cmd->cmd_c.status == CMDST_SENSE ||
1329		    siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE)
1330			siop_cmd->cmd_c.status = CMDST_SENSE_DONE;
1331		else
1332			siop_cmd->cmd_c.status = CMDST_DONE;
1333		printf(" with status %d, xs->error %d\n",
1334		    siop_cmd->cmd_c.status, siop_cmd->cmd_c.xs->error);
1335		TAILQ_REMOVE(&reset_list, siop_cmd, next);
1336		siop_scsicmd_end(siop_cmd);
1337	}
1338}
1339
1340void *
1341siop_cmd_get(void *cookie)
1342{
1343	struct siop_softc *sc = cookie;
1344	struct siop_cmd *siop_cmd;
1345	int s;
1346
1347	/* Look if a ccb is available. */
1348	s = splbio();
1349	siop_cmd = TAILQ_FIRST(&sc->free_list);
1350	if (siop_cmd != NULL) {
1351		TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
1352#ifdef DIAGNOSTIC
1353		if (siop_cmd->cmd_c.status != CMDST_FREE)
1354			panic("siop_scsicmd: new cmd not free");
1355#endif
1356		siop_cmd->cmd_c.status = CMDST_READY;
1357	}
1358	splx(s);
1359
1360	return (siop_cmd);
1361}
1362
1363void
1364siop_cmd_put(void *cookie, void *io)
1365{
1366	struct siop_softc *sc = cookie;
1367	struct siop_cmd *siop_cmd = io;
1368	int s;
1369
1370	s = splbio();
1371	siop_cmd->cmd_c.status = CMDST_FREE;
1372	TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
1373	splx(s);
1374}
1375
1376int
1377siop_scsiprobe(struct scsi_link *link)
1378{
1379	struct siop_softc *sc = link->bus->sb_adapter_softc;
1380	struct siop_target *siop_target;
1381	const int target = link->target;
1382	const int lun = link->lun;
1383	int i;
1384
1385#ifdef SIOP_DEBUG
1386	printf("%s:%d:%d: probe\n",
1387	    sc->sc_c.sc_dev.dv_xname, target, lun);
1388#endif
1389
1390	/* XXX locking */
1391
1392	siop_target = (struct siop_target*)sc->sc_c.targets[target];
1393	if (siop_target == NULL) {
1394		siop_target = malloc(sizeof(*siop_target), M_DEVBUF,
1395		    M_WAITOK | M_CANFAIL | M_ZERO);
1396		if (siop_target == NULL) {
1397			printf("%s: can't malloc memory for target %d\n",
1398			    sc->sc_c.sc_dev.dv_xname, target);
1399			return (ENOMEM);
1400		}
1401
1402		siop_target->target_c.status = TARST_PROBING;
1403		siop_target->target_c.flags  = 0;
1404		siop_target->target_c.id =
1405		    sc->sc_c.clock_div << 24; /* scntl3 */
1406		siop_target->target_c.id |=  target << 16; /* id */
1407		/* siop_target->target_c.id |= 0x0 << 8; scxfer is 0 */
1408
1409		/* get a lun switch script */
1410		siop_target->lunsw = siop_get_lunsw(sc);
1411		if (siop_target->lunsw == NULL) {
1412			printf("%s: can't alloc lunsw for target %d\n",
1413			    sc->sc_c.sc_dev.dv_xname, target);
1414			free(siop_target, M_DEVBUF, sizeof *siop_target);
1415			return (ENOMEM);
1416		}
1417		for (i = 0; i < 8; i++)
1418			siop_target->siop_lun[i] = NULL;
1419
1420		sc->sc_c.targets[target] =
1421		    (struct siop_common_target *)siop_target;
1422
1423		siop_add_reselsw(sc, target);
1424	}
1425
1426	if (siop_target->siop_lun[lun] == NULL) {
1427		siop_target->siop_lun[lun] =
1428		    malloc(sizeof(struct siop_lun), M_DEVBUF,
1429		    M_WAITOK | M_CANFAIL | M_ZERO);
1430		if (siop_target->siop_lun[lun] == NULL) {
1431			printf("%s: can't alloc siop_lun for "
1432			    "target %d lun %d\n",
1433			    sc->sc_c.sc_dev.dv_xname, target, lun);
1434			return (ENOMEM);
1435		}
1436	}
1437
1438	return (0);
1439}
1440
1441void
1442siop_scsicmd(struct scsi_xfer *xs)
1443{
1444	struct siop_softc *sc = xs->sc_link->bus->sb_adapter_softc;
1445	struct siop_cmd *siop_cmd;
1446	struct siop_target *siop_target;
1447	int s, error, i, j;
1448	const int target = xs->sc_link->target;
1449	const int lun = xs->sc_link->lun;
1450
1451#ifdef SIOP_DEBUG_SCHED
1452	printf("starting cmd for %d:%d\n", target, lun);
1453#endif
1454
1455	siop_target = (struct siop_target*)sc->sc_c.targets[target];
1456	siop_cmd = xs->io;
1457
1458	/*
1459	 * The xs may have been restarted by the scsi layer, so ensure the ccb
1460	 * starts in the proper state.
1461	 */
1462	siop_cmd->cmd_c.status = CMDST_READY;
1463
1464	/* Always reset xs->stimeout, lest we timeout_del() with trash */
1465	timeout_set(&xs->stimeout, siop_timeout, siop_cmd);
1466
1467	siop_cmd->cmd_c.siop_target = sc->sc_c.targets[target];
1468	siop_cmd->cmd_c.xs = xs;
1469	siop_cmd->cmd_c.flags = 0;
1470
1471	bzero(&siop_cmd->cmd_c.siop_tables->xscmd,
1472	    sizeof(siop_cmd->cmd_c.siop_tables->xscmd));
1473	bcopy(&xs->cmd, &siop_cmd->cmd_c.siop_tables->xscmd, xs->cmdlen);
1474	siop_cmd->cmd_c.siop_tables->cmd.count =
1475	    siop_htoc32(&sc->sc_c, xs->cmdlen);
1476
1477	/* load the DMA maps */
1478	if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1479		error = bus_dmamap_load(sc->sc_c.sc_dmat,
1480		    siop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen,
1481		    NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1482		    ((xs->flags & SCSI_DATA_IN) ?
1483			BUS_DMA_READ : BUS_DMA_WRITE));
1484		if (error) {
1485			printf("%s: unable to load data DMA map: %d\n",
1486			    sc->sc_c.sc_dev.dv_xname, error);
1487			xs->error = XS_DRIVER_STUFFUP;
1488			scsi_done(xs);
1489			return;
1490		}
1491		bus_dmamap_sync(sc->sc_c.sc_dmat,
1492		    siop_cmd->cmd_c.dmamap_data, 0,
1493		    siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1494		    (xs->flags & SCSI_DATA_IN) ?
1495		    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
1496	}
1497
1498	siop_setuptables(&siop_cmd->cmd_c);
1499	siop_cmd->saved_offset = SIOP_NOOFFSET;
1500	siop_table_sync(siop_cmd,
1501	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1502
1503	/* Negotiate transfer parameters on first non-polling command. */
1504	if (((xs->flags & SCSI_POLL) == 0) &&
1505	    siop_target->target_c.status == TARST_PROBING)
1506		siop_target->target_c.status = TARST_ASYNC;
1507
1508	s = splbio();
1509	TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next);
1510	siop_start(sc);
1511	if ((xs->flags & SCSI_POLL) == 0) {
1512		splx(s);
1513		return;
1514	}
1515
1516	/* Poll for command completion. */
1517	for(i = xs->timeout; i > 0; i--) {
1518		siop_intr(sc);
1519		if ((xs->flags & ITSDONE) == 0) {
1520			delay(1000);
1521			continue;
1522		}
1523		if (xs->cmd.opcode == INQUIRY && xs->error == XS_NOERROR) {
1524			struct scsi_inquiry_data *inqbuf =
1525			    (struct scsi_inquiry_data *)xs->data;
1526		 	if ((inqbuf->device & SID_QUAL) == SID_QUAL_BAD_LU)
1527				break;
1528			/*
1529			 * Allocate cbd's to hold maximum openings worth of
1530			 * commands. Do this now because doing it dynamically in
1531			 * siop_startcmd may cause calls to bus_dma* functions
1532			 * in interrupt context.
1533			 */
1534			for (j = 0; j < SIOP_NTAG; j += SIOP_NCMDPB)
1535				siop_morecbd(sc);
1536
1537			/*
1538			 * Set TARF_DT here because if it is turned off during
1539			 * PPR, it must STAY off!
1540			 */
1541			if ((lun == 0) && (sc->sc_c.features & SF_BUS_ULTRA3))
1542				sc->sc_c.targets[target]->flags |= TARF_DT;
1543			/*
1544			 * Can't do lun 0 here, because flags are not set yet.
1545			 * But have to do other lun's here because they never go
1546			 * through TARST_ASYNC.
1547			 */
1548			if (lun > 0)
1549				siop_add_dev(sc, target, lun);
1550		}
1551		break;
1552	}
1553	if (i == 0) {
1554		siop_timeout(siop_cmd);
1555		while ((xs->flags & ITSDONE) == 0)
1556			siop_intr(sc);
1557	}
1558
1559	splx(s);
1560}
1561
1562void
1563siop_start(struct siop_softc *sc)
1564{
1565	struct siop_cmd *siop_cmd, *next_siop_cmd;
1566	struct siop_lun *siop_lun;
1567	struct siop_xfer *siop_xfer;
1568	u_int32_t dsa;
1569	int target, lun, tag, slot;
1570	int newcmd = 0;
1571	int doingready = 0;
1572
1573	/*
1574	 * first make sure to read valid data
1575	 */
1576	siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1577
1578	/*
1579	 * The queue management here is a bit tricky: the script always looks
1580	 * at the slot from first to last, so if we always use the first
1581	 * free slot commands can stay at the tail of the queue ~forever.
1582	 * The algorithm used here is to restart from the head when we know
1583	 * that the queue is empty, and only add commands after the last one.
1584	 * When we're at the end of the queue wait for the script to clear it.
1585	 * The best thing to do here would be to implement a circular queue,
1586	 * but using only 53c720 features this can be "interesting".
1587	 * A mid-way solution could be to implement 2 queues and swap orders.
1588	 */
1589	slot = sc->sc_currschedslot;
1590	/*
1591	 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is
1592	 * free. As this is the last used slot, all previous slots are free,
1593	 * we can restart from 1.
1594	 * slot 0 is reserved for request sense commands.
1595	 */
1596	if (siop_script_read(sc, (Ent_script_sched_slot0 / 4) + slot * 2) ==
1597	    0x80000000) {
1598		slot = sc->sc_currschedslot = 1;
1599	} else {
1600		slot++;
1601	}
1602	/* first handle commands from the urgent list */
1603	siop_cmd = TAILQ_FIRST(&sc->urgent_list);
1604again:
1605	for (; siop_cmd != NULL; siop_cmd = next_siop_cmd) {
1606		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1607#ifdef DIAGNOSTIC
1608		if (siop_cmd->cmd_c.status != CMDST_READY &&
1609		    siop_cmd->cmd_c.status != CMDST_SENSE)
1610			panic("siop: non-ready cmd in ready list");
1611#endif
1612		target = siop_cmd->cmd_c.xs->sc_link->target;
1613		lun = siop_cmd->cmd_c.xs->sc_link->lun;
1614		siop_lun =
1615			((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
1616		/* if non-tagged command active, wait */
1617		if (siop_lun->siop_tag[0].active != NULL)
1618			continue;
1619		/*
1620		 * if we're in a queue full condition don't start a new
1621		 * command, unless it's a request sense
1622		 */
1623		if ((siop_lun->lun_flags & SIOP_LUNF_FULL) &&
1624		    siop_cmd->cmd_c.status == CMDST_READY)
1625			continue;
1626		/* find a free tag if needed */
1627		if (siop_cmd->cmd_c.flags & CMDFL_TAG) {
1628			for (tag = 1; tag < SIOP_NTAG; tag++) {
1629				if (siop_lun->siop_tag[tag].active == NULL)
1630					break;
1631			}
1632			if (tag == SIOP_NTAG) /* no free tag */
1633				continue;
1634		} else {
1635			tag = 0;
1636		}
1637		siop_cmd->cmd_c.tag = tag;
1638		/*
1639		 * find a free scheduler slot and load it. If it's a request
1640		 * sense we need to use slot 0.
1641		 */
1642		if (siop_cmd->cmd_c.status != CMDST_SENSE) {
1643			for (; slot < SIOP_NSLOTS; slot++) {
1644				/*
1645				 * If cmd if 0x80000000 the slot is free
1646				 */
1647				if (siop_script_read(sc,
1648				    (Ent_script_sched_slot0 / 4) + slot * 2) ==
1649				    0x80000000)
1650					break;
1651			}
1652			/* no more free slots, no need to continue */
1653			if (slot == SIOP_NSLOTS) {
1654				goto end;
1655			}
1656		} else {
1657			slot = 0;
1658			if (siop_script_read(sc, Ent_script_sched_slot0 / 4)
1659			    != 0x80000000)
1660				goto end;
1661		}
1662
1663#ifdef SIOP_DEBUG_SCHED
1664		printf("using slot %d for DSA 0x%lx\n", slot,
1665		    (u_long)siop_cmd->cmd_c.dsa);
1666#endif
1667		/* Ok, we can add the tag message */
1668		if (tag > 0) {
1669#ifdef DIAGNOSTIC
1670			int msgcount = siop_ctoh32(&sc->sc_c,
1671			    siop_cmd->cmd_tables->t_msgout.count);
1672			if (msgcount != 1)
1673				printf("%s:%d:%d: tag %d with msgcount %d\n",
1674				    sc->sc_c.sc_dev.dv_xname, target, lun, tag,
1675				    msgcount);
1676#endif
1677			siop_cmd->cmd_tables->msg_out[1] = MSG_SIMPLE_Q_TAG;
1678			siop_cmd->cmd_tables->msg_out[2] = tag;
1679			siop_cmd->cmd_tables->t_msgout.count =
1680			    siop_htoc32(&sc->sc_c, 3);
1681		}
1682		/* note that we started a new command */
1683		newcmd = 1;
1684		/* mark command as active */
1685		if (siop_cmd->cmd_c.status == CMDST_READY) {
1686			siop_cmd->cmd_c.status = CMDST_ACTIVE;
1687		} else if (siop_cmd->cmd_c.status == CMDST_SENSE) {
1688			siop_cmd->cmd_c.status = CMDST_SENSE_ACTIVE;
1689		} else
1690			panic("siop_start: bad status");
1691		if (doingready)
1692			TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
1693		else
1694			TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
1695		siop_lun->siop_tag[tag].active = siop_cmd;
1696		/* patch scripts with DSA addr */
1697		dsa = siop_cmd->cmd_c.dsa;
1698		/* first reselect switch, if we have an entry */
1699		if (siop_lun->siop_tag[tag].reseloff > 0)
1700			siop_script_write(sc,
1701			    siop_lun->siop_tag[tag].reseloff + 1,
1702			    dsa + sizeof(struct siop_common_xfer) +
1703			    Ent_ldsa_reload_dsa);
1704		/* CMD script: MOVE MEMORY addr */
1705		siop_xfer = (struct siop_xfer*)siop_cmd->cmd_tables;
1706		siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
1707		    siop_htoc32(&sc->sc_c, sc->sc_c.sc_scriptaddr +
1708		        Ent_script_sched_slot0 + slot * 8);
1709		siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
1710		/* scheduler slot: JUMP ldsa_select */
1711		siop_script_write(sc,
1712		    (Ent_script_sched_slot0 / 4) + slot * 2 + 1,
1713		    dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_select);
1714		/* handle timeout */
1715		if (siop_cmd->cmd_c.status == CMDST_ACTIVE) {
1716			if ((siop_cmd->cmd_c.xs->flags & SCSI_POLL) == 0) {
1717				/* start expire timer */
1718				timeout_add_msec(&siop_cmd->cmd_c.xs->stimeout,
1719				    siop_cmd->cmd_c.xs->timeout);
1720			}
1721		}
1722		/*
1723		 * Change JUMP cmd so that this slot will be handled
1724		 */
1725		siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2,
1726		    0x80080000);
1727		/* if we're using the request sense slot, stop here */
1728		if (slot == 0)
1729			goto end;
1730		sc->sc_currschedslot = slot;
1731		slot++;
1732	}
1733	if (doingready == 0) {
1734		/* now process ready list */
1735		doingready = 1;
1736		siop_cmd = TAILQ_FIRST(&sc->ready_list);
1737		goto again;
1738	}
1739
1740end:
1741	/* if nothing changed no need to flush cache and wakeup script */
1742	if (newcmd == 0)
1743		return;
1744	/* make sure SCRIPT processor will read valid data */
1745	siop_script_sync(sc,BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);
1746	/* Signal script it has some work to do */
1747	bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
1748	    SIOP_ISTAT, ISTAT_SIGP);
1749	/* and wait for IRQ */
1750}
1751
1752void
1753siop_timeout(void *v)
1754{
1755	struct siop_cmd *siop_cmd = v;
1756	struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
1757	int s;
1758
1759	/* deactivate callout */
1760	timeout_del(&siop_cmd->cmd_c.xs->stimeout);
1761
1762	sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1763	printf("timeout on SCSI command 0x%x\n",
1764	    siop_cmd->cmd_c.xs->cmd.opcode);
1765
1766	s = splbio();
1767	/* reset the scsi bus */
1768	siop_resetbus(&sc->sc_c);
1769	siop_cmd->cmd_c.flags |= CMDFL_TIMEOUT;
1770	siop_handle_reset(sc);
1771	splx(s);
1772}
1773
1774#ifdef DUMP_SCRIPT
1775void
1776siop_dump_script(struct siop_softc *sc)
1777{
1778	int i;
1779	for (i = 0; i < PAGE_SIZE / 4; i += 2) {
1780		printf("0x%04x: 0x%08x 0x%08x", i * 4,
1781		    siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[i]),
1782		    siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[i+1]));
1783		if ((siop_ctoh32(&sc->sc_c,
1784		     sc->sc_c.sc_script[i]) & 0xe0000000) == 0xc0000000) {
1785			i++;
1786			printf(" 0x%08x", siop_ctoh32(&sc->sc_c,
1787			    sc->sc_c.sc_script[i+1]));
1788		}
1789		printf("\n");
1790	}
1791}
1792#endif
1793
1794void
1795siop_morecbd(struct siop_softc *sc)
1796{
1797	int error, off, i, j, s;
1798	struct siop_cbd *newcbd;
1799	struct siop_xfer *xfers, *xfer;
1800	bus_addr_t dsa;
1801	u_int32_t *scr;
1802	size_t sense_size = roundup(sizeof(struct scsi_sense_data), 16);
1803
1804	/* allocate a new list head */
1805	newcbd = malloc(sizeof(struct siop_cbd), M_DEVBUF, M_NOWAIT | M_ZERO);
1806	if (newcbd == NULL) {
1807		printf("%s: can't allocate memory for command descriptors "
1808		    "head\n", sc->sc_c.sc_dev.dv_xname);
1809		return;
1810	}
1811
1812	/* allocate cmd list */
1813	newcbd->cmds = mallocarray(SIOP_NCMDPB, sizeof(struct siop_cmd),
1814	    M_DEVBUF, M_NOWAIT | M_ZERO);
1815	if (newcbd->cmds == NULL) {
1816		printf("%s: can't allocate memory for command descriptors\n",
1817		    sc->sc_c.sc_dev.dv_xname);
1818		goto bad3;
1819	}
1820
1821	newcbd->xfers = siop_dmamem_alloc(sc, PAGE_SIZE);
1822	if (newcbd->xfers == NULL) {
1823		printf("%s: unable to allocate cbd xfer DMA memory\n",
1824		    sc->sc_c.sc_dev.dv_xname);
1825		goto bad2;
1826	}
1827	xfers = SIOP_DMA_KVA(newcbd->xfers);
1828
1829	newcbd->sense = siop_dmamem_alloc(sc, sense_size * SIOP_NCMDPB);
1830	if (newcbd->sense == NULL) {
1831		printf("%s: unable to allocate cbd sense DMA memory\n",
1832		    sc->sc_c.sc_dev.dv_xname);
1833		goto bad1;
1834	}
1835
1836	for (i = 0; i < SIOP_NCMDPB; i++) {
1837		error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG,
1838		    MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1839		    &newcbd->cmds[i].cmd_c.dmamap_data);
1840		if (error) {
1841			printf("%s: unable to create data DMA map for cbd: "
1842			    "error %d\n",
1843			    sc->sc_c.sc_dev.dv_xname, error);
1844			goto bad0;
1845		}
1846	}
1847
1848	/* Use two loops since bailing out above releases allocated memory */
1849	off = (sc->sc_c.features & SF_CHIP_BE) ? 3 : 0;
1850	for (i = 0; i < SIOP_NCMDPB; i++) {
1851		newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c;
1852		newcbd->cmds[i].siop_cbdp = newcbd;
1853		xfer = &xfers[i];
1854		newcbd->cmds[i].cmd_tables = (struct siop_common_xfer *)xfer;
1855		bzero(newcbd->cmds[i].cmd_tables, sizeof(struct siop_xfer));
1856		dsa = SIOP_DMA_DVA(newcbd->xfers) +
1857		    i * sizeof(struct siop_xfer);
1858		newcbd->cmds[i].cmd_c.dsa = dsa;
1859		newcbd->cmds[i].cmd_c.status = CMDST_FREE;
1860		newcbd->cmds[i].cmd_c.sense = (struct scsi_sense_data *)(
1861		    i * sense_size +
1862		    (u_int8_t *)SIOP_DMA_KVA(newcbd->sense));
1863		xfer->siop_tables.t_msgout.count= siop_htoc32(&sc->sc_c, 1);
1864		xfer->siop_tables.t_msgout.addr = siop_htoc32(&sc->sc_c, dsa);
1865		xfer->siop_tables.t_msgin.count= siop_htoc32(&sc->sc_c, 1);
1866		xfer->siop_tables.t_msgin.addr = siop_htoc32(&sc->sc_c,
1867		    dsa + offsetof(struct siop_common_xfer, msg_in));
1868		xfer->siop_tables.t_extmsgin.count= siop_htoc32(&sc->sc_c, 2);
1869		xfer->siop_tables.t_extmsgin.addr = siop_htoc32(&sc->sc_c,
1870		    dsa + offsetof(struct siop_common_xfer, msg_in) + 1);
1871		xfer->siop_tables.t_extmsgdata.addr = siop_htoc32(&sc->sc_c,
1872		    dsa + offsetof(struct siop_common_xfer, msg_in) + 3);
1873		xfer->siop_tables.t_status.count= siop_htoc32(&sc->sc_c, 1);
1874		xfer->siop_tables.t_status.addr = siop_htoc32(&sc->sc_c,
1875		    dsa + offsetof(struct siop_common_xfer, status) + off);
1876		xfer->siop_tables.cmd.count = siop_htoc32(&sc->sc_c, 0);
1877		xfer->siop_tables.cmd.addr = siop_htoc32(&sc->sc_c,
1878		    dsa + offsetof(struct siop_common_xfer, xscmd));
1879		/* The select/reselect script */
1880		scr = &xfer->resel[0];
1881		for (j = 0; j < sizeof(load_dsa) / sizeof(load_dsa[0]); j++)
1882			scr[j] = siop_htoc32(&sc->sc_c, load_dsa[j]);
1883		/*
1884		 * 0x78000000 is a 'move data8 to reg'. data8 is the second
1885		 * octet, reg offset is the third.
1886		 */
1887		scr[Ent_rdsa0 / 4] = siop_htoc32(&sc->sc_c,
1888		    0x78100000 | ((dsa & 0x000000ff) <<  8));
1889		scr[Ent_rdsa1 / 4] = siop_htoc32(&sc->sc_c,
1890		    0x78110000 | ( dsa & 0x0000ff00       ));
1891		scr[Ent_rdsa2 / 4] = siop_htoc32(&sc->sc_c,
1892		    0x78120000 | ((dsa & 0x00ff0000) >>  8));
1893		scr[Ent_rdsa3 / 4] = siop_htoc32(&sc->sc_c,
1894		    0x78130000 | ((dsa & 0xff000000) >> 16));
1895		scr[E_ldsa_abs_reselected_Used[0]] = siop_htoc32(&sc->sc_c,
1896		    sc->sc_c.sc_scriptaddr + Ent_reselected);
1897		scr[E_ldsa_abs_reselect_Used[0]] = siop_htoc32(&sc->sc_c,
1898		    sc->sc_c.sc_scriptaddr + Ent_reselect);
1899		scr[E_ldsa_abs_selected_Used[0]] = siop_htoc32(&sc->sc_c,
1900		    sc->sc_c.sc_scriptaddr + Ent_selected);
1901		scr[E_ldsa_abs_data_Used[0]] = siop_htoc32(&sc->sc_c,
1902		    dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data);
1903		/* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
1904		scr[Ent_ldsa_data / 4] = siop_htoc32(&sc->sc_c, 0x80000000);
1905		s = splbio();
1906		TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
1907		splx(s);
1908#ifdef SIOP_DEBUG
1909		printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n",
1910		    i,
1911		    siop_ctoh32(&sc->sc_c,
1912			newcbd->cmds[i].cmd_tables->t_msgin.addr),
1913		    siop_ctoh32(&sc->sc_c,
1914			newcbd->cmds[i].cmd_tables->t_msgout.addr),
1915		    siop_ctoh32(&sc->sc_c,
1916			newcbd->cmds[i].cmd_tables->t_status.addr));
1917#endif
1918	}
1919	s = splbio();
1920	TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
1921	splx(s);
1922	return;
1923bad0:
1924	while (--i >= 0) {
1925		bus_dmamap_destroy(sc->sc_c.sc_dmat,
1926		    newcbd->cmds[i].cmd_c.dmamap_data);
1927	}
1928	siop_dmamem_free(sc, newcbd->sense);
1929bad1:
1930	siop_dmamem_free(sc, newcbd->xfers);
1931bad2:
1932	free(newcbd->cmds, M_DEVBUF, SIOP_NCMDPB * sizeof(struct siop_cmd));
1933bad3:
1934	free(newcbd, M_DEVBUF, sizeof *newcbd);
1935}
1936
1937struct siop_lunsw *
1938siop_get_lunsw(struct siop_softc *sc)
1939{
1940	struct siop_lunsw *lunsw;
1941	int i;
1942
1943	if (sc->script_free_lo + (sizeof(lun_switch) / sizeof(lun_switch[0])) >=
1944	    sc->script_free_hi)
1945		return NULL;
1946	lunsw = TAILQ_FIRST(&sc->lunsw_list);
1947	if (lunsw != NULL) {
1948#ifdef SIOP_DEBUG
1949		printf("siop_get_lunsw got lunsw at offset %d\n",
1950		    lunsw->lunsw_off);
1951#endif
1952		TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
1953		return lunsw;
1954	}
1955	lunsw = malloc(sizeof(struct siop_lunsw), M_DEVBUF, M_NOWAIT | M_ZERO);
1956	if (lunsw == NULL)
1957		return NULL;
1958#ifdef SIOP_DEBUG
1959	printf("allocating lunsw at offset %d\n", sc->script_free_lo);
1960#endif
1961	if (sc->sc_c.features & SF_CHIP_RAM) {
1962		bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
1963		    sc->script_free_lo * 4, lun_switch,
1964		    sizeof(lun_switch) / sizeof(lun_switch[0]));
1965		bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
1966		    (sc->script_free_lo + E_abs_lunsw_return_Used[0]) * 4,
1967		    sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
1968	} else {
1969		for (i = 0; i < sizeof(lun_switch) / sizeof(lun_switch[0]);
1970		    i++)
1971			sc->sc_c.sc_script[sc->script_free_lo + i] =
1972			    siop_htoc32(&sc->sc_c, lun_switch[i]);
1973		sc->sc_c.sc_script[
1974		    sc->script_free_lo + E_abs_lunsw_return_Used[0]] =
1975		    siop_htoc32(&sc->sc_c,
1976			sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
1977	}
1978	lunsw->lunsw_off = sc->script_free_lo;
1979	lunsw->lunsw_size = sizeof(lun_switch) / sizeof(lun_switch[0]);
1980	sc->script_free_lo += lunsw->lunsw_size;
1981	siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1982	return lunsw;
1983}
1984
1985void
1986siop_add_reselsw(struct siop_softc *sc, int target)
1987{
1988	int i,j;
1989	struct siop_target *siop_target;
1990	struct siop_lun *siop_lun;
1991
1992	siop_target = (struct siop_target *)sc->sc_c.targets[target];
1993	/*
1994	 * add an entry to resel switch
1995	 */
1996	siop_script_sync(sc, BUS_DMASYNC_POSTWRITE);
1997	for (i = 0; i < 15; i++) {
1998		siop_target->reseloff = Ent_resel_targ0 / 4 + i * 2;
1999		if ((siop_script_read(sc, siop_target->reseloff) & 0xff)
2000		    == 0xff) { /* it's free */
2001#ifdef SIOP_DEBUG
2002			printf("siop: target %d slot %d offset %d\n",
2003			    target, i, siop_target->reseloff);
2004#endif
2005			/* JUMP abs_foo, IF target | 0x80; */
2006			siop_script_write(sc, siop_target->reseloff,
2007			    0x800c0080 | target);
2008			siop_script_write(sc, siop_target->reseloff + 1,
2009			    sc->sc_c.sc_scriptaddr +
2010			    siop_target->lunsw->lunsw_off * 4 +
2011			    Ent_lun_switch_entry);
2012			break;
2013		}
2014	}
2015	if (i == 15) /* no free slot, shouldn't happen */
2016		panic("siop: resel switch full");
2017
2018	sc->sc_ntargets++;
2019	for (i = 0; i < 8; i++) {
2020		siop_lun = siop_target->siop_lun[i];
2021		if (siop_lun == NULL)
2022			continue;
2023		if (siop_lun->reseloff > 0) {
2024			siop_lun->reseloff = 0;
2025			for (j = 0; j < SIOP_NTAG; j++)
2026				siop_lun->siop_tag[j].reseloff = 0;
2027			siop_add_dev(sc, target, i);
2028		}
2029	}
2030	siop_update_scntl3(sc, sc->sc_c.targets[target]);
2031	siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2032}
2033
2034void
2035siop_update_scntl3(struct siop_softc *sc,
2036    struct siop_common_target *_siop_target)
2037{
2038	struct siop_target *siop_target = (struct siop_target *)_siop_target;
2039	/* MOVE target->id >> 24 TO SCNTL3 */
2040	siop_script_write(sc,
2041	    siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4),
2042	    0x78030000 | ((siop_target->target_c.id >> 16) & 0x0000ff00));
2043	/* MOVE target->id >> 8 TO SXFER */
2044	siop_script_write(sc,
2045	    siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 2,
2046	    0x78050000 | (siop_target->target_c.id & 0x0000ff00));
2047	siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2048}
2049
2050void
2051siop_add_dev(struct siop_softc *sc, int target, int lun)
2052{
2053	struct siop_lunsw *lunsw;
2054	struct siop_target *siop_target =
2055	    (struct siop_target *)sc->sc_c.targets[target];
2056	struct siop_lun *siop_lun = siop_target->siop_lun[lun];
2057	int i, ntargets, buswidth;
2058
2059	if (siop_lun->reseloff > 0)
2060		return;
2061	lunsw = siop_target->lunsw;
2062	if ((lunsw->lunsw_off + lunsw->lunsw_size) < sc->script_free_lo) {
2063		/*
2064		 * can't extend this slot. Probably not worth trying to deal
2065		 * with this case
2066		 */
2067#ifdef SIOP_DEBUG
2068		printf("%s:%d:%d: can't allocate a lun sw slot\n",
2069		    sc->sc_c.sc_dev.dv_xname, target, lun);
2070#endif
2071		return;
2072	}
2073	/* count how many free targets we still have to probe */
2074	buswidth = (sc->sc_c.features & SF_BUS_WIDE) ? 16 : 8;
2075	ntargets =  (buswidth - 1) - 1 - sc->sc_ntargets;
2076
2077	/*
2078	 * we need 8 bytes for the lun sw additional entry, and
2079	 * eventually sizeof(tag_switch) for the tag switch entry.
2080	 * Keep enough free space for the free targets that could be
2081	 * probed later.
2082	 */
2083	if (sc->script_free_lo + 2 +
2084	    (ntargets * sizeof(lun_switch) / sizeof(lun_switch[0])) >=
2085	    ((siop_target->target_c.flags & TARF_TAG) ?
2086	    sc->script_free_hi - (sizeof(tag_switch) / sizeof(tag_switch[0])) :
2087	    sc->script_free_hi)) {
2088		/*
2089		 * not enough space, probably not worth dealing with it.
2090		 * We can hold 13 tagged-queuing capable devices in the 4k RAM.
2091		 */
2092#ifdef SIOP_DEBUG
2093		printf("%s:%d:%d: not enough memory for a lun sw slot\n",
2094		    sc->sc_c.sc_dev.dv_xname, target, lun);
2095#endif
2096		return;
2097	}
2098#ifdef SIOP_DEBUG
2099	printf("%s:%d:%d: allocate lun sw entry\n",
2100	    sc->sc_c.sc_dev.dv_xname, target, lun);
2101#endif
2102	/* INT int_resellun */
2103	siop_script_write(sc, sc->script_free_lo, 0x98080000);
2104	siop_script_write(sc, sc->script_free_lo + 1, A_int_resellun);
2105	/* Now the slot entry: JUMP abs_foo, IF lun */
2106	siop_script_write(sc, sc->script_free_lo - 2,
2107	    0x800c0000 | lun);
2108	siop_script_write(sc, sc->script_free_lo - 1, 0);
2109	siop_lun->reseloff = sc->script_free_lo - 2;
2110	lunsw->lunsw_size += 2;
2111	sc->script_free_lo += 2;
2112	if (siop_target->target_c.flags & TARF_TAG) {
2113		/* we need a tag switch */
2114		sc->script_free_hi -=
2115		    sizeof(tag_switch) / sizeof(tag_switch[0]);
2116		if (sc->sc_c.features & SF_CHIP_RAM) {
2117			bus_space_write_region_4(sc->sc_c.sc_ramt,
2118			    sc->sc_c.sc_ramh,
2119			    sc->script_free_hi * 4, tag_switch,
2120			    sizeof(tag_switch) / sizeof(tag_switch[0]));
2121		} else {
2122			for(i = 0;
2123			    i < sizeof(tag_switch) / sizeof(tag_switch[0]);
2124			    i++) {
2125				sc->sc_c.sc_script[sc->script_free_hi + i] =
2126				    siop_htoc32(&sc->sc_c, tag_switch[i]);
2127			}
2128		}
2129		siop_script_write(sc,
2130		    siop_lun->reseloff + 1,
2131		    sc->sc_c.sc_scriptaddr + sc->script_free_hi * 4 +
2132		    Ent_tag_switch_entry);
2133
2134		for (i = 0; i < SIOP_NTAG; i++) {
2135			siop_lun->siop_tag[i].reseloff =
2136			    sc->script_free_hi + (Ent_resel_tag0 / 4) + i * 2;
2137		}
2138	} else {
2139		/* non-tag case; just work with the lun switch */
2140		siop_lun->siop_tag[0].reseloff =
2141		    siop_target->siop_lun[lun]->reseloff;
2142	}
2143	siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2144}
2145
2146void
2147siop_scsifree(struct scsi_link *link)
2148{
2149	struct siop_softc *sc = link->bus->sb_adapter_softc;
2150	int target = link->target;
2151	int lun = link->lun;
2152	int i;
2153	struct siop_target *siop_target;
2154
2155#ifdef SIOP_DEBUG
2156		printf("%s:%d:%d: free lun sw entry\n",
2157		    sc->sc_c.sc_dev.dv_xname, target, lun);
2158#endif
2159
2160	siop_target = (struct siop_target *)sc->sc_c.targets[target];
2161	free(siop_target->siop_lun[lun], M_DEVBUF, 0);
2162	siop_target->siop_lun[lun] = NULL;
2163	/* XXX compact sw entry too ? */
2164	/* check if we can free the whole target */
2165	for (i = 0; i < 8; i++) {
2166		if (siop_target->siop_lun[i] != NULL)
2167			return;
2168	}
2169#ifdef SIOP_DEBUG
2170	printf("%s: free siop_target for target %d lun %d lunsw offset %d\n",
2171	    sc->sc_c.sc_dev.dv_xname, target, lun,
2172	    siop_target->lunsw->lunsw_off);
2173#endif
2174	/*
2175	 * nothing here, free the target struct and resel
2176	 * switch entry
2177	 */
2178	siop_script_write(sc, siop_target->reseloff, 0x800c00ff);
2179	siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2180	TAILQ_INSERT_TAIL(&sc->lunsw_list, siop_target->lunsw, next);
2181	free(sc->sc_c.targets[target], M_DEVBUF, 0);
2182	sc->sc_c.targets[target] = NULL;
2183	sc->sc_ntargets--;
2184}
2185
2186#ifdef SIOP_STATS
2187void
2188siop_printstats(void)
2189{
2190	printf("siop_stat_intr %d\n", siop_stat_intr);
2191	printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer);
2192	printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc);
2193	printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp);
2194	printf("siop_stat_intr_saveoffset %d\n", siop_stat_intr_saveoffset);
2195	printf("siop_stat_intr_done %d\n", siop_stat_intr_done);
2196	printf("siop_stat_intr_lunresel %d\n", siop_stat_intr_lunresel);
2197	printf("siop_stat_intr_qfull %d\n", siop_stat_intr_qfull);
2198}
2199#endif
2200
2201struct siop_dmamem *
2202siop_dmamem_alloc(struct siop_softc *sc, size_t size)
2203{
2204	struct siop_dmamem *sdm;
2205	int nsegs;
2206
2207	sdm = malloc(sizeof(*sdm), M_DEVBUF, M_NOWAIT | M_ZERO);
2208	if (sdm == NULL)
2209		return (NULL);
2210
2211	sdm->sdm_size = size;
2212
2213	if (bus_dmamap_create(sc->sc_c.sc_dmat, size, 1, size, 0,
2214	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sdm->sdm_map) != 0)
2215		goto sdmfree;
2216
2217	if (bus_dmamem_alloc(sc->sc_c.sc_dmat, size, PAGE_SIZE, 0,
2218	    &sdm->sdm_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
2219		goto destroy;
2220
2221	if (bus_dmamem_map(sc->sc_c.sc_dmat, &sdm->sdm_seg, nsegs, size,
2222	    &sdm->sdm_kva, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0)
2223		goto free;
2224
2225	if (bus_dmamap_load(sc->sc_c.sc_dmat, sdm->sdm_map, sdm->sdm_kva,
2226	    size, NULL, BUS_DMA_NOWAIT) != 0)
2227		goto unmap;
2228
2229	return (sdm);
2230
2231unmap:
2232	bus_dmamem_unmap(sc->sc_c.sc_dmat, sdm->sdm_kva, size);
2233free:
2234	bus_dmamem_free(sc->sc_c.sc_dmat, &sdm->sdm_seg, 1);
2235destroy:
2236	bus_dmamap_destroy(sc->sc_c.sc_dmat, sdm->sdm_map);
2237sdmfree:
2238	free(sdm, M_DEVBUF, sizeof *sdm);
2239
2240	return (NULL);
2241}
2242
2243void
2244siop_dmamem_free(struct siop_softc *sc, struct siop_dmamem *sdm)
2245{
2246	bus_dmamap_unload(sc->sc_c.sc_dmat, sdm->sdm_map);
2247	bus_dmamem_unmap(sc->sc_c.sc_dmat, sdm->sdm_kva, sdm->sdm_size);
2248	bus_dmamem_free(sc->sc_c.sc_dmat, &sdm->sdm_seg, 1);
2249	bus_dmamap_destroy(sc->sc_c.sc_dmat, sdm->sdm_map);
2250	free(sdm, M_DEVBUF, sizeof *sdm);
2251}
2252