xref: /netbsd-src/sys/arch/prep/stand/boot/siop.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: siop.c,v 1.1 2012/05/19 14:40:13 kiyohara Exp $	*/
2 /*
3  * Copyright (c) 2010 KIYOHARA Takashi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <lib/libsa/stand.h>
29 #include <lib/libkern/libkern.h>
30 
31 #include <dev/microcode/siop/siop.out>
32 
33 #include "boot.h"
34 #include "sdvar.h"
35 
36 #define SIOP_DEFAULT_TARGET	7
37 
38 #define ALLOC(T, A)	\
39 		(T *)(((uint32_t)alloc(sizeof(T) + (A)) + (A)) & ~((A) - 1))
40 #define VTOPHYS(va)	(uint32_t)(va)
41 #define DEVTOV(pa)	(uint32_t)(pa)
42 #define wbinv(adr, siz)	_wbinv(VTOPHYS(adr), (uint32_t)(siz))
43 #define inv(adr, siz)	_inv(VTOPHYS(adr), (uint32_t)(siz))
44 
45 /* 53c810 supports little endian */
46 #define htoc32(x)	htole32(x)
47 #define ctoh32(x)	le32toh(x)
48 
49 static void siop_pci_reset(int);
50 
51 static void siop_setuptables(struct siop_adapter *, struct siop_xfer *,
52 			     struct scsi_xfer *);
53 static void siop_ma(struct siop_adapter *, struct scsi_xfer *);
54 static void siop_sdp(struct siop_adapter *, struct siop_xfer *,
55 		     struct scsi_xfer *, int);
56 static void siop_update_resid(struct siop_adapter *, struct siop_xfer *,
57 			      struct scsi_xfer *, int);
58 
59 static int siop_intr(struct siop_adapter *);
60 static void siop_scsicmd_end(struct siop_adapter *, struct scsi_xfer *);
61 static int siop_scsi_request(struct siop_adapter *, struct scsi_xfer *);
62 static void siop_start(struct siop_adapter *, struct scsi_xfer *);
63 static void siop_xfer_setup(struct siop_xfer *, void *);
64 
65 static int siop_add_reselsw(struct siop_adapter *, int, int);
66 static void siop_update_scntl3(struct siop_adapter *, int, int);
67 
68 static int _scsi_inquire(struct siop_adapter *, int, int, int, char *);
69 static void scsi_request_sense(struct siop_adapter *, struct scsi_xfer *);
70 static int scsi_interpret_sense(struct siop_adapter *, struct scsi_xfer *);
71 static int scsi_probe(struct siop_adapter *);
72 
73 static struct siop_adapter adapt;
74 
75 
76 static void
77 siop_pci_reset(int addr)
78 {
79 	int dmode, ctest5;
80 	const int maxburst = 4;			/* 53c810 */
81 
82 	dmode = readb(addr + SIOP_DMODE);
83 
84 	ctest5 = readb(addr + SIOP_CTEST5);
85 	writeb(addr + SIOP_CTEST4, readb(addr + SIOP_CTEST4) & ~CTEST4_BDIS);
86 	ctest5 &= ~CTEST5_BBCK;
87 	ctest5 |= (maxburst - 1) & CTEST5_BBCK;
88 	writeb(addr + SIOP_CTEST5, ctest5);
89 
90 	dmode |= DMODE_ERL;
91 	dmode &= ~DMODE_BL_MASK;
92 	dmode |= ((maxburst - 1) << DMODE_BL_SHIFT) & DMODE_BL_MASK;
93 	writeb(addr + SIOP_DMODE, dmode);
94 }
95 
96 
97 static void
98 siop_setuptables(struct siop_adapter *adp, struct siop_xfer *xfer,
99 		 struct scsi_xfer *xs)
100 {
101 	int msgoffset = 1;
102 
103 	xfer->siop_tables.id =
104 	    htoc32((adp->clock_div << 24) | (xs->target << 16));
105 	memset(xfer->siop_tables.msg_out, 0, sizeof(xfer->siop_tables.msg_out));
106 	/* request sense doesn't disconnect */
107 	if (xs->cmd->opcode == SCSI_REQUEST_SENSE)
108 		xfer->siop_tables.msg_out[0] = MSG_IDENTIFY(xs->lun, 0);
109 	else
110 		xfer->siop_tables.msg_out[0] = MSG_IDENTIFY(xs->lun, 1);
111 
112 	xfer->siop_tables.t_msgout.count = htoc32(msgoffset);
113 	xfer->siop_tables.status =
114 	    htoc32(SCSI_SIOP_NOSTATUS); /* set invalid status */
115 
116 	xfer->siop_tables.cmd.count = htoc32(xs->cmdlen);
117 	xfer->siop_tables.cmd.addr = htoc32(local_to_PCI((u_long)xs->cmd));
118 	if (xs->datalen != 0) {
119 		xfer->siop_tables.data[0].count = htoc32(xs->datalen);
120 		xfer->siop_tables.data[0].addr =
121 		    htoc32(local_to_PCI((u_long)xs->data));
122 	}
123 }
124 
125 static void
126 siop_ma(struct siop_adapter *adp, struct scsi_xfer *xs)
127 {
128 	int offset, dbc;
129 
130 	/*
131 	 * compute how much of the current table didn't get handled when
132 	 * a phase mismatch occurs
133 	 */
134 	if (xs->datalen == 0)
135 	    return; /* no valid data transfer */
136 
137 	offset = readb(adp->addr + SIOP_SCRATCHA + 1);
138 	if (offset >= SIOP_NSG) {
139 		printf("bad offset in siop_sdp (%d)\n", offset);
140 		return;
141 	}
142 	dbc = readl(adp->addr + SIOP_DBC) & 0x00ffffff;
143 	xs->resid = dbc;
144 }
145 
146 static void
147 siop_sdp(struct siop_adapter *adp, struct siop_xfer *xfer, struct scsi_xfer *xs,
148 	 int offset)
149 {
150 
151 	if (xs->datalen == 0)
152 	    return; /* no data pointers to save */
153 
154 	/*
155 	 * offset == SIOP_NSG may be a valid condition if we get a Save data
156 	 * pointer when the xfer is done. Just ignore the Save data pointer
157 	 * in this case
158 	 */
159 	if (offset == SIOP_NSG)
160 		return;
161 	/*
162 	 * Save data pointer. We do this by adjusting the tables to point
163 	 * at the begginning of the data not yet transfered.
164 	 * offset points to the first table with untransfered data.
165 	 */
166 
167 	/*
168 	 * before doing that we decrease resid from the ammount of data which
169 	 * has been transfered.
170 	 */
171 	siop_update_resid(adp, xfer, xs, offset);
172 
173 #if 0
174 	/*
175 	 * First let see if we have a resid from a phase mismatch. If so,
176 	 * we have to adjst the table at offset to remove transfered data.
177 	 */
178 	if (siop_cmd->flags & CMDFL_RESID) {
179 		scr_table_t *table;
180 
181 		siop_cmd->flags &= ~CMDFL_RESID;
182 		table = &xfer->siop_tables.data[offset];
183 		/* "cut" already transfered data from this table */
184 		table->addr =
185 		    htoc32(ctoh32(table->addr) + ctoh32(table->count) -
186 							siop_cmd->resid);
187 		table->count = htoc32(siop_cmd->resid);
188 	}
189 #endif
190 
191 	/*
192 	 * now we can remove entries which have been transfered.
193 	 * We just move the entries with data left at the beggining of the
194 	 * tables
195 	 */
196 	memmove(xfer->siop_tables.data, &xfer->siop_tables.data[offset],
197 	    (SIOP_NSG - offset) * sizeof(scr_table_t));
198 }
199 
200 static void
201 siop_update_resid(struct siop_adapter *adp, struct siop_xfer *xfer,
202 		  struct scsi_xfer *xs, int offset)
203 {
204 	int i;
205 
206 	if (xs->datalen == 0)
207 	    return; /* no data to transfer */
208 
209 	/*
210 	 * update resid. First account for the table entries which have
211 	 * been fully completed.
212 	 */
213 	for (i = 0; i < offset; i++)
214 		xs->resid -= ctoh32(xfer->siop_tables.data[i].count);
215 #if 0
216 	/*
217 	 * if CMDFL_RESID is set, the last table (pointed by offset) is a
218 	 * partial transfers. If not, offset points to the entry folloing
219 	 * the last full transfer.
220 	 */
221 	if (siop_cmd->flags & CMDFL_RESID) {
222 		scr_table_t *table = &xfer->siop_tables.data[offset];
223 
224 		xs->resid -= ctoh32(table->count) - xs->resid;
225 	}
226 #endif
227 }
228 
229 
230 #define CALL_SCRIPT(ent)	writel(adp->addr + SIOP_DSP, scriptaddr + ent);
231 
232 static int
233 siop_intr(struct siop_adapter *adp)
234 {
235 	struct siop_xfer *siop_xfer = NULL;
236 	struct scsi_xfer *xs = NULL;
237 	u_long scriptaddr = local_to_PCI((u_long)adp->script);
238 	int offset, target, lun, tag, restart = 0, need_reset = 0;
239 	uint32_t dsa, irqcode;
240 	uint16_t sist;
241 	uint8_t dstat, sstat1, istat;
242 
243 	istat = readb(adp->addr + SIOP_ISTAT);
244 	if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
245 		return 0;
246 	if (istat & ISTAT_INTF) {
247 		printf("INTRF\n");
248 		writeb(adp->addr + SIOP_ISTAT, ISTAT_INTF);
249 	}
250 	if ((istat & (ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
251 	    (ISTAT_DIP | ISTAT_ABRT))
252 		/* clear abort */
253 		writeb(adp->addr + SIOP_ISTAT, 0);
254 	/* use DSA to find the current siop_cmd */
255 	dsa = readl(adp->addr + SIOP_DSA);
256 	if (dsa >= local_to_PCI((u_long)adp->xfer) &&
257 	    dsa < local_to_PCI((u_long)adp->xfer) + SIOP_TABLE_SIZE) {
258 		dsa -= local_to_PCI((u_long)adp->xfer);
259 		siop_xfer = adp->xfer;
260 		_inv((u_long)siop_xfer, sizeof(*siop_xfer));
261 
262 		xs = adp->xs;
263 	}
264 
265 	if (istat & ISTAT_DIP)
266 		dstat = readb(adp->addr + SIOP_DSTAT);
267 	if (istat & ISTAT_SIP) {
268 		if (istat & ISTAT_DIP)
269 			delay(10);
270 		/*
271 		 * Can't read sist0 & sist1 independently, or we have to
272 		 * insert delay
273 		 */
274 		sist = readw(adp->addr + SIOP_SIST0);
275 		sstat1 = readb(adp->addr + SIOP_SSTAT1);
276 
277 		if ((sist & SIST0_MA) && need_reset == 0) {
278 			if (siop_xfer) {
279 				int scratcha0;
280 
281 				dstat = readb(adp->addr + SIOP_DSTAT);
282 				/*
283 				 * first restore DSA, in case we were in a S/G
284 				 * operation.
285 				 */
286 				writel(adp->addr + SIOP_DSA,
287 				    local_to_PCI((u_long)siop_xfer));
288 				scratcha0 = readb(adp->addr + SIOP_SCRATCHA);
289 				switch (sstat1 & SSTAT1_PHASE_MASK) {
290 				case SSTAT1_PHASE_STATUS:
291 				/*
292 				 * previous phase may be aborted for any reason
293 				 * ( for example, the target has less data to
294 				 * transfer than requested). Compute resid and
295 				 * just go to status, the command should
296 				 * terminate.
297 				 */
298 					if (scratcha0 & A_flag_data)
299 						siop_ma(adp, xs);
300 					else if ((dstat & DSTAT_DFE) == 0)
301 printf("PHASE STATUS: siop_clearfifo...\n");
302 //						siop_clearfifo(adp);
303 					CALL_SCRIPT(Ent_status);
304 					return 1;
305 				case SSTAT1_PHASE_MSGIN:
306 				/*
307 				 * target may be ready to disconnect
308 				 * Compute resid which would be used later
309 				 * if a save data pointer is needed.
310 				 */
311 					if (scratcha0 & A_flag_data)
312 						siop_ma(adp, xs);
313 					else if ((dstat & DSTAT_DFE) == 0)
314 printf("PHASE MSGIN: siop_clearfifo...\n");
315 //						siop_clearfifo(adp);
316 					writeb(adp->addr + SIOP_SCRATCHA,
317 					    scratcha0 & ~A_flag_data);
318 					CALL_SCRIPT(Ent_msgin);
319 					return 1;
320 				}
321 				printf("unexpected phase mismatch %d\n",
322 				    sstat1 & SSTAT1_PHASE_MASK);
323 			} else
324 				printf("phase mismatch without command\n");
325 			need_reset = 1;
326 		}
327 		if (sist & (SIST1_STO << 8)) {
328 			/* selection time out, assume there's no device here */
329 			if (siop_xfer) {
330 				xs->error = XS_SELTIMEOUT;
331 				goto end;
332 			} else
333 				printf("selection timeout without command\n");
334 		}
335 
336 		/* Else it's an unhandled exception (for now). */
337 		printf("unhandled scsi interrupt,"
338 		    " sist=0x%x sstat1=0x%x DSA=0x%x DSP=0x%lx\n",
339 		    sist, sstat1, dsa,
340 		    readl(adp->addr + SIOP_DSP) - scriptaddr);
341 		if (siop_xfer) {
342 			xs->error = XS_SELTIMEOUT;
343 			goto end;
344 		}
345 		need_reset = 1;
346 	}
347 	if (need_reset) {
348 reset:
349 		printf("XXXXX: fatal error, need reset the bus...\n");
350 		return 1;
351 	}
352 
353 //scintr:
354 	if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
355 		irqcode = readl(adp->addr + SIOP_DSPS);
356 		/*
357 		 * no command, or an inactive command is only valid for a
358 		 * reselect interrupt
359 		 */
360 		if ((irqcode & 0x80) == 0) {
361 			if (siop_xfer == NULL) {
362 				printf(
363 				    "script interrupt 0x%x with invalid DSA\n",
364 				    irqcode);
365 				goto reset;
366 			}
367 		}
368 		switch(irqcode) {
369 		case A_int_err:
370 			printf("error, DSP=0x%lx\n",
371 			    readl(adp->addr + SIOP_DSP) - scriptaddr);
372 			if (xs) {
373 				xs->error = XS_SELTIMEOUT;
374 				goto end;
375 			} else {
376 				goto reset;
377 			}
378 		case A_int_reseltarg:
379 			printf("reselect with invalid target\n");
380 			goto reset;
381 		case A_int_resellun:
382 			target = readb(adp->addr + SIOP_SCRATCHA) & 0xf;
383 			lun = readb(adp->addr + SIOP_SCRATCHA + 1);
384 			tag = readb(adp->addr + SIOP_SCRATCHA + 2);
385 			if (target != adp->xs->target ||
386 			    lun != adp->xs->lun ||
387 			    tag != 0) {
388 				printf("unknwon resellun:"
389 				    " target %d lun %d tag %d\n",
390 				    target, lun, tag);
391 				goto reset;
392 			}
393 			siop_xfer = adp->xfer;
394 			dsa = local_to_PCI((u_long)siop_xfer);
395 			writel(adp->addr + SIOP_DSP,
396 			    dsa + sizeof(struct siop_common_xfer) +
397 			    Ent_ldsa_reload_dsa);
398 			_wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
399 			return 1;
400 		case A_int_reseltag:
401 			printf("reselect with invalid tag\n");
402 			goto reset;
403 		case A_int_disc:
404 			offset = readb(adp->addr + SIOP_SCRATCHA + 1);
405 			siop_sdp(adp, siop_xfer, xs, offset);
406 #if 0
407 			/* we start again with no offset */
408 			siop_cmd->saved_offset = SIOP_NOOFFSET;
409 #endif
410 			_wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
411 			CALL_SCRIPT(Ent_script_sched);
412 			return 1;
413 		case A_int_resfail:
414 			printf("reselect failed\n");
415 			return  1;
416 		case A_int_done:
417 			if (xs == NULL) {
418 				printf("done without command, DSA=0x%lx\n",
419 				    local_to_PCI((u_long)adp->xfer));
420 				return 1;
421 			}
422 			/* update resid.  */
423 			offset = readb(adp->addr + SIOP_SCRATCHA + 1);
424 #if 0
425 			/*
426 			 * if we got a disconnect between the last data phase
427 			 * and the status phase, offset will be 0. In this
428 			 * case, siop_cmd->saved_offset will have the proper
429 			 * value if it got updated by the controller
430 			 */
431 			if (offset == 0 &&
432 			    siop_cmd->saved_offset != SIOP_NOOFFSET)
433 				offset = siop_cmd->saved_offset;
434 #endif
435 			siop_update_resid(adp, siop_xfer, xs, offset);
436 			goto end;
437 		default:
438 			printf("unknown irqcode %x\n", irqcode);
439 			if (xs) {
440 				xs->error = XS_SELTIMEOUT;
441 				goto end;
442 			}
443 			goto reset;
444 		}
445 		return 1;
446 	}
447 	/* We just should't get there */
448 	panic("siop_intr: I shouldn't be there !");
449 
450 	return 1;
451 
452 end:
453 	/*
454 	 * restart the script now if command completed properly
455 	 * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
456 	 * queue
457 	 */
458 	xs->status = ctoh32(siop_xfer->siop_tables.status);
459 	if (xs->status == SCSI_OK)
460 		writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched);
461 	else
462 		restart = 1;
463 	siop_scsicmd_end(adp, xs);
464 	if (restart)
465 		writel(adp->addr + SIOP_DSP, scriptaddr + Ent_script_sched);
466 
467 	return 1;
468 }
469 
470 static void
471 siop_scsicmd_end(struct siop_adapter *adp, struct scsi_xfer *xs)
472 {
473 
474 	switch(xs->status) {
475 	case SCSI_OK:
476 		xs->error = XS_NOERROR;
477 		break;
478 	case SCSI_BUSY:
479 	case SCSI_CHECK:
480 	case SCSI_QUEUE_FULL:
481 		xs->error = XS_BUSY;
482 		break;
483 	case SCSI_SIOP_NOCHECK:
484 		/*
485 		 * don't check status, xs->error is already valid
486 		 */
487 		break;
488 	case SCSI_SIOP_NOSTATUS:
489 		/*
490 		 * the status byte was not updated, cmd was
491 		 * aborted
492 		 */
493 		xs->error = XS_SELTIMEOUT;
494 		break;
495 	default:
496 		printf("invalid status code %d\n", xs->status);
497 		xs->error = XS_DRIVER_STUFFUP;
498 	}
499 	_inv((u_long)xs->cmd, xs->cmdlen);
500 	if (xs->datalen != 0)
501 		_inv((u_long)xs->data, xs->datalen);
502 	xs->xs_status = XS_STS_DONE;
503 }
504 
505 static int
506 siop_scsi_request(struct siop_adapter *adp, struct scsi_xfer *xs)
507 {
508 	void *xfer = adp->xfer;
509 	int timo, error;
510 
511 	if (adp->sel_t != xs->target) {
512 		const int free_lo = __arraycount(siop_script);
513 		int i;
514 		void *scriptaddr = (void *)local_to_PCI((u_long)adp->script);
515 
516 		if (adp->sel_t != -1)
517 			adp->script[Ent_resel_targ0 / 4 + adp->sel_t * 2] =
518 			    htoc32(0x800c00ff);
519 
520 		for (i = 0; i < __arraycount(lun_switch); i++)
521 			adp->script[free_lo + i] = htoc32(lun_switch[i]);
522 		adp->script[free_lo + E_abs_lunsw_return_Used[0]] =
523 		    htoc32(scriptaddr + Ent_lunsw_return);
524 
525 		siop_add_reselsw(adp, xs->target, free_lo);
526 
527 		adp->sel_t = xs->target;
528 	}
529 
530 restart:
531 
532 	siop_setuptables(adp, xfer, xs);
533 
534 	/* load the DMA maps */
535 	if (xs->datalen != 0)
536 		_inv((u_long)xs->data, xs->datalen);
537 	_wbinv((u_long)xs->cmd, xs->cmdlen);
538 
539 	_wbinv((u_long)xfer, sizeof(struct siop_xfer));
540 	siop_start(adp, xs);
541 
542 	adp->xs = xs;
543 	timo = 0;
544 	while (!(xs->xs_status & XS_STS_DONE)) {
545 		delay(1000);
546 		siop_intr(adp);
547 
548 		if (timo++ > 3000) {		/* XXXX: 3sec */
549 			printf("%s: timeout\n", __func__);
550 			return ETIMEDOUT;
551 		}
552 	}
553 
554 	if (xs->error != XS_NOERROR) {
555 		if (xs->error == XS_BUSY || xs->status == SCSI_CHECK)
556 			scsi_request_sense(adp, xs);
557 
558 		switch (xs->error) {
559 		case XS_SENSE:
560 		case XS_SHORTSENSE:
561 			error = scsi_interpret_sense(adp, xs);
562 			break;
563 		case XS_RESOURCE_SHORTAGE:
564 			printf("adapter resource shortage\n");
565 
566 			/* FALLTHROUGH */
567 		case XS_BUSY:
568 			error = EBUSY;
569 			break;
570 		case XS_REQUEUE:
571 			printf("XXXX: requeue...\n");
572 			error = ERESTART;
573 			break;
574 		case XS_SELTIMEOUT:
575 		case XS_TIMEOUT:
576 			error = EIO;
577 			break;
578 		case XS_RESET:
579 			error = EIO;
580 			break;
581 		case XS_DRIVER_STUFFUP:
582 			printf("generic HBA error\n");
583 			error = EIO;
584 			break;
585 		default:
586 			printf("invalid return code from adapter: %d\n",
587 			    xs->error);
588 			error = EIO;
589 			break;
590 		}
591 		if (error == ERESTART) {
592 			xs->error = XS_NOERROR;
593 			xs->status = SCSI_OK;
594 			xs->xs_status &= ~XS_STS_DONE;
595 			goto restart;
596 		}
597 		return error;
598 	}
599 	return 0;
600 }
601 
602 static void
603 siop_start(struct siop_adapter *adp, struct scsi_xfer *xs)
604 {
605 	struct siop_xfer *siop_xfer = adp->xfer;
606 	uint32_t dsa, *script = adp->script;
607 	int target, lun, slot;
608 	void *scriptaddr = (void *)local_to_PCI((u_long)script);
609 	const int siop_common_xfer_size = sizeof(struct siop_common_xfer);
610 
611 	/*
612 	 * The queue management here is a bit tricky: the script always looks
613 	 * at the slot from first to last, so if we always use the first
614 	 * free slot commands can stay at the tail of the queue ~forever.
615 	 * The algorithm used here is to restart from the head when we know
616 	 * that the queue is empty, and only add commands after the last one.
617 	 * When we're at the end of the queue wait for the script to clear it.
618 	 * The best thing to do here would be to implement a circular queue,
619 	 * but using only 53c720 features this can be "interesting".
620 	 * A mid-way solution could be to implement 2 queues and swap orders.
621 	 */
622 	slot = adp->currschedslot;
623 	/*
624 	 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is
625 	 * free. As this is the last used slot, all previous slots are free,
626 	 * we can restart from 0.
627 	 */
628 	if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) ==
629 	    0x80000000) {
630 		slot = adp->currschedslot = 0;
631 	} else {
632 		slot++;
633 	}
634 	target = xs->target;
635 	lun = xs->lun;
636 	/*
637 	 * find a free scheduler slot and load it.
638 	 */
639 #define SIOP_NSLOTS	0x40
640 	for (; slot < SIOP_NSLOTS; slot++) {
641 		/*
642 		 * If cmd if 0x80000000 the slot is free
643 		 */
644 		if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) ==
645 		    0x80000000)
646 			break;
647 	}
648 	if (slot == SIOP_NSLOTS) {
649 		/*
650 		 * no more free slot, no need to continue. freeze the queue
651 		 * and requeue this command.
652 		 */
653 		printf("no mode free slot\n");
654 		return;
655 	}
656 
657 	/* patch scripts with DSA addr */
658 	dsa = local_to_PCI((u_long)siop_xfer);
659 
660 	/* CMD script: MOVE MEMORY addr */
661 	siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
662 	    htoc32(scriptaddr + Ent_script_sched_slot0 + slot * 8);
663 	_wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
664 	/* scheduler slot: JUMP ldsa_select */
665 	script[(Ent_script_sched_slot0 / 4) + slot * 2 + 1] =
666 	    htoc32(dsa + siop_common_xfer_size + Ent_ldsa_select);
667 	/*
668 	 * Change JUMP cmd so that this slot will be handled
669 	 */
670 	script[(Ent_script_sched_slot0 / 4) + slot * 2] = htoc32(0x80080000);
671 	adp->currschedslot = slot;
672 
673 	/* make sure SCRIPT processor will read valid data */
674 	_wbinv((u_long)script, SIOP_SCRIPT_SIZE);
675 	/* Signal script it has some work to do */
676 	writeb(adp->addr + SIOP_ISTAT, ISTAT_SIGP);
677 	/* and wait for IRQ */
678 }
679 
680 static void
681 siop_xfer_setup(struct siop_xfer *xfer, void *scriptaddr)
682 {
683 	const int off_msg_in = offsetof(struct siop_common_xfer, msg_in);
684 	const int off_status = offsetof(struct siop_common_xfer, status);
685 	uint32_t dsa, *scr;
686 	int i;
687 
688 	memset(xfer, 0, sizeof(*xfer));
689 	dsa = local_to_PCI((u_long)xfer);
690 	xfer->siop_tables.t_msgout.count = htoc32(1);
691 	xfer->siop_tables.t_msgout.addr = htoc32(dsa);
692 	xfer->siop_tables.t_msgin.count = htoc32(1);
693 	xfer->siop_tables.t_msgin.addr = htoc32(dsa + off_msg_in);
694 	xfer->siop_tables.t_extmsgin.count = htoc32(2);
695 	xfer->siop_tables.t_extmsgin.addr = htoc32(dsa + off_msg_in + 1);
696 	xfer->siop_tables.t_extmsgdata.addr = htoc32(dsa + off_msg_in + 3);
697 	xfer->siop_tables.t_status.count = htoc32(1);
698 	xfer->siop_tables.t_status.addr = htoc32(dsa + off_status);
699 
700 	/* The select/reselect script */
701 	scr = xfer->resel;
702 	for (i = 0; i < __arraycount(load_dsa); i++)
703 		scr[i] = htoc32(load_dsa[i]);
704 
705 	/*
706 	 * 0x78000000 is a 'move data8 to reg'. data8 is the second
707 	 * octet, reg offset is the third.
708 	 */
709 	scr[Ent_rdsa0 / 4] = htoc32(0x78100000 | ((dsa & 0x000000ff) <<  8));
710 	scr[Ent_rdsa1 / 4] = htoc32(0x78110000 | ( dsa & 0x0000ff00       ));
711 	scr[Ent_rdsa2 / 4] = htoc32(0x78120000 | ((dsa & 0x00ff0000) >>  8));
712 	scr[Ent_rdsa3 / 4] = htoc32(0x78130000 | ((dsa & 0xff000000) >> 16));
713 	scr[E_ldsa_abs_reselected_Used[0]] =
714 	    htoc32(scriptaddr + Ent_reselected);
715 	scr[E_ldsa_abs_reselect_Used[0]] = htoc32(scriptaddr + Ent_reselect);
716 	scr[E_ldsa_abs_selected_Used[0]] = htoc32(scriptaddr + Ent_selected);
717 	scr[E_ldsa_abs_data_Used[0]] =
718 	    htoc32(dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data);
719 	/* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
720 	scr[Ent_ldsa_data / 4] = htoc32(0x80000000);
721 }
722 
723 static int
724 siop_add_reselsw(struct siop_adapter *adp, int target, int lunsw_off)
725 {
726 	uint32_t *script = adp->script;
727 	int reseloff;
728 	void *scriptaddr = (void *)local_to_PCI((u_long)adp->script);
729 
730 	/*
731 	 * add an entry to resel switch
732 	 */
733 	reseloff = Ent_resel_targ0 / 4 + target * 2;
734 	if ((ctoh32(script[reseloff]) & 0xff) != 0xff) {
735 		/* it's not free */
736 		printf("siop: resel switch full\n");
737 		return EBUSY;
738 	}
739 
740 	/* JUMP abs_foo, IF target | 0x80; */
741 	script[reseloff + 0] = htoc32(0x800c0080 | target);
742 	script[reseloff + 1] =
743 	    htoc32(scriptaddr + lunsw_off * 4 + Ent_lun_switch_entry);
744 
745 	siop_update_scntl3(adp, target, lunsw_off);
746 	return 0;
747 }
748 
749 static void
750 siop_update_scntl3(struct siop_adapter *adp, int target, int lunsw_off)
751 {
752 	uint32_t *script = adp->script;
753 
754 	/* MOVE target->id >> 24 TO SCNTL3 */
755 	script[lunsw_off + (Ent_restore_scntl3 / 4)] =
756 	    htoc32(0x78030000 | ((adp->clock_div >> 16) & 0x0000ff00));
757 	/* MOVE target->id >> 8 TO SXFER */
758 	script[lunsw_off + (Ent_restore_scntl3 / 4) + 2] =
759 	    htoc32(0x78050000 | (0x000000000 & 0x0000ff00));
760 	_wbinv((u_long)script, SIOP_SCRIPT_SIZE);
761 }
762 
763 
764 /*
765  * SCSI functions
766  */
767 
768 static int
769 _scsi_inquire(struct siop_adapter *adp, int t, int l, int buflen, char *buf)
770 {
771 	struct scsipi_inquiry *cmd = (struct scsipi_inquiry *)adp->cmd;
772 	struct scsipi_inquiry_data *inqbuf =
773 	    (struct scsipi_inquiry_data *)adp->data;
774 	struct scsi_xfer xs;
775 	int error;
776 
777 	memset(cmd, 0, sizeof(*cmd));
778 	cmd->opcode = INQUIRY;
779 	cmd->length = SCSIPI_INQUIRY_LENGTH_SCSI2;
780 	memset(inqbuf, 0, sizeof(*inqbuf));
781 
782 	memset(&xs, 0, sizeof(xs));
783 	xs.target = t;
784 	xs.lun = l;
785 	xs.cmdlen = sizeof(*cmd);
786 	xs.cmd = (void *)cmd;
787 	xs.datalen = SCSIPI_INQUIRY_LENGTH_SCSI2;
788 	xs.data = (void *)inqbuf;
789 
790 	xs.error = XS_NOERROR;
791 	xs.resid = xs.datalen;
792 	xs.status = SCSI_OK;
793 
794 	error = siop_scsi_request(adp, &xs);
795 	if (error != 0)
796 		return error;
797 
798 	memcpy(buf, inqbuf, buflen);
799 	return 0;
800 }
801 
802 static void
803 scsi_request_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
804 {
805 	struct scsi_request_sense *cmd = adp->sense;
806 	struct scsi_sense_data *data = (struct scsi_sense_data *)adp->data;
807 	struct scsi_xfer sense;
808 	int error;
809 
810 	memset(cmd, 0, sizeof(struct scsi_request_sense));
811 	cmd->opcode = SCSI_REQUEST_SENSE;
812 	cmd->length = sizeof(struct scsi_sense_data);
813 	memset(data, 0, sizeof(struct scsi_sense_data));
814 
815 	memset(&sense, 0, sizeof(sense));
816 	sense.target = xs->target;
817 	sense.lun = xs->lun;
818 	sense.cmdlen = sizeof(struct scsi_request_sense);
819 	sense.cmd = (void *)cmd;
820 	sense.datalen = sizeof(struct scsi_sense_data);
821 	sense.data = (void *)data;
822 
823 	sense.error = XS_NOERROR;
824 	sense.resid = sense.datalen;
825 	sense.status = SCSI_OK;
826 
827 	error = siop_scsi_request(adp, &sense);
828 	switch (error) {
829 	case 0:
830 		/* we have a valid sense */
831 		xs->error = XS_SENSE;
832 		return;
833 	case EINTR:
834 		/* REQUEST_SENSE interrupted by bus reset. */
835 		xs->error = XS_RESET;
836 		return;
837 	case EIO:
838 		 /* request sense coudn't be performed */
839 		/*
840 		 * XXX this isn't quite right but we don't have anything
841 		 * better for now
842 		 */
843 		xs->error = XS_DRIVER_STUFFUP;
844 		return;
845 	default:
846 		 /* Notify that request sense failed. */
847 		xs->error = XS_DRIVER_STUFFUP;
848 		printf("request sense failed with error %d\n", error);
849 		return;
850 	}
851 }
852 
853 /*
854  * scsi_interpret_sense:
855  *
856  *	Look at the returned sense and act on the error, determining
857  *	the unix error number to pass back.  (0 = report no error)
858  *
859  *	NOTE: If we return ERESTART, we are expected to haved
860  *	thawed the device!
861  *
862  *	THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES.
863  */
864 static int
865 scsi_interpret_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
866 {
867 	struct scsi_sense_data *sense;
868 	u_int8_t key;
869 	int error;
870 	uint32_t info;
871 	static const char *error_mes[] = {
872 		"soft error (corrected)",
873 		"not ready", "medium error",
874 		"non-media hardware failure", "illegal request",
875 		"unit attention", "readonly device",
876 		"no data found", "vendor unique",
877 		"copy aborted", "command aborted",
878 		"search returned equal", "volume overflow",
879 		"verify miscompare", "unknown error key"
880 	};
881 
882 	sense = (struct scsi_sense_data *)xs->data;
883 
884 	/* otherwise use the default */
885 	switch (SSD_RCODE(sense->response_code)) {
886 
887 		/*
888 		 * Old SCSI-1 and SASI devices respond with
889 		 * codes other than 70.
890 		 */
891 	case 0x00:		/* no error (command completed OK) */
892 		return 0;
893 	case 0x04:		/* drive not ready after it was selected */
894 		if (adp->sd->sc_flags & FLAGS_REMOVABLE)
895 			adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
896 		/* XXX - display some sort of error here? */
897 		return EIO;
898 	case 0x20:		/* invalid command */
899 		return EINVAL;
900 	case 0x25:		/* invalid LUN (Adaptec ACB-4000) */
901 		return EACCES;
902 
903 		/*
904 		 * If it's code 70, use the extended stuff and
905 		 * interpret the key
906 		 */
907 	case 0x71:		/* delayed error */
908 		key = SSD_SENSE_KEY(sense->flags);
909 		printf(" DEFERRED ERROR, key = 0x%x\n", key);
910 		/* FALLTHROUGH */
911 	case 0x70:
912 		if ((sense->response_code & SSD_RCODE_VALID) != 0)
913 			info = _4btol(sense->info);
914 		else
915 			info = 0;
916 		key = SSD_SENSE_KEY(sense->flags);
917 
918 		switch (key) {
919 		case SKEY_NO_SENSE:
920 		case SKEY_RECOVERED_ERROR:
921 			if (xs->resid == xs->datalen && xs->datalen) {
922 				/*
923 				 * Why is this here?
924 				 */
925 				xs->resid = 0;	/* not short read */
926 			}
927 		case SKEY_EQUAL:
928 			error = 0;
929 			break;
930 		case SKEY_NOT_READY:
931 			if (adp->sd->sc_flags & FLAGS_REMOVABLE)
932 				adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
933 			if (sense->asc == 0x3A) {
934 				error = ENODEV; /* Medium not present */
935 			} else
936 				error = EIO;
937 			break;
938 		case SKEY_ILLEGAL_REQUEST:
939 			error = EINVAL;
940 			break;
941 		case SKEY_UNIT_ATTENTION:
942 			if (sense->asc == 0x29 &&
943 			    sense->ascq == 0x00) {
944 				/* device or bus reset */
945 				return ERESTART;
946 			}
947 			if (adp->sd->sc_flags & FLAGS_REMOVABLE)
948 				adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
949 			if (!(adp->sd->sc_flags & FLAGS_REMOVABLE))
950 				return ERESTART;
951 			error = EIO;
952 			break;
953 		case SKEY_DATA_PROTECT:
954 			error = EROFS;
955 			break;
956 		case SKEY_BLANK_CHECK:
957 			error = 0;
958 			break;
959 		case SKEY_ABORTED_COMMAND:
960 			break;
961 		case SKEY_VOLUME_OVERFLOW:
962 			error = ENOSPC;
963 			break;
964 		default:
965 			error = EIO;
966 			break;
967 		}
968 
969 		/* Print brief(er) sense information */
970 		printf("%s", error_mes[key - 1]);
971 		if ((sense->response_code & SSD_RCODE_VALID) != 0) {
972 			switch (key) {
973 			case SKEY_NOT_READY:
974 			case SKEY_ILLEGAL_REQUEST:
975 			case SKEY_UNIT_ATTENTION:
976 			case SKEY_DATA_PROTECT:
977 				break;
978 			case SKEY_BLANK_CHECK:
979 				printf(", requested size: %d (decimal)",
980 				    info);
981 				break;
982 			case SKEY_ABORTED_COMMAND:
983 				printf(", cmd 0x%x, info 0x%x",
984 				    xs->cmd->opcode, info);
985 				break;
986 			default:
987 				printf(", info = %d (decimal)", info);
988 			}
989 		}
990 		if (sense->extra_len != 0) {
991 			int n;
992 			printf(", data =");
993 			for (n = 0; n < sense->extra_len; n++)
994 				printf(" %x", sense->csi[n]);
995 		}
996 		printf("\n");
997 		return error;
998 
999 	/*
1000 	 * Some other code, just report it
1001 	 */
1002 	default:
1003 		printf("Sense Error Code 0x%x",
1004 			SSD_RCODE(sense->response_code));
1005 		if ((sense->response_code & SSD_RCODE_VALID) != 0) {
1006 			struct scsi_sense_data_unextended *usense =
1007 			    (struct scsi_sense_data_unextended *)sense;
1008 			printf(" at block no. %d (decimal)",
1009 			    _3btol(usense->block));
1010 		}
1011 		printf("\n");
1012 		return EIO;
1013 	}
1014 }
1015 
1016 static int
1017 scsi_probe(struct siop_adapter *adp)
1018 {
1019 	struct scsipi_inquiry_data *inqbuf;
1020 	int found, t, l;
1021 	uint8_t device;
1022 	char buf[SCSIPI_INQUIRY_LENGTH_SCSI2],
1023 	    product[sizeof(inqbuf->product) + 1];
1024 
1025 	found = 0;
1026 	for (t = 0; t < 8; t++) {
1027 		if (t == adp->id)
1028 			continue;
1029 		for (l = 0; l < 8; l++) {
1030 			if (_scsi_inquire(adp, t, l, sizeof(buf), buf) != 0)
1031 				continue;
1032 
1033 			inqbuf = (struct scsipi_inquiry_data *)buf;
1034 			device = inqbuf->device & SID_TYPE;
1035 			if (device == T_NODEVICE)
1036 				continue;
1037 			if (device != T_DIRECT &&
1038 			    device != T_OPTICAL &&
1039 			    device != T_SIMPLE_DIRECT)
1040 				continue;
1041 
1042 			memset(product, 0, sizeof(product));
1043 			strncpy(product, inqbuf->product, sizeof(product) - 1);
1044 			printf("sd(%d,%d,[0-7]): <%s>\n", t, l, product);
1045 			found++;
1046 		}
1047 	}
1048 	return found;
1049 }
1050 
1051 int
1052 scsi_inquire(struct sd_softc *sd, int buflen, void *buf)
1053 {
1054 	struct siop_adapter *adp;
1055 	int error;
1056 
1057 	if (sd->sc_bus != 0)
1058 		return ENOTSUP;
1059 	if (adapt.addr == 0xffffffff)
1060 		return ENOENT;
1061 	adp = &adapt;
1062 
1063 	adp->sd = sd;
1064 	error = _scsi_inquire(adp, sd->sc_target, sd->sc_lun, buflen, buf);
1065 	adp->sd = NULL;
1066 
1067 	return error;
1068 }
1069 
1070 /*
1071  * scsi_mode_sense
1072  *	get a sense page from a device
1073  */
1074 
1075 int
1076 scsi_mode_sense(struct sd_softc *sd, int byte2, int page,
1077 		  struct scsi_mode_parameter_header_6 *data, int len)
1078 {
1079 	struct scsi_mode_sense_6 cmd;
1080 
1081 	memset(&cmd, 0, sizeof(cmd));
1082 	cmd.opcode = SCSI_MODE_SENSE_6;
1083 	cmd.byte2 = byte2;
1084 	cmd.page = page;
1085 	cmd.length = len & 0xff;
1086 
1087 	return scsi_command(sd, (void *)&cmd, sizeof(cmd), (void *)data, len);
1088 }
1089 
1090 int
1091 scsi_command(struct sd_softc *sd, void *cmd, int cmdlen, void *data,
1092 	     int datalen)
1093 {
1094 	struct siop_adapter *adp;
1095 	struct scsi_xfer xs;
1096 	int error;
1097 
1098 	if (sd->sc_bus != 0)
1099 		return ENOTSUP;
1100 	if (adapt.addr == 0xffffffff)
1101 		return ENOENT;
1102 	adp = &adapt;
1103 
1104 	memcpy(adp->cmd, cmd, cmdlen);
1105 	adp->sd = sd;
1106 
1107 	memset(&xs, 0, sizeof(xs));
1108 	xs.target = sd->sc_target;
1109 	xs.lun = sd->sc_lun;
1110 	xs.cmdlen = cmdlen;
1111 	xs.cmd = adp->cmd;
1112 	xs.datalen = datalen;
1113 	xs.data = adp->data;
1114 
1115 	xs.error = XS_NOERROR;
1116 	xs.resid = datalen;
1117 	xs.status = SCSI_OK;
1118 
1119 	error = siop_scsi_request(adp, &xs);
1120 	adp->sd = NULL;
1121 	if (error != 0)
1122 		return error;
1123 
1124 	if (datalen > 0)
1125 		memcpy(data, adp->data, datalen);
1126 	return 0;
1127 }
1128 
1129 /*
1130  * Initialize the device.
1131  */
1132 int
1133 siop_init(int bus, int dev, int func)
1134 {
1135 	struct siop_adapter tmp;
1136 	struct siop_xfer *xfer;
1137 	struct scsipi_generic *cmd;
1138 	struct scsi_request_sense *sense;
1139 	uint32_t reg;
1140 	u_long addr;
1141 	uint32_t *script;
1142 	int slot, id, i;
1143 	void *scriptaddr;
1144 	u_char *data;
1145 	const int clock_div = 3;		/* 53c810 */
1146 
1147 	slot = PCISlotnum(bus, dev, func);
1148 	if (slot == -1)
1149 		return ENOENT;
1150 
1151 	addr = PCIAddress(slot, 1, PCI_MAPREG_TYPE_MEM);
1152 	if (addr == 0xffffffff)
1153 		return EINVAL;
1154 	enablePCI(slot, 0, 1, 1);
1155 
1156 	script = ALLOC(uint32_t, SIOP_SCRIPT_SIZE);
1157 	if (script == NULL)
1158 		return ENOMEM;
1159 	scriptaddr = (void *)local_to_PCI((u_long)script);
1160 	cmd = ALLOC(struct scsipi_generic, SIOP_SCSI_COMMAND_SIZE);
1161 	if (cmd == NULL)
1162 		return ENOMEM;
1163 	sense = ALLOC(struct scsi_request_sense, SIOP_SCSI_COMMAND_SIZE);
1164 	if (sense == NULL)
1165 		return ENOMEM;
1166 	data = ALLOC(u_char, SIOP_SCSI_DATA_SIZE);
1167 	if (data == NULL)
1168 		return ENOMEM;
1169 	xfer = ALLOC(struct siop_xfer, sizeof(struct siop_xfer));
1170 	if (xfer == NULL)
1171 		return ENOMEM;
1172 	siop_xfer_setup(xfer, scriptaddr);
1173 
1174 	id = readb(addr + SIOP_SCID) & SCID_ENCID_MASK;
1175 
1176 	/* reset bus */
1177 	reg = readb(addr + SIOP_SCNTL1);
1178 	writeb(addr + SIOP_SCNTL1, reg | SCNTL1_RST);
1179 	delay(100);
1180 	writeb(addr + SIOP_SCNTL1, reg);
1181 
1182 	/* reset the chip */
1183 	writeb(addr + SIOP_ISTAT, ISTAT_SRST);
1184 	delay(1000);
1185 	writeb(addr + SIOP_ISTAT, 0);
1186 
1187 	/* init registers */
1188 	writeb(addr + SIOP_SCNTL0, SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
1189 	writeb(addr + SIOP_SCNTL1, 0);
1190 	writeb(addr + SIOP_SCNTL3, clock_div);
1191 	writeb(addr + SIOP_SXFER, 0);
1192 	writeb(addr + SIOP_DIEN, 0xff);
1193 	writeb(addr + SIOP_SIEN0, 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL));
1194 	writeb(addr + SIOP_SIEN1, 0xff & ~(SIEN1_HTH | SIEN1_GEN));
1195 	writeb(addr + SIOP_STEST2, 0);
1196 	writeb(addr + SIOP_STEST3, STEST3_TE);
1197 	writeb(addr + SIOP_STIME0, (0xb << STIME0_SEL_SHIFT));
1198 	writeb(addr + SIOP_SCID, id | SCID_RRE);
1199 	writeb(addr + SIOP_RESPID0, 1 << id);
1200 	writeb(addr + SIOP_DCNTL, DCNTL_COM);
1201 
1202 	siop_pci_reset(addr);
1203 
1204 	/* copy and patch the script */
1205 	for (i = 0; i < __arraycount(siop_script); i++)
1206 		script[i] = htoc32(siop_script[i]);
1207 	for (i = 0; i < __arraycount(E_abs_msgin_Used); i++)
1208 		script[E_abs_msgin_Used[i]] =
1209 		    htoc32(scriptaddr + Ent_msgin_space);
1210 
1211 	/* start script */
1212 	_wbinv((u_long)script, SIOP_SCRIPT_SIZE);
1213 	writel(addr + SIOP_DSP, (int)scriptaddr + Ent_reselect);
1214 
1215 	memset(&tmp, 0, sizeof(tmp));
1216 	tmp.id = id;
1217 	tmp.clock_div = clock_div;
1218 	tmp.addr = addr;
1219 	tmp.script = script;
1220 	tmp.xfer = xfer;
1221 	tmp.cmd = cmd;
1222 	tmp.sense = sense;
1223 	tmp.data = data;
1224 	tmp.currschedslot = 0;
1225 	tmp.sel_t = -1;
1226 
1227 	if (scsi_probe(&tmp) == 0) {
1228 		adapt.addr = 0xffffffff;
1229 		return ENXIO;
1230 	}
1231 	adapt = tmp;
1232 	return 0;
1233 }
1234