|
|
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.