Home | History | Annotate | Line # | Download | only in boot
      1 /*	$NetBSD: sc.c,v 1.20 2024/09/25 09:08:22 rin Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1992 OMRON Corporation.
      5  *
      6  * This code is derived from software contributed to Berkeley by
      7  * OMRON Corporation.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed by the University of
     20  *	California, Berkeley and its contributors.
     21  * 4. Neither the name of the University nor the names of its contributors
     22  *    may be used to endorse or promote products derived from this software
     23  *    without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35  * SUCH DAMAGE.
     36  *
     37  *	@(#)sc.c	8.1 (Berkeley) 6/10/93
     38  */
     39 /*
     40  * Copyright (c) 1992, 1993
     41  *	The Regents of the University of California.  All rights reserved.
     42  *
     43  * This code is derived from software contributed to Berkeley by
     44  * OMRON Corporation.
     45  *
     46  * Redistribution and use in source and binary forms, with or without
     47  * modification, are permitted provided that the following conditions
     48  * are met:
     49  * 1. Redistributions of source code must retain the above copyright
     50  *    notice, this list of conditions and the following disclaimer.
     51  * 2. Redistributions in binary form must reproduce the above copyright
     52  *    notice, this list of conditions and the following disclaimer in the
     53  *    documentation and/or other materials provided with the distribution.
     54  * 3. Neither the name of the University nor the names of its contributors
     55  *    may be used to endorse or promote products derived from this software
     56  *    without specific prior written permission.
     57  *
     58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     68  * SUCH DAMAGE.
     69  *
     70  *	@(#)sc.c	8.1 (Berkeley) 6/10/93
     71  */
     72 
     73 /*
     74  * sc.c -- SCSI Protocole Controller (SPC)  driver
     75  * remaked by A.Fujita, MAR-11-199
     76  */
     77 
     78 
     79 #define NSC	2
     80 
     81 #include <sys/param.h>
     82 #include <luna68k/stand/boot/samachdep.h>
     83 #include <luna68k/stand/boot/scsireg.h>
     84 #include <luna68k/stand/boot/scsivar.h>
     85 
     86 #define SCSI_ID		7
     87 
     88 static void screset(struct scsi_softc *);
     89 static void scprobe(struct scsi_softc *, uint, uint);
     90 static int issue_select(struct scsidevice *, uint8_t);
     91 static void ixfer_start(struct scsidevice *, int, uint8_t, int);
     92 static void ixfer_out(struct scsidevice *, int, uint8_t *);
     93 static void ixfer_in(struct scsidevice *, int, uint8_t *);
     94 static int scrun(int, int, uint8_t *, int, uint8_t *, int, volatile int *);
     95 static int scfinish(int);
     96 static void scabort(struct scsi_softc *);
     97 
     98 struct	scsi_softc scsi_softc[NSC];
     99 
    100 /*
    101  * Initialize SPC & Data Structure
    102  */
    103 
    104 int
    105 scinit(int ctlr, void *addr)
    106 {
    107 	struct scsi_softc *hs;
    108 	uint id;
    109 
    110 	if (ctlr < 0 || ctlr >= NSC)
    111 		return 0;
    112 
    113 	hs = &scsi_softc[ctlr];
    114 	hs->sc_ctlr   = ctlr;
    115 	hs->sc_spc    = addr;
    116 
    117 	hs->sc_flags  = 0;
    118 	hs->sc_phase  = BUS_FREE_PHASE;
    119 	hs->sc_target = SCSI_ID;
    120 
    121 	hs->sc_cdb    = NULL;
    122 	hs->sc_cdblen = 0;
    123 	hs->sc_buf    = NULL;
    124 	hs->sc_len    = 0;
    125 	hs->sc_lock   = NULL;
    126 
    127 	hs->sc_stat   = 0;
    128 	hs->sc_msg[0] = 0;
    129 
    130 	screset(hs);
    131 
    132 	for (id = 0; id < 7; id++)
    133 		scprobe(hs, id, 0);
    134 
    135 	return 1;
    136 }
    137 
    138 static void
    139 screset(struct scsi_softc *hs)
    140 {
    141 	struct scsidevice *hd = hs->sc_spc;
    142 
    143 	printf("sc%d at 0x%08lx: ", hs->sc_ctlr, (u_long)hs->sc_spc);
    144 
    145 	/*
    146 	 * Disable interrupts then reset the FUJI chip.
    147 	 */
    148 
    149 	hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
    150 	hd->scsi_scmd = 0;
    151 	hd->scsi_pctl = 0;
    152 	hd->scsi_temp = 0;
    153 	hd->scsi_tch  = 0;
    154 	hd->scsi_tcm  = 0;
    155 	hd->scsi_tcl  = 0;
    156 	hd->scsi_ints = 0;
    157 
    158 	/* We can use Asynchronous Transfer only */
    159 	printf("async");
    160 
    161 	/*
    162 	 * Configure MB89352 with its SCSI address, all
    163 	 * interrupts enabled & appropriate parity.
    164 	 */
    165 	hd->scsi_bdid = SCSI_ID;
    166 	hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB|
    167 			SCTL_PARITY_ENAB | SCTL_RESEL_ENAB |
    168 			SCTL_INTR_ENAB;
    169 	printf(", parity");
    170 
    171 	DELAY(400);
    172 	hd->scsi_sctl &= ~SCTL_DISABLE;
    173 
    174 	printf(", ID %d\n", SCSI_ID);
    175 }
    176 
    177 /*
    178  * XXX
    179  * sensebuf and inqbuf may be uninitialized for some cases.
    180  * Real fix should be to check return values everywhere in
    181  * scsi_request_sense(), scsi_immed_command(), and functions
    182  * called from them.
    183  */
    184 #pragma GCC diagnostic push					/* XXX { */
    185 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
    186 
    187 bool
    188 scident(uint ctlr, uint target, uint lun, struct scsi_inquiry *inqout,
    189     uint32_t *capout)
    190 {
    191 	struct scsi_inquiry inqbuf;
    192 	struct scsi_generic_cdb inq = {
    193 		6,
    194 		{ CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 }
    195 	};
    196 	uint32_t capbuf[2];
    197 	struct scsi_generic_cdb cap = {
    198 		10,
    199 		{ CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
    200 	};
    201 	int i;
    202 	int tries = 10;
    203 
    204 	/*
    205 	 * See if unit exists and is a disk then read block size & nblocks.
    206 	 */
    207 	while ((i = scsi_test_unit_rdy(ctlr, target, lun)) != 0) {
    208 		if (i < 0 || --tries < 0)
    209 			return false;
    210 		if (i == STS_CHECKCOND) {
    211 			uint8_t sensebuf[8];
    212 			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
    213 
    214 			scsi_request_sense(ctlr, target, lun, sensebuf, 8);
    215 			if (sp->class == 7 && sp->key == 6)
    216 				/* drive doing an RTZ -- give it a while */
    217 				DELAY(1000000);
    218 		}
    219 		DELAY(1000);
    220 	}
    221 	if (scsi_immed_command(ctlr, target, lun, &inq, (uint8_t *)&inqbuf,
    222 			       sizeof(inqbuf)) ||
    223 	    scsi_immed_command(ctlr, target, lun, &cap, (uint8_t *)&capbuf,
    224 			       sizeof(capbuf)))
    225 		/* doesn't exist or not a CCS device */
    226 		return false;
    227 
    228 	switch (inqbuf.type) {
    229 	case 0:		/* disk */
    230 	case 4:		/* WORM */
    231 	case 5:		/* CD-ROM */
    232 	case 7:		/* Magneto-optical */
    233 		break;
    234 	default:	/* not a disk */
    235 		return false;
    236 	}
    237 
    238 	if (inqout != NULL)
    239 		*inqout = inqbuf;
    240 	if (capout != NULL) {
    241 		/* assume big endian */
    242 		capout[0] = capbuf[0];
    243 		capout[1] = capbuf[1];
    244 	}
    245 
    246 	return true;
    247 }
    248 
    249 #pragma GCC diagnostic pop					/* XXX } */
    250 
    251 static void
    252 scprobe(struct scsi_softc *hs, uint target, uint lun)
    253 {
    254 	struct scsi_inquiry inqbuf;
    255 	uint32_t capbuf[2], blocks, blksize;
    256 	char idstr[32];
    257 	int i;
    258 
    259 	if (!scident(hs->sc_ctlr, target, lun, &inqbuf, capbuf))
    260 		return;
    261 
    262 	/* CMD_READ_CAPACITY returns the last logical data block address. */
    263 	blocks  = capbuf[0] + 1;
    264 	blksize = capbuf[1];
    265 
    266 	memcpy(idstr, &inqbuf.vendor_id, 28);
    267 	for (i = 27; i > 23; --i)
    268 		if (idstr[i] != ' ')
    269 			break;
    270 	idstr[i + 1] = '\0';
    271 	for (i = 23; i > 7; --i)
    272 		if (idstr[i] != ' ')
    273 			break;
    274 	idstr[i + 1] = '\0';
    275 	for (i = 7; i >= 0; --i)
    276 		if (idstr[i] != ' ')
    277 			break;
    278 	idstr[i + 1] = '\0';
    279 
    280 	printf(" ID %d: %s %s rev %s", target, idstr, &idstr[8], &idstr[24]);
    281 	printf(", %d bytes/sect x %d sectors\n", blksize, blocks);
    282 }
    283 
    284 
    285 /*
    286  * SPC Arbitration/Selection routine
    287  */
    288 
    289 static int
    290 issue_select(struct scsidevice *hd, uint8_t target)
    291 {
    292 
    293 	hd->scsi_pctl = 0;
    294 	hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
    295 
    296 	/* select timeout is hardcoded to 250ms */
    297 	hd->scsi_tch = 2;
    298 	hd->scsi_tcm = 113;
    299 	hd->scsi_tcl = 3;
    300 
    301 	hd->scsi_scmd = SCMD_SELECT;
    302 
    303 	return 1;
    304 }
    305 
    306 
    307 /*
    308  * SPC Manual Transfer routines
    309  */
    310 
    311 /* not yet */
    312 
    313 
    314 /*
    315  * SPC Program Transfer routines
    316  */
    317 
    318 static void
    319 ixfer_start(struct scsidevice *hd, int len, uint8_t phase, int wait)
    320 {
    321 
    322 	hd->scsi_tch  = ((len & 0xff0000) >> 16);
    323 	hd->scsi_tcm  = ((len & 0x00ff00) >>  8);
    324 	hd->scsi_tcl  =  (len & 0x0000ff);
    325 	hd->scsi_pctl = phase;
    326 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
    327 }
    328 
    329 static void
    330 ixfer_out(struct scsidevice *hd, int len, uint8_t *buf)
    331 {
    332 
    333 	for (; len > 0; len--) {
    334 		while (hd->scsi_ssts & SSTS_DREG_FULL) {
    335 			DELAY(5);
    336 		}
    337 		hd->scsi_dreg = *buf++;
    338 	}
    339 }
    340 
    341 static void
    342 ixfer_in(struct scsidevice *hd, int len, uint8_t *buf)
    343 {
    344 
    345 	for (; len > 0; len--) {
    346 		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
    347 			DELAY(5);
    348 		}
    349 		*buf++ = hd->scsi_dreg;
    350 	}
    351 }
    352 
    353 
    354 /*
    355  * SPC drive routines
    356  */
    357 
    358 static int
    359 scrun(int ctlr, int target, uint8_t *cdb, int cdblen, uint8_t *buf, int len,
    360     volatile int *lock)
    361 {
    362 	struct scsi_softc *hs;
    363 	struct scsidevice *hd;
    364 
    365 	if (ctlr < 0 || ctlr >= NSC)
    366 		return 0;
    367 
    368 	hs = &scsi_softc[ctlr];
    369 	hd = hs->sc_spc;
    370 	if (hd == NULL)
    371 		return 0;
    372 
    373 	if ((hd->scsi_ssts & (SSTS_INITIATOR | SSTS_TARGET | SSTS_BUSY)) != 0)
    374 		return 0;
    375 
    376 	hs->sc_flags  = 0;
    377 	hs->sc_phase  = ARB_SEL_PHASE;
    378 	hs->sc_target = target;
    379 
    380 	hs->sc_cdb    = cdb;
    381 	hs->sc_cdblen = cdblen;
    382 	hs->sc_buf    = buf;
    383 	hs->sc_len    = len;
    384 	hs->sc_lock   = lock;
    385 
    386 	hs->sc_stat   = 0;
    387 	hs->sc_msg[0] = 0;
    388 
    389 	*(hs->sc_lock) = SC_IN_PROGRESS;
    390 	issue_select(hd, hs->sc_target);
    391 
    392 	return 1;
    393 }
    394 
    395 static int
    396 scfinish(int ctlr)
    397 {
    398 	struct scsi_softc *hs = &scsi_softc[ctlr];
    399 	int status = hs->sc_stat;
    400 
    401 	hs->sc_flags  = 0;
    402 	hs->sc_phase  = BUS_FREE_PHASE;
    403 	hs->sc_target = SCSI_ID;
    404 
    405 	hs->sc_cdb    = NULL;
    406 	hs->sc_cdblen = 0;
    407 	hs->sc_buf    = NULL;
    408 	hs->sc_len    = 0;
    409 	hs->sc_lock   = NULL;
    410 
    411 	hs->sc_stat   = 0;
    412 	hs->sc_msg[0] = 0;
    413 
    414 	return status;
    415 }
    416 
    417 static void
    418 scabort(struct scsi_softc *hs)
    419 {
    420 	struct scsidevice *hd = hs->sc_spc;
    421 	int len;
    422 
    423 	printf("sc%d: abort  phase=0x%x, ssts=0x%x, ints=0x%x\n",
    424 	    hs->sc_ctlr, hd->scsi_psns, hd->scsi_ssts, hd->scsi_ints);
    425 
    426 	if (hd->scsi_ints != 0)
    427 		/* write register value back to register */
    428 		hd->scsi_ints = hd->scsi_ints;
    429 
    430 	if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
    431 		/* no longer connected to scsi target */
    432 		return;
    433 
    434 	/* get the number of bytes remaining in current xfer + fudge */
    435 	len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
    436 
    437 	/* for that many bus cycles, try to send an abort msg */
    438 	for (len += 1024;
    439 	    ((hd->scsi_ssts & SSTS_INITIATOR)) != 0 && --len >= 0;) {
    440 		hd->scsi_scmd = SCMD_SET_ATN;
    441 
    442 		while ((hd->scsi_psns & PSNS_REQ) == 0) {
    443 			if ((hd->scsi_ssts & SSTS_INITIATOR) == 0)
    444 				goto out;
    445 			DELAY(1);
    446 		}
    447 
    448 		if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
    449 			hd->scsi_scmd = SCMD_RST_ATN;
    450 		hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
    451 
    452 		if (hd->scsi_psns & PHASE_IO) {
    453 			/* one of the input phases - read & discard a byte */
    454 			hd->scsi_scmd = SCMD_SET_ACK;
    455 			while ((hd->scsi_psns & PSNS_REQ) != 0)
    456 				DELAY(1);
    457 			(void)hd->scsi_temp;
    458 		} else {
    459 			/* one of the output phases - send an abort msg */
    460 			hd->scsi_temp = MSG_ABORT;
    461 			hd->scsi_scmd = SCMD_SET_ACK;
    462 			while ((hd->scsi_psns & PSNS_REQ) != 0)
    463 				DELAY(1);
    464 		}
    465 
    466 		hd->scsi_scmd = SCMD_RST_ACK;
    467 	}
    468 out:
    469 	/*
    470 	 * Either the abort was successful & the bus is disconnected or
    471 	 * the device didn't listen.  If the latter, announce the problem.
    472 	 * Either way, reset the card & the SPC.
    473 	 */
    474 	if (len < 0 && hs)
    475 		printf("sc%d: abort failed.  phase=0x%x, ssts=0x%x\n",
    476 		    hs->sc_ctlr, hd->scsi_psns, hd->scsi_ssts);
    477 }
    478 
    479 
    480 /*
    481  * SCSI Command Handler
    482  */
    483 
    484 int
    485 scsi_test_unit_rdy(int ctlr, int target, int lun)
    486 {
    487 	static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
    488 	int status;
    489 	volatile int lock;
    490 
    491 #ifdef DEBUG
    492 	printf("scsi_test_unit_rdy( %d, %d, %d): Start\n", ctlr, target, lun);
    493 #endif
    494 
    495 	cdb.lun = lun;
    496 
    497 	if (scrun(ctlr, target, (void *)&cdb, 6, NULL, 0, &lock) == 0) {
    498 #ifdef DEBUG
    499 		printf("scsi_test_unit_rdy: Command Transfer Failed.\n");
    500 #endif
    501 		return -1;
    502 	}
    503 
    504 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
    505 		DELAY(10);
    506 
    507 	status = scfinish(ctlr);
    508 
    509 	if (lock == SC_IO_COMPLETE) {
    510 #ifdef DEBUG
    511 		printf("scsi_test_unit_rdy: Status -- 0x%x\n", status);
    512 #endif
    513 		return status;
    514 	} else {
    515 		return lock;
    516 	}
    517 }
    518 
    519 int
    520 scsi_request_sense(int ctlr, int target, int lun, uint8_t *buf,
    521     unsigned int len)
    522 {
    523 	static struct scsi_cdb6 cdb = {	CMD_REQUEST_SENSE };
    524 	int status;
    525 	volatile int lock;
    526 
    527 #ifdef DEBUG
    528 	printf("scsi_request_sense: Start\n");
    529 #endif
    530 
    531 	/* Request Sense        */
    532 	/* Additional Sens Length*/
    533 	/* cdbAllocation Length */
    534 	/*          */
    535 
    536 	/* Addtional Sens Field */
    537 	/* len            */
    538 
    539 	cdb.lun = lun;
    540 	cdb.len = len;
    541 
    542 	if (scrun(ctlr, target, (void *)&cdb, 6, buf, len, &lock) == 0) {
    543 #ifdef DEBUG
    544 		printf("scsi_request_sense: Command Transfer Failed.\n");
    545 #endif
    546 		return -1;
    547 	}
    548 
    549 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
    550 		DELAY(10);
    551 
    552 	status = scfinish(ctlr);
    553 
    554 	if (lock == SC_IO_COMPLETE) {
    555 #ifdef DEBUG
    556 		printf("scsi_request_sense: Status -- 0x%x\n", status);
    557 #endif
    558 		return status;
    559 	} else {
    560 		return lock;
    561 	}
    562 }
    563 
    564 int
    565 scsi_immed_command(int ctlr, int target, int lun, struct scsi_generic_cdb *cdb,
    566     uint8_t *buf, unsigned int len)
    567 {
    568 	int status;
    569 	volatile int lock;
    570 
    571 #ifdef DEBUG
    572 	printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n",
    573 	    ctlr, target, lun, cdb->len, len);
    574 #endif
    575 
    576 	cdb->cdb[1] |= lun << 5;
    577 
    578 	if (scrun(ctlr, target, (void *)&cdb->cdb[0], cdb->len, buf, len,
    579 	    &lock) == 0) {
    580 #ifdef DEBUG
    581 		printf("scsi_immed_command: Command Transfer Failed.\n");
    582 #endif
    583 		return -1;
    584 	}
    585 
    586 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
    587 		DELAY(10);
    588 
    589 	status = scfinish(ctlr);
    590 
    591 	if (lock == SC_IO_COMPLETE) {
    592 #ifdef DEBUG
    593 		printf("scsi_immed_command: Status -- 0x%x\n", status);
    594 #endif
    595 		return status;
    596 	} else {
    597 		return lock;
    598 	}
    599 }
    600 
    601 int
    602 scsi_format_unit(int ctlr, int target, int lun)
    603 {
    604 	static struct scsi_cdb6 cdb = { CMD_FORMAT_UNIT, 0, 0, 0, 0, 0 };
    605 	int status;
    606 	volatile int lock;
    607 #ifdef DEBUG
    608 	int count = 0;
    609 #endif
    610 
    611 #ifdef DEBUG
    612 	printf("scsi_format_unit( %d, %d, %d): Start\n", ctlr, target, lun);
    613 #endif
    614 
    615 	cdb.lun = lun;
    616 
    617 	if (scrun(ctlr, target, (void *)&cdb, 6, NULL, 0, &lock) == 0) {
    618 #ifdef DEBUG
    619 		printf("scsi_format_unit: Command Transfer Failed.\n");
    620 #endif
    621 		return -1;
    622 	}
    623 
    624 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
    625 		DELAY(1000000);
    626 #ifdef DEBUG
    627 		if ((++count % 60) == 0)
    628 			printf("scsi_format_unit: %d\n", count / 60);
    629 #endif
    630 	}
    631 
    632 	status = scfinish(ctlr);
    633 
    634 	if (lock == SC_IO_COMPLETE) {
    635 #ifdef DEBUG
    636 		printf("scsi_format_unit: Status -- 0x%x\n", status);
    637 #endif
    638 		return status;
    639 	} else {
    640 		return lock;
    641 	}
    642 }
    643 
    644 
    645 /*
    646  * Interrupt Routine
    647  */
    648 
    649 int
    650 scintr(void)
    651 {
    652 	struct scsi_softc *hs;
    653 	struct scsidevice *hd;
    654 	uint8_t ints, temp;
    655 	int i;
    656 	uint8_t *buf;
    657 	int len;
    658 
    659 	for (i = 0; i < NSC; i++) {
    660 		hs = &scsi_softc[i];
    661 		hd = hs->sc_spc;
    662 		if ((ints = hd->scsi_ints) != 0)
    663 			goto get_intr;
    664 	}
    665 
    666 	/* Unknown interrupt occurred */
    667 	return -1;
    668 
    669 
    670 	/*
    671 	 * Interrupt
    672 	 */
    673 
    674  get_intr:
    675 #ifdef DEBUG
    676 	printf("scintr: INTS 0x%x, SSTS 0x%x,  PCTL 0x%x,  PSNS 0x%x    0x%x\n",
    677 	    ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns, hs->sc_phase);
    678 #endif
    679 	if (ints & INTS_RESEL) {
    680 		if (hs->sc_phase == BUS_FREE_PHASE) {
    681 			temp = hd->scsi_temp & ~(1 << SCSI_ID);
    682 			for (i = 0; temp != 1; i++) {
    683 				temp >>= 1;
    684 			}
    685 			hs->sc_target = i;
    686 			*(hs->sc_lock) = SC_IN_PROGRESS;
    687 		} else
    688 			goto abort;
    689 	} else if (ints & INTS_DISCON) {
    690 		if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) ||
    691 		    (hs->sc_msg[0] == MSG_DISCONNECT)) {
    692 			hs->sc_phase  = BUS_FREE_PHASE;
    693 			hs->sc_target = SCSI_ID;
    694 			if (hs->sc_msg[0] == MSG_CMD_COMPLETE) {
    695 				/* SCSI IO complete */
    696 				*(hs->sc_lock) = SC_IO_COMPLETE;
    697 			} else {
    698 				/* Disconnected from Target */
    699 				*(hs->sc_lock) = SC_DISCONNECTED;
    700 			}
    701 			hd->scsi_ints = ints;
    702 			return 0;
    703 		} else
    704 			goto abort;
    705 	} else if (ints & INTS_CMD_DONE) {
    706 		if (hs->sc_phase == BUS_FREE_PHASE)
    707 			goto abort;
    708 		else if (hs->sc_phase == MESG_IN_PHASE) {
    709 			hd->scsi_scmd = SCMD_RST_ACK;
    710 			hd->scsi_ints = ints;
    711 			hs->sc_phase  = hd->scsi_psns & PHASE;
    712 			return 0;
    713 		}
    714 		if (hs->sc_flags & SC_SEL_TIMEOUT)
    715 			hs->sc_flags &= ~SC_SEL_TIMEOUT;
    716 	} else if (ints & INTS_SRV_REQ) {
    717 		if (hs->sc_phase != MESG_IN_PHASE)
    718 			goto abort;
    719 	} else if (ints & INTS_TIMEOUT) {
    720 		if (hs->sc_phase == ARB_SEL_PHASE) {
    721 			if (hs->sc_flags & SC_SEL_TIMEOUT) {
    722 				hs->sc_flags &= ~SC_SEL_TIMEOUT;
    723 				hs->sc_phase  = BUS_FREE_PHASE;
    724 				hs->sc_target = SCSI_ID;
    725 				/* Such SCSI Device is not connected. */
    726 				*(hs->sc_lock) = SC_DEV_NOT_FOUND;
    727 				hd->scsi_ints = ints;
    728 				return 0;
    729 			} else {
    730 				/* wait more 250 usec */
    731 				hs->sc_flags |= SC_SEL_TIMEOUT;
    732 				hd->scsi_temp = 0;
    733 				hd->scsi_tch  = 0;
    734 				hd->scsi_tcm  = 0x06;
    735 				hd->scsi_tcl  = 0x40;
    736 				hd->scsi_ints = ints;
    737 				return 0;
    738 			}
    739 		} else
    740 			goto abort;
    741 	} else
    742 		goto abort;
    743 
    744 	hd->scsi_ints = ints;
    745 
    746 	/*
    747 	 * Next SCSI Transfer
    748 	 */
    749 
    750 	while ((hd->scsi_psns & PSNS_REQ) == 0) {
    751 		DELAY(1);
    752 	}
    753 
    754 	hs->sc_phase = hd->scsi_psns & PHASE;
    755 
    756 	if ((hs->sc_phase == DATA_OUT_PHASE) ||
    757 	    (hs->sc_phase == DATA_IN_PHASE)) {
    758 		len = hs->sc_len;
    759 		buf = hs->sc_buf;
    760 	} else if (hs->sc_phase == CMD_PHASE) {
    761 		len = hs->sc_cdblen;
    762 		buf = hs->sc_cdb;
    763 	} else if (hs->sc_phase == STATUS_PHASE) {
    764 		len = 1;
    765 		buf = &hs->sc_stat;
    766 	} else {
    767 		len = 1;
    768 		buf = hs->sc_msg;
    769 	}
    770 
    771 	ixfer_start(hd, len, hs->sc_phase, 0);
    772 	if (hs->sc_phase & PHASE_IO)
    773 		ixfer_in(hd, len, buf);
    774 	else
    775 		ixfer_out(hd, len, buf);
    776 
    777 	return 0;
    778 
    779 	/*
    780 	 * SCSI Abort
    781 	 */
    782  abort:
    783 	/* SCSI IO failed */
    784 	scabort(hs);
    785 	hd->scsi_ints = ints;
    786 	*(hs->sc_lock) = SC_IO_FAILED;
    787 	return -1;
    788 }
    789