|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /** ! 26: * Copyright (c) 1994-1996 NeXT Software, Inc. All rights reserved. ! 27: * Copyright 1997 Apple Computer Inc. All Rights Reserved. ! 28: * @author Martin Minow mailto:[email protected] ! 29: * @revision 1997.02.17 Initial conversion from AMDPCSCSIDriver sources. ! 30: * ! 31: * Set tabs every 4 characters. ! 32: * ! 33: * Apple96CurioPublic.m - Chip-specific methods for Apple96 SCSI driver. ! 34: * ! 35: * Edit History ! 36: * 1997.02.18 MM Initial conversion from AMDPCSCSIDriver sources. ! 37: */ ! 38: #import "Apple96SCSI.h" ! 39: #import "Apple96CurioPublic.h" ! 40: #import "Apple96CurioPrivate.h" ! 41: #import "Apple96HWPrivate.h" ! 42: #import "Apple96CurioDBDMA.h" ! 43: #import "Apple96ISR.h" ! 44: #import <driverkit/generalFuncs.h> ! 45: #import <kernserv/prototypes.h> ! 46: ! 47: @implementation Apple96_SCSI(CurioPublic) ! 48: ! 49: /* ! 50: * This should be extended to perform a real chip self-test. ! 51: * (See the code in Copland DR1) ! 52: */ ! 53: - (IOReturn) hardwareChipSelfTest ! 54: { ! 55: IOReturn ioReturn = IO_R_SUCCESS; ! 56: UInt8 chipID; ! 57: ! 58: ENTRY("Cst hardwareChipSelfTest"); ! 59: [self disableAllInterrupts]; ! 60: CURIOresetChip(); ! 61: CURIOwriteRegister(rCF2, CF2_ENFEATURES); ! 62: CURIOsetCommandRegister(cNOP | bDMDEnBit); /* DMA Nop */ ! 63: chipID = CURIOreadRegister(rTCH); ! 64: CURIOresetChip(); ! 65: /* ! 66: * Allow the user to *disable* fast and sync if they ! 67: * were enabled by hardware probe, but do not allow the ! 68: * user to enable them if the hardware does not support ! 69: * the feature. ! 70: */ ! 71: switch (chipID) { ! 72: case 0xA2: /* NCR 53cf96 */ ! 73: case 0x12: /* AMD 53cf96 */ ! 74: gOptionSyncModeSupportedByHardware = 1; ! 75: gOptionFastModeSupportedByHardware = 1; ! 76: break; ! 77: default: /* NCR 53c96 */ ! 78: gOptionSyncModeSupportedByHardware = 0; ! 79: gOptionFastModeSupportedByHardware = 0; ! 80: break; ! 81: } ! 82: /* ! 83: * To do: write a test pattern into the fifo and check ! 84: * for correct count and bits. ! 85: */ ! 86: RESULT(ioReturn); ! 87: return (ioReturn); ! 88: } ! 89: ! 90: /* ! 91: * Reusable hardware initializer function. if resetSCSIBus is TRUE, this ! 92: * includes a SCSI reset. Handling of ioComplete of active and disconnected ! 93: * commands must be done elsewhere. Returns IO_R_SUCCESS. ! 94: * This is called with interrupts disabled. ! 95: */ ! 96: - (IOReturn) curioHardwareReset ! 97: : (Boolean) resetSCSIBus ! 98: reason : (const char *) reason ! 99: { ! 100: IOReturn ioReturn = IO_R_SUCCESS; ! 101: UInt8 configValue; ! 102: UInt8 clockConversionFactor; ! 103: UInt8 defaultSelectionTimeout; ! 104: ! 105: ENTRY("Chr curioHardwareReset"); ! 106: /* ! 107: * Temp for debugging ! 108: */ ! 109: scsiClockRate = kChipDefaultBusClockMHz; ! 110: /* ! 111: * First of all, reset interrupts, the SCSI chip, and the DMA engine. ! 112: */ ! 113: CURIOresetChip(); /* Clear out the chip */ ! 114: DBDMAreset(); /* Stop the DMA engine */ ! 115: CURIOreadInterruptRegister(); /* Clear pending interrupt */ ! 116: /* ! 117: * Initialize the chip. ! 118: */ ! 119: CURIOwriteRegister(rCF2, CF2_ENFEATURES); ! 120: CURIOsetCommandRegister(cNOP | bDMDEnBit); /* DMA Nop */ ! 121: ! 122: /* ! 123: * Init state variables. ! 124: */ ! 125: gFlagCheckForAnotherInterrupt = 0; ! 126: gBusState = SCS_DISCONNECTED; ! 127: gFlagBusBusy = FALSE; ! 128: gCurrentBusPhase = kBusPhaseBusFree; ! 129: /* ! 130: * Smash all active command state (just in case). ! 131: */ ! 132: gActiveCommand = NULL; ! 133: gCurrentTarget = kInvalidTarget; ! 134: gCurrentLUN = kInvalidLUN; ! 135: gMsgInState = kMsgInIdle; ! 136: gMsgOutPtr = gMsgPutPtr = gMsgOutBuffer; ! 137: ! 138: /* ! 139: * Configuration Register 1 ! 140: * Disable interrupt on initiator-instantiated bus reset (is this correct?) ! 141: * Enable parity. ! 142: * Set default bus ID (7) (This should be overriden by the Inspector) ! 143: */ ! 144: gInitiatorID = kDefaultInitiatorID; ! 145: configValue = CF1_SRD | CF1_ENABPAR | gInitiatorID; ! 146: if (gOptionExtendTiming) { ! 147: /* ! 148: * Per instance table. This slows down transfers on the bus. ! 149: */ ! 150: configValue |= CF1_SLOW; ! 151: } ! 152: ddmInit("Configuration 1 = 0x%x\n", configValue, 2,3,4,5); ! 153: CURIOwriteRegister(rCF1, configValue); ! 154: /* ! 155: * Clock factor and select timeout. ! 156: */ ! 157: ASSERT(scsiClockRate != 0); ! 158: /* ! 159: * Use the clock frequency (in MHz) to select the clock conversion ! 160: * factor. According to the NCR53CF94/96 data manual, the conversion ! 161: * factor is defined by the following table: Currently, we don't allow ! 162: * the caller to change selection timeout from the ANSI standard 250 Msec ! 163: * to avoid having to support floating-point register manipulation ! 164: */ ! 165: if (scsiClockRate < 10) { ! 166: IOLog("Apple96_SCSI: Clock %d MHZ too low; using 10 MHz\n", ! 167: scsiClockRate); ! 168: scsiClockRate = 10; ! 169: } ! 170: if (scsiClockRate > 40) { ! 171: IOLog("Apple96_SCSI: Clock %d MHZ too high; using 40 MHz\n", ! 172: scsiClockRate); ! 173: scsiClockRate = 40; ! 174: } ! 175: if (scsiClockRate <= 10) { ! 176: clockConversionFactor = ccf10MHz; ! 177: defaultSelectionTimeout = SelTO16Mhz; ! 178: } ! 179: else if (scsiClockRate <= 15) { ! 180: clockConversionFactor = ccf11to15MHz; ! 181: defaultSelectionTimeout = SelTO16Mhz; ! 182: } ! 183: else if (scsiClockRate <= 20) { ! 184: clockConversionFactor = ccf16to20MHz; ! 185: defaultSelectionTimeout = SelTO16Mhz; ! 186: } ! 187: else if (scsiClockRate <= 25) { ! 188: clockConversionFactor = ccf21to25MHz; ! 189: defaultSelectionTimeout = SelTO25Mhz; ! 190: } ! 191: else if (scsiClockRate <= 30) { ! 192: clockConversionFactor = ccf26to30MHz; ! 193: defaultSelectionTimeout = SelTO33Mhz; ! 194: } ! 195: else if (scsiClockRate <= 35) { ! 196: clockConversionFactor = ccf31to35MHz; ! 197: defaultSelectionTimeout = SelTO40Mhz; ! 198: } ! 199: else { ! 200: clockConversionFactor = ccf31to35MHz; ! 201: defaultSelectionTimeout = SelTO40Mhz; ! 202: } ! 203: ddmInit("clockFactor %d\n", clockConversionFactor, 2,3,4,5); ! 204: CURIOwriteRegister(rCKF, clockConversionFactor); ! 205: ddmInit("select timeout reg 0x%x\n", defaultSelectionTimeout, 2,3,4,5); ! 206: CURIOsetSelectionTimeout(defaultSelectionTimeout); ! 207: ! 208: /* ! 209: * Configuration Register 2 - enable extended features ! 210: * - mainly, 24-bit transfer count. ! 211: */ ! 212: CURIOwriteRegister(rCF2, CF2_ENFEATURES); ! 213: /* ! 214: * Configuration Register 3 ! 215: */ ! 216: configValue = 0; ! 217: if ((gOptionFastModeEnable && gOptionFastModeSupportedByHardware) ! 218: || scsiClockRate > 25) { ! 219: configValue |= CF3_FASTSCSI; ! 220: } ! 221: ddmInit("control3 = 0x%x\n", configValue, 2,3,4,5); ! 222: CURIOwriteRegister(rCF3, configValue); ! 223: /* ! 224: * Configuration Register 4 - glitch eater, active negation. ! 225: * Let's not worry about these whizzy features just yet. ! 226: */ ! 227: CURIOwriteRegister(rCF4, 0); ! 228: /* ! 229: * Go to async xfer mode for now. Sync gets enabled on a per-target ! 230: * basis in -targetContext. ! 231: */ ! 232: CURIOsetSynchronousOffset(0); ! 233: /* ! 234: * Reset SCSI bus, wait, clear possible interrupt. ! 235: */ ! 236: if (resetSCSIBus) { ! 237: if (reason != NULL) { ! 238: IOLog("%s: Resetting SCSI bus (%s)\n", ! 239: [self name], ! 240: reason ! 241: ); ! 242: } ! 243: else { ! 244: IOLog("%s: Resetting SCSI bus\n", [self name]); ! 245: } ! 246: CURIOresetSCSIBus(); ! 247: IOSleep(APPLE_SCSI_RESET_DELAY); ! 248: CURIOreadInterruptRegister(); ! 249: ddmInit("hardwareReset: enabling interrupts\n", 1,2,3,4,5); ! 250: } ! 251: ddmInit("hardwareReset: DONE\n", 1,2,3,4,5); ! 252: RESULT(ioReturn); ! 253: return (ioReturn); ! 254: } ! 255: ! 256: /* ! 257: * Terminate a DMA, including FIFO flush if necessary. Returns number of ! 258: * bytes transferred. ! 259: */ ! 260: - (UInt32) curioDMAComplete ! 261: { ! 262: UInt32 fifoResidualCount; ! 263: UInt32 actualTransferCount; ! 264: UInt32 dmaResidualCount; ! 265: UInt8 residualByte; ! 266: ! 267: ENTRY("Cdc curioDMAComplete"); ! 268: DBDMAstopTransfer(); ! 269: ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL); ! 270: /* ! 271: * Get residual count from DMA transfer. ! 272: */ ! 273: SynchronizeIO(); ! 274: dmaResidualCount = CURIOgetTransferCount(); ! 275: actualTransferCount = gActiveCommand->thisTransferLength ! 276: - dmaResidualCount; ! 277: ddmChip("curioDMAComplete (dma): thisTransferLength %d, actualTransferCount %d\n", ! 278: gActiveCommand->thisTransferLength, actualTransferCount, 3,4,5); ! 279: if (actualTransferCount > gActiveCommand->thisTransferLength) { ! 280: ddmError("fsmDMAComplete: DMA count exceeeded, %d expected, %d transferred\n", ! 281: gActiveCommand->thisTransferLength, ! 282: actualTransferCount, ! 283: 3, 4, 5 ! 284: ); ! 285: } ! 286: /* ! 287: * Advance the current data index. Note that gActiveCommand->currentDataIndex ! 288: * will exceed scsiReq->maxTransfer if the target tries to transfer too much ! 289: * data. We need to add a bit-bucket handler here. ! 290: */ ! 291: gActiveCommand->currentDataIndex += actualTransferCount; ! 292: [ gActiveCommand->mem setPosition : gActiveCommand->currentDataIndex ]; ! 293: /* ! 294: * Now, see if there are any bytes lurking in the fifo. ! 295: */ ! 296: SynchronizeIO(); ! 297: fifoResidualCount = CURIOgetFifoCount(); ! 298: if (fifoResidualCount != 0) { ! 299: ddmChip("curioDMAComplete: fifoResidualCount %d\n", ! 300: fifoResidualCount, 2, 3,4,5); ! 301: if (gActiveCommand->scsiReq->read) { ! 302: /* ! 303: * Try to move residual data from the fifo into the ! 304: * user's buffer. ! 305: */ ! 306: /* ++ Radar xxxxxx use IOMemoryDescriptor */ ! 307: [ gActiveCommand->mem setPosition : gActiveCommand->currentDataIndex ]; ! 308: for (;;) { ! 309: SynchronizeIO(); ! 310: if (CURIOgetFifoCount() == 0) { ! 311: break; ! 312: } ! 313: else { ! 314: SynchronizeIO(); ! 315: residualByte = CURIOgetFifoByte(); ! 316: [gActiveCommand->mem writeToClient : &residualByte count : 1]; ! 317: gActiveCommand->currentDataIndex++; ! 318: } ! 319: } ! 320: actualTransferCount += fifoResidualCount; /* Radar 2207320 */ ! 321: /* -- Radar xxxxxx use IOMemoryDescriptor */ ! 322: } ! 323: else { ! 324: CURIOflushFifo(); ! 325: CURIOclearTransferCountZeroBit(); ! 326: actualTransferCount -= fifoResidualCount; /* Radar 2207320 */ ! 327: gActiveCommand->currentDataIndex -= fifoResidualCount; ! 328: } ! 329: if ( gActiveCommand->mem ) /* Radar 2211821 */ ! 330: [ gActiveCommand->mem setPosition : gActiveCommand->currentDataIndex ]; ! 331: } ! 332: RESULT(actualTransferCount); ! 333: return (actualTransferCount); ! 334: } ! 335: ! 336: /* ! 337: * Prepare for power down. ! 338: * -- reset SCSI bus to get targets back to known state ! 339: * -- reset chip ! 340: * Note: this presumes that a higher-power has cleaned out all ! 341: * pending and in-progress commands. ! 342: */ ! 343: - (void) powerDown ! 344: { ! 345: ENTRY("Cpd powerDown"); ! 346: DBDMAreset(); /* Stop the DMA engine */ ! 347: CURIOresetSCSIBus(); /* Reset the SCSI bus */ ! 348: IOSleep(APPLE_SCSI_RESET_DELAY); /* Stall after reset */ ! 349: CURIOreadInterruptRegister(); /* Clear the interrupt */ ! 350: CURIOresetChip(); /* Clear out the chip */ ! 351: CURIOreadInterruptRegister(); /* Clear pending interrupt */ ! 352: EXIT(); ! 353: } ! 354: ! 355: - (void) logRegisters ! 356: : (Boolean) examineInterruptRegister ! 357: reason : (const char *) reason ! 358: { ! 359: #if 1 || DEBUG ! 360: UInt8 currentStatus; ! 361: UInt8 currentInterrupt; ! 362: UInt8 fifoDepth; ! 363: UInt32 transferCount; ! 364: ! 365: ENTRY("Clo logRegisters"); ! 366: if (reason != NULL) { ! 367: IOLog("%s: *** Log registers: %s\n", [self name], reason); ! 368: } ! 369: IOLog("%s: *** last chip status 0x%02x, interrupt 0x%02x, command 0x%02x\n", ! 370: [self name], ! 371: gSaveStatus, ! 372: gSaveInterrupt, ! 373: CURIOreadCommandRegister() ! 374: ); ! 375: IOLog("%s: *** bus state %s, bus phase %s, bus %s\n", ! 376: [self name], ! 377: IOFindNameForValue(gBusState, gAutomatonStateValues), ! 378: IOFindNameForValue(gCurrentBusPhase, scsiPhaseValues), ! 379: (gFlagBusBusy) ? "busy" : "free" ! 380: ); ! 381: currentStatus = CURIOreadStatusRegister(); ! 382: if (examineInterruptRegister) { ! 383: currentInterrupt = CURIOreadInterruptRegister(); /* Possible problem */ ! 384: IOLog("%s: *** current status %02x current intrStatus %02x\n", ! 385: [self name], ! 386: currentStatus, ! 387: currentInterrupt ! 388: ); ! 389: } ! 390: else { ! 391: IOLog("%s: *** current status %02x\n", ! 392: [self name], ! 393: currentStatus ! 394: ); ! 395: } ! 396: IOLog("%s: *** syncOffset %d syncPeriod 0x%02x\n", ! 397: [self name], ! 398: gLastSynchronousOffset, ! 399: gLastSynchronousPeriod ! 400: ); ! 401: SynchronizeIO(); ! 402: fifoDepth = CURIOgetFifoCount(); ! 403: SynchronizeIO(); ! 404: transferCount = CURIOgetTransferCount(); ! 405: IOLog("%s: *** fifoDepth %d transfer count %d\n", ! 406: [self name], ! 407: fifoDepth, ! 408: transferCount ! 409: ); ! 410: if (gActiveCommand != NULL) { ! 411: [self logCommand ! 412: : gActiveCommand ! 413: logMemory : TRUE ! 414: reason : "Active Command" ! 415: ]; ! 416: } ! 417: [self logChannelCommandArea : reason]; ! 418: [self logIOMemoryDescriptor : reason]; ! 419: [self logTimestamp : reason]; ! 420: EXIT(); ! 421: #endif /* DEBUG */ ! 422: } ! 423: ! 424: - (void) logCommand ! 425: : (const CommandBuffer *) commandPtr ! 426: logMemory : (Boolean) isLogMemoryNeeded ! 427: reason : (const char *) reason; ! 428: { ! 429: #if DEBUG ! 430: ENTRY("Clc logCommand"); ! 431: if (reason == NULL) { ! 432: reason = ""; ! 433: } ! 434: if (commandPtr == NULL) { ! 435: IOLog("%s: *** no command to log: %s.\n", ! 436: [self name], ! 437: reason ! 438: ); ! 439: } ! 440: else { ! 441: IOLog("%s: *** %s\n", ! 442: [self name], ! 443: reason ! 444: ); ! 445: IOLog("%s: *** %scommand at %08x, tag %02x, cdbLength %d, scsiReq %08x\n", ! 446: [self name], ! 447: (commandPtr == gActiveCommand) ? "active " : "", ! 448: (UInt32) commandPtr, ! 449: commandPtr->queueTag, ! 450: commandPtr->cdbLength, ! 451: (UInt32) commandPtr->scsiReq ! 452: ); ! 453: IOLog("%s: *** currentDataIndex %d, saved %d, thisTransfer %d\n", ! 454: [self name], ! 455: commandPtr->currentDataIndex, ! 456: commandPtr->savedDataIndex, ! 457: commandPtr->thisTransferLength ! 458: ); ! 459: IOLog("%s: *** active %d, is autosense %d, sense status %02x\n", ! 460: [self name], ! 461: commandPtr->flagActive, ! 462: commandPtr->flagIsAutosense, ! 463: commandPtr->autosenseStatus ! 464: ); ! 465: #if __IO_MEMORY_DESCRIPTOR_DEBUG__ ! 466: if (commandPtr->mem != NULL) { ! 467: [commandPtr->mem debugLogWithContainer : [self name]]; ! 468: } ! 469: #endif ! 470: if (commandPtr->scsiReq != NULL) { ! 471: IOSCSIRequest *scsiReq = commandPtr->scsiReq; ! 472: #if (SERIOUS_DEBUGGING || DUMP_USER_BUFFER) && __IO_MEMORY_DESCRIPTOR_DEBUG__ ! 473: if (isLogMemoryNeeded ! 474: && scsiReq != NULL ! 475: && commandPtr->mem != NULL) { ! 476: IOMemoryDescriptorContext context; ! 477: LogicalRange range; ! 478: ByteCount newPosition = 0; ! 479: ! 480: [cmdbuf->mem context : &context]; ! 481: [cmdbuf->mem setOffset : 0]; ! 482: while (newPosition < scsiReq->bytesTransferred ! 483: && [cmdbuf->mem getLogicalRange ! 484: : 1 ! 485: maxByteCount : scsiReq->bytesTransferred - newPosition ! 486: newPosition : &newPosition ! 487: actualRanges : NULL ! 488: logicalRanges : &range] != 0) { ! 489: [self logMemory : range.address ! 490: length : range.length ! 491: reason : "User buffer at I/O Complete" ! 492: ]; ! 493: } ! 494: [cmdbuf->mem setContext : &context]; ! 495: } ! 496: #endif /* (SERIOUS_DEBUGGING || DUMP_USER_BUFFER) && __IO_MEMORY_DESCRIPTOR_DEBUG__ */ ! 497: IOLog("%s: *** %d.%d, cdb: " ! 498: "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n", ! 499: [self name], ! 500: scsiReq->target, ! 501: scsiReq->lun, ! 502: ((UInt8 *) &scsiReq->cdb)[0], ! 503: ((UInt8 *) &scsiReq->cdb)[1], ! 504: ((UInt8 *) &scsiReq->cdb)[2], ! 505: ((UInt8 *) &scsiReq->cdb)[3], ! 506: ((UInt8 *) &scsiReq->cdb)[4], ! 507: ((UInt8 *) &scsiReq->cdb)[5], ! 508: ((UInt8 *) &scsiReq->cdb)[6], ! 509: ((UInt8 *) &scsiReq->cdb)[7], ! 510: ((UInt8 *) &scsiReq->cdb)[8], ! 511: ((UInt8 *) &scsiReq->cdb)[9], ! 512: ((UInt8 *) &scsiReq->cdb)[10], ! 513: ((UInt8 *) &scsiReq->cdb)[11] ! 514: ); ! 515: IOLog("%s: *** read %d, disconnect %d, maxTransfer %d, bytesTransferred %d\n", ! 516: [self name], ! 517: scsiReq->read, ! 518: scsiReq->disconnect, ! 519: scsiReq->maxTransfer, ! 520: scsiReq->bytesTransferred ! 521: ); ! 522: IOLog("%s: *** driverStatus %d, scsiStatus %02x, sense: " ! 523: "%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n", ! 524: [self name], ! 525: scsiReq->driverStatus, ! 526: scsiReq->scsiStatus, ! 527: ((UInt8 *) &scsiReq->senseData)[0], ! 528: ((UInt8 *) &scsiReq->senseData)[1], ! 529: ((UInt8 *) &scsiReq->senseData)[2], ! 530: ((UInt8 *) &scsiReq->senseData)[3], ! 531: ((UInt8 *) &scsiReq->senseData)[4], ! 532: ((UInt8 *) &scsiReq->senseData)[5], ! 533: ((UInt8 *) &scsiReq->senseData)[6], ! 534: ((UInt8 *) &scsiReq->senseData)[7], ! 535: ((UInt8 *) &scsiReq->senseData)[8], ! 536: ((UInt8 *) &scsiReq->senseData)[9], ! 537: ((UInt8 *) &scsiReq->senseData)[10], ! 538: ((UInt8 *) &scsiReq->senseData)[11] ! 539: ); ! 540: } ! 541: } ! 542: EXIT(); ! 543: #endif /* DEBUG */ ! 544: } ! 545: ! 546: - (void) logTimestamp ! 547: : (const char *) reason ! 548: { ! 549: #if DEBUG ! 550: /* ! 551: * kMaxTimestamp should be greater than twice the expected method depth ! 552: * since, if we dump the timestamp after it has wrapped around, we expect ! 553: * to lose earlier entries and, hence, the shallower method starts. ! 554: */ ! 555: #ifndef kMaxTimestampStack ! 556: #define kMaxTimestampStack 64 ! 557: #endif ! 558: ! 559: TimestampDataRecord stack[kMaxTimestampStack + 1]; /* Allocate one extra */ ! 560: UInt32 index = 0; ! 561: int start; ! 562: UInt32 count; ! 563: UInt32 maxDepth = 0; ! 564: Boolean wasEnabled; ! 565: char work[8]; ! 566: struct timeval tv; ! 567: ns_time_t lastEventTime; ! 568: UInt32 elapsed; ! 569: UInt32 sinceMethodStart; ! 570: ! 571: /* ENTRY("Clt logTimestamp"); ** No ENTRY so we don't corrupt timestamps */ ! 572: if (reason != NULL) { ! 573: IOLog("%s: *** Log timestamp: %s\n", [self name], reason); ! 574: } ! 575: /* ! 576: * In case something we call causes timestamping, we want to ! 577: * avoid getting into an infinite loop. ! 578: */ ! 579: wasEnabled = EnableTimestamp(FALSE); ! 580: lastEventTime = stack[0].eventTime; /* Initialization hack */ ! 581: for (count = 1; ReadTimestamp(&stack[index]); count++) { ! 582: work[0] = (stack[index].timestampTag) >> 24 & 0xFF; ! 583: work[1] = (stack[index].timestampTag) >> 16 & 0xFF; ! 584: work[2] = (stack[index].timestampTag) >> 8 & 0xFF; ! 585: work[3] = (stack[index].timestampTag) >> 0 & 0xFF; ! 586: work[4] = '\0'; ! 587: elapsed = (unsigned) stack[index].eventTime - lastEventTime; ! 588: lastEventTime = stack[index].eventTime; ! 589: ns_time_to_timeval(stack[index].eventTime, &tv); switch (work[0]) { ! 590: case '+': /* Entering a method */ ! 591: IOLog("%s: '%s' %u.%06u %u.%03u 0.0 %d\n", ! 592: [self name], ! 593: work, ! 594: tv.tv_sec, ! 595: tv.tv_usec, ! 596: elapsed / 1000, ! 597: elapsed - ((elapsed / 1000) * 1000), ! 598: (int) stack[index].timestampValue ! 599: ); ! 600: if (index < kMaxTimestampStack) { ! 601: ++index; ! 602: if (index > maxDepth) { ! 603: maxDepth = index; ! 604: } ! 605: } ! 606: break; ! 607: case '=': /* Intermediate tag: find the method start */ ! 608: case '-': /* End of method: find the method start */ ! 609: sinceMethodStart = 0; ! 610: for (start = index - 1; start >= 0; --start) { ! 611: if ((stack[start].timestampTag & 0x00FFFFFF) ! 612: == (stack[index].timestampTag & 0x00FFFFFF)) { ! 613: sinceMethodStart = (unsigned) stack[index].eventTime ! 614: - stack[start].eventTime; ! 615: break; ! 616: } ! 617: } ! 618: IOLog("%s: '%s' %u.%06u %u.%03u %u.%03u %d\n", ! 619: [self name], ! 620: work, ! 621: tv.tv_sec, ! 622: tv.tv_usec, ! 623: elapsed / 1000, ! 624: elapsed - ((elapsed / 1000) * 1000), ! 625: sinceMethodStart / 1000, ! 626: sinceMethodStart - ((sinceMethodStart / 1000) * 1000), ! 627: (int) stack[index].timestampValue ! 628: ); ! 629: if (start >= 0 && work[0] == '-') { ! 630: index = start; /* Pop the stack */ ! 631: } ! 632: break; ! 633: case '>': /* Tag: log the value in hex */ ! 634: case '<': /* Tag: log the value in hex */ ! 635: case '*': /* Tag: log the value in hex */ ! 636: IOLog("%s: '%s' %u.%06u %u.%03u 0.0 %08x\n", ! 637: [self name], ! 638: work, ! 639: tv.tv_sec, ! 640: tv.tv_usec, ! 641: elapsed / 1000, ! 642: elapsed - ((elapsed / 1000) * 1000), ! 643: stack[index].timestampValue ! 644: ); ! 645: /* The stack does not change */ ! 646: break; ! 647: default: ! 648: IOLog("%s: '%s' %u.%06u %u.%03u 0.0 %08x\n", ! 649: [self name], ! 650: work, ! 651: tv.tv_sec, ! 652: tv.tv_usec, ! 653: elapsed / 1000, ! 654: elapsed - ((elapsed / 1000) * 1000), ! 655: stack[index].timestampValue ! 656: ); ! 657: break; ! 658: } ! 659: } ! 660: IOLog("%s: *** %d timestamps, %d max method depth\n", ! 661: [self name], ! 662: count, ! 663: maxDepth ! 664: ); ! 665: EnableTimestamp(wasEnabled); ! 666: /* EXIT(); ** No EXIT to avoid corrupting timestamps */ ! 667: #endif /* DEBUG */ ! 668: } ! 669: ! 670: - (void) logMemory ! 671: : (const void *) buffer ! 672: length : (UInt32) length ! 673: reason : (const char *) reason ! 674: { ! 675: #ifndef kMaxLogMemoryLength ! 676: #define kMaxLogMemoryLength 512 ! 677: #endif ! 678: #if DEBUG ! 679: const UInt8 *ptr; ! 680: UInt32 start; ! 681: UInt32 i; ! 682: char work[32]; ! 683: ! 684: ENTRY("Clm logMemory"); ! 685: if (reason == NULL) { ! 686: reason = ""; ! 687: } ! 688: IOLog("%s: *** %s: log memory from %08x for %d bytes\n", ! 689: [self name], ! 690: reason, ! 691: (UInt32) buffer, ! 692: length ! 693: ); ! 694: if (buffer != NULL) { ! 695: if (length > kMaxLogMemoryLength) { ! 696: length = kMaxLogMemoryLength; ! 697: IOLog("%s: *** Logging first %d bytes\n", [self name], length); ! 698: } ! 699: ptr = (const UInt8 *) buffer; ! 700: for (start = 0; start < length; start += 16) { ! 701: IOLog("%s: *** %08x %3d:", ! 702: [self name], ! 703: (UInt32) &ptr[start], ! 704: start ! 705: ); ! 706: for (i = 0; i < 16; i++) { ! 707: if ((i % 4) == 0) { ! 708: IOLog(" "); ! 709: } ! 710: if (start + i >= length) { ! 711: IOLog(" "); ! 712: work[i] = '\0'; ! 713: } ! 714: else { ! 715: IOLog("%02x", ptr[start + i]); ! 716: work[i] = (ptr[start + i] >= ' ' && ptr[start + i] <= '~') ! 717: ? ptr[start + i] : '.'; ! 718: } ! 719: } ! 720: work[i] = '\0'; ! 721: IOLog(" %s\n", work); ! 722: } ! 723: } ! 724: EXIT(); ! 725: #endif /* DEBUG */ ! 726: } ! 727: ! 728: @end /* Apple96_SCSI(CurioPublic) */ ! 729: ! 730: /* end of Apple96_Chip.m */ ! 731:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.