|
|
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.13 Initial conversion from AMDPCSCSIDriver sources.
30: *
31: * Apple96PCISCSI.m - Architecture-specific methods for Apple96 SCSI driver.
32: *
33: * Edit History
34: * 1997.02.13 MM Initial conversion from AMDPCSCSIDriver sources.
35: * 1997.07.31 MM Radar 1670762: Correct transfer length for > 64K transfers.
36: * rewrote hardwareGetNextContiguousPhysicalTransferRange.
37: * This no longer combines adjacent physical pages, which
38: * greatly simplifies hardwareInitializeRequestCCL (which was
39: * also rewritten). Remove hard-wired logical page size values.
40: */
41: #import "Apple96SCSI.h"
42: #import <driverkit/generalFuncs.h>
43: #import <driverkit/kernelDriver.h>
44: #import <driverkit/align.h>
45: #import <kernserv/prototypes.h>
46: #import <mach/kern_return.h>
47: #import <mach/mach_interface.h>
48: #import "Apple96SCSIPrivate.h"
49: #import "Apple96HWPrivate.h"
50: #import "Apple96CurioDBDMA.h"
51: #import "Apple96CurioPrivate.h"
52: #import "bringup.h"
53: #import "Apple96Curio.h"
54: #import "MacSCSICommand.h"
55: /* bzero is defined in string.h */
56: #import <string.h>
57:
58: enum {
59: kCURIORegisterBase = 0,
60: kDBDMARegisterBase = 1
61: };
62:
63: /**
64: * These are the hardware-specific methods.
65: */
66: @implementation Apple96_SCSI(HardwarePrivate)
67:
68: /**
69: * Fetch the device's bus address and allocate one page
70: * of memory for the channel command. (Strictly speaking, we don't
71: * need an entire page, but we can use the rest of the page for
72: * a permanent status log).
73: *
74: * @param deviceDescription Specify the device to initialize.
75: * @return IO_R_SUCCESS if successful, else an error status.
76: */
77: - (IOReturn) hardwareAllocateHardwareAndChannelMemory
78: : deviceDescription
79: {
80: IOReturn ioReturn = IO_R_SUCCESS;
81: enum {
82: kCurioRegisterBase = 0,
83: kDBDMARegisterBase = 1,
84: kNumberRegisters = 2
85: };
86:
87: ENTRY("Hal hardwareAllocateHardwareAndChannelMemory");
88: gSCSIPhysicalAddress = 0;
89: gSCSIRegisterLength = 0;
90: gSCSILogicalAddress = NULL;
91: gDBDMAPhysicalAddress = 0;
92: gDBDMARegisterLength = 0;
93: gDBDMALogicalAddress = NULL;
94: /*
95: * Set the default selection timeout to the MESH value (10 msec units).
96: */
97: // gSelectionTimeout = 250 / 10;
98: /*
99: * Retrieve the system-wide logical page size and define a mask that
100: * contains only the low-order bits. Part of Radar 1670762.
101: */
102: gPageSize = page_size;
103: gPageMask = gPageSize - 1;
104: /*
105: * Allocate a page of wired-down memory in the kernel. Although
106: * Driver Kit provides a memory allocator, IOMalloc, it does
107: * not guarantee page alignment. Thus, we call the Mach kernel
108: * routine. According to the description of kalloc(), 4096 is
109: * the smallest amount of memory we can allocate. The channel
110: * command area will fit into the start of this area and the
111: * autosense area will be placed at the end.
112: */
113: gChannelCommandAreaSize = gPageSize;
114: gChannelCommandArea = (DBDMADescriptor *) kalloc(gChannelCommandAreaSize);
115: if (gChannelCommandArea == NULL) {
116: IOLog("%s: Cannot allocate channel command area %d bytes, fatal.\n",
117: [self name],
118: gChannelCommandAreaSize
119: );
120: ioReturn = IO_R_NO_MEMORY;
121: }
122: if (ioReturn == IO_R_SUCCESS) {
123: if (IOIsAligned(gChannelCommandArea, gPageSize) == 0) {
124: IOLog("%s: Command area at %08x is not page-aligned.\n",
125: [self name],
126: (UInt32) gChannelCommandArea
127: );
128: ioReturn = IO_R_NO_MEMORY;
129: }
130: }
131: if (ioReturn == IO_R_SUCCESS) {
132:
133: /*
134: * Curio-specific: use the high-end of the descriptor area for
135: * the bit bucket and autosense buffer.
136: */
137: UInt32 autosenseSize;
138:
139: autosenseSize = kMaxAutosenseByteCount;
140: gAutosenseArea = (esense_reply_t *)
141: (((UInt32) gChannelCommandArea)
142: + gChannelCommandAreaSize
143: - autosenseSize);
144: /*
145: * Determine the number of DBDMA descriptors that fit in
146: * the channel command area.
147: */
148: gDBDMADescriptorMax = (gChannelCommandAreaSize - autosenseSize)
149: / sizeof (DBDMADescriptor);
150: /*
151: * Fetch the logical and physical addresses for the
152: * Curio and DBDMA chips.
153: */
154: #if 0
155: do {
156: IORange *memoryRangeList;
157: UInt32 numMemoryRanges;
158: int i;
159:
160: memoryRangeList = [deviceDescription memoryRangeList];
161: numMemoryRanges = [deviceDescription numMemoryRanges];
162: for (i = 0; i < numMemoryRanges; i++) {
163: ddmDMA("%s: memory range[%d] %08x (%d)\n",
164: [self name],
165: i,
166: memoryRangeList[i].start,
167: memoryRangeList[i].size
168: );
169: }
170: if (numMemoryRanges != kNumberRegisters) {
171: ddmDMA("%s: Expect %d memory ranges, got %d. Fatal.\n",
172: [self name],
173: kNumberRegisters,
174: numMemoryRanges
175: );
176: ioReturn = IO_R_INVALID; /* This "can't happen" */
177: }
178: } while (0);
179: #endif
180: }
181: #if 0
182: if (ioReturn == IO_R_SUCCESS) {
183: /*
184: * We know that the first range describes the SCSI chip,
185: * and the second range describes the DBDMA chip.
186: */
187: gSCSIPhysicalAddress = (PhysicalAddress) memoryRangeList[kCURIORegisterBase].start;
188: gSCSIRegisterLength = memoryRangeList[kCURIORegisterBase].size;
189: gDBDMAPhysicalAddress = (PhysicalAddress) memoryRangeList[kDBDMARegisterBase].start;
190: gDBDMARegisterLength = memoryRangeList[kDBDMARegisterBase].size;
191: /*
192: * Weave together the logical and physical addresses.
193: * First, map the SCSI and DBDMA chips into our address space.
194: */
195: ioReturn = IOMapPhysicalIntoIOTask(
196: (UInt32) gSCSIPhysicalAddress,
197: gSCSIRegisterLength,
198: (vm_offset_t *) &gSCSILogicalAddress
199: );
200: if (ioReturn != IO_R_SUCCESS) {
201: ddmDMA("%s: Mapping SCSI chip at %08x [%d] to virtual address:"
202: " error %d (%s), fatal.\n",
203: [self name],
204: gSCSIPhysicalAddress,
205: gSCSIRegisterLength,
206: ioReturn,
207: [self stringFromReturn:ioReturn]
208: );
209: }
210: }
211: if (ioReturn == IO_R_SUCCESS) {
212: ioReturn = IOMapPhysicalIntoIOTask(
213: (UInt32) gDBDMAPhysicalAddress,
214: gDBDMARegisterLength,
215: (vm_offset_t *) &gDBDMALogicalAddress
216: );
217: if (ioReturn != IO_R_SUCCESS) {
218: ddmDMA("%s: Mapping DBDMA at %08x [%d] to virtual address:"
219: " error %d (%s), fatal.\n",
220: [self name],
221: gDBDMAPhysicalAddress,
222: gDBDMARegisterLength,
223: ioReturn,
224: [self stringFromReturn:ioReturn]
225: );
226: }
227: }
228: #else
229: /*
230: * Temp (?) Use hard-wired addresses until the registry is complete.
231: */
232: if (ioReturn == IO_R_SUCCESS) {
233: gSCSILogicalAddress = (UInt8 *) PCI_ASC_BASE_PHYS;
234: gSCSIPhysicalAddress = (PhysicalAddress) PCI_ASC_BASE_PHYS;
235: gSCSIRegisterLength = 0x100;
236: gDBDMALogicalAddress = (DBDMAChannelRegisters *) PCI_DMA_BASE_PHYS;
237: gDBDMAPhysicalAddress = (PhysicalAddress) PCI_DMA_BASE_PHYS;
238: gDBDMARegisterLength = 0x20;
239: }
240: #endif
241: if (ioReturn == IO_R_SUCCESS) {
242: /*
243: * Ensure that the addresses are valid.
244: */
245: #if 0 /* probe_rb is not present (yet?) */
246: ASSERT(probe_rb((UInt8 *) gSCSILogicalAddress) == 0);
247: ASSERT(probe_rb((UInt8 *) gDBDMALogicalAddress) == 0);
248: #endif
249: /*
250: * Get the physical address corresponding the DBDMA channel area.
251: */
252: ioReturn = IOPhysicalFromVirtual(
253: IOVmTaskSelf(),
254: (vm_offset_t) gChannelCommandArea,
255: (vm_offset_t *) &gDBDMAChannelAddress
256: );
257: if (ioReturn != IO_R_SUCCESS) {
258: IOLog("%s: Mapping channel at %08x to physical address: error %d (%s), fatal.\n",
259: [self name],
260: (UInt32) gChannelCommandArea,
261: ioReturn,
262: [self stringFromReturn:ioReturn]
263: );
264: }
265: }
266: if (ioReturn == IO_R_SUCCESS) {
267: gAutosenseAddress = gDBDMAChannelAddress
268: + (((UInt32) gAutosenseArea) - ((UInt32) gChannelCommandArea));
269: [self initializeChannelProgram];
270: }
271: /*
272: * What do we do on failure? Should we try to deallocate the stuff
273: * we created, or will the system do this for us?
274: */
275: RESULT(ioReturn);
276: return (ioReturn);
277: }
278:
279: /**
280: * Perform one-time-only channel command program initialization.
281: */
282: - (void) initializeChannelProgram
283: {
284: ENTRY("Hic initializeChanelProgram");
285: /*
286: * Set the interrupt, branch, and wait DBDMA registers.
287: * Caution: the following MESH interrupt register bits are
288: * reverse polarity and are in a different position.
289: * The pattern is: 0x00MM00VV, where MM is a mask byte
290: * and VV is a value byte to match.
291: * 0x80 means NO errors (kMeshIntrError)
292: * 0x40 means NO exceptions (kMeshIntrException)
293: * 0x20 means NO command done (kMeshIntrCmdDone)
294: * Branch Select is used with BRANCH_FALSE
295: */
296: DBDMASetInterruptSelect(0x00000000); /* Never let DBDMA interrupt */
297: DBDMASetWaitSelect(0x00200020); /* Wait until command done */
298: DBDMASetBranchSelect(0x00000000); /* Never branch on error */
299: EXIT();
300: }
301:
302: /**
303: * When a (legitimate) data phase starts, this method is called to configure
304: * the DBDMA Channel Command list. Autosense is simple (as we "cannot" be
305: * called more than once), while ordinary data transfers are arbitrarily complex.
306: */
307: - (IOReturn) hardwareInitializeCCL
308: {
309: IOReturn ioReturn;
310:
311: ENTRY("Hcc hardwareInitializeCCL");
312: ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
313: /**
314: * First, make sure that the DBDMA chip is idle.
315: */
316: DBDMAreset();
317: DBDMAspinUntilIdle();
318: if (gActiveCommand->flagIsAutosense) {
319: UInt32 actualAutosenseTransferLength;
320: /*
321: * This should be provided by the client (and checked that it is
322: * less than or equal to kMaxAutosenseByteCount). Note that this
323: * sequence is duplicated in Apple96Curio.m.
324: */
325: actualAutosenseTransferLength = sizeof (esense_reply_t);
326: ASSERT(actualAutosenseTransferLength <= kMaxAutosenseByteCount);
327: ASSERT(actualAutosenseTransferLength <= 255);
328: bzero(gAutosenseArea, actualAutosenseTransferLength);
329: MakeCCDescriptor(
330: &gChannelCommandArea[0],
331: INPUT_LAST | actualAutosenseTransferLength,
332: (UInt32) gAutosenseAddress
333: );
334: MakeCCDescriptor(&gChannelCommandArea[1], STOP_CMD, 0);
335: flush_cache_v((vm_offset_t) gChannelCommandArea, sizeof (DBDMADescriptor) * 2);
336: gActiveCommand->thisTransferLength = actualAutosenseTransferLength;
337: ioReturn = IO_R_SUCCESS;
338: }
339: else {
340: ioReturn = [self hardwareInitializeRequestCCL];
341: }
342: RESULT(ioReturn);
343: return (ioReturn);
344: }
345:
346: /**
347: * Initialize the data transfer channel command list for a normal SCSI command.
348: * This is not an optimal implementation, but it simplifies maintaining a
349: * common code base with the NuBus Curio/AMIC hardware interface.
350: * Note that the last DBDMA command must be INPUT_LAST or OUTPUT_LAST to handle
351: * synchronous transfer odd-byte disconnect.
352: *
353: * Significantly revised for Radar 1670762.
354: */
355: - (IOReturn) hardwareInitializeRequestCCL
356: {
357: CommandBuffer *cmdBuf;
358: IOSCSIRequest *scsiReq;
359: DBDMADescriptor *descriptorPtr; /* -> the current data descriptor */
360: DBDMADescriptor *descriptorMax; /* -> beyond the last data descr. */
361: IOReturn ioReturn = IO_R_SUCCESS;
362: UInt32 dbdmaOp; /* Opcode for DBDMA request */
363: unsigned int rangeByteCount;
364: unsigned int actualRanges;
365: unsigned int i;
366: #define kMaxPhysicalRange 16
367: PhysicalRange range[kMaxPhysicalRange];
368:
369: ENTRY("Hir hardwareInitializeRequestCCL");
370: ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
371: cmdBuf = gActiveCommand;
372: scsiReq = cmdBuf->scsiReq;
373: ASSERT(scsiReq->target == gCurrentTarget && scsiReq->lun == gCurrentLUN);
374: /*
375: * Select the correct DBDMA command for this command.
376: */
377: if (scsiReq->read) {
378: dbdmaOp = INPUT_MORE;
379: }
380: else {
381: dbdmaOp = OUTPUT_MORE;
382: }
383: /*
384: * How many descriptors can we store (need some slop for the terminator commands).
385: * Get a pointer to the first free descriptor and the total number of bytes left
386: * to transfer in this I/O request.
387: */
388: descriptorPtr = gChannelCommandArea;
389: descriptorMax = &descriptorPtr[gDBDMADescriptorMax];
390: /*
391: * cmdBuf->thisTransferLength will contain the actual number of bytes we
392: * intend to transfer in this DMA request, which is needed when DMA completes
393: * to recover the residual transfer length.
394: */
395: cmdBuf->thisTransferLength = 0;
396: ddmDMA("Req CCL, start %8d, max size %8d\n",
397: cmdBuf->currentDataIndex,
398: scsiReq->maxTransfer - cmdBuf->currentDataIndex,
399: 3, 4, 5
400: );
401: /* + Radar xxxxxx -- Use IOMemoryDescriptors */
402: while (descriptorPtr < descriptorMax
403: && cmdBuf->thisTransferLength < kMaxDMATransfer) {
404: rangeByteCount = [cmdBuf->mem getPhysicalRanges
405: : kMaxPhysicalRange
406: maxByteCount : (kMaxDMATransfer - cmdBuf->thisTransferLength)
407: newPosition : NULL
408: actualRanges : &actualRanges
409: physicalRanges : range
410: ];
411: #if 0
412: IOLog("rangeByteCount %d, actualRanges %d, range[0] = %08x, %d\n",
413: rangeByteCount, actualRanges,
414: (UInt32) range[0].address,
415: range[0].length
416: );
417: #endif
418: if (rangeByteCount == 0) {
419: break;
420: }
421: for (i = 0; i < actualRanges; i++) {
422: #if 0
423: IOLog("%d: %08x for %d\n",
424: i, (UInt32) range[i].address, range[i].length);
425: #endif
426: #if 1
427: if (range[i].length == 0) {
428: IOLog("%d: %08x for %d\n",
429: i, (UInt32) range[i].address, range[i].length);
430: [self logIOMemoryDescriptor : "Bogus length"];
431: MakeCCDescriptor(descriptorPtr + 1, STOP_CMD, 0);
432: [self logChannelCommandArea : "Bogus length"];
433: IOPanic("Bogus length\n");
434: }
435: #endif
436: MakeCCDescriptor(descriptorPtr,
437: (dbdmaOp | range[i].length),
438: (unsigned int) range[i].address
439: );
440: descriptorPtr++;
441: }
442: cmdBuf->thisTransferLength += rangeByteCount;
443: }
444: /* - Radar xxxxxx -- Use IOMemoryDescriptors */
445: if (descriptorPtr > gChannelCommandArea) {
446: /*
447: * We stored at least one descriptor. Change the last one so it
448: * is an INPUT_LAST or OUTPUT_LAST.
449: */
450: SetCCOperation(
451: &descriptorPtr[-1],
452: GetCCOperation(&descriptorPtr[-1]) ^ OUTPUT_LAST
453: );
454: } /* Set "last operation" bit in the command */
455: MakeCCDescriptor(descriptorPtr, STOP_CMD, 0);
456: descriptorPtr++;
457: ASSERT(descriptorPtr < &gChannelCommandArea[gDBDMADescriptorMax]);
458: flush_cache_v(
459: (vm_offset_t) gChannelCommandArea,
460: ((UInt32) descriptorPtr) - ((UInt32) gChannelCommandArea)
461: );
462: #if 0 // ddmDMA
463: IOLog("DMA setup, %d descriptors: thisTransferLength %d\n",
464: descriptorPtr - gChannelCommandArea,
465: cmdBuf->thisTransferLength,
466: 3, 4, 5
467: );
468: #endif
469: RESULT(ioReturn);
470: return (ioReturn);
471: }
472:
473:
474: /**
475: * Start a request after [self hardwareStart] has figured out what to do.
476: */
477: - (void) hardwareStartSCSIRequest
478: {
479: register CommandBuffer *cmdBuf;
480: IOSCSIRequest *scsiReq;
481: UInt8 selectCmd;
482:
483: ENTRY("Hsr hardwareStartSCSIRequest");
484: ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
485: cmdBuf = gActiveCommand;
486: scsiReq = cmdBuf->scsiReq;
487: ASSERT(scsiReq->target == gCurrentTarget && scsiReq->lun == gCurrentLUN);
488: /*
489: * Flush the fifo, then load synchronous registers and the target bus ID
490: */
491: CURIOflushFifo();
492: CURIOsetDestinationID(scsiReq->target);
493: /*
494: * Put the contents of the message buffer into the fifo. The Curio makes this
495: * slightly messy. The command depends on the number of message bytes. The
496: * "select ATN and stop" case only occurs when we negotiate synchronous transfers.
497: */
498: switch (gMsgOutPtr - gMsgPutPtr) {
499: case 0: /* Select, no ATN, send CDB */
500: gLastMsgOut[0] = gLastMsgOut[1] = kScsiMsgNop;
501: selectCmd = cSlctNoAtn;
502: break;
503: case 1: /* Select, ATN, 1 Msg, send CDB */
504: gLastMsgOut[0] = gMsgPutPtr[0];
505: gLastMsgOut[1] = kScsiMsgNop;
506: selectCmd = cSlctAtn;
507: break;
508: case 3: /* Select, ATN, 3 Msg, send CDB */
509: gLastMsgOut[0] = gMsgPutPtr[0];
510: gLastMsgOut[1] = gMsgPutPtr[1];
511: selectCmd = cSlctAtn3;
512: break;
513: default: /* Select, ATN, 1 Msg, stop */
514: gLastMsgOut[0] = gMsgPutPtr[0];
515: gLastMsgOut[1] = kScsiMsgNop;
516: selectCmd = cSlctAtnStp;
517: break;
518: }
519: if ((gMsgOutPtr - gMsgPutPtr) > 3
520: || (cmdBuf->flagIsAutosense == FALSE
521: && (gMsgOutPtr - gMsgPutPtr) + gActiveCommand->cdbLength >= 16)) {
522: CURIOputByteIntoFifo(*gMsgPutPtr++);
523: selectCmd = cSlctAtnStp;
524: }
525: else {
526: while (gMsgPutPtr < gMsgOutPtr) {
527: CURIOputByteIntoFifo(*gMsgPutPtr++);
528: }
529: }
530: if (selectCmd != cSlctAtnStp) {
531: CURIOputCommandIntoFifo();
532: }
533: /* ** ** **
534: * ** ** ** Can a caller override the default timeout?
535: * ** ** **
536: */
537: // CURIOsetSelectionTimeout(gSelectionTimeout);
538: /*
539: * Initialize the finite state automaton and start the Curio.
540: */
541: gBusState = SCS_SELECTING;
542: gCurrentBusPhase = kBusPhaseBusFree;
543: CURIOsetCommandRegister(selectCmd);
544: EXIT();
545: }
546:
547: - (void) clearChannelCommandResults
548: {
549: ENTRY("Hcc clearChannelCommandResults");
550: EXIT();
551: }
552:
553: /**
554: * Debug log channel command area
555: */
556: - (void) logChannelCommandArea
557: : (const char *) reason
558: {
559: #if DEBUG
560: DBDMADescriptor *descriptorPtr; /* -> the current data descriptor */
561: DBDMADescriptor *descriptorMax; /* -> beyond the last data descr. */
562: UInt32 operation;
563: UInt32 address;
564: UInt32 cmdDep;
565: UInt32 result;
566: UInt32 status;
567: const char *opName;
568: const char *keyName;
569: const char *intName = "";
570: const char *branchName = "";
571: const char *waitName = "";
572: Boolean first;
573:
574: ENTRY("Dlo logChannelCommandArea");
575: status = DBDMAGetChannelStatus();
576: if (reason != NULL) {
577: IOLog("%s: *** %s\n", [self name], reason);
578: }
579: IOLog("%s: *** DBDMA sts %08x, cmdPtr %08x,"
580: " branchSel %08x, byteCount %08x, ccl @ %08x\n",
581: [self name],
582: status,
583: DBDMAGetCommandPtr(),
584: (UInt32) DBDMAGetBranchSelect(),
585: (UInt32) DBDMAGetWaitSelect(),
586: (UInt32) gChannelCommandArea
587: );
588: if ((status & 0x00008000) != 0) {
589: IOLog("%s: *** status: run\n", [self name]);
590: }
591: if ((status & 0x00004000) != 0) {
592: IOLog("%s: *** status: pause\n", [self name]);
593: }
594: if ((status & 0x00002000) != 0) {
595: IOLog("%s: *** status: flush\n", [self name]);
596: }
597: if ((status & 0x00001000) != 0) {
598: IOLog("%s: *** status: wake\n", [self name]);
599: }
600: if ((status & 0x00000800) != 0) {
601: IOLog("%s: *** status: dead\n", [self name]);
602: }
603: if ((status & 0x00000400) != 0) {
604: IOLog("%s: *** status: active\n", [self name]);
605: }
606: if ((status & 0x000000100) != 0) {
607: IOLog("%s: *** status: bt\n", [self name]);
608: }
609: if ((status & 0xFFFF02FF) != 0) {
610: IOLog("%s: *** other status set\n", [self name]);
611: }
612: descriptorPtr = gChannelCommandArea;
613: descriptorMax = &descriptorPtr[gDBDMADescriptorMax];
614: for (; descriptorPtr < descriptorMax; descriptorPtr++) {
615: operation = GetCCOperation(descriptorPtr);
616: address = GetCCAddress(descriptorPtr);
617: cmdDep = GetCCCmdDep(descriptorPtr);
618: result = GetCCResult(descriptorPtr);
619: IOLog("%s: *** dma[%2d]: op %08x, addr %08x, cmddep %08x, res %08x\n",
620: [self name],
621: descriptorPtr - gChannelCommandArea,
622: operation,
623: address,
624: cmdDep,
625: result
626: );
627: switch (operation & kdbdmaCmdMask) {
628: case OUTPUT_MORE: opName = "Output More"; break;
629: case OUTPUT_LAST: opName = "Output Last"; break;
630: case INPUT_MORE: opName = "Input More"; break;
631: case INPUT_LAST: opName = "Input Last"; break;
632: case STORE_QUAD: opName = "Store Quad"; break;
633: case LOAD_QUAD: opName = "Load Quad"; break;
634: case NOP_CMD: opName = "NOP"; break;
635: case STOP_CMD: opName = "Stop"; break;
636: default: opName = "Op Unknown"; break;
637: }
638: switch (operation & kdbdmaKeyMask) {
639: case KEY_STREAM0: keyName = "Stream 0"; break;
640: case KEY_STREAM1: keyName = "Stream 1"; break;
641: case KEY_STREAM2: keyName = "Stream 2"; break;
642: case KEY_STREAM3: keyName = "Stream 3"; break;
643: case KEY_REGS: keyName = "Regs"; break;
644: case KEY_SYSTEM: keyName = "System"; break;
645: case KEY_DEVICE: keyName = "System"; break;
646: default: keyName = "Unknown"; break;
647: }
648: switch (operation & kdbdmaIMask) {
649: case kIntNever: intName = "never"; break;
650: case kIntIfTrue: intName = "if True"; break;
651: case kIntIfFalse: intName = "if False"; break;
652: case kIntAlways: intName = "always"; break;
653: }
654: switch (operation & kdbdmaBMask) {
655: case kBranchNever: branchName = "never"; break;
656: case kBranchIfTrue: branchName = "if True"; break;
657: case kBranchIfFalse: branchName = "if False"; break;
658: case kBranchAlways: branchName = "always"; break;
659: }
660: switch (operation & kdbdmaWMask) {
661: case kWaitNever: waitName = "never"; break;
662: case kWaitIfTrue: waitName = "if True"; break;
663: case kWaitIfFalse: waitName = "if False"; break;
664: case kWaitAlways: waitName = "always"; break;
665: }
666: IOLog("%s: *** [%2d]: op %s, key %s, int %s, branch %s, wait %s, count %d,"
667: " residual %d, status %04x",
668: [self name],
669: descriptorPtr - gChannelCommandArea,
670: opName,
671: keyName,
672: intName,
673: branchName,
674: waitName,
675: (operation & kdbdmaReqCountMask),
676: result & kdbdmaResCountMask,
677: (result & kdbdmaXferStatusMask) >> 16
678: );
679: first = TRUE;
680: if ((result & kdbdmaXferStatusMask) == 0) {
681: IOLog(" (no status)\n");
682: }
683: else {
684: if ((result & kXferStatusRun) != 0) {
685: IOLog(": Run");
686: result &= ~kXferStatusRun;
687: first = FALSE;
688: }
689: if ((result & kXferStatusPause) != 0) {
690: IOLog("%s Pause", (first) ? ":" : ",");
691: result &= kXferStatusPause;
692: first = FALSE;
693: }
694: if ((result & kXferStatusFlush) != 0) {
695: IOLog("%s Flush", (first) ? ":" : ",");
696: result &= kXferStatusFlush;
697: first = FALSE;
698: }
699: if ((result & kXferStatusWake) != 0) {
700: IOLog("%s Wake", (first) ? ":" : ",");
701: result &= kXferStatusWake;
702: first = FALSE;
703: }
704: if ((result & kXferStatusDead) != 0) {
705: IOLog("%s Dead", (first) ? ":" : ",");
706: result &= kXferStatusDead;
707: first = FALSE;
708: }
709: if ((result & kXferStatusActive) != 0) {
710: IOLog("%s Active", (first) ? ":" : ",");
711: result &= kXferStatusActive;
712: first = FALSE;
713: }
714: if ((result & kXferStatusBt) != 0) {
715: IOLog("%s Branch True", (first) ? ":" : ",");
716: result &= kXferStatusBt;
717: first = FALSE;
718: }
719: if (result != 0) {
720: IOLog("%s Other", (first) ? ":" : ",");
721: }
722: IOLog("\n");
723: }
724: if ((operation & kdbdmaCmdMask) == STOP_CMD || operation == 0) {
725: break;
726: }
727: }
728: EXIT();
729: #endif /* DEBUG */
730: }
731:
732: - (void) logIOMemoryDescriptor
733: : (const char *) info
734: {
735: #if DEBUG
736: const char *intro = " \"";
737: const char *outro = "\"";
738: IOMemoryDescriptorState state;
739:
740: if (gActiveCommand != NULL && gActiveCommand->mem != NULL) {
741: [gActiveCommand->mem state : &state];
742: if (info == NULL || info[0] == '\0') {
743: info = intro = outro = "";
744: }
745: IOLog("IOMemoryDescriptor%s%s%s: %d offset in %d, %d maxSeg\n",
746: intro, info, outro,
747: [gActiveCommand->mem currentOffset],
748: [gActiveCommand->mem totalByteCount],
749: [gActiveCommand->mem maxSegmentCount]
750: );
751: IOLog("IOMemoryDescriptor%s%s%s: range %d, logical %d in %d, physical %d in %d\n",
752: intro, info, outro,
753: state.rangeIndex,
754: state.logicalOffset,
755: state.ioRange.size,
756: state.physicalOffset,
757: state.physical.length
758: );
759: }
760: else {
761: IOLog("Null IOMemoryDescriptor\n");
762: }
763: #endif /* DEBUG */
764: }
765:
766:
767: @end /* Apple96_SCSI(HardwarePrivate) */
768:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.