1 /* $NetBSD: sc.c,v 1.11 2014/04/16 11:18:00 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 *, u_char); 91 static void ixfer_start(struct scsidevice *, int, u_char, int); 92 static void ixfer_out(struct scsidevice *, int, u_char *); 93 static void ixfer_in(struct scsidevice *, int, u_char *); 94 static int scrun(int, int, u_char *, int, u_char *, 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 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 u_char 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, (u_char *)&inqbuf, 212 sizeof(inqbuf)) || 213 scsi_immed_command(ctlr, target, lun, &cap, (u_char *)&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 int 274 issue_select(struct scsidevice *hd, u_char 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 void 303 ixfer_start(struct scsidevice *hd, int len, u_char 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 void 314 ixfer_out(struct scsidevice *hd, int len, u_char *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 void 326 ixfer_in(struct scsidevice *hd, int len, u_char *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 int 343 scrun(int ctlr, int target, u_char *cdb, int cdblen, u_char *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)) 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 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 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, 409 hd->scsi_ints); 410 411 if (hd->scsi_ints != 0) 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; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) { 423 hd->scsi_scmd = SCMD_SET_ATN; 424 425 while ((hd->scsi_psns & PSNS_REQ) == 0) { 426 if ((hd->scsi_ssts & SSTS_INITIATOR) == 0) 427 goto out; 428 DELAY(1); 429 } 430 431 if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) 432 hd->scsi_scmd = SCMD_RST_ATN; 433 hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE; 434 435 if (hd->scsi_psns & PHASE_IO) { 436 /* one of the input phases - read & discard a byte */ 437 hd->scsi_scmd = SCMD_SET_ACK; 438 while (hd->scsi_psns & PSNS_REQ) 439 DELAY(1); 440 (void)hd->scsi_temp; 441 } else { 442 /* one of the output phases - send an abort msg */ 443 hd->scsi_temp = MSG_ABORT; 444 hd->scsi_scmd = SCMD_SET_ACK; 445 while (hd->scsi_psns & PSNS_REQ) 446 DELAY(1); 447 } 448 449 hd->scsi_scmd = SCMD_RST_ACK; 450 } 451 out: 452 /* 453 * Either the abort was successful & the bus is disconnected or 454 * the device didn't listen. If the latter, announce the problem. 455 * Either way, reset the card & the SPC. 456 */ 457 if (len < 0 && hs) 458 printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n", 459 hs->sc_ctlr, hd->scsi_psns, hd->scsi_ssts); 460 } 461 462 463 /* 464 * SCSI Command Handler 465 */ 466 467 int 468 scsi_test_unit_rdy(int ctlr, int target, int lun) 469 { 470 static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY }; 471 int status; 472 volatile int lock; 473 474 #ifdef DEBUG 475 printf("scsi_test_unit_rdy( %d, %d, %d): Start\n", ctlr, target, lun); 476 #endif 477 478 cdb.lun = lun; 479 480 if (!(scrun(ctlr, target, (void *)&cdb, 6, NULL, 0, &lock))) { 481 #ifdef DEBUG 482 printf("scsi_test_unit_rdy: Command Transfer Failed.\n"); 483 #endif 484 return -1; 485 } 486 487 while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) 488 DELAY(10); 489 490 status = scfinish(ctlr); 491 492 if (lock == SC_IO_COMPLETE) { 493 #ifdef DEBUG 494 printf("scsi_test_unit_rdy: Status -- 0x%x\n", status); 495 #endif 496 return status; 497 } else { 498 return lock; 499 } 500 } 501 502 int 503 scsi_request_sense(int ctlr, int target, int lun, u_char *buf, unsigned int len) 504 { 505 static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE }; 506 int status; 507 volatile int lock; 508 509 #ifdef DEBUG 510 printf("scsi_request_sense: Start\n"); 511 #endif 512 513 /* Request Senseの場合、転送されるデータ長はターゲットに依存し、 */ 514 /* センスデータの8バイト目のAdditional Sens Lengthにより動的に決定する。*/ 515 /* ここではデーター転送数をcdbのAllocation Lengthに最低長である8バイト */ 516 /* を固定して、SPCの処理シーケンスを崩さないようにしている。 */ 517 518 /* テープユニットの状態を調べるため、Addtional Sens Fieldをアクセスする */ 519 /* 必要があるのでデバイスドライバ側でlenを決定することにする */ 520 521 cdb.lun = lun; 522 cdb.len = len; 523 524 if (!(scrun(ctlr, target, (void *)&cdb, 6, buf, len, &lock))) { 525 #ifdef DEBUG 526 printf("scsi_request_sense: Command Transfer Failed.\n"); 527 #endif 528 return -1; 529 } 530 531 while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) 532 DELAY(10); 533 534 status = scfinish(ctlr); 535 536 if (lock == SC_IO_COMPLETE) { 537 #ifdef DEBUG 538 printf("scsi_request_sense: Status -- 0x%x\n", status); 539 #endif 540 return status; 541 } else { 542 return lock; 543 } 544 } 545 546 int 547 scsi_immed_command(int ctlr, int target, int lun, struct scsi_generic_cdb *cdb, 548 u_char *buf, unsigned int len) 549 { 550 int status; 551 volatile int lock; 552 553 #ifdef DEBUG 554 printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n", 555 ctlr, target, lun, cdb->len, len); 556 #endif 557 558 cdb->cdb[1] |= lun << 5; 559 560 if (!(scrun(ctlr, target, (void *)&cdb->cdb[0], cdb->len, buf, len, 561 &lock))) { 562 #ifdef DEBUG 563 printf("scsi_immed_command: Command Transfer Failed.\n"); 564 #endif 565 return -1; 566 } 567 568 while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) 569 DELAY(10); 570 571 status = scfinish(ctlr); 572 573 if (lock == SC_IO_COMPLETE) { 574 #ifdef DEBUG 575 printf("scsi_immed_command: Status -- 0x%x\n", status); 576 #endif 577 return status; 578 } else { 579 return lock; 580 } 581 } 582 583 int 584 scsi_format_unit(int ctlr, int target, int lun) 585 { 586 static struct scsi_cdb6 cdb = { CMD_FORMAT_UNIT, 0, 0, 0, 0, 0 }; 587 int status; 588 volatile int lock; 589 #ifdef DEBUG 590 int count = 0; 591 #endif 592 593 #ifdef DEBUG 594 printf("scsi_format_unit( %d, %d, %d): Start\n", ctlr, target, lun); 595 #endif 596 597 cdb.lun = lun; 598 599 if (!(scrun(ctlr, target, (void *)&cdb, 6, (u_char *) 0, 0, &lock))) { 600 #ifdef DEBUG 601 printf("scsi_format_unit: Command Transfer Failed.\n"); 602 #endif 603 return -1; 604 } 605 606 while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) { 607 DELAY(1000000); 608 #ifdef DEBUG 609 if ((++count % 60) == 0) 610 printf("scsi_format_unit: %d\n", count / 60); 611 #endif 612 } 613 614 status = scfinish(ctlr); 615 616 if (lock == SC_IO_COMPLETE) { 617 #ifdef DEBUG 618 printf("scsi_format_unit: Status -- 0x%x\n", status); 619 #endif 620 return status; 621 } else { 622 return lock; 623 } 624 } 625 626 627 /* 628 * Interrupt Routine 629 */ 630 631 int 632 scintr(void) 633 { 634 struct scsi_softc *hs; 635 struct scsidevice *hd; 636 u_char ints, temp; 637 int i; 638 u_char *buf; 639 int len; 640 641 for (i = 0; i < NSC; i++) { 642 hs = &scsi_softc[i]; 643 hd = hs->sc_spc; 644 if ((ints = hd->scsi_ints) != 0) 645 goto get_intr; 646 } 647 648 /* Unknown Interrupt occured */ 649 return -1; 650 651 652 /* 653 * Interrupt 654 */ 655 656 get_intr: 657 #ifdef DEBUG 658 printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x 0x%x\n", 659 ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns, 660 hs->sc_phase); 661 #endif 662 if (ints & INTS_RESEL) { 663 if (hs->sc_phase == BUS_FREE_PHASE) { 664 temp = hd->scsi_temp & ~(1 << SCSI_ID); 665 for (i = 0; temp != 1; i++) { 666 temp >>= 1; 667 } 668 hs->sc_target = i; 669 *(hs->sc_lock) = SC_IN_PROGRESS; 670 } else 671 goto abort; 672 } else if (ints & INTS_DISCON) { 673 if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || 674 (hs->sc_msg[0] == MSG_DISCONNECT)) { 675 hs->sc_phase = BUS_FREE_PHASE; 676 hs->sc_target = SCSI_ID; 677 if (hs->sc_msg[0] == MSG_CMD_COMPLETE) 678 /* SCSI IO complete */ 679 *(hs->sc_lock) = SC_IO_COMPLETE; 680 else 681 /* Cisconnected from Target */ 682 *(hs->sc_lock) = SC_DISCONNECTED; 683 hd->scsi_ints = ints; 684 return 0; 685 } else 686 goto abort; 687 } else if (ints & INTS_CMD_DONE) { 688 if (hs->sc_phase == BUS_FREE_PHASE) 689 goto abort; 690 else if (hs->sc_phase == MESG_IN_PHASE) { 691 hd->scsi_scmd = SCMD_RST_ACK; 692 hd->scsi_ints = ints; 693 hs->sc_phase = hd->scsi_psns & PHASE; 694 return 0; 695 } 696 if (hs->sc_flags & SC_SEL_TIMEOUT) 697 hs->sc_flags &= ~SC_SEL_TIMEOUT; 698 } else if (ints & INTS_SRV_REQ) { 699 if (hs->sc_phase != MESG_IN_PHASE) 700 goto abort; 701 } else if (ints & INTS_TIMEOUT) { 702 if (hs->sc_phase == ARB_SEL_PHASE) { 703 if (hs->sc_flags & SC_SEL_TIMEOUT) { 704 hs->sc_flags &= ~SC_SEL_TIMEOUT; 705 hs->sc_phase = BUS_FREE_PHASE; 706 hs->sc_target = SCSI_ID; 707 /* Such SCSI Device is not conected. */ 708 *(hs->sc_lock) = SC_DEV_NOT_FOUND; 709 hd->scsi_ints = ints; 710 return 0; 711 } else { 712 /* wait more 250 usec */ 713 hs->sc_flags |= SC_SEL_TIMEOUT; 714 hd->scsi_temp = 0; 715 hd->scsi_tch = 0; 716 hd->scsi_tcm = 0x06; 717 hd->scsi_tcl = 0x40; 718 hd->scsi_ints = ints; 719 return 0; 720 } 721 } else 722 goto abort; 723 } else 724 goto abort; 725 726 hd->scsi_ints = ints; 727 728 /* 729 * Next SCSI Transfer 730 */ 731 732 while ((hd->scsi_psns & PSNS_REQ) == 0) { 733 DELAY(1); 734 } 735 736 hs->sc_phase = hd->scsi_psns & PHASE; 737 738 if ((hs->sc_phase == DATA_OUT_PHASE) || 739 (hs->sc_phase == DATA_IN_PHASE)) { 740 len = hs->sc_len; 741 buf = hs->sc_buf; 742 } else if (hs->sc_phase == CMD_PHASE) { 743 len = hs->sc_cdblen; 744 buf = hs->sc_cdb; 745 } else if (hs->sc_phase == STATUS_PHASE) { 746 len = 1; 747 buf = &hs->sc_stat; 748 } else { 749 len = 1; 750 buf = hs->sc_msg; 751 } 752 753 ixfer_start(hd, len, hs->sc_phase, 0); 754 if (hs->sc_phase & PHASE_IO) 755 ixfer_in(hd, len, buf); 756 else 757 ixfer_out(hd, len, buf); 758 759 return 0; 760 761 /* 762 * SCSI Abort 763 */ 764 abort: 765 /* SCSI IO failed */ 766 scabort(hs); 767 hd->scsi_ints = ints; 768 *(hs->sc_lock) = SC_IO_FAILED; 769 return -1; 770 } 771