xref: /netbsd-src/sys/arch/luna68k/stand/boot/sc.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: sc.c,v 1.17 2018/02/09 22:08:28 jakllsch 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 bool
178 scident(uint ctlr, uint target, uint lun, struct scsi_inquiry *inqout,
179     uint32_t *capout)
180 {
181 	struct scsi_inquiry inqbuf;
182 	struct scsi_generic_cdb inq = {
183 		6,
184 		{ CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 }
185 	};
186 	uint32_t capbuf[2];
187 	struct scsi_generic_cdb cap = {
188 		10,
189 		{ CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
190 	};
191 	int i;
192 	int tries = 10;
193 
194 	/*
195 	 * See if unit exists and is a disk then read block size & nblocks.
196 	 */
197 	while ((i = scsi_test_unit_rdy(ctlr, target, lun)) != 0) {
198 		if (i < 0 || --tries < 0)
199 			return false;
200 		if (i == STS_CHECKCOND) {
201 			uint8_t sensebuf[8];
202 			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
203 
204 			scsi_request_sense(ctlr, target, lun, sensebuf, 8);
205 			if (sp->class == 7 && sp->key == 6)
206 				/* drive doing an RTZ -- give it a while */
207 				DELAY(1000000);
208 		}
209 		DELAY(1000);
210 	}
211 	if (scsi_immed_command(ctlr, target, lun, &inq, (uint8_t *)&inqbuf,
212 			       sizeof(inqbuf)) ||
213 	    scsi_immed_command(ctlr, target, lun, &cap, (uint8_t *)&capbuf,
214 			       sizeof(capbuf)))
215 		/* doesn't exist or not a CCS device */
216 		return false;
217 
218 	switch (inqbuf.type) {
219 	case 0:		/* disk */
220 	case 4:		/* WORM */
221 	case 5:		/* CD-ROM */
222 	case 7:		/* Magneto-optical */
223 		break;
224 	default:	/* not a disk */
225 		return false;
226 	}
227 
228 	if (inqout != NULL)
229 		*inqout = inqbuf;
230 	if (capout != NULL) {
231 		/* assume big endian */
232 		capout[0] = capbuf[0];
233 		capout[1] = capbuf[1];
234 	}
235 
236 	return true;
237 }
238 
239 static void
240 scprobe(struct scsi_softc *hs, uint target, uint lun)
241 {
242 	struct scsi_inquiry inqbuf;
243 	uint32_t capbuf[2];
244 	char idstr[32];
245 	int i;
246 
247 	if (!scident(hs->sc_ctlr, target, lun, &inqbuf, capbuf))
248 		return;
249 
250 	memcpy(idstr, &inqbuf.vendor_id, 28);
251 	for (i = 27; i > 23; --i)
252 		if (idstr[i] != ' ')
253 			break;
254 	idstr[i + 1] = '\0';
255 	for (i = 23; i > 7; --i)
256 		if (idstr[i] != ' ')
257 			break;
258 	idstr[i + 1] = '\0';
259 	for (i = 7; i >= 0; --i)
260 		if (idstr[i] != ' ')
261 			break;
262 	idstr[i + 1] = '\0';
263 
264 	printf(" ID %d: %s %s rev %s", target, idstr, &idstr[8], &idstr[24]);
265 	printf(", %d bytes/sect x %d sectors\n", capbuf[1], capbuf[0]);
266 }
267 
268 
269 /*
270  * SPC Arbitration/Selection routine
271  */
272 
273 static int
274 issue_select(struct scsidevice *hd, uint8_t target)
275 {
276 
277 	hd->scsi_pctl = 0;
278 	hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
279 
280 	/* select timeout is hardcoded to 250ms */
281 	hd->scsi_tch = 2;
282 	hd->scsi_tcm = 113;
283 	hd->scsi_tcl = 3;
284 
285 	hd->scsi_scmd = SCMD_SELECT;
286 
287 	return 1;
288 }
289 
290 
291 /*
292  * SPC Manual Transfer routines
293  */
294 
295 /* not yet */
296 
297 
298 /*
299  * SPC Program Transfer routines
300  */
301 
302 static void
303 ixfer_start(struct scsidevice *hd, int len, uint8_t phase, int wait)
304 {
305 
306 	hd->scsi_tch  = ((len & 0xff0000) >> 16);
307 	hd->scsi_tcm  = ((len & 0x00ff00) >>  8);
308 	hd->scsi_tcl  =  (len & 0x0000ff);
309 	hd->scsi_pctl = phase;
310 	hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
311 }
312 
313 static void
314 ixfer_out(struct scsidevice *hd, int len, uint8_t *buf)
315 {
316 
317 	for (; len > 0; len--) {
318 		while (hd->scsi_ssts & SSTS_DREG_FULL) {
319 			DELAY(5);
320 		}
321 		hd->scsi_dreg = *buf++;
322 	}
323 }
324 
325 static void
326 ixfer_in(struct scsidevice *hd, int len, uint8_t *buf)
327 {
328 
329 	for (; len > 0; len--) {
330 		while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
331 			DELAY(5);
332 		}
333 		*buf++ = hd->scsi_dreg;
334 	}
335 }
336 
337 
338 /*
339  * SPC drive routines
340  */
341 
342 static int
343 scrun(int ctlr, int target, uint8_t *cdb, int cdblen, uint8_t *buf, int len,
344     volatile int *lock)
345 {
346 	struct scsi_softc *hs;
347 	struct scsidevice *hd;
348 
349 	if (ctlr < 0 || ctlr >= NSC)
350 		return 0;
351 
352 	hs = &scsi_softc[ctlr];
353 	hd = hs->sc_spc;
354 	if (hd == NULL)
355 		return 0;
356 
357 	if ((hd->scsi_ssts & (SSTS_INITIATOR | SSTS_TARGET | SSTS_BUSY)) != 0)
358 		return 0;
359 
360 	hs->sc_flags  = 0;
361 	hs->sc_phase  = ARB_SEL_PHASE;
362 	hs->sc_target = target;
363 
364 	hs->sc_cdb    = cdb;
365 	hs->sc_cdblen = cdblen;
366 	hs->sc_buf    = buf;
367 	hs->sc_len    = len;
368 	hs->sc_lock   = lock;
369 
370 	hs->sc_stat   = 0;
371 	hs->sc_msg[0] = 0;
372 
373 	*(hs->sc_lock) = SC_IN_PROGRESS;
374 	issue_select(hd, hs->sc_target);
375 
376 	return 1;
377 }
378 
379 static int
380 scfinish(int ctlr)
381 {
382 	struct scsi_softc *hs = &scsi_softc[ctlr];
383 	int status = hs->sc_stat;
384 
385 	hs->sc_flags  = 0;
386 	hs->sc_phase  = BUS_FREE_PHASE;
387 	hs->sc_target = SCSI_ID;
388 
389 	hs->sc_cdb    = NULL;
390 	hs->sc_cdblen = 0;
391 	hs->sc_buf    = NULL;
392 	hs->sc_len    = 0;
393 	hs->sc_lock   = NULL;
394 
395 	hs->sc_stat   = 0;
396 	hs->sc_msg[0] = 0;
397 
398 	return status;
399 }
400 
401 static void
402 scabort(struct scsi_softc *hs)
403 {
404 	struct scsidevice *hd = hs->sc_spc;
405 	int len;
406 
407 	printf("sc%d: abort  phase=0x%x, ssts=0x%x, ints=0x%x\n",
408 	    hs->sc_ctlr, hd->scsi_psns, hd->scsi_ssts, hd->scsi_ints);
409 
410 	if (hd->scsi_ints != 0)
411 		/* write register value back to register */
412 		hd->scsi_ints = hd->scsi_ints;
413 
414 	if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
415 		/* no longer connected to scsi target */
416 		return;
417 
418 	/* get the number of bytes remaining in current xfer + fudge */
419 	len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
420 
421 	/* for that many bus cycles, try to send an abort msg */
422 	for (len += 1024;
423 	    ((hd->scsi_ssts & SSTS_INITIATOR)) != 0 && --len >= 0;) {
424 		hd->scsi_scmd = SCMD_SET_ATN;
425 
426 		while ((hd->scsi_psns & PSNS_REQ) == 0) {
427 			if ((hd->scsi_ssts & SSTS_INITIATOR) == 0)
428 				goto out;
429 			DELAY(1);
430 		}
431 
432 		if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
433 			hd->scsi_scmd = SCMD_RST_ATN;
434 		hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
435 
436 		if (hd->scsi_psns & PHASE_IO) {
437 			/* one of the input phases - read & discard a byte */
438 			hd->scsi_scmd = SCMD_SET_ACK;
439 			while ((hd->scsi_psns & PSNS_REQ) != 0)
440 				DELAY(1);
441 			(void)hd->scsi_temp;
442 		} else {
443 			/* one of the output phases - send an abort msg */
444 			hd->scsi_temp = MSG_ABORT;
445 			hd->scsi_scmd = SCMD_SET_ACK;
446 			while ((hd->scsi_psns & PSNS_REQ) != 0)
447 				DELAY(1);
448 		}
449 
450 		hd->scsi_scmd = SCMD_RST_ACK;
451 	}
452 out:
453 	/*
454 	 * Either the abort was successful & the bus is disconnected or
455 	 * the device didn't listen.  If the latter, announce the problem.
456 	 * Either way, reset the card & the SPC.
457 	 */
458 	if (len < 0 && hs)
459 		printf("sc%d: abort failed.  phase=0x%x, ssts=0x%x\n",
460 		    hs->sc_ctlr, hd->scsi_psns, hd->scsi_ssts);
461 }
462 
463 
464 /*
465  * SCSI Command Handler
466  */
467 
468 int
469 scsi_test_unit_rdy(int ctlr, int target, int lun)
470 {
471 	static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
472 	int status;
473 	volatile int lock;
474 
475 #ifdef DEBUG
476 	printf("scsi_test_unit_rdy( %d, %d, %d): Start\n", ctlr, target, lun);
477 #endif
478 
479 	cdb.lun = lun;
480 
481 	if (scrun(ctlr, target, (void *)&cdb, 6, NULL, 0, &lock) == 0) {
482 #ifdef DEBUG
483 		printf("scsi_test_unit_rdy: Command Transfer Failed.\n");
484 #endif
485 		return -1;
486 	}
487 
488 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
489 		DELAY(10);
490 
491 	status = scfinish(ctlr);
492 
493 	if (lock == SC_IO_COMPLETE) {
494 #ifdef DEBUG
495 		printf("scsi_test_unit_rdy: Status -- 0x%x\n", status);
496 #endif
497 		return status;
498 	} else {
499 		return lock;
500 	}
501 }
502 
503 int
504 scsi_request_sense(int ctlr, int target, int lun, uint8_t *buf,
505     unsigned int len)
506 {
507 	static struct scsi_cdb6 cdb = {	CMD_REQUEST_SENSE };
508 	int status;
509 	volatile int lock;
510 
511 #ifdef DEBUG
512 	printf("scsi_request_sense: Start\n");
513 #endif
514 
515 	/* Request Senseの場合、転送されるデータ長はターゲットに依存し、        */
516 	/* センスデータの8バイト目のAdditional Sens Lengthにより動的に決定する。*/
517 	/* ここではデーター転送数をcdbのAllocation Lengthに最低長である8バイト */
518 	/* を固定して、SPCの処理シーケンスを崩さないようにしている。         */
519 
520 	/* テープユニットの状態を調べるため、Addtional Sens Fieldをアクセスする */
521 	/* 必要があるのでデバイスドライバ側でlenを決定することにする            */
522 
523 	cdb.lun = lun;
524 	cdb.len = len;
525 
526 	if (scrun(ctlr, target, (void *)&cdb, 6, buf, len, &lock) == 0) {
527 #ifdef DEBUG
528 		printf("scsi_request_sense: Command Transfer Failed.\n");
529 #endif
530 		return -1;
531 	}
532 
533 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
534 		DELAY(10);
535 
536 	status = scfinish(ctlr);
537 
538 	if (lock == SC_IO_COMPLETE) {
539 #ifdef DEBUG
540 		printf("scsi_request_sense: Status -- 0x%x\n", status);
541 #endif
542 		return status;
543 	} else {
544 		return lock;
545 	}
546 }
547 
548 int
549 scsi_immed_command(int ctlr, int target, int lun, struct scsi_generic_cdb *cdb,
550     uint8_t *buf, unsigned int len)
551 {
552 	int status;
553 	volatile int lock;
554 
555 #ifdef DEBUG
556 	printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n",
557 	    ctlr, target, lun, cdb->len, len);
558 #endif
559 
560 	cdb->cdb[1] |= lun << 5;
561 
562 	if (scrun(ctlr, target, (void *)&cdb->cdb[0], cdb->len, buf, len,
563 	    &lock) == 0) {
564 #ifdef DEBUG
565 		printf("scsi_immed_command: Command Transfer Failed.\n");
566 #endif
567 		return -1;
568 	}
569 
570 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
571 		DELAY(10);
572 
573 	status = scfinish(ctlr);
574 
575 	if (lock == SC_IO_COMPLETE) {
576 #ifdef DEBUG
577 		printf("scsi_immed_command: Status -- 0x%x\n", status);
578 #endif
579 		return status;
580 	} else {
581 		return lock;
582 	}
583 }
584 
585 int
586 scsi_format_unit(int ctlr, int target, int lun)
587 {
588 	static struct scsi_cdb6 cdb = { CMD_FORMAT_UNIT, 0, 0, 0, 0, 0 };
589 	int status;
590 	volatile int lock;
591 #ifdef DEBUG
592 	int count = 0;
593 #endif
594 
595 #ifdef DEBUG
596 	printf("scsi_format_unit( %d, %d, %d): Start\n", ctlr, target, lun);
597 #endif
598 
599 	cdb.lun = lun;
600 
601 	if (scrun(ctlr, target, (void *)&cdb, 6, NULL, 0, &lock) == 0) {
602 #ifdef DEBUG
603 		printf("scsi_format_unit: Command Transfer Failed.\n");
604 #endif
605 		return -1;
606 	}
607 
608 	while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
609 		DELAY(1000000);
610 #ifdef DEBUG
611 		if ((++count % 60) == 0)
612 			printf("scsi_format_unit: %d\n", count / 60);
613 #endif
614 	}
615 
616 	status = scfinish(ctlr);
617 
618 	if (lock == SC_IO_COMPLETE) {
619 #ifdef DEBUG
620 		printf("scsi_format_unit: Status -- 0x%x\n", status);
621 #endif
622 		return status;
623 	} else {
624 		return lock;
625 	}
626 }
627 
628 
629 /*
630  * Interrupt Routine
631  */
632 
633 int
634 scintr(void)
635 {
636 	struct scsi_softc *hs;
637 	struct scsidevice *hd;
638 	uint8_t ints, temp;
639 	int i;
640 	uint8_t *buf;
641 	int len;
642 
643 	for (i = 0; i < NSC; i++) {
644 		hs = &scsi_softc[i];
645 		hd = hs->sc_spc;
646 		if ((ints = hd->scsi_ints) != 0)
647 			goto get_intr;
648 	}
649 
650 	/* Unknown Interrupt occured */
651 	return -1;
652 
653 
654 	/*
655 	 * Interrupt
656 	 */
657 
658  get_intr:
659 #ifdef DEBUG
660 	printf("scintr: INTS 0x%x, SSTS 0x%x,  PCTL 0x%x,  PSNS 0x%x    0x%x\n",
661 	    ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns, hs->sc_phase);
662 #endif
663 	if (ints & INTS_RESEL) {
664 		if (hs->sc_phase == BUS_FREE_PHASE) {
665 			temp = hd->scsi_temp & ~(1 << SCSI_ID);
666 			for (i = 0; temp != 1; i++) {
667 				temp >>= 1;
668 			}
669 			hs->sc_target = i;
670 			*(hs->sc_lock) = SC_IN_PROGRESS;
671 		} else
672 			goto abort;
673 	} else if (ints & INTS_DISCON) {
674 		if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) ||
675 		    (hs->sc_msg[0] == MSG_DISCONNECT)) {
676 			hs->sc_phase  = BUS_FREE_PHASE;
677 			hs->sc_target = SCSI_ID;
678 			if (hs->sc_msg[0] == MSG_CMD_COMPLETE) {
679 				/* SCSI IO complete */
680 				*(hs->sc_lock) = SC_IO_COMPLETE;
681 			} else {
682 				/* Disconnected from Target */
683 				*(hs->sc_lock) = SC_DISCONNECTED;
684 			}
685 			hd->scsi_ints = ints;
686 			return 0;
687 		} else
688 			goto abort;
689 	} else if (ints & INTS_CMD_DONE) {
690 		if (hs->sc_phase == BUS_FREE_PHASE)
691 			goto abort;
692 		else if (hs->sc_phase == MESG_IN_PHASE) {
693 			hd->scsi_scmd = SCMD_RST_ACK;
694 			hd->scsi_ints = ints;
695 			hs->sc_phase  = hd->scsi_psns & PHASE;
696 			return 0;
697 		}
698 		if (hs->sc_flags & SC_SEL_TIMEOUT)
699 			hs->sc_flags &= ~SC_SEL_TIMEOUT;
700 	} else if (ints & INTS_SRV_REQ) {
701 		if (hs->sc_phase != MESG_IN_PHASE)
702 			goto abort;
703 	} else if (ints & INTS_TIMEOUT) {
704 		if (hs->sc_phase == ARB_SEL_PHASE) {
705 			if (hs->sc_flags & SC_SEL_TIMEOUT) {
706 				hs->sc_flags &= ~SC_SEL_TIMEOUT;
707 				hs->sc_phase  = BUS_FREE_PHASE;
708 				hs->sc_target = SCSI_ID;
709 				/* Such SCSI Device is not connected. */
710 				*(hs->sc_lock) = SC_DEV_NOT_FOUND;
711 				hd->scsi_ints = ints;
712 				return 0;
713 			} else {
714 				/* wait more 250 usec */
715 				hs->sc_flags |= SC_SEL_TIMEOUT;
716 				hd->scsi_temp = 0;
717 				hd->scsi_tch  = 0;
718 				hd->scsi_tcm  = 0x06;
719 				hd->scsi_tcl  = 0x40;
720 				hd->scsi_ints = ints;
721 				return 0;
722 			}
723 		} else
724 			goto abort;
725 	} else
726 		goto abort;
727 
728 	hd->scsi_ints = ints;
729 
730 	/*
731 	 * Next SCSI Transfer
732 	 */
733 
734 	while ((hd->scsi_psns & PSNS_REQ) == 0) {
735 		DELAY(1);
736 	}
737 
738 	hs->sc_phase = hd->scsi_psns & PHASE;
739 
740 	if ((hs->sc_phase == DATA_OUT_PHASE) ||
741 	    (hs->sc_phase == DATA_IN_PHASE)) {
742 		len = hs->sc_len;
743 		buf = hs->sc_buf;
744 	} else if (hs->sc_phase == CMD_PHASE) {
745 		len = hs->sc_cdblen;
746 		buf = hs->sc_cdb;
747 	} else if (hs->sc_phase == STATUS_PHASE) {
748 		len = 1;
749 		buf = &hs->sc_stat;
750 	} else {
751 		len = 1;
752 		buf = hs->sc_msg;
753 	}
754 
755 	ixfer_start(hd, len, hs->sc_phase, 0);
756 	if (hs->sc_phase & PHASE_IO)
757 		ixfer_in(hd, len, buf);
758 	else
759 		ixfer_out(hd, len, buf);
760 
761 	return 0;
762 
763 	/*
764 	 * SCSI Abort
765 	 */
766  abort:
767 	/* SCSI IO failed */
768 	scabort(hs);
769 	hd->scsi_ints = ints;
770 	*(hs->sc_lock) = SC_IO_FAILED;
771 	return -1;
772 }
773