1 /* $NetBSD: sc.c,v 1.19 2021/12/10 20:36:02 andvar 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 /* センスデータの8バイト目のAdditional Sens Lengthにより動的に決定する。*/ 521 /* ここではデーター転送数をcdbのAllocation Lengthに最低長である8バイト */ 522 /* を固定して、SPCの処理シーケンスを崩さないようにしている。 */ 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 occurred */ 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