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