|
|
1.1 ! root 1: /* ! 2: * @(#)si.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc. ! 3: */ ! 4: #include <sys/types.h> ! 5: #include <sys/inode.h> ! 6: #include <sys/buf.h> ! 7: #include <sun/dklabel.h> ! 8: #include <sun/dkio.h> ! 9: #include <sundev/screg.h> ! 10: #include <sundev/sireg.h> ! 11: #include <sundev/scsi.h> ! 12: #include "saio.h" ! 13: #include <machine/sunromvec.h> ! 14: #include <machine/idprom.h> ! 15: ! 16: /* ! 17: * Low-level routines common to all devices on the SCSI bus. ! 18: */ ! 19: ! 20: /* ! 21: * Interface to the routines in this module is via a second "sip" ! 22: * structure contained in the caller's local variables. ! 23: * ! 24: * This "sip" must be initialized with sip->si_boottab = sidriver ! 25: * and must then be devopen()ed before any I/O can be done. ! 26: * ! 27: * The device must be closed with devclose(). ! 28: */ ! 29: ! 30: ! 31: /* how si addresses look to the si vme scsi dma hardware */ ! 32: #define SI_VME_DMA_ADDR(x) (((int)x)&0x000FFFFF) ! 33: ! 34: /* how si addresses look to the sun3/50 scsi dma hardware */ ! 35: #define SI_OB_DMA_ADDR(x) (((int)x)&0x00FFFFFF) ! 36: struct sidma { ! 37: struct udc_table udct; /* dma information for udc */ ! 38: }; ! 39: ! 40: /* ! 41: * The interfaces we export ! 42: */ ! 43: extern char *devalloc(); ! 44: extern char *resalloc(); ! 45: extern int nullsys(); ! 46: int siopen(); ! 47: ! 48: struct boottab sidriver = ! 49: {"sd", nullsys, nullsys, siopen, nullsys, ! 50: nullsys, "", 0}; ! 51: ! 52: ! 53: #define SI_VME_BASE 0x200000 ! 54: #define SI_OB_BASE 0x140000 ! 55: #define SI_SIZE 0x4000 ! 56: ! 57: /* ! 58: * Probe for si host adaptor interface. ! 59: * Return 1 if found one, 0 otherwise. ! 60: */ ! 61: int ! 62: siprobe(sip) ! 63: register struct saioreq *sip; ! 64: { ! 65: register struct scsi_si_reg *sir; ! 66: struct idprom id; ! 67: register int base; ! 68: register int scsi_nstd; ! 69: register int ctlr; ! 70: enum MAPTYPES space; ! 71: ! 72: /* determine type of si interface */ ! 73: if (idprom(IDFORM_1, &id) == IDFORM_1) { ! 74: if (id.id_machine == IDM_SUN3_M25) { ! 75: return (1); ! 76: } else { ! 77: base = SI_VME_BASE; ! 78: space = MAP_VME24A16D; ! 79: scsi_nstd = 2; ! 80: } ! 81: } else { ! 82: return (0); ! 83: } ! 84: ! 85: /* get base address of registers */ ! 86: if (sip->si_ctlr < scsi_nstd) { ! 87: ctlr = base + (sip->si_ctlr * SI_SIZE); ! 88: } else { ! 89: return (0); ! 90: } ! 91: ! 92: /* now map it in */ ! 93: if ((sir = (struct scsi_si_reg *)devalloc(space, ctlr, ! 94: sizeof(struct scsi_si_reg))) == 0) { ! 95: return (0); ! 96: } ! 97: ! 98: /* ! 99: * SI vme scsi host adaptor occupies 2K bytes in the vme ! 100: * address space. SC vme scsi host adaptor occupies 4K ! 101: * bytes in the vme address space. ! 102: * peek past 2K bytes to determine which host adaptor is there. ! 103: */ ! 104: if (peek((int)sir+0x800) == -1) { ! 105: return (1); ! 106: } else { ! 107: return (0); ! 108: } ! 109: } ! 110: ! 111: /* ! 112: * Open the SCSI host adapter. ! 113: */ ! 114: int ! 115: siopen(sip) ! 116: register struct saioreq *sip; ! 117: { ! 118: register struct scsi_si_reg *sir; ! 119: struct idprom id; ! 120: register int base; ! 121: register int scsi_nstd; ! 122: enum MAPTYPES space; ! 123: ! 124: /* determine type of si interface */ ! 125: if (idprom(IDFORM_1, &id) == IDFORM_1) { ! 126: if (id.id_machine == IDM_SUN3_M25) { ! 127: base = SI_OB_BASE; ! 128: space = MAP_OBIO; ! 129: scsi_nstd = 1; ! 130: } else { ! 131: base = SI_VME_BASE; ! 132: space = MAP_VME24A16D; ! 133: scsi_nstd = 2; ! 134: } ! 135: } else { ! 136: return (-1); ! 137: } ! 138: ! 139: /* get base address of registers */ ! 140: if (sip->si_ctlr < scsi_nstd) { ! 141: sip->si_ctlr = base + (sip->si_ctlr * SI_SIZE); ! 142: } else { ! 143: return (-1); ! 144: } ! 145: ! 146: /* now map it in */ ! 147: sip->si_devaddr = devalloc(space, sip->si_ctlr, ! 148: sizeof(struct scsi_si_reg)); ! 149: if (sip->si_devaddr == 0) { ! 150: return (-1); ! 151: } ! 152: ! 153: /* allocate dma resources */ ! 154: if (base == SI_OB_BASE) { ! 155: sip->si_dmaaddr = resalloc(RES_DMAMEM, sizeof(struct sidma)); ! 156: if (sip->si_dmaaddr == 0) { ! 157: return (-1); ! 158: } ! 159: } else { ! 160: sip->si_dmaaddr = 0; ! 161: } ! 162: ! 163: /* reset registers */ ! 164: sir = (struct scsi_si_reg *) sip->si_devaddr; ! 165: sir->csr = 0; ! 166: DELAY(10); ! 167: sir->csr = SI_CSR_SCSI_RES | SI_CSR_FIFO_RES; ! 168: sir->bcr = 0; ! 169: if (base == SI_VME_BASE) { ! 170: sir->dma_addr = 0; ! 171: sir->dma_count = 0; ! 172: sir->iv_am = VME_SUPV_DATA_24; ! 173: } ! 174: return (0); ! 175: } ! 176: ! 177: ! 178: /* ! 179: * Write a command to the SCSI bus. ! 180: * ! 181: * The supplied sip is the one opened by siopen(). ! 182: * DMA is done based on sip->si_ma and sip->si_cc. ! 183: * ! 184: * Returns -1 for error, otherwise returns the residual count not DMAed ! 185: * (zero for success). ! 186: * ! 187: * FIXME, this must be accessed via a boottab vector, ! 188: * to allow host adap to switch. ! 189: * Must pass cdb, scb in sip somewhere... ! 190: */ ! 191: int ! 192: sidoit(cdb, scb, sip) ! 193: struct scsi_cdb *cdb; ! 194: struct scsi_scb *scb; ! 195: register struct saioreq *sip; ! 196: { ! 197: register struct scsi_si_reg *sir; ! 198: register char *cp; ! 199: register int i; ! 200: register int b; ! 201: register int ob; ! 202: u_char junk; ! 203: ! 204: /* get to scsi control logic registers */ ! 205: sir = (struct scsi_si_reg *) sip->si_devaddr; ! 206: if (sip->si_dmaaddr) { ! 207: ob = 1; ! 208: } else { ! 209: ob = 0; ! 210: } ! 211: ! 212: i = 100000; ! 213: for(;;) { ! 214: if ((sir->sbc_rreg.cbsr & SBC_CBSR_BSY) == 0) { ! 215: break; ! 216: } ! 217: if (i-- <= 0) { ! 218: si_reset(sir, ob); ! 219: return (-1); ! 220: } ! 221: } ! 222: ! 223: /* select target */ ! 224: sir->sbc_wreg.odr = (1 << sip->si_unit) | SI_HOST_ID; ! 225: sir->sbc_wreg.icr = SBC_ICR_DATA; ! 226: sir->sbc_wreg.icr |= SBC_ICR_SEL; ! 227: ! 228: /* wait for target to acknowledge our selection */ ! 229: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_BSY, 1) == 0) { ! 230: sc_error("sel, cbsr bsy never set"); ! 231: goto failed; ! 232: } ! 233: sir->sbc_wreg.icr = 0; ! 234: ! 235: /* do initial dma setup */ ! 236: sir->bcr = 0; /* also reset dma_count for vme */ ! 237: if (sip->si_cc > 0) { ! 238: if ((cdb->cmd == SC_READ) || (cdb->cmd == SC_REQUEST_SENSE)) { ! 239: sir->csr &= ~SI_CSR_SEND; ! 240: } else { ! 241: sir->csr |= SI_CSR_SEND; ! 242: } ! 243: sir->csr &= ~SI_CSR_FIFO_RES; ! 244: sir->csr |= SI_CSR_FIFO_RES; ! 245: sir->bcr = sip->si_cc; ! 246: if (ob == 0) ! 247: sir->bcrh = 0; ! 248: } ! 249: ! 250: /* put command onto scsi bus */ ! 251: cp = (char *)cdb; ! 252: if (si_putbyte(sir, PHASE_COMMAND, cp, sizeof(struct scsi_cdb)) == 0) { ! 253: sc_error("put of cmd onto scsi bus failed"); ! 254: goto failed; ! 255: } ! 256: ! 257: /* finish dma setup and wait for dma completion */ ! 258: if (sip->si_cc > 0) { ! 259: if (ob) { ! 260: si_ob_dma_setup(sir, ! 261: &(((struct sidma *)sip->si_dmaaddr)->udct), cdb->cmd, ! 262: sip->si_cc, sip->si_ma); ! 263: } else { ! 264: if ((int)sip->si_ma & 1) { ! 265: sc_error("dma begins on odd address"); ! 266: goto failed; ! 267: } else if ((int)sip->si_ma & 2) { ! 268: sir->csr |= SI_CSR_BPCON; ! 269: } else { ! 270: sir->csr &= ~SI_CSR_BPCON; ! 271: } ! 272: sir->dma_addr = SI_VME_DMA_ADDR(sip->si_ma); ! 273: sir->dma_count = sip->si_cc; ! 274: } ! 275: ! 276: /* setup sbc and start dma */ ! 277: sir->sbc_wreg.mr |= SBC_MR_DMA; ! 278: if ((cdb->cmd == SC_READ) || (cdb->cmd == SC_REQUEST_SENSE)) { ! 279: sir->sbc_wreg.tcr = TCR_DATA_IN; ! 280: sir->sbc_wreg.ircv = 0; ! 281: } else { ! 282: sir->sbc_wreg.tcr = TCR_DATA_OUT; ! 283: sir->sbc_wreg.icr = SBC_ICR_DATA; ! 284: sir->sbc_wreg.send = 0; ! 285: } ! 286: if (ob == 0) { ! 287: sir->csr |= SI_CSR_DMA_EN; ! 288: } ! 289: ! 290: /* wait for dma completion */ ! 291: if (si_wait(&sir->csr, ! 292: SI_CSR_SBC_IP|SI_CSR_DMA_IP|SI_CSR_DMA_CONFLICT, 1) ! 293: == 0) { ! 294: sc_error("dma never completed"); ! 295: if (ob == 0) { ! 296: sir->csr &= ~SI_CSR_DMA_EN; ! 297: } ! 298: si_dma_cleanup(sir, ob); ! 299: goto failed; ! 300: } ! 301: if (ob == 0) { ! 302: sir->csr &= ~SI_CSR_DMA_EN; ! 303: } ! 304: ! 305: /* check reason for dma completion */ ! 306: if (sir->csr & SI_CSR_SBC_IP) { ! 307: /* dma operation should end with a phase mismatch */ ! 308: si_sbc_wait(&sir->sbc_rreg.bsr, SBC_BSR_PMTCH, 0); ! 309: } else { ! 310: if (sir->csr & SI_CSR_DMA_CONFLICT) { ! 311: sc_error("invalid reg access during dma"); ! 312: } else if (sir->csr & SI_CSR_DMA_BUS_ERR) { ! 313: sc_error("bus error during dma"); ! 314: } else { ! 315: if (ob) ! 316: sc_error("unknown dma failure"); ! 317: else ! 318: sc_error("dma overrun"); ! 319: } ! 320: si_dma_cleanup(sir, ob); ! 321: goto failed; ! 322: } ! 323: ! 324: /* handle special dma recv situations */ ! 325: if ((cdb->cmd == SC_READ) || (cdb->cmd == SC_REQUEST_SENSE)) { ! 326: if (ob) { ! 327: sir->udc_raddr = UDC_ADR_COUNT; ! 328: if (si_wait(&sir->csr, SI_CSR_FIFO_EMPTY, 1) == 0) { ! 329: sc_error("fifo never emptied"); ! 330: si_dma_cleanup(sir, ob); ! 331: goto failed; ! 332: } ! 333: /* if odd byte recv, must grab last byte by hand */ ! 334: if ((sip->si_cc - sir->bcr) & 1) { ! 335: cp = sip->si_ma + (sip->si_cc - sir->bcr) - 1; ! 336: *cp = (sir->fifo_data & 0xff00) >> 8; ! 337: ! 338: /* udc may not dma last word */ ! 339: } else if (((sir->udc_rdata*2) - sir->bcr) == 2) { ! 340: cp = sip->si_ma + (sip->si_cc - sir->bcr); ! 341: *(cp - 2) = (sir->fifo_data & 0xff00) >> 8; ! 342: *(cp - 1) = sir->fifo_data & 0x00ff; ! 343: } ! 344: ! 345: } else if ((sir->csr & SI_CSR_LOB) != 0) { ! 346: cp = sip->si_ma + (sip->si_cc - sir->bcr); ! 347: if ((sir->csr & SI_CSR_BPCON) == 0) { ! 348: switch (sir->csr & SI_CSR_LOB) { ! 349: case SI_CSR_LOB_THREE: ! 350: *(cp - 3) = (sir->bpr & 0xff000000) >> 24; ! 351: *(cp - 2) = (sir->bpr & 0x00ff0000) >> 16; ! 352: *(cp - 1) = (sir->bpr & 0x0000ff00) >> 8; ! 353: break; ! 354: case SI_CSR_LOB_TWO: ! 355: *(cp - 2) = (sir->bpr & 0xff000000) >> 24; ! 356: *(cp - 1) = (sir->bpr & 0x00ff0000) >> 16; ! 357: break; ! 358: case SI_CSR_LOB_ONE: ! 359: *(cp - 1) = (sir->bpr & 0xff000000) >> 24; ! 360: break; ! 361: } ! 362: } else { ! 363: *(cp - 1) = (sir->bpr & 0x0000ff00) >> 8; ! 364: } ! 365: } ! 366: } ! 367: ! 368: /* clear sbc interrupt */ ! 369: junk = sir->sbc_rreg.clr; ! 370: ! 371: /* cleanup after a dma operation */ ! 372: si_dma_cleanup(sir, ob); ! 373: } ! 374: ! 375: /* get status */ ! 376: cp = (char *)scb; ! 377: for (i = 0;;) { ! 378: b = si_getbyte(sir, PHASE_STATUS); ! 379: if (b == -1) { ! 380: break; ! 381: } ! 382: if (i < STATUS_LEN) { ! 383: cp[i++] = b; ! 384: } ! 385: } ! 386: b = si_getbyte(sir, PHASE_MSG_IN); ! 387: if (b != SC_COMMAND_COMPLETE) { ! 388: if (b >= 0) { /* if not, si_getbyte already printed msg */ ! 389: sc_error("invalid message"); ! 390: } ! 391: goto failed; ! 392: } ! 393: return (sip->si_cc - sir->bcr); ! 394: ! 395: failed: ! 396: si_reset(sir, ob); ! 397: return (-1); ! 398: } ! 399: ! 400: si_ob_dma_setup(sir, udct, cmd, cc, ma) ! 401: register struct scsi_si_reg *sir; ! 402: register struct udc_table *udct; ! 403: register u_char cmd; ! 404: register int cc; ! 405: register char *ma; ! 406: { ! 407: /* setup udc dma info */ ! 408: udct->haddr = ((SI_OB_DMA_ADDR(ma) & 0xff0000) >> 8) | ! 409: UDC_ADDR_INFO; ! 410: udct->laddr = SI_OB_DMA_ADDR(ma) & 0xffff; ! 411: udct->hcmr = UDC_CMR_HIGH; ! 412: udct->count = cc / 2; ! 413: if ((cmd == SC_READ) || (cmd == SC_REQUEST_SENSE)) { ! 414: udct->rsel = UDC_RSEL_RECV; ! 415: udct->lcmr = UDC_CMR_LRECV; ! 416: } else { ! 417: udct->rsel = UDC_RSEL_SEND; ! 418: udct->lcmr = UDC_CMR_LSEND; ! 419: if (cc & 1) { ! 420: udct->count++; ! 421: } ! 422: } ! 423: ! 424: /* initialize chain address register */ ! 425: DELAY(SI_UDC_WAIT); ! 426: sir->udc_raddr = UDC_ADR_CAR_HIGH; ! 427: DELAY(SI_UDC_WAIT); ! 428: sir->udc_rdata = ((int)udct & 0xff0000) >> 8; ! 429: DELAY(SI_UDC_WAIT); ! 430: sir->udc_raddr = UDC_ADR_CAR_LOW; ! 431: DELAY(SI_UDC_WAIT); ! 432: sir->udc_rdata = (int)udct & 0xffff; ! 433: ! 434: /* initialize master mode register */ ! 435: DELAY(SI_UDC_WAIT); ! 436: sir->udc_raddr = UDC_ADR_MODE; ! 437: DELAY(SI_UDC_WAIT); ! 438: sir->udc_rdata = UDC_MODE; ! 439: ! 440: /* issue start chain command */ ! 441: DELAY(SI_UDC_WAIT); ! 442: sir->udc_raddr = UDC_ADR_COMMAND; ! 443: DELAY(SI_UDC_WAIT); ! 444: sir->udc_rdata = UDC_CMD_STRT_CHN; ! 445: } ! 446: ! 447: /* ! 448: * Reset some register information after a dma operation. ! 449: */ ! 450: si_dma_cleanup(sir, ob) ! 451: register struct scsi_si_reg *sir; ! 452: register int ob; ! 453: { ! 454: if (ob) { ! 455: sir->udc_raddr = UDC_ADR_COMMAND; ! 456: DELAY(SI_UDC_WAIT); ! 457: sir->udc_rdata = UDC_CMD_RESET; ! 458: } else { ! 459: sir->csr &- ~SI_CSR_DMA_EN; ! 460: sir->dma_addr = 0; ! 461: } ! 462: sir->sbc_wreg.mr &= ~SBC_MR_DMA; ! 463: sir->sbc_wreg.icr = 0; ! 464: sir->sbc_wreg.tcr = 0; ! 465: } ! 466: ! 467: /* ! 468: * Wait for a condition to be (de)asserted. ! 469: */ ! 470: si_wait(reg, cond, set) ! 471: register u_short *reg; ! 472: register u_short cond; ! 473: register int set; ! 474: { ! 475: register int i; ! 476: register u_short regval; ! 477: ! 478: for (i = 0; i < 1000000; i++) { ! 479: regval = *reg; ! 480: if ((set == 1) && (regval & cond)) { ! 481: return (1); ! 482: } ! 483: if ((set == 0) && !(regval & cond)) { ! 484: return (1); ! 485: } ! 486: DELAY(600); ! 487: } ! 488: return (0); ! 489: } ! 490: ! 491: /* ! 492: * Wait for a condition to be (de)asserted on the scsi bus. ! 493: */ ! 494: si_sbc_wait(reg, cond, set) ! 495: register caddr_t reg; ! 496: register u_char cond; ! 497: register int set; ! 498: { ! 499: register int i; ! 500: register u_char regval; ! 501: ! 502: for (i = 0; i < 1000000; i++) { ! 503: regval = *reg; ! 504: if ((set == 1) && (regval & cond)) { ! 505: return (1); ! 506: } ! 507: if ((set == 0) && !(regval & cond)) { ! 508: return (1); ! 509: } ! 510: DELAY(600); ! 511: } ! 512: return (0); ! 513: } ! 514: ! 515: /* ! 516: * Put a byte onto the scsi bus. ! 517: */ ! 518: si_putbyte(sir, phase, data, numbytes) ! 519: register struct scsi_si_reg *sir; ! 520: register u_short phase; ! 521: register u_char *data; ! 522: register int numbytes; ! 523: { ! 524: register int i; ! 525: ! 526: /* set up tcr so a phase match will occur */ ! 527: if (phase == PHASE_COMMAND) { ! 528: sir->sbc_wreg.tcr = TCR_COMMAND; ! 529: } else if (phase == PHASE_MSG_OUT) { ! 530: sir->sbc_wreg.tcr = TCR_MSG_OUT; ! 531: } else { ! 532: sc_error("putbyte, bad phase specified"); ! 533: return (0); ! 534: } ! 535: ! 536: /* put all desired bytes onto scsi bus */ ! 537: for (i = 0; i < numbytes; i++) { ! 538: /* wait for target to request a byte */ ! 539: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1) == 0) { ! 540: sc_error("putbyte: target never set REQ"); ! 541: return (0); ! 542: } ! 543: ! 544: /* load data for transfer */ ! 545: sir->sbc_wreg.odr = *data++; ! 546: sir->sbc_wreg.icr = SBC_ICR_DATA; ! 547: ! 548: /* make sure phase match occurred */ ! 549: if ((sir->sbc_rreg.bsr & SBC_BSR_PMTCH) == 0) { ! 550: sc_error("putbyte: phase mismatch"); ! 551: return (0); ! 552: } ! 553: ! 554: /* complete req/ack handshake */ ! 555: sir->sbc_wreg.icr |= SBC_ICR_ACK; ! 556: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0) == 0) { ! 557: sc_error("putbyte: target never released REQ"); ! 558: return (0); ! 559: } ! 560: sir->sbc_wreg.icr = 0; ! 561: } ! 562: sir->sbc_wreg.tcr = 0; ! 563: return (1); ! 564: } ! 565: ! 566: /* ! 567: * Get a byte from the scsi bus. ! 568: */ ! 569: si_getbyte(sir, phase) ! 570: register struct scsi_si_reg *sir; ! 571: register u_short phase; ! 572: { ! 573: register u_char data; ! 574: ! 575: /* set up tcr so a phase match will occur */ ! 576: if (phase == PHASE_STATUS) { ! 577: sir->sbc_wreg.tcr = TCR_STATUS; ! 578: } else if (phase == PHASE_MSG_IN) { ! 579: sir->sbc_wreg.tcr = TCR_MSG_IN; ! 580: } else { ! 581: sc_error("getbyte, bad phase specified"); ! 582: return (-1); ! 583: } ! 584: ! 585: /* wait for target request */ ! 586: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1) == 0) { ! 587: sc_error("getbyte: target never set REQ"); ! 588: sir->sbc_wreg.tcr = 0; ! 589: return (-1); ! 590: } ! 591: ! 592: /* check for correct information phase on scsi bus */ ! 593: if (phase != (sir->sbc_rreg.cbsr & CBSR_PHASE_BITS)) { ! 594: if (phase != PHASE_STATUS) { ! 595: sc_error("getbyte: phase mismatch"); ! 596: } ! 597: sir->sbc_wreg.tcr = 0; ! 598: return (-1); ! 599: } ! 600: ! 601: /* grab data */ ! 602: data = sir->sbc_rreg.cdr; ! 603: sir->sbc_wreg.icr = SBC_ICR_ACK; ! 604: ! 605: /* complete req/ack handshake */ ! 606: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0) == 0) { ! 607: sc_error("getbyte: target never released REQ"); ! 608: sir->sbc_wreg.icr = 0; ! 609: sir->sbc_wreg.tcr = 0; ! 610: return (-1); ! 611: } ! 612: sir->sbc_wreg.icr = 0; ! 613: sir->sbc_wreg.tcr = 0; ! 614: return (data); ! 615: } ! 616: ! 617: /* ! 618: * Reset SCSI control logic. ! 619: */ ! 620: si_reset(sir, ob) ! 621: register struct scsi_si_reg *sir; ! 622: register int ob; ! 623: { ! 624: register u_char junk; ! 625: ! 626: /* reset bcr, fifo, udc, and sbc */ ! 627: sir->bcr = 0; ! 628: sir->csr = 0; ! 629: DELAY(10); ! 630: sir->csr = SI_CSR_SCSI_RES|SI_CSR_FIFO_RES; ! 631: if (ob == 0) { ! 632: sir->dma_addr = 0; ! 633: sir->dma_count = 0; ! 634: } ! 635: ! 636: /* issue scsi bus reset */ ! 637: sir->sbc_wreg.icr = SBC_ICR_RST; ! 638: DELAY(50); ! 639: sir->sbc_wreg.icr = 0; ! 640: junk = sir->sbc_rreg.clr; ! 641: DELAY(10000000); ! 642: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.