|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Van Jacobson of Lawrence Berkeley Laboratory. ! 7: * ! 8: * Redistribution and use in source and binary forms, with or without ! 9: * modification, are permitted provided that the following conditions ! 10: * are met: ! 11: * 1. Redistributions of source code must retain the above copyright ! 12: * notice, this list of conditions and the following disclaimer. ! 13: * 2. Redistributions in binary form must reproduce the above copyright ! 14: * notice, this list of conditions and the following disclaimer in the ! 15: * documentation and/or other materials provided with the distribution. ! 16: * 3. All advertising materials mentioning features or use of this software ! 17: * must display the following acknowledgement: ! 18: * This product includes software developed by the University of ! 19: * California, Berkeley and its contributors. ! 20: * 4. Neither the name of the University nor the names of its contributors ! 21: * may be used to endorse or promote products derived from this software ! 22: * without specific prior written permission. ! 23: * ! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 34: * SUCH DAMAGE. ! 35: * ! 36: * @(#)scsi.c 7.5 (Berkeley) 5/4/91 ! 37: */ ! 38: ! 39: /* ! 40: * HP9000/3xx 98658 SCSI host adaptor driver. ! 41: */ ! 42: #include "scsi.h" ! 43: #if NSCSI > 0 ! 44: ! 45: #ifndef lint ! 46: static char rcsid[] = "$Header: scsi.c,v 1.4 91/01/17 12:50:18 mike Exp $"; ! 47: #endif ! 48: ! 49: #include "sys/param.h" ! 50: #include "sys/systm.h" ! 51: #include "sys/buf.h" ! 52: #include "device.h" ! 53: ! 54: #include "scsivar.h" ! 55: #include "scsireg.h" ! 56: #include "dmavar.h" ! 57: ! 58: #include "../include/cpu.h" ! 59: #include "../hp300/isr.h" ! 60: ! 61: /* ! 62: * SCSI delays ! 63: * In u-seconds, primarily for state changes on the SPC. ! 64: */ ! 65: #define SCSI_CMD_WAIT 1000 /* wait per step of 'immediate' cmds */ ! 66: #define SCSI_DATA_WAIT 1000 /* wait per data in/out step */ ! 67: #define SCSI_INIT_WAIT 50000 /* wait per step (both) during init */ ! 68: ! 69: extern void isrlink(); ! 70: extern void _insque(); ! 71: extern void _remque(); ! 72: ! 73: int scsiinit(), scsigo(), scsiintr(), scsixfer(); ! 74: void scsistart(), scsidone(), scsifree(), scsireset(); ! 75: struct driver scsidriver = { ! 76: scsiinit, "scsi", (int (*)())scsistart, scsigo, scsiintr, ! 77: (int (*)())scsidone, ! 78: }; ! 79: ! 80: struct scsi_softc scsi_softc[NSCSI]; ! 81: struct isr scsi_isr[NSCSI]; ! 82: ! 83: int scsi_cmd_wait = SCSI_CMD_WAIT; ! 84: int scsi_data_wait = SCSI_DATA_WAIT; ! 85: int scsi_init_wait = SCSI_INIT_WAIT; ! 86: ! 87: int scsi_nosync = 1; /* inhibit sync xfers if 1 */ ! 88: int scsi_pridma = 0; /* use "priority" dma */ ! 89: ! 90: #ifdef DEBUG ! 91: int scsi_debug = 0; ! 92: #define WAITHIST ! 93: #endif ! 94: ! 95: #ifdef WAITHIST ! 96: #define MAXWAIT 1022 ! 97: u_int ixstart_wait[MAXWAIT+2]; ! 98: u_int ixin_wait[MAXWAIT+2]; ! 99: u_int ixout_wait[MAXWAIT+2]; ! 100: u_int mxin_wait[MAXWAIT+2]; ! 101: u_int mxin2_wait[MAXWAIT+2]; ! 102: u_int cxin_wait[MAXWAIT+2]; ! 103: u_int fxfr_wait[MAXWAIT+2]; ! 104: u_int sgo_wait[MAXWAIT+2]; ! 105: #define HIST(h,w) (++h[((w)>MAXWAIT? MAXWAIT : ((w) < 0 ? -1 : (w))) + 1]); ! 106: #else ! 107: #define HIST(h,w) ! 108: #endif ! 109: ! 110: #define b_cylin b_resid ! 111: ! 112: static void ! 113: scsiabort(hs, hd, where) ! 114: register struct scsi_softc *hs; ! 115: volatile register struct scsidevice *hd; ! 116: char *where; ! 117: { ! 118: int len; ! 119: u_char junk; ! 120: ! 121: printf("scsi%d: abort from %s: phase=0x%x, ssts=0x%x, ints=0x%x\n", ! 122: hs->sc_hc->hp_unit, where, hd->scsi_psns, hd->scsi_ssts, ! 123: hd->scsi_ints); ! 124: ! 125: hd->scsi_ints = hd->scsi_ints; ! 126: hd->scsi_csr = 0; ! 127: if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0) ! 128: /* no longer connected to scsi target */ ! 129: return; ! 130: ! 131: /* get the number of bytes remaining in current xfer + fudge */ ! 132: len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl; ! 133: ! 134: /* for that many bus cycles, try to send an abort msg */ ! 135: for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) { ! 136: hd->scsi_scmd = SCMD_SET_ATN; ! 137: while ((hd->scsi_psns & PSNS_REQ) == 0) { ! 138: if (! (hd->scsi_ssts & SSTS_INITIATOR)) ! 139: goto out; ! 140: DELAY(1); ! 141: } ! 142: if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) ! 143: hd->scsi_scmd = SCMD_RST_ATN; ! 144: hd->scsi_pctl = hd->scsi_psns & PHASE; ! 145: if (hd->scsi_psns & PHASE_IO) { ! 146: /* one of the input phases - read & discard a byte */ ! 147: hd->scsi_scmd = SCMD_SET_ACK; ! 148: if (hd->scsi_tmod == 0) ! 149: while (hd->scsi_psns & PSNS_REQ) ! 150: DELAY(1); ! 151: junk = hd->scsi_temp; ! 152: } else { ! 153: /* one of the output phases - send an abort msg */ ! 154: hd->scsi_temp = MSG_ABORT; ! 155: hd->scsi_scmd = SCMD_SET_ACK; ! 156: if (hd->scsi_tmod == 0) ! 157: while (hd->scsi_psns & PSNS_REQ) ! 158: DELAY(1); ! 159: } ! 160: hd->scsi_scmd = SCMD_RST_ACK; ! 161: } ! 162: out: ! 163: /* ! 164: * Either the abort was successful & the bus is disconnected or ! 165: * the device didn't listen. If the latter, announce the problem. ! 166: * Either way, reset the card & the SPC. ! 167: */ ! 168: if (len < 0 && hs) ! 169: printf("scsi%d: abort failed. phase=0x%x, ssts=0x%x\n", ! 170: hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts); ! 171: ! 172: if (! ((junk = hd->scsi_ints) & INTS_RESEL)) { ! 173: hd->scsi_sctl |= SCTL_CTRLRST; ! 174: DELAY(1); ! 175: hd->scsi_sctl &=~ SCTL_CTRLRST; ! 176: hd->scsi_hconf = 0; ! 177: hd->scsi_ints = hd->scsi_ints; ! 178: } ! 179: } ! 180: ! 181: /* ! 182: * XXX Set/reset long delays. ! 183: * ! 184: * if delay == 0, reset default delays ! 185: * if delay < 0, set both delays to default long initialization values ! 186: * if delay > 0, set both delays to this value ! 187: * ! 188: * Used when a devices is expected to respond slowly (e.g. during ! 189: * initialization). ! 190: */ ! 191: void ! 192: scsi_delay(delay) ! 193: int delay; ! 194: { ! 195: static int saved_cmd_wait, saved_data_wait; ! 196: ! 197: if (delay) { ! 198: saved_cmd_wait = scsi_cmd_wait; ! 199: saved_data_wait = scsi_data_wait; ! 200: if (delay > 0) ! 201: scsi_cmd_wait = scsi_data_wait = delay; ! 202: else ! 203: scsi_cmd_wait = scsi_data_wait = scsi_init_wait; ! 204: } else { ! 205: scsi_cmd_wait = saved_cmd_wait; ! 206: scsi_data_wait = saved_data_wait; ! 207: } ! 208: } ! 209: ! 210: int ! 211: scsiinit(hc) ! 212: register struct hp_ctlr *hc; ! 213: { ! 214: register struct scsi_softc *hs = &scsi_softc[hc->hp_unit]; ! 215: register struct scsidevice *hd = (struct scsidevice *)hc->hp_addr; ! 216: ! 217: if ((hd->scsi_id & ID_MASK) != SCSI_ID) ! 218: return(0); ! 219: hc->hp_ipl = SCSI_IPL(hd->scsi_csr); ! 220: hs->sc_hc = hc; ! 221: hs->sc_dq.dq_unit = hc->hp_unit; ! 222: hs->sc_dq.dq_driver = &scsidriver; ! 223: hs->sc_sq.dq_forw = hs->sc_sq.dq_back = &hs->sc_sq; ! 224: scsi_isr[hc->hp_unit].isr_intr = scsiintr; ! 225: scsi_isr[hc->hp_unit].isr_ipl = hc->hp_ipl; ! 226: scsi_isr[hc->hp_unit].isr_arg = hc->hp_unit; ! 227: isrlink(&scsi_isr[hc->hp_unit]); ! 228: scsireset(hc->hp_unit); ! 229: return(1); ! 230: } ! 231: ! 232: void ! 233: scsireset(unit) ! 234: register int unit; ! 235: { ! 236: register struct scsi_softc *hs = &scsi_softc[unit]; ! 237: volatile register struct scsidevice *hd = ! 238: (struct scsidevice *)hs->sc_hc->hp_addr; ! 239: u_int i; ! 240: ! 241: if (hs->sc_flags & SCSI_ALIVE) ! 242: scsiabort(hs, hd, "reset"); ! 243: ! 244: printf("scsi%d: ", unit); ! 245: ! 246: hd->scsi_id = 0xFF; ! 247: DELAY(100); ! 248: /* ! 249: * Disable interrupts then reset the FUJI chip. ! 250: */ ! 251: hd->scsi_csr = 0; ! 252: hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; ! 253: hd->scsi_scmd = 0; ! 254: hd->scsi_tmod = 0; ! 255: hd->scsi_pctl = 0; ! 256: hd->scsi_temp = 0; ! 257: hd->scsi_tch = 0; ! 258: hd->scsi_tcm = 0; ! 259: hd->scsi_tcl = 0; ! 260: hd->scsi_ints = 0; ! 261: ! 262: if ((hd->scsi_id & ID_WORD_DMA) == 0) { ! 263: hs->sc_flags |= SCSI_DMA32; ! 264: printf("32 bit dma, "); ! 265: } ! 266: ! 267: /* Determine Max Synchronous Transfer Rate */ ! 268: if (scsi_nosync) ! 269: i = 3; ! 270: else ! 271: i = SCSI_SYNC_XFER(hd->scsi_hconf); ! 272: switch (i) { ! 273: case 0: ! 274: hs->sc_sync = TMOD_SYNC | 0x3e; /* 250 nsecs */ ! 275: printf("250ns sync"); ! 276: break; ! 277: case 1: ! 278: hs->sc_sync = TMOD_SYNC | 0x5e; /* 375 nsecs */ ! 279: printf("375ns sync"); ! 280: break; ! 281: case 2: ! 282: hs->sc_sync = TMOD_SYNC | 0x7d; /* 500 nsecs */ ! 283: printf("500ns sync"); ! 284: break; ! 285: case 3: ! 286: hs->sc_sync = 0; ! 287: printf("async"); ! 288: break; ! 289: } ! 290: ! 291: /* ! 292: * Configure the FUJI chip with its SCSI address, all ! 293: * interrupts enabled & appropriate parity. ! 294: */ ! 295: i = (~hd->scsi_hconf) & 0x7; ! 296: hs->sc_scsi_addr = 1 << i; ! 297: hd->scsi_bdid = i; ! 298: if (hd->scsi_hconf & HCONF_PARITY) ! 299: hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | ! 300: SCTL_SEL_ENAB | SCTL_RESEL_ENAB | ! 301: SCTL_INTR_ENAB | SCTL_PARITY_ENAB; ! 302: else { ! 303: hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | ! 304: SCTL_SEL_ENAB | SCTL_RESEL_ENAB | ! 305: SCTL_INTR_ENAB; ! 306: printf(", no parity"); ! 307: } ! 308: hd->scsi_sctl &=~ SCTL_DISABLE; ! 309: ! 310: printf(", scsi id %d\n", i); ! 311: hs->sc_flags |= SCSI_ALIVE; ! 312: } ! 313: ! 314: static void ! 315: scsierror(hs, hd, ints) ! 316: register struct scsi_softc *hs; ! 317: volatile register struct scsidevice *hd; ! 318: u_char ints; ! 319: { ! 320: int unit = hs->sc_hc->hp_unit; ! 321: char *sep = ""; ! 322: ! 323: printf("scsi%d: ", unit); ! 324: if (ints & INTS_RST) { ! 325: DELAY(100); ! 326: if (hd->scsi_hconf & HCONF_SD) ! 327: printf("spurious RST interrupt"); ! 328: else ! 329: printf("hardware error - check fuse"); ! 330: sep = ", "; ! 331: } ! 332: if ((ints & INTS_HARD_ERR) || hd->scsi_serr) { ! 333: if (hd->scsi_serr & SERR_SCSI_PAR) { ! 334: printf("%sparity err", sep); ! 335: sep = ", "; ! 336: } ! 337: if (hd->scsi_serr & SERR_SPC_PAR) { ! 338: printf("%sSPC parity err", sep); ! 339: sep = ", "; ! 340: } ! 341: if (hd->scsi_serr & SERR_TC_PAR) { ! 342: printf("%sTC parity err", sep); ! 343: sep = ", "; ! 344: } ! 345: if (hd->scsi_serr & SERR_PHASE_ERR) { ! 346: printf("%sphase err", sep); ! 347: sep = ", "; ! 348: } ! 349: if (hd->scsi_serr & SERR_SHORT_XFR) { ! 350: printf("%ssync short transfer err", sep); ! 351: sep = ", "; ! 352: } ! 353: if (hd->scsi_serr & SERR_OFFSET) { ! 354: printf("%ssync offset error", sep); ! 355: sep = ", "; ! 356: } ! 357: } ! 358: if (ints & INTS_TIMEOUT) ! 359: printf("%sSPC select timeout error", sep); ! 360: if (ints & INTS_SRV_REQ) ! 361: printf("%sspurious SRV_REQ interrupt", sep); ! 362: if (ints & INTS_CMD_DONE) ! 363: printf("%sspurious CMD_DONE interrupt", sep); ! 364: if (ints & INTS_DISCON) ! 365: printf("%sspurious disconnect interrupt", sep); ! 366: if (ints & INTS_RESEL) ! 367: printf("%sspurious reselect interrupt", sep); ! 368: if (ints & INTS_SEL) ! 369: printf("%sspurious select interrupt", sep); ! 370: printf("\n"); ! 371: } ! 372: ! 373: static int ! 374: issue_select(hd, target, our_addr) ! 375: volatile register struct scsidevice *hd; ! 376: u_char target, our_addr; ! 377: { ! 378: if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) ! 379: return (1); ! 380: ! 381: if (hd->scsi_ints & INTS_DISCON) ! 382: hd->scsi_ints = INTS_DISCON; ! 383: ! 384: hd->scsi_pctl = 0; ! 385: hd->scsi_temp = (1 << target) | our_addr; ! 386: /* select timeout is hardcoded to 2ms */ ! 387: hd->scsi_tch = 0; ! 388: hd->scsi_tcm = 32; ! 389: hd->scsi_tcl = 4; ! 390: ! 391: hd->scsi_scmd = SCMD_SELECT; ! 392: return (0); ! 393: } ! 394: ! 395: static int ! 396: wait_for_select(hd) ! 397: volatile register struct scsidevice *hd; ! 398: { ! 399: u_char ints; ! 400: ! 401: while ((ints = hd->scsi_ints) == 0) ! 402: DELAY(1); ! 403: hd->scsi_ints = ints; ! 404: return (!(hd->scsi_ssts & SSTS_INITIATOR)); ! 405: } ! 406: ! 407: static int ! 408: ixfer_start(hd, len, phase, wait) ! 409: volatile register struct scsidevice *hd; ! 410: int len; ! 411: u_char phase; ! 412: register int wait; ! 413: { ! 414: ! 415: hd->scsi_tch = len >> 16; ! 416: hd->scsi_tcm = len >> 8; ! 417: hd->scsi_tcl = len; ! 418: hd->scsi_pctl = phase; ! 419: hd->scsi_tmod = 0; /*XXX*/ ! 420: hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; ! 421: ! 422: /* wait for xfer to start or svc_req interrupt */ ! 423: while ((hd->scsi_ssts & SSTS_BUSY) == 0) { ! 424: if (hd->scsi_ints || --wait < 0) { ! 425: #ifdef DEBUG ! 426: if (scsi_debug) ! 427: printf("ixfer_start fail: i%x, w%d\n", ! 428: hd->scsi_ints, wait); ! 429: #endif ! 430: HIST(ixstart_wait, wait) ! 431: return (0); ! 432: } ! 433: DELAY(1); ! 434: } ! 435: HIST(ixstart_wait, wait) ! 436: return (1); ! 437: } ! 438: ! 439: static int ! 440: ixfer_out(hd, len, buf) ! 441: volatile register struct scsidevice *hd; ! 442: int len; ! 443: register u_char *buf; ! 444: { ! 445: register int wait = scsi_data_wait; ! 446: ! 447: for (; len > 0; --len) { ! 448: while (hd->scsi_ssts & SSTS_DREG_FULL) { ! 449: if (hd->scsi_ints || --wait < 0) { ! 450: #ifdef DEBUG ! 451: if (scsi_debug) ! 452: printf("ixfer_out fail: l%d i%x w%d\n", ! 453: len, hd->scsi_ints, wait); ! 454: #endif ! 455: HIST(ixout_wait, wait) ! 456: return (len); ! 457: } ! 458: DELAY(1); ! 459: } ! 460: hd->scsi_dreg = *buf++; ! 461: } ! 462: HIST(ixout_wait, wait) ! 463: return (0); ! 464: } ! 465: ! 466: static void ! 467: ixfer_in(hd, len, buf) ! 468: volatile register struct scsidevice *hd; ! 469: int len; ! 470: register u_char *buf; ! 471: { ! 472: register int wait = scsi_data_wait; ! 473: ! 474: for (; len > 0; --len) { ! 475: while (hd->scsi_ssts & SSTS_DREG_EMPTY) { ! 476: if (hd->scsi_ints || --wait < 0) { ! 477: while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) { ! 478: *buf++ = hd->scsi_dreg; ! 479: --len; ! 480: } ! 481: #ifdef DEBUG ! 482: if (scsi_debug) ! 483: printf("ixfer_in fail: l%d i%x w%d\n", ! 484: len, hd->scsi_ints, wait); ! 485: #endif ! 486: HIST(ixin_wait, wait) ! 487: return; ! 488: } ! 489: DELAY(1); ! 490: } ! 491: *buf++ = hd->scsi_dreg; ! 492: } ! 493: HIST(ixin_wait, wait) ! 494: } ! 495: ! 496: static int ! 497: mxfer_in(hd, len, buf, phase) ! 498: volatile register struct scsidevice *hd; ! 499: register int len; ! 500: register u_char *buf; ! 501: register u_char phase; ! 502: { ! 503: register int wait = scsi_cmd_wait; ! 504: register int i; ! 505: ! 506: hd->scsi_tmod = 0; ! 507: for (i = 0; i < len; ++i) { ! 508: /* ! 509: * manual sez: reset ATN before ACK is sent. ! 510: */ ! 511: if (hd->scsi_psns & PSNS_ATN) ! 512: hd->scsi_scmd = SCMD_RST_ATN; ! 513: /* ! 514: * wait for the request line (which says the target ! 515: * wants to give us data). If the phase changes while ! 516: * we're waiting, we're done. ! 517: */ ! 518: while ((hd->scsi_psns & PSNS_REQ) == 0) { ! 519: if (--wait < 0) { ! 520: HIST(mxin_wait, wait) ! 521: return (-1); ! 522: } ! 523: if ((hd->scsi_psns & PHASE) != phase || ! 524: (hd->scsi_ssts & SSTS_INITIATOR) == 0) ! 525: goto out; ! 526: ! 527: DELAY(1); ! 528: } ! 529: /* ! 530: * set ack (which says we're ready for the data, wait for ! 531: * req to go away (target says data is available), grab the ! 532: * data, then reset ack (say we've got the data). ! 533: */ ! 534: hd->scsi_pctl = phase; ! 535: hd->scsi_scmd = SCMD_SET_ACK; ! 536: while (hd->scsi_psns & PSNS_REQ) { ! 537: if (--wait < 0) { ! 538: HIST(mxin_wait, wait) ! 539: return (-2); ! 540: } ! 541: DELAY(1); ! 542: } ! 543: *buf++ = hd->scsi_temp; ! 544: hd->scsi_scmd = SCMD_RST_ACK; ! 545: } ! 546: out: ! 547: HIST(mxin_wait, wait) ! 548: /* ! 549: * Wait for manual transfer to finish. ! 550: * Avoids occasional "unexpected phase" errors in finishxfer ! 551: * formerly addressed by per-slave delays. ! 552: */ ! 553: wait = scsi_cmd_wait; ! 554: while ((hd->scsi_ssts & SSTS_ACTIVE) == SSTS_INITIATOR) { ! 555: if (--wait < 0) ! 556: break; ! 557: DELAY(1); ! 558: } ! 559: HIST(mxin2_wait, wait) ! 560: return (i); ! 561: } ! 562: ! 563: /* ! 564: * SCSI 'immediate' command: issue a command to some SCSI device ! 565: * and get back an 'immediate' response (i.e., do programmed xfer ! 566: * to get the response data). 'cbuf' is a buffer containing a scsi ! 567: * command of length clen bytes. 'buf' is a buffer of length 'len' ! 568: * bytes for data. The transfer direction is determined by the device ! 569: * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the ! 570: * command must supply no data. 'xferphase' is the bus phase the ! 571: * caller expects to happen after the command is issued. It should ! 572: * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE. ! 573: */ ! 574: static int ! 575: scsiicmd(hs, target, cbuf, clen, buf, len, xferphase) ! 576: struct scsi_softc *hs; ! 577: int target; ! 578: u_char *cbuf; ! 579: int clen; ! 580: u_char *buf; ! 581: int len; ! 582: u_char xferphase; ! 583: { ! 584: volatile register struct scsidevice *hd = ! 585: (struct scsidevice *)hs->sc_hc->hp_addr; ! 586: u_char phase, ints; ! 587: register int wait; ! 588: ! 589: /* select the SCSI bus (it's an error if bus isn't free) */ ! 590: if (issue_select(hd, target, hs->sc_scsi_addr)) ! 591: return (-1); ! 592: if (wait_for_select(hd)) ! 593: return (-1); ! 594: /* ! 595: * Wait for a phase change (or error) then let the device ! 596: * sequence us through the various SCSI phases. ! 597: */ ! 598: hs->sc_stat[0] = 0xff; ! 599: hs->sc_msg[0] = 0xff; ! 600: phase = CMD_PHASE; ! 601: while (1) { ! 602: wait = scsi_cmd_wait; ! 603: switch (phase) { ! 604: ! 605: case CMD_PHASE: ! 606: if (ixfer_start(hd, clen, phase, wait)) ! 607: if (ixfer_out(hd, clen, cbuf)) ! 608: goto abort; ! 609: phase = xferphase; ! 610: break; ! 611: ! 612: case DATA_IN_PHASE: ! 613: if (len <= 0) ! 614: goto abort; ! 615: wait = scsi_data_wait; ! 616: if (ixfer_start(hd, len, phase, wait) || ! 617: !(hd->scsi_ssts & SSTS_DREG_EMPTY)) ! 618: ixfer_in(hd, len, buf); ! 619: phase = STATUS_PHASE; ! 620: break; ! 621: ! 622: case DATA_OUT_PHASE: ! 623: if (len <= 0) ! 624: goto abort; ! 625: wait = scsi_data_wait; ! 626: if (ixfer_start(hd, len, phase, wait)) { ! 627: if (ixfer_out(hd, len, buf)) ! 628: goto abort; ! 629: } ! 630: phase = STATUS_PHASE; ! 631: break; ! 632: ! 633: case STATUS_PHASE: ! 634: wait = scsi_data_wait; ! 635: if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) || ! 636: !(hd->scsi_ssts & SSTS_DREG_EMPTY)) ! 637: ixfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat); ! 638: phase = MESG_IN_PHASE; ! 639: break; ! 640: ! 641: case MESG_IN_PHASE: ! 642: if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) || ! 643: !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { ! 644: ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg); ! 645: hd->scsi_scmd = SCMD_RST_ACK; ! 646: } ! 647: phase = BUS_FREE_PHASE; ! 648: break; ! 649: ! 650: case BUS_FREE_PHASE: ! 651: goto out; ! 652: ! 653: default: ! 654: printf("scsi%d: unexpected phase %d in icmd from %d\n", ! 655: hs->sc_hc->hp_unit, phase, target); ! 656: goto abort; ! 657: } ! 658: /* wait for last command to complete */ ! 659: while ((ints = hd->scsi_ints) == 0) { ! 660: if (--wait < 0) { ! 661: HIST(cxin_wait, wait) ! 662: goto abort; ! 663: } ! 664: DELAY(1); ! 665: } ! 666: HIST(cxin_wait, wait) ! 667: hd->scsi_ints = ints; ! 668: if (ints & INTS_SRV_REQ) ! 669: phase = hd->scsi_psns & PHASE; ! 670: else if (ints & INTS_DISCON) ! 671: goto out; ! 672: else if ((ints & INTS_CMD_DONE) == 0) { ! 673: scsierror(hs, hd, ints); ! 674: goto abort; ! 675: } ! 676: } ! 677: abort: ! 678: scsiabort(hs, hd, "icmd"); ! 679: out: ! 680: return (hs->sc_stat[0]); ! 681: } ! 682: ! 683: /* ! 684: * Finish SCSI xfer command: After the completion interrupt from ! 685: * a read/write operation, sequence through the final phases in ! 686: * programmed i/o. This routine is a lot like scsiicmd except we ! 687: * skip (and don't allow) the select, cmd out and data in/out phases. ! 688: */ ! 689: static void ! 690: finishxfer(hs, hd, target) ! 691: struct scsi_softc *hs; ! 692: volatile register struct scsidevice *hd; ! 693: int target; ! 694: { ! 695: u_char phase, ints; ! 696: ! 697: /* ! 698: * We specified padding xfer so we ended with either a phase ! 699: * change interrupt (normal case) or an error interrupt (handled ! 700: * elsewhere). Reset the board dma logic then try to get the ! 701: * completion status & command done msg. The reset confuses ! 702: * the SPC REQ/ACK logic so we have to do any status/msg input ! 703: * operations via 'manual xfer'. ! 704: */ ! 705: if (hd->scsi_ssts & SSTS_BUSY) { ! 706: int wait = scsi_cmd_wait; ! 707: ! 708: /* wait for dma operation to finish */ ! 709: while (hd->scsi_ssts & SSTS_BUSY) { ! 710: if (--wait < 0) { ! 711: #ifdef DEBUG ! 712: if (scsi_debug) ! 713: printf("finishxfer fail: ssts %x\n", ! 714: hd->scsi_ssts); ! 715: #endif ! 716: HIST(fxfr_wait, wait) ! 717: goto abort; ! 718: } ! 719: } ! 720: HIST(fxfr_wait, wait) ! 721: } ! 722: hd->scsi_scmd |= SCMD_PROG_XFR; ! 723: hd->scsi_sctl |= SCTL_CTRLRST; ! 724: DELAY(1); ! 725: hd->scsi_sctl &=~ SCTL_CTRLRST; ! 726: hd->scsi_hconf = 0; ! 727: hs->sc_stat[0] = 0xff; ! 728: hs->sc_msg[0] = 0xff; ! 729: hd->scsi_csr = 0; ! 730: hd->scsi_ints = ints = hd->scsi_ints; ! 731: while (1) { ! 732: phase = hd->scsi_psns & PHASE; ! 733: switch (phase) { ! 734: ! 735: case STATUS_PHASE: ! 736: if (mxfer_in(hd, sizeof(hs->sc_stat), hs->sc_stat, ! 737: phase) <= 0) ! 738: goto abort; ! 739: break; ! 740: ! 741: case MESG_IN_PHASE: ! 742: if (mxfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg, ! 743: phase) < 0) ! 744: goto abort; ! 745: break; ! 746: ! 747: case BUS_FREE_PHASE: ! 748: return; ! 749: ! 750: default: ! 751: printf("scsi%d: unexpected phase %d in finishxfer from %d\n", ! 752: hs->sc_hc->hp_unit, phase, target); ! 753: goto abort; ! 754: } ! 755: if (ints = hd->scsi_ints) { ! 756: hd->scsi_ints = ints; ! 757: if (ints & INTS_DISCON) ! 758: return; ! 759: else if (ints & ~(INTS_SRV_REQ|INTS_CMD_DONE)) { ! 760: scsierror(hs, hd, ints); ! 761: break; ! 762: } ! 763: } ! 764: if ((hd->scsi_ssts & SSTS_INITIATOR) == 0) ! 765: return; ! 766: } ! 767: abort: ! 768: scsiabort(hs, hd, "finishxfer"); ! 769: hs->sc_stat[0] = 0xfe; ! 770: } ! 771: ! 772: int ! 773: scsi_test_unit_rdy(ctlr, slave, unit) ! 774: int ctlr, slave, unit; ! 775: { ! 776: register struct scsi_softc *hs = &scsi_softc[ctlr]; ! 777: static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY }; ! 778: ! 779: cdb.lun = unit; ! 780: return (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0, ! 781: STATUS_PHASE)); ! 782: } ! 783: ! 784: int ! 785: scsi_request_sense(ctlr, slave, unit, buf, len) ! 786: int ctlr, slave, unit; ! 787: u_char *buf; ! 788: unsigned len; ! 789: { ! 790: register struct scsi_softc *hs = &scsi_softc[ctlr]; ! 791: static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE }; ! 792: ! 793: cdb.lun = unit; ! 794: cdb.len = len; ! 795: return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE)); ! 796: } ! 797: ! 798: int ! 799: scsi_immed_command(ctlr, slave, unit, cdb, buf, len, rd) ! 800: int ctlr, slave, unit; ! 801: struct scsi_fmt_cdb *cdb; ! 802: u_char *buf; ! 803: unsigned len; ! 804: { ! 805: register struct scsi_softc *hs = &scsi_softc[ctlr]; ! 806: ! 807: cdb->cdb[1] |= unit << 5; ! 808: return (scsiicmd(hs, slave, cdb->cdb, cdb->len, buf, len, ! 809: rd != 0? DATA_IN_PHASE : DATA_OUT_PHASE)); ! 810: } ! 811: ! 812: /* ! 813: * The following routines are test-and-transfer i/o versions of read/write ! 814: * for things like reading disk labels and writing core dumps. The ! 815: * routine scsigo should be used for normal data transfers, NOT these ! 816: * routines. ! 817: */ ! 818: int ! 819: scsi_tt_read(ctlr, slave, unit, buf, len, blk, bshift) ! 820: int ctlr, slave, unit; ! 821: u_char *buf; ! 822: u_int len; ! 823: daddr_t blk; ! 824: int bshift; ! 825: { ! 826: register struct scsi_softc *hs = &scsi_softc[ctlr]; ! 827: struct scsi_cdb10 cdb; ! 828: int stat; ! 829: int old_wait = scsi_data_wait; ! 830: ! 831: scsi_data_wait = 300000; ! 832: bzero(&cdb, sizeof(cdb)); ! 833: cdb.cmd = CMD_READ_EXT; ! 834: cdb.lun = unit; ! 835: blk >>= bshift; ! 836: cdb.lbah = blk >> 24; ! 837: cdb.lbahm = blk >> 16; ! 838: cdb.lbalm = blk >> 8; ! 839: cdb.lbal = blk; ! 840: cdb.lenh = len >> (8 + DEV_BSHIFT + bshift); ! 841: cdb.lenl = len >> (DEV_BSHIFT + bshift); ! 842: stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE); ! 843: scsi_data_wait = old_wait; ! 844: return (stat); ! 845: } ! 846: ! 847: int ! 848: scsi_tt_write(ctlr, slave, unit, buf, len, blk, bshift) ! 849: int ctlr, slave, unit; ! 850: u_char *buf; ! 851: u_int len; ! 852: daddr_t blk; ! 853: int bshift; ! 854: { ! 855: register struct scsi_softc *hs = &scsi_softc[ctlr]; ! 856: struct scsi_cdb10 cdb; ! 857: int stat; ! 858: int old_wait = scsi_data_wait; ! 859: ! 860: scsi_data_wait = 300000; ! 861: ! 862: bzero(&cdb, sizeof(cdb)); ! 863: cdb.cmd = CMD_WRITE_EXT; ! 864: cdb.lun = unit; ! 865: blk >>= bshift; ! 866: cdb.lbah = blk >> 24; ! 867: cdb.lbahm = blk >> 16; ! 868: cdb.lbalm = blk >> 8; ! 869: cdb.lbal = blk; ! 870: cdb.lenh = len >> (8 + DEV_BSHIFT + bshift); ! 871: cdb.lenl = len >> (DEV_BSHIFT + bshift); ! 872: stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE); ! 873: scsi_data_wait = old_wait; ! 874: return (stat); ! 875: } ! 876: ! 877: int ! 878: scsireq(dq) ! 879: register struct devqueue *dq; ! 880: { ! 881: register struct devqueue *hq; ! 882: ! 883: hq = &scsi_softc[dq->dq_ctlr].sc_sq; ! 884: insque(dq, hq->dq_back); ! 885: if (dq->dq_back == hq) ! 886: return(1); ! 887: return(0); ! 888: } ! 889: ! 890: int ! 891: scsiustart(unit) ! 892: int unit; ! 893: { ! 894: register struct scsi_softc *hs = &scsi_softc[unit]; ! 895: ! 896: hs->sc_dq.dq_ctlr = DMA0 | DMA1; ! 897: if (dmareq(&hs->sc_dq)) ! 898: return(1); ! 899: return(0); ! 900: } ! 901: ! 902: void ! 903: scsistart(unit) ! 904: int unit; ! 905: { ! 906: register struct devqueue *dq; ! 907: ! 908: dq = scsi_softc[unit].sc_sq.dq_forw; ! 909: (dq->dq_driver->d_go)(dq->dq_unit); ! 910: } ! 911: ! 912: int ! 913: scsigo(ctlr, slave, unit, bp, cdb, pad) ! 914: int ctlr, slave, unit; ! 915: struct buf *bp; ! 916: struct scsi_fmt_cdb *cdb; ! 917: int pad; ! 918: { ! 919: register struct scsi_softc *hs = &scsi_softc[ctlr]; ! 920: volatile register struct scsidevice *hd = ! 921: (struct scsidevice *)hs->sc_hc->hp_addr; ! 922: int i, dmaflags; ! 923: u_char phase, ints, cmd; ! 924: ! 925: cdb->cdb[1] |= unit << 5; ! 926: ! 927: /* select the SCSI bus (it's an error if bus isn't free) */ ! 928: if (issue_select(hd, slave, hs->sc_scsi_addr) || wait_for_select(hd)) { ! 929: dmafree(&hs->sc_dq); ! 930: return (1); ! 931: } ! 932: /* ! 933: * Wait for a phase change (or error) then let the device ! 934: * sequence us through command phase (we may have to take ! 935: * a msg in/out before doing the command). If the disk has ! 936: * to do a seek, it may be a long time until we get a change ! 937: * to data phase so, in the absense of an explicit phase ! 938: * change, we assume data phase will be coming up and tell ! 939: * the SPC to start a transfer whenever it does. We'll get ! 940: * a service required interrupt later if this assumption is ! 941: * wrong. Otherwise we'll get a service required int when ! 942: * the transfer changes to status phase. ! 943: */ ! 944: phase = CMD_PHASE; ! 945: while (1) { ! 946: register int wait = scsi_cmd_wait; ! 947: ! 948: switch (phase) { ! 949: ! 950: case CMD_PHASE: ! 951: if (ixfer_start(hd, cdb->len, phase, wait)) ! 952: if (ixfer_out(hd, cdb->len, cdb->cdb)) ! 953: goto abort; ! 954: break; ! 955: ! 956: case MESG_IN_PHASE: ! 957: if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait)|| ! 958: !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { ! 959: ixfer_in(hd, sizeof(hs->sc_msg), hs->sc_msg); ! 960: hd->scsi_scmd = SCMD_RST_ACK; ! 961: } ! 962: phase = BUS_FREE_PHASE; ! 963: break; ! 964: ! 965: case DATA_IN_PHASE: ! 966: case DATA_OUT_PHASE: ! 967: goto out; ! 968: ! 969: default: ! 970: printf("scsi%d: unexpected phase %d in go from %d\n", ! 971: hs->sc_hc->hp_unit, phase, slave); ! 972: goto abort; ! 973: } ! 974: while ((ints = hd->scsi_ints) == 0) { ! 975: if (--wait < 0) { ! 976: HIST(sgo_wait, wait) ! 977: goto abort; ! 978: } ! 979: DELAY(1); ! 980: } ! 981: HIST(sgo_wait, wait) ! 982: hd->scsi_ints = ints; ! 983: if (ints & INTS_SRV_REQ) ! 984: phase = hd->scsi_psns & PHASE; ! 985: else if (ints & INTS_CMD_DONE) ! 986: goto out; ! 987: else { ! 988: scsierror(hs, hd, ints); ! 989: goto abort; ! 990: } ! 991: } ! 992: out: ! 993: /* ! 994: * Reset the card dma logic, setup the dma channel then ! 995: * get the dio part of the card set for a dma xfer. ! 996: */ ! 997: hd->scsi_hconf = 0; ! 998: cmd = CSR_IE; ! 999: dmaflags = DMAGO_NOINT; ! 1000: if (scsi_pridma) ! 1001: dmaflags |= DMAGO_PRI; ! 1002: if (bp->b_flags & B_READ) ! 1003: dmaflags |= DMAGO_READ; ! 1004: if ((hs->sc_flags & SCSI_DMA32) && ! 1005: ((int)bp->b_un.b_addr & 3) == 0 && (bp->b_bcount & 3) == 0) { ! 1006: cmd |= CSR_DMA32; ! 1007: dmaflags |= DMAGO_LWORD; ! 1008: } else ! 1009: dmaflags |= DMAGO_WORD; ! 1010: dmago(hs->sc_dq.dq_ctlr, bp->b_un.b_addr, bp->b_bcount, dmaflags); ! 1011: ! 1012: if (bp->b_flags & B_READ) { ! 1013: cmd |= CSR_DMAIN; ! 1014: phase = DATA_IN_PHASE; ! 1015: } else ! 1016: phase = DATA_OUT_PHASE; ! 1017: /* ! 1018: * DMA enable bits must be set after size and direction bits. ! 1019: */ ! 1020: hd->scsi_csr = cmd; ! 1021: hd->scsi_csr |= (CSR_DE0 << hs->sc_dq.dq_ctlr); ! 1022: /* ! 1023: * Setup the SPC for the transfer. We don't want to take ! 1024: * first a command complete then a service required interrupt ! 1025: * at the end of the transfer so we try to disable the cmd ! 1026: * complete by setting the transfer counter to more bytes ! 1027: * than we expect. (XXX - This strategy may have to be ! 1028: * modified to deal with devices that return variable length ! 1029: * blocks, e.g., some tape drives.) ! 1030: */ ! 1031: cmd = SCMD_XFR; ! 1032: i = (unsigned)bp->b_bcount; ! 1033: if (pad) { ! 1034: cmd |= SCMD_PAD; ! 1035: /* ! 1036: * XXX - If we don't do this, the last 2 or 4 bytes ! 1037: * (depending on word/lword DMA) of a read get trashed. ! 1038: * It looks like it is necessary for the DMA to complete ! 1039: * before the SPC goes into "pad mode"??? Note: if we ! 1040: * also do this on a write, the request never completes. ! 1041: */ ! 1042: if (bp->b_flags & B_READ) ! 1043: i += 2; ! 1044: #ifdef DEBUG ! 1045: hs->sc_flags |= SCSI_PAD; ! 1046: if (i & 1) ! 1047: printf("scsi%d: odd byte count: %d bytes @ %d\n", ! 1048: ctlr, i, bp->b_cylin); ! 1049: #endif ! 1050: } else ! 1051: i += 4; ! 1052: hd->scsi_tch = i >> 16; ! 1053: hd->scsi_tcm = i >> 8; ! 1054: hd->scsi_tcl = i; ! 1055: hd->scsi_pctl = phase; ! 1056: hd->scsi_tmod = 0; ! 1057: hd->scsi_scmd = cmd; ! 1058: hs->sc_flags |= SCSI_IO; ! 1059: return (0); ! 1060: abort: ! 1061: scsiabort(hs, hd, "go"); ! 1062: dmafree(&hs->sc_dq); ! 1063: return (1); ! 1064: } ! 1065: ! 1066: void ! 1067: scsidone(unit) ! 1068: register int unit; ! 1069: { ! 1070: volatile register struct scsidevice *hd = ! 1071: (struct scsidevice *)scsi_softc[unit].sc_hc->hp_addr; ! 1072: ! 1073: #ifdef DEBUG ! 1074: if (scsi_debug) ! 1075: printf("scsi%d: done called!\n"); ! 1076: #endif ! 1077: /* dma operation is done -- turn off card dma */ ! 1078: hd->scsi_csr &=~ (CSR_DE1|CSR_DE0); ! 1079: } ! 1080: ! 1081: int ! 1082: scsiintr(unit) ! 1083: register int unit; ! 1084: { ! 1085: register struct scsi_softc *hs = &scsi_softc[unit]; ! 1086: volatile register struct scsidevice *hd = ! 1087: (struct scsidevice *)hs->sc_hc->hp_addr; ! 1088: register u_char ints; ! 1089: register struct devqueue *dq; ! 1090: ! 1091: if ((hd->scsi_csr & (CSR_IE|CSR_IR)) != (CSR_IE|CSR_IR)) ! 1092: return (0); ! 1093: ! 1094: ints = hd->scsi_ints; ! 1095: if ((ints & INTS_SRV_REQ) && (hs->sc_flags & SCSI_IO)) { ! 1096: /* ! 1097: * this should be the normal i/o completion case. ! 1098: * get the status & cmd complete msg then let the ! 1099: * device driver look at what happened. ! 1100: */ ! 1101: #ifdef DEBUG ! 1102: int len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | ! 1103: hd->scsi_tcl; ! 1104: if (!(hs->sc_flags & SCSI_PAD)) ! 1105: len -= 4; ! 1106: hs->sc_flags &=~ SCSI_PAD; ! 1107: #endif ! 1108: dq = hs->sc_sq.dq_forw; ! 1109: finishxfer(hs, hd, dq->dq_slave); ! 1110: hs->sc_flags &=~ SCSI_IO; ! 1111: dmafree(&hs->sc_dq); ! 1112: (dq->dq_driver->d_intr)(dq->dq_unit, hs->sc_stat[0]); ! 1113: } else { ! 1114: /* Something unexpected happened -- deal with it. */ ! 1115: hd->scsi_ints = ints; ! 1116: hd->scsi_csr = 0; ! 1117: scsierror(hs, hd, ints); ! 1118: scsiabort(hs, hd, "intr"); ! 1119: if (hs->sc_flags & SCSI_IO) { ! 1120: hs->sc_flags &=~ SCSI_IO; ! 1121: dmafree(&hs->sc_dq); ! 1122: dq = hs->sc_sq.dq_forw; ! 1123: (dq->dq_driver->d_intr)(dq->dq_unit, -1); ! 1124: } ! 1125: } ! 1126: return(1); ! 1127: } ! 1128: ! 1129: void ! 1130: scsifree(dq) ! 1131: register struct devqueue *dq; ! 1132: { ! 1133: register struct devqueue *hq; ! 1134: ! 1135: hq = &scsi_softc[dq->dq_ctlr].sc_sq; ! 1136: remque(dq); ! 1137: if ((dq = hq->dq_forw) != hq) ! 1138: (dq->dq_driver->d_start)(dq->dq_unit); ! 1139: } ! 1140: ! 1141: /* ! 1142: * (XXX) The following routine is needed for the SCSI tape driver ! 1143: * to read odd-size records. ! 1144: */ ! 1145: ! 1146: #include "st.h" ! 1147: #if NST > 0 ! 1148: int ! 1149: scsi_tt_oddio(ctlr, slave, unit, buf, len, b_flags, freedma) ! 1150: int ctlr, slave, unit, b_flags; ! 1151: u_char *buf; ! 1152: u_int len; ! 1153: { ! 1154: register struct scsi_softc *hs = &scsi_softc[ctlr]; ! 1155: struct scsi_cdb6 cdb; ! 1156: u_char iphase; ! 1157: int stat; ! 1158: ! 1159: /* ! 1160: * First free any DMA channel that was allocated. ! 1161: * We can't use DMA to do this transfer. ! 1162: */ ! 1163: if (freedma) ! 1164: dmafree(hs->sc_dq); ! 1165: /* ! 1166: * Initialize command block ! 1167: */ ! 1168: bzero(&cdb, sizeof(cdb)); ! 1169: cdb.lun = unit; ! 1170: cdb.lbam = (len >> 16) & 0xff; ! 1171: cdb.lbal = (len >> 8) & 0xff; ! 1172: cdb.len = len & 0xff; ! 1173: if (buf == 0) { ! 1174: cdb.cmd = CMD_SPACE; ! 1175: cdb.lun |= 0x00; ! 1176: len = 0; ! 1177: iphase = MESG_IN_PHASE; ! 1178: } else if (b_flags & B_READ) { ! 1179: cdb.cmd = CMD_READ; ! 1180: iphase = DATA_IN_PHASE; ! 1181: } else { ! 1182: cdb.cmd = CMD_WRITE; ! 1183: iphase = DATA_OUT_PHASE; ! 1184: } ! 1185: /* ! 1186: * Perform command (with very long delays) ! 1187: */ ! 1188: scsi_delay(30000000); ! 1189: stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, iphase); ! 1190: scsi_delay(0); ! 1191: return (stat); ! 1192: } ! 1193: #endif ! 1194: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.