sc.c revision 1.18 1 /* $NetBSD: sc.c,v 1.18 2021/06/15 17:16:16 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/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], blocks, blksize;
244 char idstr[32];
245 int i;
246
247 if (!scident(hs->sc_ctlr, target, lun, &inqbuf, capbuf))
248 return;
249
250 /* CMD_READ_CAPACITY returns the last logical data block address. */
251 blocks = capbuf[0] + 1;
252 blksize = capbuf[1];
253
254 memcpy(idstr, &inqbuf.vendor_id, 28);
255 for (i = 27; i > 23; --i)
256 if (idstr[i] != ' ')
257 break;
258 idstr[i + 1] = '\0';
259 for (i = 23; i > 7; --i)
260 if (idstr[i] != ' ')
261 break;
262 idstr[i + 1] = '\0';
263 for (i = 7; i >= 0; --i)
264 if (idstr[i] != ' ')
265 break;
266 idstr[i + 1] = '\0';
267
268 printf(" ID %d: %s %s rev %s", target, idstr, &idstr[8], &idstr[24]);
269 printf(", %d bytes/sect x %d sectors\n", blksize, blocks);
270 }
271
272
273 /*
274 * SPC Arbitration/Selection routine
275 */
276
277 static int
278 issue_select(struct scsidevice *hd, uint8_t target)
279 {
280
281 hd->scsi_pctl = 0;
282 hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
283
284 /* select timeout is hardcoded to 250ms */
285 hd->scsi_tch = 2;
286 hd->scsi_tcm = 113;
287 hd->scsi_tcl = 3;
288
289 hd->scsi_scmd = SCMD_SELECT;
290
291 return 1;
292 }
293
294
295 /*
296 * SPC Manual Transfer routines
297 */
298
299 /* not yet */
300
301
302 /*
303 * SPC Program Transfer routines
304 */
305
306 static void
307 ixfer_start(struct scsidevice *hd, int len, uint8_t phase, int wait)
308 {
309
310 hd->scsi_tch = ((len & 0xff0000) >> 16);
311 hd->scsi_tcm = ((len & 0x00ff00) >> 8);
312 hd->scsi_tcl = (len & 0x0000ff);
313 hd->scsi_pctl = phase;
314 hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
315 }
316
317 static void
318 ixfer_out(struct scsidevice *hd, int len, uint8_t *buf)
319 {
320
321 for (; len > 0; len--) {
322 while (hd->scsi_ssts & SSTS_DREG_FULL) {
323 DELAY(5);
324 }
325 hd->scsi_dreg = *buf++;
326 }
327 }
328
329 static void
330 ixfer_in(struct scsidevice *hd, int len, uint8_t *buf)
331 {
332
333 for (; len > 0; len--) {
334 while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
335 DELAY(5);
336 }
337 *buf++ = hd->scsi_dreg;
338 }
339 }
340
341
342 /*
343 * SPC drive routines
344 */
345
346 static int
347 scrun(int ctlr, int target, uint8_t *cdb, int cdblen, uint8_t *buf, int len,
348 volatile int *lock)
349 {
350 struct scsi_softc *hs;
351 struct scsidevice *hd;
352
353 if (ctlr < 0 || ctlr >= NSC)
354 return 0;
355
356 hs = &scsi_softc[ctlr];
357 hd = hs->sc_spc;
358 if (hd == NULL)
359 return 0;
360
361 if ((hd->scsi_ssts & (SSTS_INITIATOR | SSTS_TARGET | SSTS_BUSY)) != 0)
362 return 0;
363
364 hs->sc_flags = 0;
365 hs->sc_phase = ARB_SEL_PHASE;
366 hs->sc_target = target;
367
368 hs->sc_cdb = cdb;
369 hs->sc_cdblen = cdblen;
370 hs->sc_buf = buf;
371 hs->sc_len = len;
372 hs->sc_lock = lock;
373
374 hs->sc_stat = 0;
375 hs->sc_msg[0] = 0;
376
377 *(hs->sc_lock) = SC_IN_PROGRESS;
378 issue_select(hd, hs->sc_target);
379
380 return 1;
381 }
382
383 static int
384 scfinish(int ctlr)
385 {
386 struct scsi_softc *hs = &scsi_softc[ctlr];
387 int status = hs->sc_stat;
388
389 hs->sc_flags = 0;
390 hs->sc_phase = BUS_FREE_PHASE;
391 hs->sc_target = SCSI_ID;
392
393 hs->sc_cdb = NULL;
394 hs->sc_cdblen = 0;
395 hs->sc_buf = NULL;
396 hs->sc_len = 0;
397 hs->sc_lock = NULL;
398
399 hs->sc_stat = 0;
400 hs->sc_msg[0] = 0;
401
402 return status;
403 }
404
405 static void
406 scabort(struct scsi_softc *hs)
407 {
408 struct scsidevice *hd = hs->sc_spc;
409 int len;
410
411 printf("sc%d: abort phase=0x%x, ssts=0x%x, ints=0x%x\n",
412 hs->sc_ctlr, hd->scsi_psns, hd->scsi_ssts, hd->scsi_ints);
413
414 if (hd->scsi_ints != 0)
415 /* write register value back to register */
416 hd->scsi_ints = hd->scsi_ints;
417
418 if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
419 /* no longer connected to scsi target */
420 return;
421
422 /* get the number of bytes remaining in current xfer + fudge */
423 len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
424
425 /* for that many bus cycles, try to send an abort msg */
426 for (len += 1024;
427 ((hd->scsi_ssts & SSTS_INITIATOR)) != 0 && --len >= 0;) {
428 hd->scsi_scmd = SCMD_SET_ATN;
429
430 while ((hd->scsi_psns & PSNS_REQ) == 0) {
431 if ((hd->scsi_ssts & SSTS_INITIATOR) == 0)
432 goto out;
433 DELAY(1);
434 }
435
436 if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
437 hd->scsi_scmd = SCMD_RST_ATN;
438 hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
439
440 if (hd->scsi_psns & PHASE_IO) {
441 /* one of the input phases - read & discard a byte */
442 hd->scsi_scmd = SCMD_SET_ACK;
443 while ((hd->scsi_psns & PSNS_REQ) != 0)
444 DELAY(1);
445 (void)hd->scsi_temp;
446 } else {
447 /* one of the output phases - send an abort msg */
448 hd->scsi_temp = MSG_ABORT;
449 hd->scsi_scmd = SCMD_SET_ACK;
450 while ((hd->scsi_psns & PSNS_REQ) != 0)
451 DELAY(1);
452 }
453
454 hd->scsi_scmd = SCMD_RST_ACK;
455 }
456 out:
457 /*
458 * Either the abort was successful & the bus is disconnected or
459 * the device didn't listen. If the latter, announce the problem.
460 * Either way, reset the card & the SPC.
461 */
462 if (len < 0 && hs)
463 printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n",
464 hs->sc_ctlr, hd->scsi_psns, hd->scsi_ssts);
465 }
466
467
468 /*
469 * SCSI Command Handler
470 */
471
472 int
473 scsi_test_unit_rdy(int ctlr, int target, int lun)
474 {
475 static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
476 int status;
477 volatile int lock;
478
479 #ifdef DEBUG
480 printf("scsi_test_unit_rdy( %d, %d, %d): Start\n", ctlr, target, lun);
481 #endif
482
483 cdb.lun = lun;
484
485 if (scrun(ctlr, target, (void *)&cdb, 6, NULL, 0, &lock) == 0) {
486 #ifdef DEBUG
487 printf("scsi_test_unit_rdy: Command Transfer Failed.\n");
488 #endif
489 return -1;
490 }
491
492 while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
493 DELAY(10);
494
495 status = scfinish(ctlr);
496
497 if (lock == SC_IO_COMPLETE) {
498 #ifdef DEBUG
499 printf("scsi_test_unit_rdy: Status -- 0x%x\n", status);
500 #endif
501 return status;
502 } else {
503 return lock;
504 }
505 }
506
507 int
508 scsi_request_sense(int ctlr, int target, int lun, uint8_t *buf,
509 unsigned int len)
510 {
511 static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
512 int status;
513 volatile int lock;
514
515 #ifdef DEBUG
516 printf("scsi_request_sense: Start\n");
517 #endif
518
519 /* Request Sense */
520 /* Additional Sens Length*/
521 /* cdbAllocation Length */
522 /* */
523
524 /* Addtional Sens Field */
525 /* len */
526
527 cdb.lun = lun;
528 cdb.len = len;
529
530 if (scrun(ctlr, target, (void *)&cdb, 6, buf, len, &lock) == 0) {
531 #ifdef DEBUG
532 printf("scsi_request_sense: Command Transfer Failed.\n");
533 #endif
534 return -1;
535 }
536
537 while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
538 DELAY(10);
539
540 status = scfinish(ctlr);
541
542 if (lock == SC_IO_COMPLETE) {
543 #ifdef DEBUG
544 printf("scsi_request_sense: Status -- 0x%x\n", status);
545 #endif
546 return status;
547 } else {
548 return lock;
549 }
550 }
551
552 int
553 scsi_immed_command(int ctlr, int target, int lun, struct scsi_generic_cdb *cdb,
554 uint8_t *buf, unsigned int len)
555 {
556 int status;
557 volatile int lock;
558
559 #ifdef DEBUG
560 printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n",
561 ctlr, target, lun, cdb->len, len);
562 #endif
563
564 cdb->cdb[1] |= lun << 5;
565
566 if (scrun(ctlr, target, (void *)&cdb->cdb[0], cdb->len, buf, len,
567 &lock) == 0) {
568 #ifdef DEBUG
569 printf("scsi_immed_command: Command Transfer Failed.\n");
570 #endif
571 return -1;
572 }
573
574 while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
575 DELAY(10);
576
577 status = scfinish(ctlr);
578
579 if (lock == SC_IO_COMPLETE) {
580 #ifdef DEBUG
581 printf("scsi_immed_command: Status -- 0x%x\n", status);
582 #endif
583 return status;
584 } else {
585 return lock;
586 }
587 }
588
589 int
590 scsi_format_unit(int ctlr, int target, int lun)
591 {
592 static struct scsi_cdb6 cdb = { CMD_FORMAT_UNIT, 0, 0, 0, 0, 0 };
593 int status;
594 volatile int lock;
595 #ifdef DEBUG
596 int count = 0;
597 #endif
598
599 #ifdef DEBUG
600 printf("scsi_format_unit( %d, %d, %d): Start\n", ctlr, target, lun);
601 #endif
602
603 cdb.lun = lun;
604
605 if (scrun(ctlr, target, (void *)&cdb, 6, NULL, 0, &lock) == 0) {
606 #ifdef DEBUG
607 printf("scsi_format_unit: Command Transfer Failed.\n");
608 #endif
609 return -1;
610 }
611
612 while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
613 DELAY(1000000);
614 #ifdef DEBUG
615 if ((++count % 60) == 0)
616 printf("scsi_format_unit: %d\n", count / 60);
617 #endif
618 }
619
620 status = scfinish(ctlr);
621
622 if (lock == SC_IO_COMPLETE) {
623 #ifdef DEBUG
624 printf("scsi_format_unit: Status -- 0x%x\n", status);
625 #endif
626 return status;
627 } else {
628 return lock;
629 }
630 }
631
632
633 /*
634 * Interrupt Routine
635 */
636
637 int
638 scintr(void)
639 {
640 struct scsi_softc *hs;
641 struct scsidevice *hd;
642 uint8_t ints, temp;
643 int i;
644 uint8_t *buf;
645 int len;
646
647 for (i = 0; i < NSC; i++) {
648 hs = &scsi_softc[i];
649 hd = hs->sc_spc;
650 if ((ints = hd->scsi_ints) != 0)
651 goto get_intr;
652 }
653
654 /* Unknown Interrupt occured */
655 return -1;
656
657
658 /*
659 * Interrupt
660 */
661
662 get_intr:
663 #ifdef DEBUG
664 printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x 0x%x\n",
665 ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns, hs->sc_phase);
666 #endif
667 if (ints & INTS_RESEL) {
668 if (hs->sc_phase == BUS_FREE_PHASE) {
669 temp = hd->scsi_temp & ~(1 << SCSI_ID);
670 for (i = 0; temp != 1; i++) {
671 temp >>= 1;
672 }
673 hs->sc_target = i;
674 *(hs->sc_lock) = SC_IN_PROGRESS;
675 } else
676 goto abort;
677 } else if (ints & INTS_DISCON) {
678 if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) ||
679 (hs->sc_msg[0] == MSG_DISCONNECT)) {
680 hs->sc_phase = BUS_FREE_PHASE;
681 hs->sc_target = SCSI_ID;
682 if (hs->sc_msg[0] == MSG_CMD_COMPLETE) {
683 /* SCSI IO complete */
684 *(hs->sc_lock) = SC_IO_COMPLETE;
685 } else {
686 /* Disconnected from Target */
687 *(hs->sc_lock) = SC_DISCONNECTED;
688 }
689 hd->scsi_ints = ints;
690 return 0;
691 } else
692 goto abort;
693 } else if (ints & INTS_CMD_DONE) {
694 if (hs->sc_phase == BUS_FREE_PHASE)
695 goto abort;
696 else if (hs->sc_phase == MESG_IN_PHASE) {
697 hd->scsi_scmd = SCMD_RST_ACK;
698 hd->scsi_ints = ints;
699 hs->sc_phase = hd->scsi_psns & PHASE;
700 return 0;
701 }
702 if (hs->sc_flags & SC_SEL_TIMEOUT)
703 hs->sc_flags &= ~SC_SEL_TIMEOUT;
704 } else if (ints & INTS_SRV_REQ) {
705 if (hs->sc_phase != MESG_IN_PHASE)
706 goto abort;
707 } else if (ints & INTS_TIMEOUT) {
708 if (hs->sc_phase == ARB_SEL_PHASE) {
709 if (hs->sc_flags & SC_SEL_TIMEOUT) {
710 hs->sc_flags &= ~SC_SEL_TIMEOUT;
711 hs->sc_phase = BUS_FREE_PHASE;
712 hs->sc_target = SCSI_ID;
713 /* Such SCSI Device is not connected. */
714 *(hs->sc_lock) = SC_DEV_NOT_FOUND;
715 hd->scsi_ints = ints;
716 return 0;
717 } else {
718 /* wait more 250 usec */
719 hs->sc_flags |= SC_SEL_TIMEOUT;
720 hd->scsi_temp = 0;
721 hd->scsi_tch = 0;
722 hd->scsi_tcm = 0x06;
723 hd->scsi_tcl = 0x40;
724 hd->scsi_ints = ints;
725 return 0;
726 }
727 } else
728 goto abort;
729 } else
730 goto abort;
731
732 hd->scsi_ints = ints;
733
734 /*
735 * Next SCSI Transfer
736 */
737
738 while ((hd->scsi_psns & PSNS_REQ) == 0) {
739 DELAY(1);
740 }
741
742 hs->sc_phase = hd->scsi_psns & PHASE;
743
744 if ((hs->sc_phase == DATA_OUT_PHASE) ||
745 (hs->sc_phase == DATA_IN_PHASE)) {
746 len = hs->sc_len;
747 buf = hs->sc_buf;
748 } else if (hs->sc_phase == CMD_PHASE) {
749 len = hs->sc_cdblen;
750 buf = hs->sc_cdb;
751 } else if (hs->sc_phase == STATUS_PHASE) {
752 len = 1;
753 buf = &hs->sc_stat;
754 } else {
755 len = 1;
756 buf = hs->sc_msg;
757 }
758
759 ixfer_start(hd, len, hs->sc_phase, 0);
760 if (hs->sc_phase & PHASE_IO)
761 ixfer_in(hd, len, buf);
762 else
763 ixfer_out(hd, len, buf);
764
765 return 0;
766
767 /*
768 * SCSI Abort
769 */
770 abort:
771 /* SCSI IO failed */
772 scabort(hs);
773 hd->scsi_ints = ints;
774 *(hs->sc_lock) = SC_IO_FAILED;
775 return -1;
776 }
777