Home | History | Annotate | Line # | Download | only in boot
siop.c revision 1.5
      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 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 	/*
    656 	 * find a free scheduler slot and load it.
    657 	 */
    658 #define SIOP_NSLOTS	0x40
    659 	for (; slot < SIOP_NSLOTS; slot++) {
    660 		/*
    661 		 * If cmd if 0x80000000 the slot is free
    662 		 */
    663 		if (ctoh32(script[(Ent_script_sched_slot0 / 4) + slot * 2]) ==
    664 		    0x80000000)
    665 			break;
    666 	}
    667 	if (slot == SIOP_NSLOTS) {
    668 		/*
    669 		 * no more free slot, no need to continue. freeze the queue
    670 		 * and requeue this command.
    671 		 */
    672 		printf("no mode free slot\n");
    673 		return;
    674 	}
    675 
    676 	/* patch scripts with DSA addr */
    677 	dsa = local_to_PCI((u_long)siop_xfer);
    678 
    679 	/* CMD script: MOVE MEMORY addr */
    680 	siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
    681 	    htoc32(scriptaddr + Ent_script_sched_slot0 + slot * 8);
    682 	_wbinv((u_long)siop_xfer, sizeof(*siop_xfer));
    683 	/* scheduler slot: JUMP ldsa_select */
    684 	script[(Ent_script_sched_slot0 / 4) + slot * 2 + 1] =
    685 	    htoc32(dsa + siop_common_xfer_size + Ent_ldsa_select);
    686 	/*
    687 	 * Change JUMP cmd so that this slot will be handled
    688 	 */
    689 	script[(Ent_script_sched_slot0 / 4) + slot * 2] = htoc32(0x80080000);
    690 	adp->currschedslot = slot;
    691 
    692 	/* make sure SCRIPT processor will read valid data */
    693 	_wbinv((u_long)script, SIOP_SCRIPT_SIZE);
    694 	/* Signal script it has some work to do */
    695 	writeb(adp->addr + SIOP_ISTAT, ISTAT_SIGP);
    696 	/* and wait for IRQ */
    697 }
    698 
    699 static void
    700 siop_xfer_setup(struct siop_xfer *xfer, void *scriptaddr)
    701 {
    702 	const int off_msg_in = offsetof(struct siop_common_xfer, msg_in);
    703 	const int off_status = offsetof(struct siop_common_xfer, status);
    704 	uint32_t dsa, *scr;
    705 	int i;
    706 
    707 	memset(xfer, 0, sizeof(*xfer));
    708 	dsa = local_to_PCI((u_long)xfer);
    709 	xfer->siop_tables.t_msgout.count = htoc32(1);
    710 	xfer->siop_tables.t_msgout.addr = htoc32(dsa);
    711 	xfer->siop_tables.t_msgin.count = htoc32(1);
    712 	xfer->siop_tables.t_msgin.addr = htoc32(dsa + off_msg_in);
    713 	xfer->siop_tables.t_extmsgin.count = htoc32(2);
    714 	xfer->siop_tables.t_extmsgin.addr = htoc32(dsa + off_msg_in + 1);
    715 	xfer->siop_tables.t_extmsgdata.addr = htoc32(dsa + off_msg_in + 3);
    716 	xfer->siop_tables.t_status.count = htoc32(1);
    717 	xfer->siop_tables.t_status.addr = htoc32(dsa + off_status);
    718 
    719 	/* The select/reselect script */
    720 	scr = xfer->resel;
    721 	for (i = 0; i < __arraycount(load_dsa); i++)
    722 		scr[i] = htoc32(load_dsa[i]);
    723 
    724 	/*
    725 	 * 0x78000000 is a 'move data8 to reg'. data8 is the second
    726 	 * octet, reg offset is the third.
    727 	 */
    728 	scr[Ent_rdsa0 / 4] = htoc32(0x78100000 | ((dsa & 0x000000ff) <<  8));
    729 	scr[Ent_rdsa1 / 4] = htoc32(0x78110000 | ( dsa & 0x0000ff00       ));
    730 	scr[Ent_rdsa2 / 4] = htoc32(0x78120000 | ((dsa & 0x00ff0000) >>  8));
    731 	scr[Ent_rdsa3 / 4] = htoc32(0x78130000 | ((dsa & 0xff000000) >> 16));
    732 	scr[E_ldsa_abs_reselected_Used[0]] =
    733 	    htoc32(scriptaddr + Ent_reselected);
    734 	scr[E_ldsa_abs_reselect_Used[0]] = htoc32(scriptaddr + Ent_reselect);
    735 	scr[E_ldsa_abs_selected_Used[0]] = htoc32(scriptaddr + Ent_selected);
    736 	scr[E_ldsa_abs_data_Used[0]] =
    737 	    htoc32(dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data);
    738 	/* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
    739 	scr[Ent_ldsa_data / 4] = htoc32(0x80000000);
    740 }
    741 
    742 static int
    743 siop_add_reselsw(struct siop_adapter *adp, int target, int lunsw_off)
    744 {
    745 	uint32_t *script = adp->script;
    746 	int reseloff;
    747 	void *scriptaddr = (void *)local_to_PCI((u_long)adp->script);
    748 
    749 	/*
    750 	 * add an entry to resel switch
    751 	 */
    752 	reseloff = Ent_resel_targ0 / 4 + target * 2;
    753 	if ((ctoh32(script[reseloff]) & 0xff) != 0xff) {
    754 		/* it's not free */
    755 		printf("siop: resel switch full\n");
    756 		return EBUSY;
    757 	}
    758 
    759 	/* JUMP abs_foo, IF target | 0x80; */
    760 	script[reseloff + 0] = htoc32(0x800c0080 | target);
    761 	script[reseloff + 1] =
    762 	    htoc32(scriptaddr + lunsw_off * 4 + Ent_lun_switch_entry);
    763 
    764 	siop_update_scntl3(adp, target, lunsw_off);
    765 	return 0;
    766 }
    767 
    768 static void
    769 siop_update_scntl3(struct siop_adapter *adp, int target, int lunsw_off)
    770 {
    771 	uint32_t *script = adp->script;
    772 
    773 	/* MOVE target->id >> 24 TO SCNTL3 */
    774 	script[lunsw_off + (Ent_restore_scntl3 / 4)] =
    775 	    htoc32(0x78030000 | ((adp->clock_div >> 16) & 0x0000ff00));
    776 	/* MOVE target->id >> 8 TO SXFER */
    777 	script[lunsw_off + (Ent_restore_scntl3 / 4) + 2] =
    778 	    htoc32(0x78050000 | (0x000000000 & 0x0000ff00));
    779 	_wbinv((u_long)script, SIOP_SCRIPT_SIZE);
    780 }
    781 
    782 
    783 /*
    784  * SCSI functions
    785  */
    786 
    787 static int
    788 _scsi_inquire(struct siop_adapter *adp, int t, int l, int buflen, char *buf)
    789 {
    790 	struct scsipi_inquiry *cmd = (struct scsipi_inquiry *)adp->cmd;
    791 	struct scsipi_inquiry_data *inqbuf =
    792 	    (struct scsipi_inquiry_data *)adp->data;
    793 	struct scsi_xfer xs;
    794 	int error;
    795 
    796 	memset(cmd, 0, sizeof(*cmd));
    797 	cmd->opcode = INQUIRY;
    798 	cmd->length = SCSIPI_INQUIRY_LENGTH_SCSI2;
    799 	memset(inqbuf, 0, sizeof(*inqbuf));
    800 
    801 	memset(&xs, 0, sizeof(xs));
    802 	xs.target = t;
    803 	xs.lun = l;
    804 	xs.cmdlen = sizeof(*cmd);
    805 	xs.cmd = (void *)cmd;
    806 	xs.datalen = SCSIPI_INQUIRY_LENGTH_SCSI2;
    807 	xs.data = (void *)inqbuf;
    808 
    809 	xs.error = XS_NOERROR;
    810 	xs.resid = xs.datalen;
    811 	xs.status = SCSI_OK;
    812 
    813 	error = siop_scsi_request(adp, &xs);
    814 	if (error != 0)
    815 		return error;
    816 
    817 	memcpy(buf, inqbuf, buflen);
    818 	return 0;
    819 }
    820 
    821 static void
    822 scsi_request_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
    823 {
    824 	struct scsi_request_sense *cmd = adp->sense;
    825 	struct scsi_sense_data *data = (struct scsi_sense_data *)adp->data;
    826 	struct scsi_xfer sense;
    827 	int error;
    828 
    829 	memset(cmd, 0, sizeof(struct scsi_request_sense));
    830 	cmd->opcode = SCSI_REQUEST_SENSE;
    831 	cmd->length = sizeof(struct scsi_sense_data);
    832 	memset(data, 0, sizeof(struct scsi_sense_data));
    833 
    834 	memset(&sense, 0, sizeof(sense));
    835 	sense.target = xs->target;
    836 	sense.lun = xs->lun;
    837 	sense.cmdlen = sizeof(struct scsi_request_sense);
    838 	sense.cmd = (void *)cmd;
    839 	sense.datalen = sizeof(struct scsi_sense_data);
    840 	sense.data = (void *)data;
    841 
    842 	sense.error = XS_NOERROR;
    843 	sense.resid = sense.datalen;
    844 	sense.status = SCSI_OK;
    845 
    846 	error = siop_scsi_request(adp, &sense);
    847 	switch (error) {
    848 	case 0:
    849 		/* we have a valid sense */
    850 		xs->error = XS_SENSE;
    851 		return;
    852 	case EINTR:
    853 		/* REQUEST_SENSE interrupted by bus reset. */
    854 		xs->error = XS_RESET;
    855 		return;
    856 	case EIO:
    857 		 /* request sense coudn't be performed */
    858 		/*
    859 		 * XXX this isn't quite right but we don't have anything
    860 		 * better for now
    861 		 */
    862 		xs->error = XS_DRIVER_STUFFUP;
    863 		return;
    864 	default:
    865 		 /* Notify that request sense failed. */
    866 		xs->error = XS_DRIVER_STUFFUP;
    867 		printf("request sense failed with error %d\n", error);
    868 		return;
    869 	}
    870 }
    871 
    872 /*
    873  * scsi_interpret_sense:
    874  *
    875  *	Look at the returned sense and act on the error, determining
    876  *	the unix error number to pass back.  (0 = report no error)
    877  *
    878  *	NOTE: If we return ERESTART, we are expected to haved
    879  *	thawed the device!
    880  *
    881  *	THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES.
    882  */
    883 static int
    884 scsi_interpret_sense(struct siop_adapter *adp, struct scsi_xfer *xs)
    885 {
    886 	struct scsi_sense_data *sense;
    887 	u_int8_t key;
    888 	int error;
    889 	uint32_t info;
    890 	static const char *error_mes[] = {
    891 		"soft error (corrected)",
    892 		"not ready", "medium error",
    893 		"non-media hardware failure", "illegal request",
    894 		"unit attention", "readonly device",
    895 		"no data found", "vendor unique",
    896 		"copy aborted", "command aborted",
    897 		"search returned equal", "volume overflow",
    898 		"verify miscompare", "unknown error key"
    899 	};
    900 
    901 	sense = (struct scsi_sense_data *)xs->data;
    902 
    903 	DPRINTF((" sense debug information:\n"));
    904 	DPRINTF(("\tcode 0x%x valid %d\n",
    905 		SSD_RCODE(sense->response_code),
    906 		sense->response_code & SSD_RCODE_VALID ? 1 : 0));
    907 	DPRINTF(("\tseg 0x%x key 0x%x ili 0x%x eom 0x%x fmark 0x%x\n",
    908 		sense->segment,
    909 		SSD_SENSE_KEY(sense->flags),
    910 		sense->flags & SSD_ILI ? 1 : 0,
    911 		sense->flags & SSD_EOM ? 1 : 0,
    912 		sense->flags & SSD_FILEMARK ? 1 : 0));
    913 	DPRINTF(("\ninfo: 0x%x 0x%x 0x%x 0x%x followed by %d "
    914 		"extra bytes\n",
    915 		sense->info[0],
    916 		sense->info[1],
    917 		sense->info[2],
    918 		sense->info[3],
    919 		sense->extra_len));
    920 
    921 	switch (SSD_RCODE(sense->response_code)) {
    922 
    923 		/*
    924 		 * Old SCSI-1 and SASI devices respond with
    925 		 * codes other than 70.
    926 		 */
    927 	case 0x00:		/* no error (command completed OK) */
    928 		return 0;
    929 	case 0x04:		/* drive not ready after it was selected */
    930 		if (adp->sd->sc_flags & FLAGS_REMOVABLE)
    931 			adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
    932 		/* XXX - display some sort of error here? */
    933 		return EIO;
    934 	case 0x20:		/* invalid command */
    935 		return EINVAL;
    936 	case 0x25:		/* invalid LUN (Adaptec ACB-4000) */
    937 		return EACCES;
    938 
    939 		/*
    940 		 * If it's code 70, use the extended stuff and
    941 		 * interpret the key
    942 		 */
    943 	case 0x71:		/* delayed error */
    944 		key = SSD_SENSE_KEY(sense->flags);
    945 		printf(" DEFERRED ERROR, key = 0x%x\n", key);
    946 		/* FALLTHROUGH */
    947 	case 0x70:
    948 		if ((sense->response_code & SSD_RCODE_VALID) != 0)
    949 			info = _4btol(sense->info);
    950 		else
    951 			info = 0;
    952 		key = SSD_SENSE_KEY(sense->flags);
    953 
    954 		switch (key) {
    955 		case SKEY_NO_SENSE:
    956 		case SKEY_RECOVERED_ERROR:
    957 			if (xs->resid == xs->datalen && xs->datalen) {
    958 				/*
    959 				 * Why is this here?
    960 				 */
    961 				xs->resid = 0;	/* not short read */
    962 			}
    963 		case SKEY_EQUAL:
    964 			error = 0;
    965 			break;
    966 		case SKEY_NOT_READY:
    967 			if (adp->sd->sc_flags & FLAGS_REMOVABLE)
    968 				adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
    969 			if (sense->asc == 0x3A) {
    970 				error = ENODEV; /* Medium not present */
    971 			} else
    972 				error = EIO;
    973 			break;
    974 		case SKEY_ILLEGAL_REQUEST:
    975 			error = EINVAL;
    976 			break;
    977 		case SKEY_UNIT_ATTENTION:
    978 			if (sense->asc == 0x29 &&
    979 			    sense->ascq == 0x00) {
    980 				/* device or bus reset */
    981 				return ERESTART;
    982 			}
    983 			if (adp->sd->sc_flags & FLAGS_REMOVABLE)
    984 				adp->sd->sc_flags &= ~FLAGS_MEDIA_LOADED;
    985 			if (!(adp->sd->sc_flags & FLAGS_REMOVABLE))
    986 				return ERESTART;
    987 			error = EIO;
    988 			break;
    989 		case SKEY_DATA_PROTECT:
    990 			error = EROFS;
    991 			break;
    992 		case SKEY_BLANK_CHECK:
    993 			error = 0;
    994 			break;
    995 		case SKEY_ABORTED_COMMAND:
    996 			break;
    997 		case SKEY_VOLUME_OVERFLOW:
    998 			error = ENOSPC;
    999 			break;
   1000 		default:
   1001 			error = EIO;
   1002 			break;
   1003 		}
   1004 
   1005 		/* Print brief(er) sense information */
   1006 		printf("%s", error_mes[key - 1]);
   1007 		if ((sense->response_code & SSD_RCODE_VALID) != 0) {
   1008 			switch (key) {
   1009 			case SKEY_NOT_READY:
   1010 			case SKEY_ILLEGAL_REQUEST:
   1011 			case SKEY_UNIT_ATTENTION:
   1012 			case SKEY_DATA_PROTECT:
   1013 				break;
   1014 			case SKEY_BLANK_CHECK:
   1015 				printf(", requested size: %d (decimal)",
   1016 				    info);
   1017 				break;
   1018 			case SKEY_ABORTED_COMMAND:
   1019 				printf(", cmd 0x%x, info 0x%x",
   1020 				    xs->cmd->opcode, info);
   1021 				break;
   1022 			default:
   1023 				printf(", info = %d (decimal)", info);
   1024 			}
   1025 		}
   1026 		if (sense->extra_len != 0) {
   1027 			int n;
   1028 			printf(", data =");
   1029 			for (n = 0; n < sense->extra_len; n++)
   1030 				printf(" %x", sense->csi[n]);
   1031 		}
   1032 		printf("\n");
   1033 		return error;
   1034 
   1035 	/*
   1036 	 * Some other code, just report it
   1037 	 */
   1038 	default:
   1039 		printf("Sense Error Code 0x%x",
   1040 			SSD_RCODE(sense->response_code));
   1041 		if ((sense->response_code & SSD_RCODE_VALID) != 0) {
   1042 			struct scsi_sense_data_unextended *usense =
   1043 			    (struct scsi_sense_data_unextended *)sense;
   1044 			printf(" at block no. %d (decimal)",
   1045 			    _3btol(usense->block));
   1046 		}
   1047 		printf("\n");
   1048 		return EIO;
   1049 	}
   1050 }
   1051 
   1052 static int
   1053 scsi_probe(struct siop_adapter *adp)
   1054 {
   1055 	struct scsipi_inquiry_data *inqbuf;
   1056 	int found, t, l;
   1057 	uint8_t device;
   1058 	char buf[SCSIPI_INQUIRY_LENGTH_SCSI2],
   1059 	    product[sizeof(inqbuf->product) + 1];
   1060 
   1061 	found = 0;
   1062 	for (t = 0; t < 8; t++) {
   1063 		if (t == adp->id)
   1064 			continue;
   1065 		for (l = 0; l < 8; l++) {
   1066 			if (_scsi_inquire(adp, t, l, sizeof(buf), buf) != 0)
   1067 				continue;
   1068 
   1069 			inqbuf = (struct scsipi_inquiry_data *)buf;
   1070 			device = inqbuf->device & SID_TYPE;
   1071 			if (device == T_NODEVICE)
   1072 				continue;
   1073 			if (device != T_DIRECT &&
   1074 			    device != T_OPTICAL &&
   1075 			    device != T_SIMPLE_DIRECT)
   1076 				continue;
   1077 
   1078 			memset(product, 0, sizeof(product));
   1079 			strncpy(product, inqbuf->product, sizeof(product) - 1);
   1080 			printf("/dev/disk/scsi/0%d%d: <%s>\n", t, l, product);
   1081 			found++;
   1082 		}
   1083 	}
   1084 	return found;
   1085 }
   1086 
   1087 int
   1088 scsi_inquire(struct sd_softc *sd, int buflen, void *buf)
   1089 {
   1090 	struct siop_adapter *adp;
   1091 	int error;
   1092 
   1093 	if (sd->sc_bus != 0)
   1094 		return ENOTSUP;
   1095 	if (adapt.addr == 0)
   1096 		return ENOENT;
   1097 	adp = &adapt;
   1098 
   1099 	adp->sd = sd;
   1100 	error = _scsi_inquire(adp, sd->sc_target, sd->sc_lun, buflen, buf);
   1101 	adp->sd = NULL;
   1102 
   1103 	return error;
   1104 }
   1105 
   1106 /*
   1107  * scsi_mode_sense
   1108  *	get a sense page from a device
   1109  */
   1110 
   1111 int
   1112 scsi_mode_sense(struct sd_softc *sd, int byte2, int page,
   1113 		  struct scsi_mode_parameter_header_6 *data, int len)
   1114 {
   1115 	struct scsi_mode_sense_6 cmd;
   1116 
   1117 	memset(&cmd, 0, sizeof(cmd));
   1118 	cmd.opcode = SCSI_MODE_SENSE_6;
   1119 	cmd.byte2 = byte2;
   1120 	cmd.page = page;
   1121 	cmd.length = len & 0xff;
   1122 
   1123 	return scsi_command(sd, (void *)&cmd, sizeof(cmd), (void *)data, len);
   1124 }
   1125 
   1126 int
   1127 scsi_command(struct sd_softc *sd, void *cmd, int cmdlen, void *data,
   1128 	     int datalen)
   1129 {
   1130 	struct siop_adapter *adp;
   1131 	struct scsi_xfer xs;
   1132 	int error;
   1133 
   1134 	if (sd->sc_bus != 0)
   1135 		return ENOTSUP;
   1136 	if (adapt.addr == 0)
   1137 		return ENOENT;
   1138 	adp = &adapt;
   1139 
   1140 	memcpy(adp->cmd, cmd, cmdlen);
   1141 	adp->sd = sd;
   1142 
   1143 	memset(&xs, 0, sizeof(xs));
   1144 	xs.target = sd->sc_target;
   1145 	xs.lun = sd->sc_lun;
   1146 	xs.cmdlen = cmdlen;
   1147 	xs.cmd = adp->cmd;
   1148 	xs.datalen = datalen;
   1149 	xs.data = adp->data;
   1150 
   1151 	xs.error = XS_NOERROR;
   1152 	xs.resid = datalen;
   1153 	xs.status = SCSI_OK;
   1154 
   1155 	error = siop_scsi_request(adp, &xs);
   1156 	adp->sd = NULL;
   1157 	if (error != 0)
   1158 		return error;
   1159 
   1160 	if (datalen > 0)
   1161 		memcpy(data, adp->data, datalen);
   1162 	return 0;
   1163 }
   1164 
   1165 /*
   1166  * Initialize the device.
   1167  */
   1168 int
   1169 siop_init(int bus, int dev, int func)
   1170 {
   1171 	struct siop_adapter tmp;
   1172 	struct siop_xfer *xfer;
   1173 	struct scsipi_generic *cmd;
   1174 	struct scsi_request_sense *sense;
   1175 	uint32_t reg;
   1176 	u_long addr;
   1177 	uint32_t *script;
   1178 	int slot, id, i;
   1179 	void *scriptaddr;
   1180 	u_char *data;
   1181 	const int clock_div = 3;		/* 53c810 */
   1182 
   1183 	slot = PCISlotnum(bus, dev, func);
   1184 	if (slot == -1)
   1185 		return ENOENT;
   1186 
   1187 	addr = PCIAddress(slot, 1, PCI_MAPREG_TYPE_MEM);
   1188 	if (addr == 0xffffffff)
   1189 		return EINVAL;
   1190 	enablePCI(slot, 0, 1, 1);
   1191 
   1192 	script = ALLOC(uint32_t, SIOP_SCRIPT_SIZE);
   1193 	if (script == NULL)
   1194 		return ENOMEM;
   1195 	scriptaddr = (void *)local_to_PCI((u_long)script);
   1196 	cmd = ALLOC(struct scsipi_generic, SIOP_SCSI_COMMAND_SIZE);
   1197 	if (cmd == NULL)
   1198 		return ENOMEM;
   1199 	sense = ALLOC(struct scsi_request_sense, SIOP_SCSI_COMMAND_SIZE);
   1200 	if (sense == NULL)
   1201 		return ENOMEM;
   1202 	data = ALLOC(u_char, SIOP_SCSI_DATA_SIZE);
   1203 	if (data == NULL)
   1204 		return ENOMEM;
   1205 	xfer = ALLOC(struct siop_xfer, sizeof(struct siop_xfer));
   1206 	if (xfer == NULL)
   1207 		return ENOMEM;
   1208 	siop_xfer_setup(xfer, scriptaddr);
   1209 
   1210 	id = readb(addr + SIOP_SCID) & SCID_ENCID_MASK;
   1211 
   1212 	/* reset bus */
   1213 	reg = readb(addr + SIOP_SCNTL1);
   1214 	writeb(addr + SIOP_SCNTL1, reg | SCNTL1_RST);
   1215 	delay(100);
   1216 	writeb(addr + SIOP_SCNTL1, reg);
   1217 
   1218 	/* reset the chip */
   1219 	writeb(addr + SIOP_ISTAT, ISTAT_SRST);
   1220 	delay(1000);
   1221 	writeb(addr + SIOP_ISTAT, 0);
   1222 
   1223 	/* init registers */
   1224 	writeb(addr + SIOP_SCNTL0, SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
   1225 	writeb(addr + SIOP_SCNTL1, 0);
   1226 	writeb(addr + SIOP_SCNTL3, clock_div);
   1227 	writeb(addr + SIOP_SXFER, 0);
   1228 	writeb(addr + SIOP_DIEN, 0xff);
   1229 	writeb(addr + SIOP_SIEN0, 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL));
   1230 	writeb(addr + SIOP_SIEN1, 0xff & ~(SIEN1_HTH | SIEN1_GEN));
   1231 	writeb(addr + SIOP_STEST2, 0);
   1232 	writeb(addr + SIOP_STEST3, STEST3_TE);
   1233 	writeb(addr + SIOP_STIME0, (0xb << STIME0_SEL_SHIFT));
   1234 	writeb(addr + SIOP_SCID, id | SCID_RRE);
   1235 	writeb(addr + SIOP_RESPID0, 1 << id);
   1236 	writeb(addr + SIOP_DCNTL, DCNTL_COM);
   1237 
   1238 	/* BeBox uses PCIC */
   1239 	writeb(addr + SIOP_STEST1, STEST1_SCLK);
   1240 
   1241 	siop_pci_reset(addr);
   1242 
   1243 	/* copy and patch the script */
   1244 	for (i = 0; i < __arraycount(siop_script); i++)
   1245 		script[i] = htoc32(siop_script[i]);
   1246 	for (i = 0; i < __arraycount(E_abs_msgin_Used); i++)
   1247 		script[E_abs_msgin_Used[i]] =
   1248 		    htoc32(scriptaddr + Ent_msgin_space);
   1249 
   1250 	/* start script */
   1251 	_wbinv((u_long)script, SIOP_SCRIPT_SIZE);
   1252 	writel(addr + SIOP_DSP, (int)scriptaddr + Ent_reselect);
   1253 
   1254 	memset(&tmp, 0, sizeof(tmp));
   1255 	tmp.id = id;
   1256 	tmp.clock_div = clock_div;
   1257 	tmp.addr = addr;
   1258 	tmp.script = script;
   1259 	tmp.xfer = xfer;
   1260 	tmp.cmd = cmd;
   1261 	tmp.sense = sense;
   1262 	tmp.data = data;
   1263 	tmp.currschedslot = 0;
   1264 	tmp.sel_t = -1;
   1265 
   1266 	if (scsi_probe(&tmp) == 0)
   1267 		return ENXIO;
   1268 	adapt = tmp;
   1269 	return 0;
   1270 }
   1271