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