|
|
1.1 ! root 1: /* Copyright (c) 1994 NeXT Computer, Inc. All rights reserved. ! 2: * ! 3: * AMD_ChipPrivate.m - methods used only by AMD_Chip module. ! 4: * ! 5: * HISTORY ! 6: * 2 Nov 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: ! 22: @implementation AMD_SCSI(ChipPrivate) ! 23: ! 24: /* ! 25: * Determine if SCSI interrupt is pending. ! 26: */ ! 27: - (sintPending_t)scsiInterruptPending ! 28: { ! 29: unsigned char sstat; ! 30: ! 31: sstat = READ_REG(scsiStat); ! 32: if (sstat & SS_INTERRUPT) { ! 33: return SINT_DEVICE; ! 34: } ! 35: else { ! 36: return SINT_NONE; ! 37: } ! 38: } ! 39: ! 40: /* ! 41: * Methods invoked upon interrupt. One per legal scState. All assume that ! 42: * status and interrupt status have been captured in saveStatus and ! 43: * saveIntrStatus. ! 44: */ ! 45: ! 46: /* ! 47: * Disconnected - only legal event here is reselection. ! 48: */ ! 49: - (void)fsmDisconnected ! 50: { ! 51: ddm_chip("fsmDisconnected\n", 1,2,3,4,5); ! 52: ASSERT(activeCmd == NULL); ! 53: if(saveIntrStatus & IS_RESELECTED) { ! 54: /* ! 55: * We've been reselected. ! 56: */ ! 57: ! 58: unsigned char selectByte; ! 59: unsigned fifoDepth; ! 60: unsigned char msg; ! 61: ! 62: /* ! 63: * Make sure there's a selection byte and an ! 64: * identify message in the fifo. ! 65: */ ! 66: fifoDepth = READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK; ! 67: ddm_chip("reselect: fifoDepth %d\n", fifoDepth, 2,3,4,5); ! 68: if(fifoDepth != 2) { ! 69: ddm_err("reselection, fifoDepth %d\n", fifoDepth, ! 70: 2,3,4,5); ! 71: IOLog("AMD53C974: Bad FIFO count (%d) on Reselect\n", ! 72: fifoDepth); ! 73: [self hwAbort:SR_IOST_HW ! 74: reason:NULL]; ! 75: return; ! 76: ! 77: } ! 78: ! 79: /* ! 80: * make sure target set his bit. ! 81: */ ! 82: if ((selectByte = READ_REG(scsiFifo) &~ (1 << hostId)) == 0) { ! 83: ddm_err("fsmDisconnected: reselection failed" ! 84: " - no target bit\n", 1,2,3,4,5); ! 85: [self hwAbort:SR_IOST_BV ! 86: reason:"No target bit on Reselect"]; ! 87: return; ! 88: } ! 89: ! 90: /* ! 91: * figure out target from bit that's on. ! 92: */ ! 93: for (reselTarget = 0; ! 94: (selectByte & 1) == 0; ! 95: reselTarget++, selectByte>>=1) { ! 96: continue; ! 97: } ! 98: ! 99: /* ! 100: * first message byte must be identify. ! 101: */ ! 102: msg = READ_REG(scsiFifo); ! 103: if (saveStatus & SS_PARITYERROR) { ! 104: ddm_err("fsmDisconnected: reselected parity error\n", ! 105: 1,2,3,4,5); ! 106: [self hwAbort:SR_IOST_PARITY ! 107: reason:"Parity error on Reselect"]; ! 108: return; ! 109: } ! 110: if ((msg & MSG_IDENTIFYMASK) == 0) { ! 111: ddm_err("fsmDisconnected: reselection failed - " ! 112: "bad msg byte (0x%x)\n", msg, 2,3,4,5); ! 113: [self hwAbort:SR_IOST_BV ! 114: reason:"Bad ID Message on Reselect"]; ! 115: return; ! 116: } ! 117: reselLun = msg & MSG_ID_LUNMASK; ! 118: currMsgInCnt = 0; ! 119: ! 120: /* ! 121: * At this point, the chip is waiting for us to validate ! 122: * the identify message. If cmd queueing is enabled ! 123: * for this target, the target is waiting to send a queue ! 124: * tag message, so we have to tell the chip to ! 125: * drop ACK before we proceed with the reselection. ! 126: * ! 127: * In case of sync mode, we need to load target context right ! 128: * now, before dropping ACK, because the target might go ! 129: * straight to a data in or data out as soon as ACK drops. ! 130: */ ! 131: [self targetContext:reselTarget]; ! 132: scState = SCS_ACCEPTINGMSG; ! 133: reselPending = 1; ! 134: WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); ! 135: WRITE_REG(scsiCmd, SCMD_MSG_ACCEPTED); ! 136: ddm_chip("reselPending: target %d lun %d\n", ! 137: reselTarget, reselLun, 3,4,5); ! 138: ! 139: } else if(saveIntrStatus & IS_SCSIRESET) { ! 140: /* ! 141: * TBD - for now ignore, we get one of these by resetting the ! 142: * chip. If an I/O is pending, it'll probably time out. ! 143: * Maybe we want to return SR_IOST_RESET on the pending ! 144: * command... ! 145: */ ! 146: ddm_chip("fsmDisconnected: ignoring reset interrupt\n", ! 147: 1,2,3,4,5); ! 148: } else { ! 149: /* ! 150: * I'm confused.... ! 151: */ ! 152: [self hwAbort:SR_IOST_BV ! 153: reason:"bad interrupt while disconnected"]; ! 154: } ! 155: } ! 156: ! 157: ! 158: /* ! 159: * One of three things can happen here - the selection could succeed (though ! 160: * with possible imcomplete message out), it could time out, or we can be ! 161: * reselected. ! 162: */ ! 163: #define CATCH_SELECT_TO 1 ! 164: ! 165: - (void)fsmSelecting ! 166: { ! 167: unsigned char fifoDepth; ! 168: unsigned char phase; ! 169: IOSCSIRequest *scsiReq = activeCmd->scsiReq; ! 170: ! 171: ddm_chip("fsmSelecting\n", 1,2,3,4,5); ! 172: ASSERT(activeCmd != NULL); ! 173: if (saveIntrStatus & IS_DISCONNECT) { ! 174: /* ! 175: * selection timed-out. Abort this request. ! 176: */ ! 177: #if CATCH_SELECT_TO ! 178: /* DEBUG ONLY */ ! 179: if(scsiReq->cdb.cdb_opcode != C6OP_INQUIRY) { ! 180: IOLog("Unexpected Select Timeout\n"); ! 181: } ! 182: #endif CATCH_SELECT_TO ! 183: ddm_chip("***SELECTION TIMEOUT for target %d\n", ! 184: activeCmd->scsiReq->target, 2,3,4,5); ! 185: WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); ! 186: scState = SCS_DISCONNECTED; ! 187: scsiReq->driverStatus = SR_IOST_SELTO; ! 188: [self ioComplete:activeCmd]; ! 189: activeCmd = NULL; ! 190: } ! 191: else if(saveIntrStatus == (IS_SUCCESSFUL_OP|IS_SERVICE_REQ)) { ! 192: ! 193: ddm_chip("selection seqstep=%d\n", ! 194: saveSeqStep & INS_STATE_MASK, 2,3,4,5); ! 195: ! 196: switch (saveSeqStep & INS_STATE_MASK) { ! 197: case 0: ! 198: /* ! 199: * No message phase. If we really wanted one, ! 200: * this could be significant... ! 201: */ ! 202: if(activeCmd->queueTag != QUEUE_TAG_NONTAGGED) { ! 203: /* ! 204: * This target can't do command queueing. ! 205: */ ! 206: [self disableMode:AM_CmdQueue]; ! 207: } ! 208: if(SDTR_State == SNS_HOST_INIT_NEEDED) { ! 209: /* ! 210: * We were trying to do an SDTR. ! 211: */ ! 212: [self disableMode:AM_Sync]; ! 213: SDTR_State = SNS_NONE; ! 214: } ! 215: ! 216: /* ! 217: * OK, let's try to continue following phase ! 218: * changes. ! 219: */ ! 220: scState = SCS_INITIATOR; ! 221: break; ! 222: ! 223: case 3: /* didn't complete cmd phase, parity? */ ! 224: case 4: /* everything worked */ ! 225: case 1: /* everything worked, SCMD_SELECT_ATN_STOP ! 226: * case */ ! 227: ! 228: /* ! 229: * We're connected. Start following the target's phase ! 230: * changes. ! 231: * ! 232: * If we're trying to do sync negotiation, ! 233: * this is the place to do it. In that case, we ! 234: * sent a SCMD_SELECT_ATN_STOP command, and ! 235: * ATN is now asserted (and we're hopefully in ! 236: * msg out phase). We want to send 5 bytes. ! 237: * Drop them into currMsgOut[] and prime the ! 238: * msgOutState machine. ! 239: */ ! 240: if(SDTR_State == SNS_HOST_INIT_NEEDED) { ! 241: [self createSDTR:currMsgOut inboundMsg:NULL]; ! 242: currMsgOutCnt = MSG_SDTR_LENGTH; ! 243: msgOutState = MOS_WAITING; ! 244: } ! 245: scState = SCS_INITIATOR; ! 246: break; ! 247: ! 248: case 2: ! 249: /* ! 250: * Either no command phase, or imcomplete message ! 251: * transfer. ! 252: */ ! 253: fifoDepth = READ_REG(currFifoState) & ! 254: FS_FIFO_LEVEL_MASK; ! 255: phase = saveStatus & SS_PHASEMASK; ! 256: ddm_chip("INCOMPLETE SELECT; fifoDepth %d phase %s\n", ! 257: fifoDepth, ! 258: IOFindNameForValue(phase, scsiPhaseValues), ! 259: 3,4,5); ! 260: if(activeCmd->queueTag != QUEUE_TAG_NONTAGGED) { ! 261: /* ! 262: * This target can't do command queueing. ! 263: */ ! 264: [self disableMode:AM_CmdQueue]; ! 265: } ! 266: ! 267: /* ! 268: * Spec says ATN is asserted if all message bytes ! 269: * were not sent. ! 270: */ ! 271: if(fifoDepth > activeCmd->cdbLength) { ! 272: WRITE_REG(scsiCmd, SCMD_CLR_ATN); ! 273: } ! 274: ! 275: /* ! 276: * OK, let's try to continue following phase ! 277: * changes. ! 278: */ ! 279: scState = SCS_INITIATOR; ! 280: break; ! 281: ! 282: default: ! 283: [self hwAbort:SR_IOST_HW ! 284: reason:"Selection sequence Error"]; ! 285: break; ! 286: } ! 287: } ! 288: else if(saveIntrStatus & IS_RESELECTED) { ! 289: /* ! 290: * We got reselected while trying to do a selection. ! 291: * Enqueue this cmdBuf on the HEAD of pendingQ, then deal ! 292: * with the reselect. ! 293: * Tricky case, we have to "deactivate" this command ! 294: * since this hwStart attempt failed. ! 295: */ ! 296: queue_enter_first(&pendingQ, activeCmd, commandBuf *, link); ! 297: [self deactivateCmd:activeCmd]; ! 298: ddm_chip("reselect while trying to select target %d\n", ! 299: activeCmd->scsiReq->target, 2,3,4,5); ! 300: activeCmd = NULL; ! 301: scState = SCS_DISCONNECTED; ! 302: ! 303: /* ! 304: * Go deal with reselect. ! 305: */ ! 306: [self fsmDisconnected]; ! 307: } ! 308: else { ! 309: ddm_err("fsmSelecting: Bogus select/reselect interrupt\n", ! 310: 1,2,3,4,5); ! 311: [self hwAbort:SR_IOST_HW ! 312: reason: "Bogus select/reselect interrupt"]; ! 313: return; ! 314: } ! 315: return; ! 316: } ! 317: ! 318: /* ! 319: * This one is illegal. ! 320: */ ! 321: - (void)fsmInitiator ! 322: { ! 323: ddm_chip("fsmInitiator\n", 1,2,3,4,5); ! 324: [self hwAbort:SR_IOST_HW reason:"Interrupt as Initiator"]; ! 325: } ! 326: ! 327: /* ! 328: * We just did a SCMD_INIT_CMD_CMPLT command, hopefully all that's left is ! 329: * to drop ACK. Command Complete message is handled in fscAcceptingMsg. ! 330: */ ! 331: - (void)fsmCompleting ! 332: { ! 333: ddm_chip("fsmCompleting\n", 1,2,3,4,5); ! 334: ASSERT(activeCmd != NULL); ! 335: if(saveIntrStatus & IS_DISCONNECT) { ! 336: ddm_err("unexpected completing disconnect\n", ! 337: 1,2,3,4,5); ! 338: return; ! 339: } ! 340: if(saveIntrStatus & IS_SUCCESSFUL_OP) { ! 341: /* ! 342: * Got both status and msg in fifo; Ack is still true. ! 343: */ ! 344: if((READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK) != 2) { ! 345: /* ! 346: * This is pretty bogus - we expect a status and ! 347: * msg in the fifo. ! 348: */ ! 349: [self hwAbort:SR_IOST_HW reason:"InitComplete fifo" ! 350: " level"]; ! 351: return; ! 352: } ! 353: activeCmd->scsiReq->scsiStatus = READ_REG(scsiFifo); ! 354: currMsgInCnt = 1; ! 355: currMsgIn[0] = READ_REG(scsiFifo); ! 356: ddm_chip("fsmCompleting: status 0x%x msg 0x%x\n", ! 357: activeCmd->scsiReq->scsiStatus, ! 358: currMsgIn[0], 3,4,5); ! 359: if (saveStatus & SS_PARITYERROR) { ! 360: ddm_err("fsmCompleting: parity error on msg in\n", ! 361: 1,2,3,4,5); ! 362: [self hwAbort:SR_IOST_PARITY ! 363: reason:"Parity error on message in"]; ! 364: return; ! 365: } ! 366: scState = SCS_ACCEPTINGMSG; ! 367: WRITE_REG(scsiCmd, SCMD_MSG_ACCEPTED); ! 368: return; ! 369: } else { ! 370: /* ! 371: * Must have just got a status byte only. This is kind of ! 372: * weird, but let's try to handle it. ! 373: */ ! 374: ddm_err("fsmCompleting: status only on complete\n", ! 375: 1,2,3,4,5); ! 376: if((READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK) != 1) { ! 377: [self hwAbort:SR_IOST_HW ! 378: reason:"Bad Fifo level on Cmd Complete"]; ! 379: return; ! 380: } ! 381: activeCmd->scsiReq->scsiStatus = READ_REG(scsiFifo); ! 382: if(saveStatus & SS_PARITYERROR) { ! 383: ddm_err("fsmCompleting: parity error on status\n", ! 384: 1,2,3,4,5); ! 385: [self hwAbort:SR_IOST_PARITY ! 386: reason:"Parity Error on Cmd Complete"]; ! 387: return; ! 388: } ! 389: ! 390: /* ! 391: * Back to watching phase changes. Why the target isn't in ! 392: * message in we have yet to find out. ! 393: */ ! 394: scState = SCS_INITIATOR; ! 395: } ! 396: } ! 397: ! 398: /* ! 399: * DMA Complete. ! 400: */ ! 401: - (void)fsmDMAing ! 402: { ! 403: u_int bytesMoved; ! 404: ! 405: ddm_chip("fsmDMAing\n", 1,2,3,4,5); ! 406: ASSERT(activeCmd != NULL); ! 407: ! 408: bytesMoved = [self dmaTerminate]; ! 409: if(bytesMoved > activeCmd->currentByteCount) { ! 410: ddm_err("fsmDMAing: DMA transfer count exceeeded\n", ! 411: 1,2,3,4,5); ! 412: ddm_err(" expected %d, moved %d\n", ! 413: activeCmd->currentByteCount, bytesMoved, 3,4,5); ! 414: bytesMoved = activeCmd->currentByteCount; ! 415: } ! 416: ((char *)activeCmd->currentPtr) += bytesMoved; ! 417: activeCmd->currentByteCount -= bytesMoved; ! 418: if(saveStatus & SS_PARITYERROR) { ! 419: ddm_err("fsmDMAing: SCSI Data Parity Error\n", 1,2,3,4,5); ! 420: [self hwAbort:SR_IOST_PARITY reason:"SCSI Data Parity Error"]; ! 421: return; ! 422: } ! 423: /* ! 424: * Back to watching phase changes. ! 425: */ ! 426: scState = SCS_INITIATOR; ! 427: } ! 428: ! 429: /* ! 430: * Just completed the SCMD_TRANSFER_INFO operation for message in. ACK is ! 431: * still true. Stash the current message byte in currMsgIn[] and proceed to ! 432: * fsmAcceptingMsg after a SCMD_MSG_ACCEPTED. ! 433: */ ! 434: - (void)fsmGettingMsg ! 435: { ! 436: BOOL setAtn = NO; ! 437: ! 438: ASSERT((activeCmd != NULL) || reselPending); ! 439: if(saveIntrStatus & IS_DISCONNECT) { ! 440: ddm_chip("fsmGettingMsg: message In Disconnect\n", 1,2,3,4,5); ! 441: /* ! 442: * This error is handled on return... ! 443: */ ! 444: return; ! 445: } ! 446: if((READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK) != 1) { ! 447: ddm_chip("Message In fifo error\n", 1,2,3,4,5); ! 448: [self hwAbort:SR_IOST_HW reason:"Message In fifo error"]; ! 449: return; ! 450: } ! 451: ! 452: currMsgIn[currMsgInCnt++] = READ_REG(scsiFifo); ! 453: if(currMsgInCnt > AMD_MSG_SIZE) { ! 454: [self hwAbort:SR_IOST_BV ! 455: reason:"Too Many Message bytes received"]; ! 456: } ! 457: if(saveStatus & SS_PARITYERROR) { ! 458: ddm_err("fsmGettingMsg: parity error on Message In\n", ! 459: 1,2,3,4,5); ! 460: [self hwAbort:SR_IOST_PARITY ! 461: reason:"parity error on Message In"]; ! 462: return; ! 463: } ! 464: ddm_chip("fsmGettingMsg: currMsgIn[%d] = 0x%x (%s)\n", currMsgInCnt-1, ! 465: currMsgIn[currMsgInCnt-1], ! 466: IOFindNameForValue(currMsgIn[currMsgInCnt-1], ! 467: scsiMsgValues), 4,5); ! 468: ! 469: /* ! 470: * Handle special cases. ! 471: */ ! 472: ! 473: /* ! 474: * 1. If this is the last byte of an unsolicited sync negotiation, ! 475: * we have to assert ATN right now. The message is actually ! 476: * fully parsed, and a response SDTR message created, in ! 477: * fsmAcceptingMsg. ! 478: * ! 479: * This parsing is pretty crude; if we come up with other special ! 480: * cases, we might rewrite this or come up with some state variables ! 481: * to help us. ! 482: */ ! 483: if((currMsgInCnt >= MSG_SDTR_LENGTH) && (SDTR_State == SNS_NONE)) { ! 484: ! 485: int start = currMsgInCnt - MSG_SDTR_LENGTH; ! 486: ! 487: if((currMsgIn[start] == MSG_EXTENDED) && ! 488: (currMsgIn[start+1] == (MSG_SDTR_LENGTH - 2)) && ! 489: (currMsgIn[start+2] == MSG_SDTR)) { ! 490: ddm_chip("UNSOLICITED SDTR IN; setting ATN\n", ! 491: 1,2,3,4,5); ! 492: WRITE_REG(scsiCmd, SCMD_SET_ATN); ! 493: setAtn = YES; ! 494: SDTR_State = SNS_TARGET_INIT; ! 495: } ! 496: } ! 497: ! 498: /* ! 499: * 2. If this was a message reject, it's possible that an extended ! 500: * message out was prematurely aborted, with ATN still true. ! 501: * Clear it so we don't do another (needless) message out. ! 502: * Avoid this, of course, if we set ATN in this method for ! 503: * any reason. ! 504: */ ! 505: if((currMsgIn[currMsgInCnt - 1] == MSG_MSGREJECT) && ! 506: (currMsgOutCnt > 1) && ! 507: !setAtn) { ! 508: ddm_chip("fsmGettingMsg: Message Reject; clearing ATN\n", ! 509: 1,2,3,4,5); ! 510: WRITE_REG(scsiCmd, SCMD_CLR_ATN); ! 511: } ! 512: ! 513: /* ! 514: * No need to clear FIFO; its depth was one on entry, and we read ! 515: * the byte. Note that clearing FIFO after the SCS_ACCEPTINGMSG ! 516: * might disturb possible sync data in transfer. ! 517: */ ! 518: WRITE_REG(scsiCmd, SCMD_MSG_ACCEPTED); ! 519: scState = SCS_ACCEPTINGMSG; ! 520: ! 521: } ! 522: ! 523: /* ! 524: * Just finished a message in; Ack is false. If phase is still ! 525: * message in, we're in the midst of an extended message or additional ! 526: * message bytes on reselect. Otherwise, message in is complete; ! 527: * process currMsgIn[]. ! 528: */ ! 529: - (void)fsmAcceptingMsg ! 530: { ! 531: unsigned char phase = saveStatus & SS_PHASEMASK; ! 532: unsigned index; ! 533: perTargetData *perTargetPtr; ! 534: ! 535: ddm_chip("fsmAcceptingMsg: phase %s\n", ! 536: IOFindNameForValue(phase, scsiPhaseValues), 2,3,4,5); ! 537: if((phase == PHASE_MSGIN) && !(saveIntrStatus & IS_DISCONNECT)) { ! 538: ! 539: /* ! 540: * More message bytes to follow. ! 541: * We have to qualify with !IS_DISCONNECT to cover the ! 542: * case of some targets (like the Exabyte tape drive) ! 543: * which bogusly keep CD, IO, and MSG asserted after ! 544: * they drop BSY upon command complete. ! 545: */ ! 546: WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); ! 547: WRITE_REG(scsiCmd, SCMD_TRANSFER_INFO); ! 548: scState = SCS_GETTINGMSG; ! 549: return; ! 550: } ! 551: ! 552: /* ! 553: * Message in complete. Handle message(s) in currMsgIn[]. ! 554: */ ! 555: if(reselPending) { ! 556: ! 557: /* ! 558: * We're expecting either: ! 559: * -- no messages, or ! 560: * -- queue tag and/or Save Pointers. ! 561: */ ! 562: unsigned char tag = QUEUE_TAG_NONTAGGED; ! 563: ! 564: ASSERT(activeCmd == NULL); ! 565: for(index=0; index<currMsgInCnt; index++) { ! 566: switch(currMsgIn[index]) { ! 567: case MSG_RESTOREPTRS: ! 568: ddm_chip("unnecessary restore pointers\n", ! 569: 1,2,3,4,5); ! 570: continue; /* to next message */ ! 571: ! 572: case MSG_SIMPLE_QUEUE_TAG: ! 573: if(index == (currMsgInCnt-1)) { ! 574: [self hwAbort: SR_IOST_BV ! 575: reason:"Queue tag message, no tag"]; ! 576: return; ! 577: } ! 578: tag = currMsgIn[++index]; ! 579: break; ! 580: ! 581: /* ! 582: * handle others here...? ! 583: */ ! 584: default: ! 585: IOLog("AMD53C974: bad msg (0x%x) after identify\n", ! 586: currMsgIn[index]); ! 587: [self hwAbort: SR_IOST_BV reason:NULL]; ! 588: return; ! 589: } ! 590: } ! 591: ! 592: if([self reselect:reselTarget ! 593: lun:reselLun ! 594: queueTag:tag] == YES) { ! 595: /* ! 596: * Found a disconnected commandBuf to reconnect. ! 597: * ! 598: * IDENTIFY msg implies restore ptrs. ! 599: */ ! 600: reselPending = 0; ! 601: ASSERT(activeCmd != NULL); ! 602: activeCmd->currentPtr = activeCmd->savedPtr; ! 603: activeCmd->currentByteCount = ! 604: activeCmd->savedByteCount; ! 605: scState = SCS_INITIATOR; ! 606: return; ! 607: } ! 608: else { ! 609: IOLog("AMD53C974: Illegal reselect (target %d lun " ! 610: "%d tag %d)\n", reselTarget, reselLun, tag); ! 611: [self hwAbort: SR_IOST_BV ! 612: reason:NULL]; ! 613: return; ! 614: } ! 615: } /* reselect pending */ ! 616: ! 617: /* ! 618: * Handle all other messages. ! 619: */ ! 620: ASSERT(activeCmd != NULL); ! 621: perTargetPtr = &perTarget[activeCmd->scsiReq->target]; ! 622: for(index=0; index<currMsgInCnt; index++) { ! 623: switch(currMsgIn[index]) { ! 624: case MSG_CMDCMPLT: ! 625: /* ! 626: * Bus really should be free; we came here from ! 627: * fsmCompleting. ! 628: */ ! 629: if(!(saveIntrStatus & IS_DISCONNECT)) { ! 630: ddm_err("fsmAcceptingMsg: Command Complete" ! 631: " but no Disconnect\n", 1,2,3,4,5); ! 632: [self hwAbort:SR_IOST_BV ! 633: reason:"No Disconnect On Command" ! 634: " Complete"]; ! 635: return; ! 636: } ! 637: ! 638: /* ! 639: * TA DA! ! 640: */ ! 641: scState = SCS_DISCONNECTED; ! 642: activeCmd->scsiReq->driverStatus = SR_IOST_GOOD; ! 643: [self ioComplete:activeCmd]; ! 644: activeCmd = NULL; ! 645: return; ! 646: ! 647: case MSG_DISCONNECT: ! 648: /* ! 649: * This could be in fsmGettingMsg, where we could ! 650: * handle it gracefully by doing a MSGREJ, but this ! 651: * is such a bogus error that we'll just reset the ! 652: * offender. ! 653: */ ! 654: if(!activeCmd->discEnable) { ! 655: ddm_chip("***Illegal Disconnect attempt\n", ! 656: 1,2,3,4,5); ! 657: IOLog("AMD53C974: Illegal disconnect attempt" ! 658: " on target %d\n", ! 659: activeCmd->scsiReq->target); ! 660: [self hwAbort:SR_IOST_BV ! 661: reason:NULL]; ! 662: return; ! 663: } ! 664: scState = SCS_DISCONNECTED; ! 665: [self disconnect]; ! 666: return; ! 667: ! 668: case MSG_SAVEPTRS: ! 669: activeCmd->savedPtr = activeCmd->currentPtr; ! 670: activeCmd->savedByteCount = ! 671: activeCmd->currentByteCount; ! 672: break; ! 673: ! 674: case MSG_RESTOREPTRS: ! 675: activeCmd->currentPtr = activeCmd->savedPtr; ! 676: activeCmd->currentByteCount = ! 677: activeCmd->savedByteCount; ! 678: break; ! 679: ! 680: case MSG_MSGREJECT: ! 681: /* ! 682: * look at last message sent; may have to ! 683: * disable sync or cmd queue mode for this target. ! 684: * This assumes that we don't send SDTR and queue tag ! 685: * in the same message. ! 686: */ ! 687: ddm_chip("fsmAcceptingMsg: MESSAGE REJECT RECEIVED " ! 688: "from target %d\n", ! 689: activeCmd->scsiReq->target, 2,3,4,5); ! 690: if(currMsgOutCnt == 0) { ! 691: /* ! 692: * Huh? We haven't sent a message recently... ! 693: */ ! 694: [self hwAbort:SR_IOST_BV ! 695: reason:"Unexpected Message Reject"]; ! 696: return; ! 697: } ! 698: switch(currMsgOut[0]) { ! 699: case MSG_SIMPLE_QUEUE_TAG: ! 700: [self disableMode:AM_CmdQueue]; ! 701: break; ! 702: case MSG_EXTENDED: ! 703: /* ! 704: * Only one we ever send is sync negotiation.. ! 705: */ ! 706: if(currMsgOut[2] == MSG_SDTR) { ! 707: [self disableMode:AM_Sync]; ! 708: SDTR_State = SNS_NONE; ! 709: break; ! 710: } ! 711: else { ! 712: [self hwAbort:SR_IOST_INT ! 713: reason:"Currupted Message Buffer"]; ! 714: return; ! 715: } ! 716: default: ! 717: IOLog("AMD53C974: %s Message Rejected\n", ! 718: IOFindNameForValue(currMsgOut[0], ! 719: scsiMsgValues)); ! 720: /* oh well... */ ! 721: break; ! 722: } ! 723: ! 724: /* ! 725: * In any case, we're definitely thru with the ! 726: * outbound message buffer. ! 727: */ ! 728: currMsgOutCnt = 0; ! 729: break; ! 730: ! 731: case MSG_LNKCMDCMPLT: ! 732: case MSG_LNKCMDCMPLTFLAG: ! 733: /* ! 734: * This should never happen, because hwStart trashes ! 735: * commands with the LINK bit on. ! 736: */ ! 737: [self hwAbort:SR_IOST_BV reason:"Linked command"]; ! 738: return; ! 739: ! 740: case MSG_EXTENDED: ! 741: /* ! 742: * The only valid one is sync negotiation.... ! 743: */ ! 744: switch(currMsgIn[index+2]) { ! 745: case MSG_SDTR: ! 746: if(currMsgIn[index+1] != (MSG_SDTR_LENGTH-2)) { ! 747: [self hwAbort:SR_IOST_BV ! 748: reason:"Bad Extended Msg Length"]; ! 749: return; ! 750: } ! 751: switch(SDTR_State) { ! 752: case SNS_HOST_INIT: ! 753: /* ! 754: * Just completed SDTR that we initiated. ! 755: */ ! 756: if([self parseSDTR:&currMsgIn[index]] ! 757: == NO) { ! 758: [self hwAbort:SR_IOST_HW ! 759: reason:"Bad SDTR Parameters"]; ! 760: return; ! 761: } ! 762: ! 763: /* ! 764: * Successful SDTR. ! 765: */ ! 766: ddm_chip("host-init SDTR COMPLETE\n", ! 767: 1,2,3,4,5); ! 768: SDTR_State = SNS_NONE; ! 769: break; ! 770: ! 771: case SNS_TARGET_INIT: ! 772: /* ! 773: * Target-initiated negotiaited. This ! 774: * was detected in fsmGettingMsg, where ! 775: * we set ATN true. ! 776: * Cons up a response and prime the message ! 777: * out state machine to send it. ! 778: */ ! 779: [self createSDTR : currMsgOut ! 780: inboundMsg : &currMsgIn[index]]; ! 781: currMsgOutCnt = MSG_SDTR_LENGTH; ! 782: msgOutState = MOS_WAITING; ! 783: break; ! 784: ! 785: default: ! 786: IOPanic("AMD53C974: Bad SDTR_State"); ! 787: } ! 788: ! 789: /* ! 790: * Skip over the rest of this message; index ! 791: * should point to the last byte of this message. ! 792: */ ! 793: index += (MSG_SDTR_LENGTH - 1); ! 794: break; ! 795: ! 796: default: ! 797: IOLog("AMD53C974: Unexpected Extended Message " ! 798: "(0x%x) Received\n", ! 799: currMsgIn[index+2]); ! 800: [self hwAbort:SR_IOST_BV reason:NULL]; ! 801: return; ! 802: } ! 803: break; ! 804: ! 805: default: ! 806: /* ! 807: * all others are unacceptable. ! 808: */ ! 809: IOLog("AMD53C974: Illegal message (0x%x)\n", ! 810: currMsgIn[index]); ! 811: [self messageOut:MSG_MSGREJECT]; ! 812: } ! 813: } /* for index */ ! 814: ! 815: /* ! 816: * Default case for 'break' from above switch - back to following ! 817: * phase changes. ! 818: */ ! 819: scState = SCS_INITIATOR; ! 820: } ! 821: ! 822: /* ! 823: * Just completed the SCMD_TRANSFER_INFO operation for message out. ! 824: */ ! 825: - (void)fsmSendingMsg ! 826: { ! 827: ddm_chip("fsmSendingMsg\n", 1,2,3,4,5); ! 828: ASSERT(activeCmd != NULL); ! 829: scState = SCS_INITIATOR; ! 830: if(SDTR_State == SNS_TARGET_INIT) { ! 831: /* ! 832: * If the message we just sent was a SDTR, we've just ! 833: * completed a target-initiated SDTR sequence. ! 834: * Note this assumes that an outbound SDTR in this ! 835: * situation is the only message in currMsgOut[]. ! 836: * This will have to change if we send a queue tag and ! 837: * SDTR in the sqame message. ! 838: */ ! 839: if((currMsgOutCnt == MSG_SDTR_LENGTH) && ! 840: (currMsgOut[0] == MSG_EXTENDED) && ! 841: (currMsgOut[1] == (MSG_SDTR_LENGTH - 2)) && ! 842: (currMsgOut[2] == MSG_SDTR)) { ! 843: ! 844: ddm_chip("fsmSendingMsg: target-init SDTR complete\n", ! 845: 1,2,3,4,5); ! 846: if([self parseSDTR:currMsgOut] == NO) { ! 847: /* ! 848: * Shouldn't fail; we generated this ! 849: * message ourself... ! 850: */ ! 851: IOPanic("AMD53C974: SDTR Problem\n"); ! 852: } ! 853: SDTR_State = SNS_NONE; ! 854: } ! 855: } ! 856: } ! 857: ! 858: ! 859: /* ! 860: * Just completed the SCMD_TRANSFER_INFO operation for command. ! 861: */ ! 862: - (void)fsmSendingCmd ! 863: { ! 864: ddm_chip("fsmSendingCmd\n", 1,2,3,4,5); ! 865: ASSERT(activeCmd != NULL); ! 866: scState = SCS_INITIATOR; ! 867: } ! 868: ! 869: /* ! 870: * Follow SCSI Phase change. Called while SCS_INITIATOR. ! 871: */ ! 872: - (void)fsmPhaseChange ! 873: { ! 874: int phase; ! 875: char *cp; ! 876: cdb_t *cdbp; ! 877: int i; ! 878: sc_status_t rtn; ! 879: ! 880: ddm_chip("fsmPhaseChange\n", 1,2,3,4,5); ! 881: ASSERT(activeCmd != NULL); ! 882: ! 883: /* ! 884: * Advance msg out state machine -- SCSI spec says if ! 885: * we do a msg out phase and then see another phase ! 886: * we can assume msg was transmitted without error. ! 887: * However, if we're in msg in, we may have a message reject ! 888: * coming in, so we'll keep currMsgOut[] valid in that case. ! 889: * ! 890: * FIXME - one case which this would not cover is the queue tag ! 891: * message saved in currMsgOut[] during selection. We don't ! 892: * go to MOS_SAWMSGOUT in that case. problem? ! 893: */ ! 894: phase = saveStatus & SS_PHASEMASK; ! 895: if ((phase != PHASE_MSGOUT) && ! 896: (phase != PHASE_MSGIN) && ! 897: (msgOutState == MOS_SAWMSGOUT)) { ! 898: msgOutState = MOS_NONE; ! 899: currMsgOutCnt = 0; ! 900: } ! 901: ! 902: /* ! 903: * If we just sent a host-initiated SDTR and the target went ! 904: * to something other than phase in, we assume that the negotiation ! 905: * failed. This is in violation of the spec, but the Sony CDROM ! 906: * does this. ! 907: */ ! 908: if((SDTR_State == SNS_HOST_INIT) && (phase != PHASE_MSGIN)) { ! 909: ddm_chip("IMPLIED SNS_HOST_INIT Reject\n", 1,2,3,4,5); ! 910: [self disableMode:AM_Sync]; ! 911: SDTR_State = SNS_NONE; ! 912: } ! 913: ! 914: /* ! 915: * make sure we start off with a clean slate. ! 916: * ! 917: * NO - this can disturb possible sync data in! We'll need to cover ! 918: * this in individual cases elsewhere... ! 919: */ ! 920: /* WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); */ ! 921: ddm_chip("fsmPhaseChange: phase = %s\n", ! 922: IOFindNameForValue(phase, scsiPhaseValues), 2,3,4,5); ! 923: ! 924: switch (phase) { ! 925: ! 926: case PHASE_COMMAND: ! 927: /* ! 928: * The normal case here is after a host-initiated SDTR ! 929: * sequence. ! 930: */ ! 931: ddm_chip("fsmPhaseChange: command phase\n", 1,2,3,4,5); ! 932: WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); ! 933: cdbp = &activeCmd->scsiReq->cdb; ! 934: cp = (char *)cdbp; ! 935: for(i=0; i<activeCmd->cdbLength; i++) { ! 936: WRITE_REG(scsiFifo, *cp++); ! 937: } ! 938: ! 939: #if 0 ! 940: /* ! 941: * This causes extra bytes to sit around in the fifo ! 942: * if we go straight to data phase after this, and ! 943: * we can't clear the fifo at that time in case ! 944: * we're in sync data in... ! 945: */ ! 946: /* ! 947: * fill fifo to avoid spurious command phase for target ! 948: * chips that try to get max command length ! 949: */ ! 950: for (i = 12 - activeCmd->cdbLength; i > 0; i--) ! 951: WRITE_REG(scsiFifo, 0); ! 952: #endif 0 ! 953: WRITE_REG(scsiCmd, SCMD_TRANSFER_INFO); ! 954: scState = SCS_SENDINGCMD; ! 955: break; ! 956: ! 957: case PHASE_DATAOUT: /* To Target from Initiator (write) */ ! 958: if(activeCmd->scsiReq->read) { ! 959: [self hwAbort:SR_IOST_BV reason:"bad i/o direction"]; ! 960: break; ! 961: } ! 962: if(rtn = [self dmaStart]) { ! 963: [self hwAbort:rtn ! 964: reason: IOFindNameForValue(rtn, ! 965: IOScStatusStrings)]; ! 966: break; ! 967: } ! 968: break; ! 969: ! 970: case PHASE_DATAIN: /* From Target to Initiator (read) */ ! 971: if(!activeCmd->scsiReq->read) { ! 972: [self hwAbort:SR_IOST_BV reason:"bad i/o direction"]; ! 973: break; ! 974: } ! 975: if(rtn = [self dmaStart]) { ! 976: [self hwAbort:rtn ! 977: reason: IOFindNameForValue(rtn, ! 978: IOScStatusStrings)]; ! 979: break; ! 980: } ! 981: break; ! 982: ! 983: case PHASE_STATUS: /* Status from Target to Initiator */ ! 984: /* ! 985: * fsmCompleting will collect the STATUS byte ! 986: * (and hopefully a MSG) from the fifo when this ! 987: * completes. ! 988: */ ! 989: scState = SCS_COMPLETING; ! 990: currMsgInCnt = 0; ! 991: WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); ! 992: WRITE_REG(scsiCmd, SCMD_INIT_CMD_CMPLT); ! 993: break; ! 994: ! 995: case PHASE_MSGIN: /* Message from Target to Initiator */ ! 996: scState = SCS_GETTINGMSG; ! 997: currMsgInCnt = 0; ! 998: WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); ! 999: WRITE_REG(scsiCmd, SCMD_TRANSFER_INFO); ! 1000: break; ! 1001: ! 1002: case PHASE_MSGOUT: /* Message from Initiator to Target */ ! 1003: WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); ! 1004: if(msgOutState == MOS_WAITING) { ! 1005: int i; ! 1006: ! 1007: ASSERT(currMsgOutCnt != 0); ! 1008: for(i=0; i<currMsgOutCnt; i++) { ! 1009: ddm_chip("msg out: writing 0x%x\n", ! 1010: currMsgOut[i], 2,3,4,5); ! 1011: WRITE_REG(scsiFifo, currMsgOut[i]); ! 1012: } ! 1013: msgOutState = MOS_SAWMSGOUT; ! 1014: if(SDTR_State == SNS_HOST_INIT_NEEDED) { ! 1015: /* ! 1016: * sending SDTR message after select. ! 1017: */ ! 1018: ASSERT(currMsgOut[0] == MSG_EXTENDED); ! 1019: ASSERT(currMsgOut[2] == MSG_SDTR); ! 1020: ASSERT(currMsgOutCnt == MSG_SDTR_LENGTH); ! 1021: ddm_chip("going to SNS_HOST_INIT\n", ! 1022: 1,2,3,4,5); ! 1023: SDTR_State = SNS_HOST_INIT; ! 1024: } ! 1025: } else { ! 1026: /* ! 1027: * Target went to msg out and we don't have ! 1028: * anything to send! Just give it a nop. ! 1029: */ ! 1030: ddm_chip("msg out: sending MSG_NOP\n", 1,2,3,4,5); ! 1031: WRITE_REG(scsiFifo, MSG_NOP); ! 1032: } ! 1033: ! 1034: scState = SCS_SENDINGMSG; ! 1035: /* ! 1036: * ATN is automatically cleared when transfer info completes. ! 1037: */ ! 1038: WRITE_REG(scsiCmd, SCMD_TRANSFER_INFO); ! 1039: break; ! 1040: ! 1041: default: ! 1042: [self hwAbort:SR_IOST_HW reason:"Bad SCSI phase"]; ! 1043: break; ! 1044: } ! 1045: } ! 1046: ! 1047: /* ! 1048: * Set up to send single-byte message. ! 1049: */ ! 1050: - (void) messageOut : (u_char)msg ! 1051: { ! 1052: ddm_chip("messageOut (0x%x)\n", msg, 2,3,4,5); ! 1053: currMsgOut[0] = msg; ! 1054: currMsgOutCnt = 1; ! 1055: msgOutState = MOS_WAITING; ! 1056: WRITE_REG(scsiCmd, SCMD_SET_ATN); ! 1057: } ! 1058: ! 1059: ! 1060: /* ! 1061: * Load syncPeriod, syncOffset for activeCmd per perTarget values. ! 1062: */ ! 1063: - (void)targetContext : (unsigned) target ! 1064: { ! 1065: perTargetData *perTargetPtr; ! 1066: ! 1067: perTargetPtr = &perTarget[target]; ! 1068: if(!syncModeEnable || ! 1069: perTargetPtr->syncDisable || ! 1070: (perTargetPtr->syncXferOffset == 0)) { ! 1071: /* ! 1072: * Easy case, async. ! 1073: */ ! 1074: WRITE_REG(syncOffset, 0); ! 1075: ddm_chip("targetContext(%d): ASYNC\n", target, 2,3,4,5); ! 1076: #ifdef DEBUG ! 1077: syncOffsetShadow = 0; ! 1078: #endif DEBUG ! 1079: } ! 1080: else { ! 1081: unsigned char periodReg; ! 1082: unsigned char offsetReg; ! 1083: ! 1084: periodReg = nsPeriodToSyncPeriodReg( ! 1085: perTargetPtr->syncXferPeriod, ! 1086: fastModeEnable, scsiClockRate); ! 1087: WRITE_REG(syncPeriod, periodReg); ! 1088: ! 1089: /* ! 1090: * FIXME - might eventually want to use non-default ! 1091: * values for RAD and RAA... ! 1092: */ ! 1093: offsetReg = (perTargetPtr->syncXferOffset | ! 1094: SOR_RAD_DEFAULT | SOR_RAA_DEFAULT); ! 1095: WRITE_REG(syncOffset, offsetReg); ! 1096: ddm_chip("targetContext(%d): period 0x%x offset %d\n", ! 1097: target, periodReg, offsetReg, 4,5); ! 1098: #ifdef DEBUG ! 1099: syncOffsetShadow = offsetReg; ! 1100: syncPeriodShadow = periodReg; ! 1101: #endif DEBUG ! 1102: } ! 1103: } ! 1104: ! 1105: /* ! 1106: * Parse and validate 5-byte SDTR message. If valid, save in perTarget ! 1107: * and in hardware. Returns YES if valid, else NO. ! 1108: * ! 1109: * Specified message buffer could be from either currMsgIn[] or ! 1110: * currMsgOut[]. ! 1111: */ ! 1112: - (BOOL)parseSDTR : (unsigned char *)sdtrMessage ! 1113: { ! 1114: unsigned nsPeriod; ! 1115: unsigned char fastClock; ! 1116: unsigned minPeriod; ! 1117: perTargetData *perTargetPtr; ! 1118: ! 1119: ASSERT(activeCmd != NULL); ! 1120: perTargetPtr = &perTarget[activeCmd->scsiReq->target]; ! 1121: ! 1122: if(sdtrMessage[0] != MSG_EXTENDED) { ! 1123: goto Bad; ! 1124: } ! 1125: if(sdtrMessage[1] != (MSG_SDTR_LENGTH - 2)) { ! 1126: goto Bad; ! 1127: } ! 1128: if(sdtrMessage[2] != MSG_SDTR) { ! 1129: goto Bad; ! 1130: } ! 1131: ! 1132: /* ! 1133: * period ! 1134: */ ! 1135: nsPeriod = SDTR_TO_NS_PERIOD(sdtrMessage[3]); ! 1136: fastClock = READ_REG(control3) & CR3_FAST_CLOCK; ! 1137: if(fastClock && fastModeEnable) { ! 1138: minPeriod = MIN_PERIOD_FASTCLK_FASTSCSI; ! 1139: } ! 1140: else { ! 1141: minPeriod = MIN_PERIOD_NORM; ! 1142: } ! 1143: if(nsPeriod < minPeriod) { ! 1144: goto Bad; ! 1145: } ! 1146: perTargetPtr->syncXferPeriod = nsPeriod; ! 1147: ! 1148: /* ! 1149: * Offset ! 1150: */ ! 1151: if(sdtrMessage[4] > AMD_MAX_SYNC_OFFSET) { ! 1152: goto Bad; ! 1153: } ! 1154: perTargetPtr->syncXferOffset = sdtrMessage[4]; ! 1155: ! 1156: /* ! 1157: * Success. ! 1158: */ ! 1159: perTargetPtr->syncDisable = 0; ! 1160: perTargetPtr->syncNegotNeeded = 0; ! 1161: [self targetContext:activeCmd->scsiReq->target]; ! 1162: ! 1163: ddm_chip("parseSDTR SUCCESS: %02x %02x %02x %02x %02x\n", ! 1164: sdtrMessage[0], sdtrMessage[1], sdtrMessage[2], ! 1165: sdtrMessage[3], sdtrMessage[4]); ! 1166: ddm_chip(" period %d offset %d\n", perTargetPtr->syncXferPeriod, ! 1167: perTargetPtr->syncXferOffset, 3,4,5); ! 1168: return YES; ! 1169: ! 1170: Bad: ! 1171: ddm_chip("parseSDTR FAIL: 02%x %02x %02x %02x %02x\n", ! 1172: sdtrMessage[0], sdtrMessage[1], sdtrMessage[2], ! 1173: sdtrMessage[3], sdtrMessage[4]); ! 1174: return NO; ! 1175: } ! 1176: ! 1177: /* ! 1178: * Cons up a SDTR message appropriate for both our hardware and a possible ! 1179: * target-generated SDTR message. If inboundMsg is NULL, we just use ! 1180: * the parameters we want. ! 1181: */ ! 1182: - (void)createSDTR : (unsigned char *)outboundMsg // required ! 1183: inboundMsg : (unsigned char *)inboundMsg ! 1184: { ! 1185: unsigned desiredNsPeriod; ! 1186: unsigned inboundNsPeriod; ! 1187: unsigned offset = AMD_MAX_SYNC_OFFSET; ! 1188: unsigned char fastClock; ! 1189: ! 1190: outboundMsg[0] = MSG_EXTENDED; ! 1191: outboundMsg[1] = MSG_SDTR_LENGTH - 2; ! 1192: outboundMsg[2] = MSG_SDTR; ! 1193: ! 1194: /* ! 1195: * period ! 1196: */ ! 1197: fastClock = READ_REG(control3) & CR3_FAST_CLOCK; ! 1198: if(fastClock && fastModeEnable) { ! 1199: desiredNsPeriod = MIN_PERIOD_FASTCLK_FASTSCSI; ! 1200: } ! 1201: else { ! 1202: desiredNsPeriod = MIN_PERIOD_NORM; ! 1203: } ! 1204: if(inboundMsg) { ! 1205: inboundNsPeriod = SDTR_TO_NS_PERIOD(inboundMsg[3]); ! 1206: } ! 1207: else { ! 1208: inboundNsPeriod = desiredNsPeriod; ! 1209: } ! 1210: if(inboundNsPeriod > desiredNsPeriod) { ! 1211: /* ! 1212: * Target is slower than us ! 1213: */ ! 1214: desiredNsPeriod = inboundNsPeriod; ! 1215: } ! 1216: outboundMsg[3] = NS_PERIOD_TO_SDTR(desiredNsPeriod); ! 1217: ! 1218: /* ! 1219: * Offset ! 1220: */ ! 1221: if(inboundMsg) { ! 1222: offset = inboundMsg[4]; ! 1223: if(offset > AMD_MAX_SYNC_OFFSET) { ! 1224: /* ! 1225: * target's buffer smaller than ours ! 1226: */ ! 1227: offset = AMD_MAX_SYNC_OFFSET; ! 1228: } ! 1229: } ! 1230: outboundMsg[4] = offset; ! 1231: ! 1232: ddm_chip("createSDTR: %02x %02x %02x %02x %02x\n", ! 1233: outboundMsg[0], outboundMsg[1], outboundMsg[2], ! 1234: outboundMsg[3], outboundMsg[4]); ! 1235: ddm_chip(" period %d offset %d\n", desiredNsPeriod, offset, 3,4,5); ! 1236: } ! 1237: ! 1238: /* ! 1239: * Disable specified mode for activeCmd's target. If mode is currently ! 1240: * enabled, we'll log a message to the console. ! 1241: */ ! 1242: - (void)disableMode : (AMD_Mode)mode ! 1243: { ! 1244: int target; ! 1245: perTargetData *perTargetPtr; ! 1246: const char *modeStr = NULL; ! 1247: ! 1248: ASSERT(activeCmd != NULL); ! 1249: target = activeCmd->scsiReq->target; ! 1250: perTargetPtr = &perTarget[target]; ! 1251: switch(mode) { ! 1252: case AM_Sync: ! 1253: if(perTargetPtr->syncDisable == 0) { ! 1254: perTargetPtr->syncDisable = 1; ! 1255: modeStr = "Synchronous Transfer Mode"; ! 1256: } ! 1257: [self targetContext:activeCmd->scsiReq->target]; ! 1258: break; ! 1259: case AM_CmdQueue: ! 1260: if(perTargetPtr->cmdQueueDisable == 0) { ! 1261: perTargetPtr->cmdQueueDisable = 1; ! 1262: modeStr = "Command Queueing"; ! 1263: } ! 1264: break; ! 1265: } ! 1266: ddm_chip("DISABLING %s for target %d\n", modeStr, target, 3,4,5); ! 1267: if(modeStr) { ! 1268: IOLog("AMD53C974: DISABLING %s for target %d\n", ! 1269: modeStr, target); ! 1270: } ! 1271: } ! 1272: ! 1273: @end /* AMD_SCSI(ChipPrivate) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.