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