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