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