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