Home | History | Annotate | Line # | Download | only in boot
sc.c revision 1.1
      1 /*	$NetBSD: sc.c,v 1.1 2013/01/05 17:44:24 tsutsui 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	1
     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/device.h>
     85 #include <luna68k/stand/boot/scsivar.h>
     86 
     87 #define SCSI_IPL	2
     88 #define SCSI_ID		7
     89 
     90 static int scinit(void *);
     91 static void screset(int);
     92 static int issue_select(struct scsidevice *, u_char);
     93 static void ixfer_start(struct scsidevice *, int, u_char, int);
     94 static void ixfer_out(struct scsidevice *, int, u_char *);
     95 static void ixfer_in(struct scsidevice *, int, u_char *);
     96 static int scrun(int, int, u_char *, int, u_char *, int, volatile int *);
     97 static int scfinish(int);
     98 static void scabort(struct scsi_softc *, struct scsidevice *);
     99 static int scstart(void);
    100 static int scgo(void);
    101 static int scdone(void);
    102 
    103 struct	driver scdriver = {
    104 	scinit, "sc", scstart, scgo, scintr, scdone
    105 };
    106 
    107 struct	scsi_softc scsi_softc[NSC];
    108 
    109 /*
    110  * Initialize SPC & Data Structure
    111  */
    112 
    113 int
    114 scinit(void *arg)
    115 {
    116 	struct hp_ctlr *hc = arg;
    117 	struct scsi_softc *hs = &scsi_softc[hc->hp_unit];
    118 
    119 	hc->hp_ipl    = SCSI_IPL;
    120 	hs->sc_hc     = hc;
    121 
    122 	hs->sc_flags  = 0;
    123 	hs->sc_phase  = BUS_FREE_PHASE;
    124 	hs->sc_target = SCSI_ID;
    125 
    126 	hs->sc_cdb    = NULL;
    127 	hs->sc_cdblen = 0;
    128 	hs->sc_buf    = NULL;
    129 	hs->sc_len    = 0;
    130 	hs->sc_lock   = NULL;
    131 
    132 	hs->sc_stat   = 0;
    133 	hs->sc_msg[0] = 0;
    134 
    135 	screset(hc->hp_unit);
    136 	return(1);
    137 }
    138 
    139 void
    140 screset(int unit)
    141 {
    142 	struct scsi_softc *hs = &scsi_softc[unit];
    143 	struct scsidevice *hd = (struct scsidevice *)hs->sc_hc->hp_addr;
    144 
    145 	printf("sc%d: ", unit);
    146 
    147 	/*
    148 	 * Disable interrupts then reset the FUJI chip.
    149 	 */
    150 
    151 	hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
    152 	hd->scsi_scmd = 0;
    153 	hd->scsi_pctl = 0;
    154 	hd->scsi_temp = 0;
    155 	hd->scsi_tch  = 0;
    156 	hd->scsi_tcm  = 0;
    157 	hd->scsi_tcl  = 0;
    158 	hd->scsi_ints = 0;
    159 
    160 	/* We can use Asynchronous Transfer only */
    161 	printf("async");
    162 
    163 	/*
    164 	 * Configure MB89352 with its SCSI address, all
    165 	 * interrupts enabled & appropriate parity.
    166 	 */
    167 	hd->scsi_bdid = SCSI_ID;
    168 	hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB|
    169 			SCTL_PARITY_ENAB | SCTL_RESEL_ENAB |
    170 			SCTL_INTR_ENAB;
    171 	printf(", parity");
    172 
    173 	DELAY(400);
    174 	hd->scsi_sctl &= ~SCTL_DISABLE;
    175 
    176 	printf(", scsi id %d\n", SCSI_ID);
    177 }
    178 
    179 
    180 /*
    181  * SPC Arbitration/Selection routine
    182  */
    183 
    184 int
    185 issue_select(struct scsidevice *hd, u_char target)
    186 {
    187 	hd->scsi_pctl = 0;
    188 	hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
    189 
    190 	/* select timeout is hardcoded to 2ms */
    191 	hd->scsi_tch = 0;
    192 	hd->scsi_tcm = 32;
    193 	hd->scsi_tcl = 4;
    194 
    195 	hd->scsi_scmd = SCMD_SELECT;
    196 
    197 	return (1);
    198 }
    199 
    200 
    201 /*
    202  * SPC Manual Transfer routines
    203  */
    204 
    205 /* not yet */
    206 
    207 
    208 /*
    209  * SPC Program Transfer routines
    210  */
    211 
    212 void
    213 ixfer_start(struct scsidevice *hd, int len, u_char phase, int wait)
    214 {
    215 	hd->scsi_tch  = ((len & 0xff0000) >> 16);
    216 	hd->scsi_tcm  = ((len & 0x00ff00) >>  8);
    217 	hd->scsi_tcl  =  (len & 0x0000ff);
    218 	hd->scsi_pctl = phase;
    219 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
    220 }
    221 
    222 void
    223 ixfer_out(struct scsidevice *hd, int len, u_char *buf)
    224 {
    225 	for(; len > 0; len--) {
    226 		while (hd->scsi_ssts & SSTS_DREG_FULL) {
    227 			DELAY(5);
    228 		}
    229 		hd->scsi_dreg = *buf++;
    230 	}
    231 }
    232 
    233 void
    234 ixfer_in(struct scsidevice *hd, int len, u_char *buf)
    235 {
    236 	for (; len > 0; len--) {
    237 		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
    238 			DELAY(5);
    239 		}
    240 		*buf++ = hd->scsi_dreg;
    241 	}
    242 }
    243 
    244 
    245 /*
    246  * SPC drive routines
    247  */
    248 
    249 int
    250 scrun(int ctlr, int slave, u_char *cdb, int cdblen, u_char *buf, int len,
    251     volatile int *lock)
    252 {
    253 	struct scsi_softc *hs = &scsi_softc[ctlr];
    254 	struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr;
    255 
    256 	if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
    257 		return(0);
    258 
    259 	hs->sc_flags  = 0;
    260 	hs->sc_phase  = ARB_SEL_PHASE;
    261 	hs->sc_target = slave;
    262 
    263 	hs->sc_cdb    = cdb;
    264 	hs->sc_cdblen = cdblen;
    265 	hs->sc_buf    = buf;
    266 	hs->sc_len    = len;
    267 	hs->sc_lock   = lock;
    268 
    269 	hs->sc_stat   = 0;
    270 	hs->sc_msg[0] = 0;
    271 
    272 	*(hs->sc_lock) = SC_IN_PROGRESS;
    273 	issue_select(hd, hs->sc_target);
    274 
    275 	return(1);
    276 }
    277 
    278 int
    279 scfinish(int ctlr)
    280 {
    281 	struct scsi_softc *hs = &scsi_softc[ctlr];
    282 	int status = hs->sc_stat;
    283 
    284 	hs->sc_flags  = 0;
    285 	hs->sc_phase  = BUS_FREE_PHASE;
    286 	hs->sc_target = SCSI_ID;
    287 
    288 	hs->sc_cdb    = NULL;
    289 	hs->sc_cdblen = 0;
    290 	hs->sc_buf    = NULL;
    291 	hs->sc_len    = 0;
    292 	hs->sc_lock   = NULL;
    293 
    294 	hs->sc_stat   = 0;
    295 	hs->sc_msg[0] = 0;
    296 
    297 	return(status);
    298 }
    299 
    300 void
    301 scabort(struct scsi_softc *hs, struct scsidevice *hd)
    302 {
    303 	int len;
    304 	u_char junk;
    305 
    306 	printf("sc%d: abort  phase=0x%x, ssts=0x%x, ints=0x%x\n",
    307 		hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts,
    308 		hd->scsi_ints);
    309 
    310 	if (hd->scsi_ints != 0)
    311 		hd->scsi_ints = hd->scsi_ints;
    312 
    313 	if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
    314 		/* no longer connected to scsi target */
    315 		return;
    316 
    317 	/* get the number of bytes remaining in current xfer + fudge */
    318 	len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
    319 
    320 	/* for that many bus cycles, try to send an abort msg */
    321 	for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
    322 		hd->scsi_scmd = SCMD_SET_ATN;
    323 
    324 		while ((hd->scsi_psns & PSNS_REQ) == 0) {
    325 			if (! (hd->scsi_ssts & SSTS_INITIATOR))
    326 				goto out;
    327 			DELAY(1);
    328 		}
    329 
    330 		if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
    331 			hd->scsi_scmd = SCMD_RST_ATN;
    332 		hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
    333 
    334 		if (hd->scsi_psns & PHASE_IO) {
    335 			/* one of the input phases - read & discard a byte */
    336 			hd->scsi_scmd = SCMD_SET_ACK;
    337 			while (hd->scsi_psns & PSNS_REQ)
    338 				DELAY(1);
    339 			junk = hd->scsi_temp;
    340 		} else {
    341 			/* one of the output phases - send an abort msg */
    342 			hd->scsi_temp = MSG_ABORT;
    343 			hd->scsi_scmd = SCMD_SET_ACK;
    344 			while (hd->scsi_psns & PSNS_REQ)
    345 				DELAY(1);
    346 		}
    347 
    348 		hd->scsi_scmd = SCMD_RST_ACK;
    349 	}
    350 out:
    351 	/*
    352 	 * Either the abort was successful & the bus is disconnected or
    353 	 * the device didn't listen.  If the latter, announce the problem.
    354 	 * Either way, reset the card & the SPC.
    355 	 */
    356 	if (len < 0 && hs)
    357 		printf("sc%d: abort failed.  phase=0x%x, ssts=0x%x\n",
    358 			hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts);
    359 }
    360 
    361 
    362 /*
    363  * SCSI Command Handler
    364  */
    365 
    366 int
    367 scsi_test_unit_rdy(int ctlr, int slave, int unit)
    368 {
    369 	static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
    370 	int status;
    371 	volatile int lock;
    372 
    373 #ifdef DEBUG
    374 	printf("scsi_test_unit_rdy( %d, %d, %d): Start\n", ctlr, slave, unit);
    375 #endif
    376 
    377 	cdb.lun = unit;
    378 
    379 	if (!(scrun(ctlr, slave, (void *)&cdb, 6, NULL, 0, &lock))) {
    380 #ifdef DEBUG
    381 		printf("scsi_test_unit_rdy: Command Transfer Failed.\n");
    382 #endif
    383 		return(-1);
    384 	}
    385 
    386 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
    387 		DELAY(10);
    388 
    389 	status = scfinish(ctlr);
    390 
    391 	if (lock == SC_IO_COMPLETE) {
    392 #ifdef DEBUG
    393 		printf("scsi_test_unit_rdy: Status -- 0x%x\n", status);
    394 #endif
    395 		return(status);
    396 	} else {
    397 		return(lock);
    398 	}
    399 }
    400 
    401 int
    402 scsi_request_sense(int ctlr, int slave, int unit, u_char *buf, unsigned int len)
    403 {
    404 	static struct scsi_cdb6 cdb = {	CMD_REQUEST_SENSE };
    405 	int status;
    406 	volatile int lock;
    407 
    408 #ifdef DEBUG
    409 	printf("scsi_request_sense: Start\n");
    410 #endif
    411 
    412 	/* Request Sense$N>l9g!"E>Aw$5$l$k%G!<%?D9$O%?!<%2368H$K0MB8$7!"        */
    413 	/* %;%s%9%G!<%?$N#8/usr/src/sys/luna68k/stand/SCCS/s.sc.c$%HL\$NAddtional Sens Length$K$h$jF0E*$K7hDj$9$k!#*/
    414 	/* $3$3$G$O%G!<%?!<E>Aw?t$rcdb$NAllocation Length$K:GDcD9$G$"$k#8/usr/src/sys/luna68k/stand/SCCS/s.sc.c$%H */
    415 	/* $r8GDj$7$F!"#S#P#C$N=hM}%7!<%1%s%9$rJx$5$J$$$h$&$K$7$F$$$k!#         */
    416 
    417 	/* %F!<@(#)sc.c	8.1f%K373H$N>uBV$rD4$Y$k$?$a!"Addtional Sens Field$r%"%/%;%9$9$k */
    418 	/* I,MW$,$"$k$N$G6/10/93P%$%98.1i%$%PB&$Glen$r7hDj$9$k$3$H$K$9$k            */
    419 
    420 	cdb.lun = unit;
    421 	cdb.len = len;
    422 
    423 	if (!(scrun(ctlr, slave, (void *)&cdb, 6, buf, len, &lock))) {
    424 #ifdef DEBUG
    425 		printf("scsi_request_sense: Command Transfer Failed.\n");
    426 #endif
    427 		return(-1);
    428 	}
    429 
    430 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
    431 		DELAY(10);
    432 
    433 	status = scfinish(ctlr);
    434 
    435 	if (lock == SC_IO_COMPLETE) {
    436 #ifdef DEBUG
    437 		printf("scsi_request_sense: Status -- 0x%x\n", status);
    438 #endif
    439 		return(status);
    440 	} else {
    441 		return(lock);
    442 	}
    443 }
    444 
    445 int
    446 scsi_immed_command(int ctlr, int slave, int unit, struct scsi_fmt_cdb *cdb,
    447     u_char *buf, unsigned int len)
    448 {
    449 	int status;
    450 	volatile int lock;
    451 
    452 #ifdef DEBUG
    453 	printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n",
    454 	       ctlr, slave, unit, cdb->len, len);
    455 #endif
    456 
    457 	cdb->cdb[1] |= unit << 5;
    458 
    459 	if (!(scrun(ctlr, slave, (void *)&cdb->cdb[0], cdb->len, buf, len, &lock))) {
    460 #ifdef DEBUG
    461 		printf("scsi_immed_command: Command Transfer Failed.\n");
    462 #endif
    463 		return(-1);
    464 	}
    465 
    466 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
    467 		DELAY(10);
    468 
    469 	status = scfinish(ctlr);
    470 
    471 	if (lock == SC_IO_COMPLETE) {
    472 #ifdef DEBUG
    473 		printf("scsi_immed_command: Status -- 0x%x\n", status);
    474 #endif
    475 		return(status);
    476 	} else {
    477 		return(lock);
    478 	}
    479 }
    480 
    481 int
    482 scsi_format_unit(int ctlr, int slave, int unit)
    483 {
    484 	static struct scsi_cdb6 cdb = { CMD_FORMAT_UNIT, 0, 0, 0, 0, 0 };
    485 	int status;
    486 	volatile int lock;
    487 #ifdef DEBUG
    488 	int count = 0;
    489 #endif
    490 
    491 #ifdef DEBUG
    492 	printf("scsi_format_unit( %d, %d, %d): Start\n", ctlr, slave, unit);
    493 #endif
    494 
    495 	cdb.lun = unit;
    496 
    497 	if (!(scrun(ctlr, slave, (void *)&cdb, 6, (u_char *) 0, 0, &lock))) {
    498 #ifdef DEBUG
    499 		printf("scsi_format_unit: Command Transfer Failed.\n");
    500 #endif
    501 		return(-1);
    502 	}
    503 
    504 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
    505 		DELAY(1000000);
    506 #ifdef DEBUG
    507 		if ((++count % 60) == 0)
    508 			printf("scsi_format_unit: %d\n", count / 60);
    509 #endif
    510 	}
    511 
    512 	status = scfinish(ctlr);
    513 
    514 	if (lock == SC_IO_COMPLETE) {
    515 #ifdef DEBUG
    516 		printf("scsi_format_unit: Status -- 0x%x\n", status);
    517 #endif
    518 		return(status);
    519 	} else {
    520 		return(lock);
    521 	}
    522 }
    523 
    524 
    525 /*
    526  * ????
    527  */
    528 
    529 int
    530 scstart(void)
    531 {
    532 
    533 	return 0;
    534 }
    535 
    536 int
    537 scgo(void)
    538 {
    539 
    540 	return 0;
    541 }
    542 
    543 int
    544 scdone(void)
    545 {
    546 
    547 	return 0;
    548 }
    549 
    550 
    551 /*
    552  * Interrupt Routine
    553  */
    554 
    555 int
    556 scintr(void)
    557 {
    558 	struct scsi_softc *hs;
    559 	struct scsidevice *hd;
    560 	u_char ints, temp;
    561 	int i;
    562 	u_char *buf;
    563 	int len;
    564 
    565 	for (i = 0; i < NSC; i++) {
    566 		hs = &scsi_softc[i];
    567 		hd = (struct scsidevice *) hs->sc_hc->hp_addr;
    568 		if ((ints = hd->scsi_ints) != 0)
    569 			goto get_intr;
    570 	}
    571 
    572 	/* Unknown Interrupt occured */
    573 	return -1;
    574 
    575 
    576 	/*
    577 	 * Interrupt
    578 	 */
    579 
    580  get_intr:
    581 #ifdef DEBUG
    582 	printf("scintr: INTS 0x%x, SSTS 0x%x,  PCTL 0x%x,  PSNS 0x%x    0x%x\n",
    583 	        ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns,
    584 	        hs->sc_phase);
    585 #endif
    586 	if (ints & INTS_RESEL) {
    587 		if (hs->sc_phase == BUS_FREE_PHASE) {
    588 			temp = hd->scsi_temp & ~(1 << SCSI_ID);
    589 			for (i = 0; temp != 1; i++) {
    590 				temp >>= 1;
    591 			}
    592 			hs->sc_target = i;
    593 			*(hs->sc_lock) = SC_IN_PROGRESS;
    594 		} else
    595 			goto abort;
    596 	} else if (ints & INTS_DISCON) {
    597 		if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || (hs->sc_msg[0] == MSG_DISCONNECT)) {
    598 			hs->sc_phase  = BUS_FREE_PHASE;
    599 			hs->sc_target = SCSI_ID;
    600 			if (hs->sc_msg[0] == MSG_CMD_COMPLETE)
    601 				/* SCSI IO complete */
    602 				*(hs->sc_lock) = SC_IO_COMPLETE;
    603 			else
    604 				/* Cisconnected from Target */
    605 				*(hs->sc_lock) = SC_DISCONNECTED;
    606 			hd->scsi_ints = ints;
    607 			return 0;
    608 		} else
    609 			goto abort;
    610 	} else if (ints & INTS_CMD_DONE) {
    611 		if (hs->sc_phase == BUS_FREE_PHASE)
    612 			goto abort;
    613 		else if (hs->sc_phase == MESG_IN_PHASE) {
    614 			hd->scsi_scmd = SCMD_RST_ACK;
    615 			hd->scsi_ints = ints;
    616 			hs->sc_phase  = hd->scsi_psns & PHASE;
    617 			return 0;
    618 		}
    619 		if (hs->sc_flags & SC_SEL_TIMEOUT)
    620 			hs->sc_flags &= ~SC_SEL_TIMEOUT;
    621 	} else if (ints & INTS_SRV_REQ) {
    622 		if (hs->sc_phase != MESG_IN_PHASE)
    623 			goto abort;
    624 	} else if (ints & INTS_TIMEOUT) {
    625 		if (hs->sc_phase == ARB_SEL_PHASE) {
    626 			if (hs->sc_flags & SC_SEL_TIMEOUT) {
    627 				hs->sc_flags &= ~SC_SEL_TIMEOUT;
    628 				hs->sc_phase  = BUS_FREE_PHASE;
    629 				hs->sc_target = SCSI_ID;
    630 				/* Such SCSI Device is not conected. */
    631 				*(hs->sc_lock) = SC_DEV_NOT_FOUND;
    632 				hd->scsi_ints = ints;
    633 				return 0;
    634 			} else {
    635 				/* wait more 250 usec */
    636 				hs->sc_flags |= SC_SEL_TIMEOUT;
    637 				hd->scsi_temp = 0;
    638 				hd->scsi_tch  = 0;
    639 				hd->scsi_tcm  = 0x06;
    640 				hd->scsi_tcl  = 0x40;
    641 				hd->scsi_ints = ints;
    642 				return 0;
    643 			}
    644 		} else
    645 			goto abort;
    646 	} else
    647 		goto abort;
    648 
    649 	hd->scsi_ints = ints;
    650 
    651 	/*
    652 	 * Next SCSI Transfer
    653 	 */
    654 
    655 	while ((hd->scsi_psns & PSNS_REQ) == 0) {
    656 		DELAY(1);
    657 	}
    658 
    659 	hs->sc_phase = hd->scsi_psns & PHASE;
    660 
    661 	if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) {
    662 		len = hs->sc_len;
    663 		buf = hs->sc_buf;
    664 	} else if (hs->sc_phase == CMD_PHASE) {
    665 		len = hs->sc_cdblen;
    666 		buf = hs->sc_cdb;
    667 	} else if (hs->sc_phase == STATUS_PHASE) {
    668 		len = 1;
    669 		buf = &hs->sc_stat;
    670 	} else {
    671 		len = 1;
    672 		buf = hs->sc_msg;
    673 	}
    674 
    675 	ixfer_start(hd, len, hs->sc_phase, 0);
    676 	if (hs->sc_phase & PHASE_IO)
    677 		ixfer_in(hd, len, buf);
    678 	else
    679 		ixfer_out(hd, len, buf);
    680 
    681 	return 0;
    682 
    683 	/*
    684 	 * SCSI Abort
    685 	 */
    686  abort:
    687 	/* SCSI IO failed */
    688 	scabort(hs, hd);
    689 	hd->scsi_ints = ints;
    690 	*(hs->sc_lock) = SC_IO_FAILED;
    691 	return -1;
    692 }
    693