|
|
1.1 ! root 1: /* Copyright (c) 1994 NeXT Computer, Inc. All rights reserved. ! 2: * ! 3: * AMD_Chip.m - chip (53C974/79C974) specific methods for AMD SCSI driver ! 4: * ! 5: * HISTORY ! 6: * 21 Oct 94 Doug Mitchell at NeXT ! 7: * Created. ! 8: */ ! 9: ! 10: #import "AMD_Chip.h" ! 11: #import "AMD_ChipPrivate.h" ! 12: #import "AMD_Private.h" ! 13: #import "AMD_x86.h" ! 14: #import "AMD_Regs.h" ! 15: #import "AMD_Types.h" ! 16: #import "AMD_ddm.h" ! 17: #import "bringup.h" ! 18: #import <driverkit/generalFuncs.h> ! 19: #import <kernserv/prototypes.h> ! 20: ! 21: IONamedValue scsiMsgValues[] = { ! 22: {MSG_CMDCMPLT, "Command Complete" }, ! 23: {MSG_EXTENDED, "Extended Message" }, ! 24: {MSG_SAVEPTRS, "Save Pointers" }, ! 25: {MSG_RESTOREPTRS, "Restore Pointers" }, ! 26: {MSG_DISCONNECT, "Disconnect" }, ! 27: {MSG_IDETERR, "Initiator Det Error" }, ! 28: {MSG_ABORT, "Abort" }, ! 29: {MSG_MSGREJECT, "Message Reject" }, ! 30: {MSG_NOP, "Nop" }, ! 31: {MSG_MSGPARERR, "Message parity Error" }, ! 32: {0, NULL } ! 33: }; ! 34: ! 35: #ifdef DDM_DEBUG ! 36: IONamedValue scsiPhaseValues[] = { ! 37: {PHASE_DATAOUT, "data_out" }, ! 38: {PHASE_DATAIN, "data_in" }, ! 39: {PHASE_COMMAND, "command" }, ! 40: {PHASE_STATUS, "status" }, ! 41: {PHASE_MSGOUT, "message_out" }, ! 42: {PHASE_MSGIN, "message_in" }, ! 43: {0, NULL } ! 44: }; ! 45: ! 46: #endif DDM_DEBUG ! 47: ! 48: #ifdef DEBUG ! 49: /* ! 50: * For IOFindNameForValue() and ddm's. ! 51: */ ! 52: IONamedValue scStateValues[] = { ! 53: {SCS_UNINITIALIZED, "SCS_UNINITIALIZED" }, ! 54: {SCS_DISCONNECTED, "SCS_DISCONNECTED" }, ! 55: {SCS_SELECTING, "SCS_SELECTING" }, ! 56: {SCS_INITIATOR, "SCS_INITIATOR" }, ! 57: {SCS_COMPLETING, "SCS_COMPLETING" }, ! 58: {SCS_DMAING, "SCS_DMAING" }, ! 59: {SCS_ACCEPTINGMSG, "SCS_ACCEPTINGMSG" }, ! 60: {SCS_SENDINGMSG, "SCS_SENDINGMSG" }, ! 61: {SCS_GETTINGMSG, "SCS_GETTINGMSG" }, ! 62: {SCS_SENDINGCMD, "SCS_SENDINGCMD" }, ! 63: {0, NULL }, ! 64: }; ! 65: #endif DEBUG ! 66: ! 67: @implementation AMD_SCSI(Chip) ! 68: ! 69: /* ! 70: * One-time-only init and probe. Returns YES if a functioning chip is ! 71: * found, else returns NO. -hwReset must be called subsequent to this ! 72: * to enable operation of the chip. ! 73: */ ! 74: - (BOOL)probeChip ! 75: { ! 76: int target; ! 77: ! 78: /* ! 79: * Init sync mode to async, until we negotiate. ! 80: */ ! 81: for(target=0; target<SCSI_NTARGETS; target++) { ! 82: perTarget[target].syncXferOffset = 0; ! 83: } ! 84: return YES; ! 85: } ! 86: ! 87: /* ! 88: * Reusable 53C974 init function. This includes a SCSI reset. ! 89: * Handling of ioComplete of active and disconnected commands must be done ! 90: * elsewhere. Returns non-zero on error. ! 91: */ ! 92: - (int)hwReset : (const char *)reason ! 93: { ! 94: int target; ! 95: unsigned char reg; ! 96: ! 97: /* ! 98: * First of all, reset interrupts, the SCSI block, and the DMA engine. ! 99: */ ! 100: [self disableAllInterrupts]; ! 101: WRITE_REG(scsiCmd, SCMD_RESET_DEVICE); ! 102: WRITE_REG(scsiCmd, SCMD_NOP); ! 103: [self dmaIdle]; ! 104: ! 105: /* ! 106: * Clear possible pending interrupt. ! 107: */ ! 108: READ_REG(intrStatus); ! 109: ! 110: /* ! 111: * Init state variables. ! 112: */ ! 113: reselPending = 0; ! 114: scState = SCS_DISCONNECTED; ! 115: activeCmd = NULL; ! 116: currMsgInCnt = 0; ! 117: currMsgOutCnt = 0; ! 118: msgOutState = MOS_NONE; ! 119: SDTR_State = SNS_NONE; ! 120: ! 121: /* ! 122: * Sync negotiation is needed after a reset. ! 123: */ ! 124: for(target=0; target<SCSI_NTARGETS; target++) { ! 125: perTarget[target].syncNegotNeeded = 1; ! 126: } ! 127: ! 128: /* ! 129: * Control1.... ! 130: */ ! 131: reg = CR1_RESET_INTR_DIS | CR1_PERR_ENABLE | AMD_SCSI_ID; ! 132: if(extendTiming) { ! 133: /* ! 134: * Per instance table. This slows down transfers on the ! 135: * bus. ! 136: */ ! 137: reg |= CR1_EXTEND_TIMING; ! 138: } ! 139: WRITE_REG(control1, reg); ! 140: ddm_init("control1 = 0x%x\n", reg, 2,3,4,5); ! 141: hostId = AMD_SCSI_ID; ! 142: ! 143: /* ! 144: * Clock factor and select timeout. ! 145: */ ! 146: ASSERT(scsiClockRate != 0); ! 147: if(scsiClockRate < 10) { ! 148: IOLog("AMD53C974: Clock %d MHZ too low; using 10 MHz\n", ! 149: scsiClockRate); ! 150: scsiClockRate = 10; ! 151: } ! 152: if(scsiClockRate > 40) { ! 153: IOLog("AMD53C974: Clock %d MHZ too high; using 40 MHz\n", ! 154: scsiClockRate); ! 155: scsiClockRate = 40; ! 156: } ! 157: reg = AMD_CLOCK_FACTOR(scsiClockRate) & 0x7; ! 158: WRITE_REG(clockFactor, reg); ! 159: ddm_init("clockFactor %d\n", reg, 2,3,4,5); ! 160: reg = amdSelectTimeout(AMD_SELECT_TO, scsiClockRate); ! 161: WRITE_REG(scsiTimeout, reg); ! 162: ddm_init("select timeout reg 0x%x\n", reg, 2,3,4,5); ! 163: ! 164: /* ! 165: * control2 - enable extended features - mainly, 24-bit transfer count. ! 166: */ ! 167: WRITE_REG(control2, CR2_ENABLE_FEAT); ! 168: ! 169: /* ! 170: * control3 ! 171: */ ! 172: reg = 0; ! 173: if(fastModeEnable) { ! 174: reg |= CR3_FAST_SCSI; ! 175: } ! 176: if(scsiClockRate > 25) { ! 177: reg |= CR3_FAST_CLOCK; ! 178: } ! 179: ddm_init("control3 = 0x%x\n", reg, 2,3,4,5); ! 180: WRITE_REG(control3, reg); ! 181: ! 182: /* ! 183: * control4 - glitch eater, active negation. Let's not ! 184: * worry about these whizzy features just yet. ! 185: */ ! 186: WRITE_REG(control4, 0); ! 187: ! 188: /* ! 189: * Go to async xfer mode for now. Sync gets enabled on a per-target ! 190: * basis in -targetContext. ! 191: */ ! 192: WRITE_REG(syncOffset, 0); ! 193: ! 194: /* ! 195: * Reset SCSI bus, wait, clear possible interrupt. ! 196: */ ! 197: WRITE_REG(scsiCmd, SCMD_RESET_SCSI); ! 198: if(reason) { ! 199: IOLog("AMD53C974: Resetting SCSI bus (%s)\n", reason); ! 200: } ! 201: else { ! 202: IOLog("AMD53C974: Resetting SCSI bus\n"); ! 203: } ! 204: IOSleep(AMD_SCSI_RESET_DELAY); ! 205: READ_REG(intrStatus); ! 206: ! 207: ddm_init("hwReset: enabling interrupts\n", 1,2,3,4,5); ! 208: [self enableAllInterrupts]; ! 209: ! 210: ddm_init("hwReset: DONE\n", 1,2,3,4,5); ! 211: return 0; ! 212: } ! 213: ! 214: /* ! 215: * reset SCSI bus. ! 216: */ ! 217: - (void)scsiReset ! 218: { ! 219: WRITE_REG(scsiCmd, SCMD_RESET_SCSI); ! 220: READ_REG(intrStatus); ! 221: } ! 222: ! 223: /* ! 224: * Start a SCSI transaction for the specified command. ActiveCmd must be ! 225: * NULL. A return of HWS_REJECT indicates that caller may try again ! 226: * with another command; HWS_BUSY indicates a condition other than ! 227: * (activeCmd != NULL) which prevents the processing of the command. ! 228: */ ! 229: - (hwStartReturn)hwStart : (commandBuf *)cmdBuf ! 230: { ! 231: unsigned char cdb_ctrl; ! 232: IOSCSIRequest *scsiReq = cmdBuf->scsiReq; ! 233: cdb_t *cdbp = &scsiReq->cdb; ! 234: unsigned char identify_msg = 0; ! 235: unsigned char *cp; ! 236: unsigned char okToDisc; ! 237: unsigned char okToQueue; ! 238: perTargetData *perTargetPtr; ! 239: int i; ! 240: BOOL cmdQueueDisableFlag = NO; ! 241: unsigned char selectCmd; ! 242: ! 243: ddm_chip("hwStart cmdBuf = 0x%x opcode %s\n", cmdBuf, ! 244: IOFindNameForValue(cdbp->cdb_opcode, IOSCSIOpcodeStrings), ! 245: 3,4,5); ! 246: ASSERT(activeCmd == NULL); ! 247: ! 248: /* ! 249: * Currently, the only reason we return HWS_BUSY is if we have ! 250: * a reselect pending. ! 251: */ ! 252: if(reselPending) { ! 253: queue_enter(&pendingQ, cmdBuf, commandBuf *, link); ! 254: return HWS_BUSY; ! 255: } ! 256: ASSERT(scState == SCS_DISCONNECTED); ! 257: ! 258: /* ! 259: * Initialize driver return values and state machine. ! 260: */ ! 261: cmdBuf->currentByteCount = cmdBuf->savedByteCount = ! 262: scsiReq->maxTransfer; ! 263: scsiReq->bytesTransferred = 0; ! 264: cmdBuf->savedPtr = cmdBuf->currentPtr = (vm_offset_t)cmdBuf->buffer; ! 265: scsiReq->driverStatus = SR_IOST_INVALID; ! 266: scsiReq->totalTime = 0ULL; ! 267: scsiReq->latentTime = 0ULL; ! 268: ! 269: /* ! 270: * Figure out what kind of cdb we've been given and grab the ctrl byte. ! 271: */ ! 272: switch (SCSI_OPGROUP(cdbp->cdb_opcode)) { ! 273: case OPGROUP_0: ! 274: cmdBuf->cdbLength = sizeof(cdb_6_t); ! 275: cdb_ctrl = cdbp->cdb_c6.c6_ctrl; ! 276: break; ! 277: case OPGROUP_1: ! 278: case OPGROUP_2: ! 279: cmdBuf->cdbLength = sizeof(cdb_10_t); ! 280: cdb_ctrl = cdbp->cdb_c10.c10_ctrl; ! 281: break; ! 282: case OPGROUP_5: ! 283: cmdBuf->cdbLength = sizeof(cdb_12_t); ! 284: cdb_ctrl = cdbp->cdb_c12.c12_ctrl; ! 285: break; ! 286: case OPGROUP_6: ! 287: cmdBuf->cdbLength = (scsiReq->cdbLength ? ! 288: scsiReq->cdbLength : sizeof (struct cdb_6)); ! 289: cdb_ctrl = 0; ! 290: break; ! 291: case OPGROUP_7: ! 292: cmdBuf->cdbLength = (scsiReq->cdbLength ? ! 293: scsiReq->cdbLength : sizeof (struct cdb_10)); ! 294: cdb_ctrl = 0; ! 295: break; ! 296: default: ! 297: goto abortReq; ! 298: } ! 299: ddm_chip("cdbLength = %d\n", cmdBuf->cdbLength, 2,3,4,5); ! 300: ! 301: /* ! 302: * Do a little command snooping. ! 303: */ ! 304: perTargetPtr = &perTarget[scsiReq->target]; ! 305: switch(cdbp->cdb_opcode) { ! 306: case C6OP_INQUIRY: ! 307: /* ! 308: * The first command SCSIDisk sends us is an Inquiry command. ! 309: * This never gets retried, so avoid a possible ! 310: * reject of a command queue tag. Avoid this hack if ! 311: * there are any other commands outstanding for this ! 312: * target/lun. ! 313: */ ! 314: if(activeArray[scsiReq->target][scsiReq->lun] == 0) { ! 315: cmdQueueDisableFlag = YES; ! 316: } ! 317: break; ! 318: ! 319: case C6OP_REQSENSE: ! 320: /* ! 321: * Always force sync renegotiation on this one to ! 322: * catch independent target power cycles. ! 323: */ ! 324: if(SYNC_RENEGOT_ON_REQ_SENSE) { ! 325: perTargetPtr->syncNegotNeeded = 1; ! 326: } ! 327: break; ! 328: } ! 329: ! 330: /* ! 331: * Avoid command queueing if if we're going to do sync ! 332: * negotiation. ! 333: * FIXME - this might be illegal - what if we're doing a request ! 334: * sense in response to a legitimate error, and there are ! 335: * tagged commands pending? ! 336: */ ! 337: if(perTargetPtr->syncNegotNeeded && ! 338: !perTargetPtr->syncDisable && ! 339: syncModeEnable) { ! 340: cmdQueueDisableFlag = YES; ! 341: SDTR_State = SNS_HOST_INIT_NEEDED; ! 342: ddm_chip("hwStart: entering SNS_HOST_INIT_NEEDED state\n", ! 343: 1,2,3,4,5); ! 344: } ! 345: else { ! 346: SDTR_State = SNS_NONE; ! 347: } ! 348: ! 349: /* ! 350: * Determine from myriad sources whether or not it's OK to ! 351: * disconnect and to use command queueing. ! 352: */ ! 353: okToQueue = cmdQueueEnable && // global per driver ! 354: !scsiReq->cmdQueueDisable && // per I/O ! 355: !perTargetPtr->cmdQueueDisable && // per target ! 356: !cmdQueueDisableFlag; // inquiry hack ! 357: okToDisc = ([self numReserved] > // > 1 target on bus ! 358: (1 + SCSI_NLUNS)) || ! 359: okToQueue; // hope to do cmd q'ing ! 360: #if FORCE_DISCONNECTS ! 361: okToDisc = 1; ! 362: #else FORCE_DISCONNECTS ! 363: if(!scsiReq->disconnect) { ! 364: /* ! 365: * This overrides everything... ! 366: */ ! 367: okToQueue = okToDisc = 0; ! 368: } ! 369: #endif FORCE_DISCONNECTS ! 370: cmdBuf->discEnable = okToDisc; ! 371: if(okToQueue) { ! 372: /* ! 373: * Avoid using tag QUEUE_TAG_NONTAGGED... ! 374: */ ! 375: cmdBuf->queueTag = nextQueueTag; ! 376: if(++nextQueueTag == QUEUE_TAG_NONTAGGED) { ! 377: nextQueueTag++; ! 378: } ! 379: } ! 380: else { ! 381: cmdBuf->queueTag = QUEUE_TAG_NONTAGGED; ! 382: } ! 383: ! 384: /* ! 385: * Make sure nothing unreasonable has been asked of us. ! 386: */ ! 387: if((cdb_ctrl & CTRL_LINKFLAG) != CTRL_NOLINK) { ! 388: ddm_err("Linked CDB (Unimplemented)\n", ! 389: 1,2,3,4,5); ! 390: goto abortReq; ! 391: } ! 392: ! 393: /* ! 394: * OK, this command is hot. ! 395: */ ! 396: [self activateCommand:cmdBuf]; ! 397: ! 398: scState = SCS_SELECTING; ! 399: msgOutState = MOS_NONE; ! 400: bzero(currMsgIn, AMD_MSG_SIZE); ! 401: bzero(currMsgOut, AMD_MSG_SIZE); ! 402: currMsgInCnt = 0; ! 403: currMsgOutCnt = 0; ! 404: ! 405: /* ! 406: * Load per-target context. ! 407: */ ! 408: [self targetContext:scsiReq->target]; ! 409: ! 410: /* ! 411: * set target bus id ! 412: * punch message(s), optional cdb into fifo ! 413: * write appropriate select command ! 414: */ ! 415: ddm_chip("hwStart: opcode 0x%x targ %d lun %d maxTransfer 0x%x\n", ! 416: cdbp->cdb_opcode, scsiReq->target, scsiReq->lun, ! 417: scsiReq->maxTransfer, 5); ! 418: WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); ! 419: WRITE_REG(scsiDestID, scsiReq->target); ! 420: identify_msg = MSG_IDENTIFYMASK | (scsiReq->lun & MSG_ID_LUNMASK); ! 421: if(okToDisc) { ! 422: identify_msg |= MSG_ID_DISCONN; ! 423: } ! 424: ! 425: WRITE_REG(scsiFifo, identify_msg); ! 426: ! 427: /* ! 428: * Note this logic assumes that queue tag and SDTR messages are ! 429: * mutually exclusive... ! 430: */ ! 431: if(SDTR_State == SNS_HOST_INIT_NEEDED) { ! 432: selectCmd = SCMD_SELECT_ATN_STOP; ! 433: } ! 434: else { ! 435: if(okToQueue) { ! 436: WRITE_REG(scsiFifo, MSG_SIMPLE_QUEUE_TAG); ! 437: WRITE_REG(scsiFifo, cmdBuf->queueTag); ! 438: ! 439: /* ! 440: * Save these in currMsgOut[] in case ! 441: * the target rejects this message. ! 442: */ ! 443: currMsgOut[0] = MSG_SIMPLE_QUEUE_TAG; ! 444: currMsgOut[1] = cmdBuf->queueTag; ! 445: currMsgOutCnt = 2; ! 446: } ! 447: cp = (u_char *)cdbp; ! 448: for(i=0; i<cmdBuf->cdbLength; i++) { ! 449: WRITE_REG(scsiFifo, *cp++); ! 450: } ! 451: if(okToQueue) { ! 452: selectCmd = SCMD_SELECT_ATN_3; ! 453: } ! 454: else { ! 455: selectCmd = SCMD_SELECT_ATN; ! 456: } ! 457: } ! 458: WRITE_REG(scsiCmd, selectCmd); ! 459: IOGetTimestamp(&cmdBuf->startTime); ! 460: return HWS_OK; ! 461: ! 462: abortReq: ! 463: scsiReq->driverStatus = SR_IOST_CMDREJ; ! 464: [self ioComplete:cmdBuf]; ! 465: return HWS_REJECT; ! 466: } ! 467: ! 468: /* ! 469: * SCSI device interrupt handler. ! 470: */ ! 471: - (void)hwInterrupt ! 472: { ! 473: ddm_chip("hwInterrupt: activeCmd 0x%x\n", activeCmd, 2,3,4,5); ! 474: ! 475: switch([self scsiInterruptPending]) { ! 476: case SINT_NONE: ! 477: /* ! 478: * Must be another device.... ! 479: */ ! 480: [self enableAllInterrupts]; ! 481: return; ! 482: case SINT_DEVICE: ! 483: case SINT_DMA: ! 484: break; ! 485: default: ! 486: /* ! 487: * What do we do now, batman? ! 488: */ ! 489: [self hwAbort:SR_IOST_HW reason:"Bad Interrupt Received"]; ! 490: return; ! 491: } ! 492: ! 493: goAgain: ! 494: /* ! 495: * Save interrupt state. ! 496: */ ! 497: saveStatus = READ_REG(scsiStat); ! 498: saveSeqStep = READ_REG(internState); ! 499: saveIntrStatus = READ_REG(intrStatus); ! 500: ! 501: ddm_chip(" status 0x%x intstatus 0x%x scState %s\n", ! 502: saveStatus, saveIntrStatus, ! 503: IOFindNameForValue(scState, scStateValues), 4,5); ! 504: if((saveStatus & SS_ILLEGALOP) || (saveIntrStatus & IS_ILLEGALCMD)) { ! 505: ! 506: /* ! 507: * Software screwup. Start over from scratch. ! 508: */ ! 509: IOLog("AMD53C974: hardware command reject\n"); ! 510: [self hwAbort:SR_IOST_INT reason:"Hardware Command Reject"]; ! 511: return; ! 512: } ! 513: ! 514: /* ! 515: * OK, grind thru the state machine. ! 516: */ ! 517: switch(scState) { ! 518: case SCS_DISCONNECTED: ! 519: [self fsmDisconnected]; ! 520: break; ! 521: case SCS_SELECTING: ! 522: [self fsmSelecting]; ! 523: break; ! 524: case SCS_INITIATOR: ! 525: [self fsmInitiator]; ! 526: break; ! 527: case SCS_COMPLETING: ! 528: [self fsmCompleting]; ! 529: break; ! 530: case SCS_DMAING: ! 531: [self fsmDMAing]; ! 532: break; ! 533: case SCS_ACCEPTINGMSG: ! 534: [self fsmAcceptingMsg]; ! 535: break; ! 536: case SCS_SENDINGMSG: ! 537: [self fsmSendingMsg]; ! 538: break; ! 539: case SCS_GETTINGMSG: ! 540: [self fsmGettingMsg]; ! 541: break; ! 542: case SCS_SENDINGCMD: ! 543: [self fsmSendingCmd]; ! 544: break; ! 545: default: ! 546: IOPanic("AMD53C974: Bad scState"); ! 547: } /* switch scState */ ! 548: ! 549: if ((scState != SCS_DISCONNECTED) && ! 550: (saveIntrStatus & IS_DISCONNECT)) { ! 551: /* ! 552: * the target just up and went away. This is a catch-all ! 553: * trap for any unexpected disconnect. ! 554: */ ! 555: ddm_err("hwInterrupt: target disconnected\n", 1,2,3,4,5); ! 556: scState = SCS_DISCONNECTED; ! 557: if(activeCmd != NULL) { ! 558: activeCmd->scsiReq->driverStatus = SR_IOST_TABT; ! 559: [self ioComplete:activeCmd]; ! 560: activeCmd = NULL; ! 561: } ! 562: } ! 563: ! 564: /* ! 565: * Handle a SCSI Phase change if necessary. ! 566: */ ! 567: if (scState == SCS_INITIATOR) ! 568: [self fsmPhaseChange]; ! 569: #ifdef DEBUG ! 570: else { ! 571: ddm_chip("hwInterrupt #2: scState %s\n", ! 572: IOFindNameForValue(scState, scStateValues), ! 573: 2,3,4,5); ! 574: } ! 575: #endif DEBUG ! 576: ! 577: /* ! 578: * If we're off the bus, enable reselection at chip level. ! 579: */ ! 580: if (scState == SCS_DISCONNECTED) { ! 581: ddm_chip("hwInterrupt: enabling reselection\n", 1,2,3,4,5); ! 582: WRITE_REG(scsiCmd, SCMD_ENABLE_SELECT); ! 583: } ! 584: ! 585: ! 586: /* ! 587: * If another SCSI interrupt is pending, go for it again (avoiding ! 588: * an unnecessary enableInterrupt and msg_receive()). ! 589: */ ! 590: switch([self scsiInterruptPending]) { ! 591: case SINT_DEVICE: ! 592: #if INTR_LATENCY_TEST ! 593: ddm_chip("hwInterrupt: INTR TRUE; EXITING FOR MEASUREMENT\n", ! 594: 1,2,3,4,5); ! 595: break; ! 596: #else INTR_LATENCY_TEST ! 597: ddm_chip("hwInterrupt: going again without enabling " ! 598: "interrupt\n", 1,2,3,4,5); ! 599: goto goAgain; ! 600: #endif INTR_LATENCY_TEST ! 601: default: ! 602: break; ! 603: } ! 604: ! 605: [self enableAllInterrupts]; ! 606: ! 607: /* ! 608: * One more thing - if we're still disconnected, enable processing ! 609: * of new commands. ! 610: */ ! 611: if(scState == SCS_DISCONNECTED) ! 612: [self busFree]; ! 613: ddm_chip("hwInterrupt: DONE; scState %s\n", ! 614: IOFindNameForValue(scState, scStateValues), 2,3,4,5); ! 615: } ! 616: ! 617: ! 618: - (void)logRegs ! 619: { ! 620: #if DEBUG ! 621: unsigned char cs, cis; ! 622: unsigned char fifoDepth; ! 623: unsigned scsiXfrCnt; ! 624: unsigned value; ! 625: ! 626: IOLog("*** saveStatus 0x%x saveIntrStatus 0x%x\n", ! 627: saveStatus, saveIntrStatus); ! 628: IOLog("*** scState = %s scsiCmd = 0x%x\n", ! 629: IOFindNameForValue(scState, scStateValues), ! 630: READ_REG(scsiCmd)); ! 631: ! 632: cs = READ_REG(scsiStat); ! 633: cis = READ_REG(intrStatus); ! 634: IOLog("*** current status 0x%x current intrStatus 0x%x\n", cs, cis); ! 635: ! 636: IOLog("*** syncOffset %d syncPeriod 0x%x\n", ! 637: syncOffsetShadow, syncPeriodShadow); ! 638: ! 639: fifoDepth = READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK; ! 640: scsiXfrCnt = READ_REG(currXfrCntLow); ! 641: value = READ_REG(currXfrCntMid); ! 642: scsiXfrCnt += (value << 8); ! 643: value = READ_REG(currXfrCntHi); ! 644: scsiXfrCnt += (value << 16); ! 645: IOLog("*** fifoDepth %d scsiXfrCnt 0x%x\n", fifoDepth, scsiXfrCnt); ! 646: #endif DEBUG ! 647: } ! 648: ! 649: ! 650: @end /* AMD_SCSI(Chip) */ ! 651: ! 652: /* end of AMD_Chip.m */ ! 653:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.