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