|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * HISTORY ! 26: * ! 27: */ ! 28: ! 29: #include <libkern/OSByteOrder.h> ! 30: #include <IOKit/IOMemoryCursor.h> ! 31: ! 32: #include "AppleOHCI.h" ! 33: #include <IOKit/usb/USB.h> ! 34: ! 35: #define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme ! 36: #define DEBUGLOG kprintf ! 37: #define nil (0) ! 38: ! 39: #define super IOUSBController ! 40: #define self this ! 41: ! 42: #define NUM_BUFFER_PAGES 9 // 54 ! 43: #define NUM_TDS 255 // 1500 ! 44: #define NUM_EDS 256 // 1500 ! 45: #define NUM_ITDS 192 // 1300 ! 46: ! 47: // TDs per page == 85 ! 48: // EDs per page == 128 ! 49: // ITDs per page == 64 ! 50: ! 51: static int GetEDType(OHCIEndpointDescriptorPtr pED); ! 52: static void ProcessCompletedITD (OHCIIsochTransferDescriptorPtr pITD, IOReturn status); ! 53: extern void print_td(OHCIGeneralTransferDescriptorPtr pTD); ! 54: extern void print_itd(OHCIIsochTransferDescriptorPtr x); ! 55: ! 56: static IOReturn TranslateStatusToUSBError(UInt32 status); ! 57: ! 58: OSDefineMetaClassAndStructors(AppleOHCI, IOUSBController) ! 59: ! 60: bool AppleOHCI::init(OSDictionary * propTable) ! 61: { ! 62: if (!super::init(propTable)) return false; ! 63: ! 64: _intLock = IOLockAlloc(); ! 65: if (!_intLock) ! 66: return(false); ! 67: ! 68: pOHCIUIMData = (OHCIUIMDataPtr) IOMalloc(sizeof(OHCIUIMData)); ! 69: if (!pOHCIUIMData) ! 70: { ! 71: IOLog("%s: Unable to allocate memory (1)\n", getName()); ! 72: return(false); ! 73: } ! 74: bzero( pOHCIUIMData, sizeof(OHCIUIMData)); ! 75: ! 76: return (true); ! 77: } ! 78: ! 79: void AppleOHCI::SetVendorInfo(void) ! 80: { ! 81: OSData *vendProp, *deviceProp, *revisionProp; ! 82: ! 83: // get this chips vendID, deviceID, revisionID ! 84: vendProp = (OSData *) _device->getProperty( "vendor-id" ); ! 85: if (vendProp) ! 86: _vendorID = *((UInt32 *) vendProp->getBytesNoCopy()); ! 87: deviceProp = (OSData *) _device->getProperty( "device-id" ); ! 88: if (deviceProp) ! 89: _deviceID = *((UInt32 *) deviceProp->getBytesNoCopy()); ! 90: revisionProp = (OSData *) _device->getProperty( "revision-id" ); ! 91: if (revisionProp) ! 92: _revisionID = *((UInt32 *) revisionProp->getBytesNoCopy()); ! 93: } ! 94: ! 95: IOReturn AppleOHCI::UIMInitialize(IOService * provider) ! 96: { ! 97: /* UInt16 ivalue, ivalue2; */ ! 98: IOReturn err = 0; ! 99: OHCIRegistersPtr pOHCIRegisters; ! 100: UInt32 lvalue; ! 101: ! 102: #if (DEBUGGING_LEVEL > 0) ! 103: IOLog("%s: initializing UIM\n", getName()); ! 104: #endif ! 105: ! 106: _device = OSDynamicCast(IOPCIDevice, provider); ! 107: if(_device == NULL) ! 108: return kIOReturnBadArgument; ! 109: ! 110: do { ! 111: ! 112: if (!(_deviceBase = provider->mapDeviceMemoryWithIndex(0))) ! 113: { ! 114: IOLog("%s: unable to get device memory\n", getName()); ! 115: break; ! 116: } ! 117: ! 118: IOLog("%s: config @ %lx (%lx)\n", getName(), ! 119: _deviceBase->getVirtualAddress(), ! 120: _deviceBase->getPhysicalAddress()); ! 121: ! 122: SetVendorInfo(); ! 123: ! 124: interruptSource = IOInterruptEventSource:: ! 125: interruptEventSource(this, &OHCIUIMInterruptHandler, _device); ! 126: if (!interruptSource ! 127: || (_workLoop->addEventSource(interruptSource) != kIOReturnSuccess)) ! 128: continue; ! 129: ! 130: _genCursor = ! 131: IONaturalMemoryCursor::withSpecification(PAGE_SIZE, PAGE_SIZE); ! 132: if(!_genCursor) ! 133: continue; ! 134: ! 135: _isoCursor = ! 136: IONaturalMemoryCursor::withSpecification(kUSBMaxIsocFrameReqCount, ! 137: kUSBMaxIsocFrameReqCount); ! 138: if(!_isoCursor) ! 139: continue; ! 140: ! 141: /* ! 142: * Initialize my data and the hardware ! 143: */ ! 144: pOHCIUIMData->errataBits = GetErrataBits(_vendorID, _deviceID, _revisionID); ! 145: ! 146: #if (DEBUGGING_LEVEL > 0) ! 147: IOLog("%s: errata bits=%lx\n", getName(), pOHCIUIMData->errataBits); ! 148: #endif ! 149: pOHCIUIMData->pageSize = PAGE_SIZE; ! 150: pOHCIUIMData->pOHCIRegisters = pOHCIRegisters = ! 151: (OHCIRegistersPtr) _deviceBase->getVirtualAddress(); ! 152: ! 153: #if (DEBUGGING_LEVEL > 2) ! 154: dumpRegs(); ! 155: #endif ! 156: ! 157: // enable the card ! 158: lvalue = _device->configRead32(cwCommand); ! 159: _device->configWrite32(cwCommand, (lvalue & 0xffff0000) | ! 160: (cwCommandEnableBusMaster | ! 161: cwCommandEnableMemorySpace)); ! 162: ! 163: // Allocate TDs, EDs; FIXME get real numbers to use, CPU specific. ! 164: if ((err = OHCIUIMAllocateMemory(NUM_TDS, NUM_EDS, NUM_ITDS))) ! 165: continue; ! 166: ! 167: pOHCIRegisters->hcControlCurrentED = 0; ! 168: pOHCIRegisters->hcControlHeadED = 0; ! 169: pOHCIRegisters->hcDoneHead = 0; ! 170: IOSync(); ! 171: ! 172: // Set up HCCA. ! 173: IOPhysicalAddress physAddr; ! 174: pOHCIUIMData->pHCCA = (Ptr) IOMallocContiguous(kHCCAsize, kHCCAalignment, &physAddr); ! 175: if (!pOHCIUIMData->pHCCA) ! 176: { ! 177: IOLog("%s: Unable to allocate memory (2)\n", getName()); ! 178: err = kIOReturnNoMemory; ! 179: continue; ! 180: } ! 181: ! 182: OSWriteLittleInt32(&pOHCIRegisters->hcHCCA, 0, physAddr); ! 183: IOSync(); ! 184: ! 185: // Set the HC to write the donehead to the HCCA, and enable interrupts ! 186: pOHCIRegisters->hcInterruptStatus = OSSwapInt32(kOHCIHcInterrupt_WDH); ! 187: IOSync(); ! 188: ! 189: // Enable the interrupt delivery. ! 190: _workLoop->enableAllInterrupts(); ! 191: ! 192: // Initialize the Root Hub registers ! 193: OHCIRootHubPower(1 /* kOn */); ! 194: IOSync(); ! 195: pOHCIUIMData->rootHubFuncAddress = 1; ! 196: ! 197: // set up Interrupt transfer tree ! 198: if ((err = OHCIUIMIsochronousInitialize())) continue; ! 199: if ((err = OHCIUIMInterruptInitialize())) continue; ! 200: if ((err = OHCIUIMBulkInitialize())) continue; ! 201: if ((err = OHCIUIMControlInitialize())) continue; ! 202: ! 203: // Set up hcFmInterval. ! 204: UInt32 hcFSMPS; // in register hcFmInterval ! 205: UInt32 hcFI; // in register hcFmInterval ! 206: UInt32 hcPS; // in register hcPeriodicStart ! 207: ! 208: hcFI = OSReadLittleInt32(&pOHCIRegisters->hcFmInterval, 0) & kOHCIHcFmInterval_FI; ! 209: // this formula is from the OHCI spec, section 5.4 ! 210: hcFSMPS = ((((hcFI-kOHCIMax_OverHead) * 6)/7) << kOHCIHcFmInterval_FSMPSPhase); ! 211: hcPS = (hcFI * 9) / 10; // per spec- 90% ! 212: OSWriteLittleInt32(&pOHCIRegisters->hcFmInterval, 0, hcFI | hcFSMPS); ! 213: OSWriteLittleInt32(&pOHCIRegisters->hcPeriodicStart, 0, hcPS); ! 214: ! 215: IOSync(); ! 216: ! 217: ! 218: // Just so we all start from the same place, reset the OHCI. ! 219: pOHCIRegisters->hcControl = ! 220: OSSwapInt32 ((kOHCIFunctionalState_Reset ! 221: << kOHCIHcControl_HCFSPhase)); ! 222: IOSync(); ! 223: ! 224: // Set OHCI to operational state and enable processing of control list. ! 225: pOHCIRegisters->hcControl = ! 226: OSSwapInt32 ((kOHCIFunctionalState_Operational ! 227: << kOHCIHcControl_HCFSPhase) ! 228: | kOHCIHcControl_CLE | kOHCIHcControl_BLE ! 229: | kOHCIHcControl_PLE | kOHCIHcControl_IE); ! 230: IOSync(); ! 231: ! 232: pOHCIRegisters->hcInterruptEnable = ! 233: OSSwapInt32 (kOHCIHcInterrupt_MIE | kOHCIDefaultInterrupts); ! 234: IOSync(); ! 235: ! 236: if (pOHCIUIMData->errataBits & kErrataLSHSOpti) ! 237: OptiLSHSFix(); ! 238: ! 239: //naga (*pOHCIUIMData->interruptEnabler)(pOHCIUIMData->interruptSetMember, nil); ! 240: ! 241: return(kIOReturnSuccess); ! 242: ! 243: } while (false); ! 244: ! 245: IOLog("%s: Error occurred (%d)\n", getName(), err); ! 246: UIMFinalize(); ! 247: ! 248: if (interruptSource) interruptSource->release(); ! 249: ! 250: return(err); ! 251: } ! 252: ! 253: IOReturn AppleOHCI::UIMFinalize(void) ! 254: { ! 255: OHCIRegistersPtr pOHCIRegisters = pOHCIUIMData->pOHCIRegisters; ! 256: ! 257: ! 258: IOLog ("UIMFinalize (shutting down HW)\n"); ! 259: ! 260: // Disable All OHCI Interrupts ! 261: pOHCIRegisters->hcInterruptDisable = kOHCIHcInterrupt_MIE; ! 262: IOSync(); ! 263: ! 264: // Place the USB bus into the Reset State ! 265: pOHCIRegisters->hcControl = OSSwapInt32((kOHCIFunctionalState_Reset ! 266: << kOHCIHcControl_HCFSPhase)); ! 267: IOSync(); ! 268: ! 269: // need to wait at least 1ms here ! 270: IOSleep(2); ! 271: ! 272: // Take away the controllers ability be a bus master. ! 273: _device->configWrite32(cwCommand, cwCommandEnableMemorySpace); ! 274: ! 275: // Clear all Processing Registers ! 276: pOHCIRegisters->hcHCCA = 0; ! 277: pOHCIRegisters->hcPeriodCurrentED = 0; ! 278: pOHCIRegisters->hcControlHeadED = 0; ! 279: pOHCIRegisters->hcControlCurrentED = 0; ! 280: pOHCIRegisters->hcBulkHeadED = 0; ! 281: pOHCIRegisters->hcBulkCurrentED = 0; ! 282: pOHCIRegisters->hcDoneHead = 0; ! 283: IOSync(); ! 284: ! 285: // turn off the global power ! 286: // FIXME check for per-port vs. Global power control ! 287: OHCIRootHubPower(0 /* kOff */); ! 288: IOSync(); ! 289: ! 290: //status = OHCIUIMFinalizeOHCIUIMData ((OHCIUIMDataPtr) pOHCIUIMData); ! 291: ! 292: IOLog("OHCIUIMFinalize Exit\n"); ! 293: ! 294: return(kIOReturnSuccess); ! 295: } ! 296: ! 297: /* ! 298: * got an error on a TD with no completion routine. ! 299: * Search for a later TD on the same end point which does have one, ! 300: * so we can tell upper layes of the error. ! 301: */ ! 302: void AppleOHCI::doCallback(OHCIGeneralTransferDescriptorPtr nextTD, ! 303: UInt32 transferStatus, ! 304: UInt32 bufferSizeRemaining) ! 305: { ! 306: OHCIGeneralTransferDescriptorPtr pCurrentTD; ! 307: OHCIEndpointDescriptorPtr pED; ! 308: UInt32 PhysAddr; ! 309: ! 310: pED = (OHCIEndpointDescriptorPtr) nextTD->pEndpoint; ! 311: ! 312: PhysAddr = (UInt32) OSSwapInt32(pED->tdQueueHeadPtr) & kOHCIHeadPMask; ! 313: nextTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress(PhysAddr); ! 314: ! 315: pCurrentTD = nextTD; ! 316: if(pCurrentTD == nil) { ! 317: IOLog("No transfer descriptors in AppleOHCI::doCallback!\n"); ! 318: return; ! 319: } ! 320: while (pCurrentTD->pLogicalNext != nil) ! 321: { ! 322: bufferSizeRemaining += findBufferRemaining (pCurrentTD); ! 323: ! 324: // make sure this TD won't be added to any future buffer ! 325: // remaining calculations ! 326: pCurrentTD->currentBufferPtr = 0; ! 327: ! 328: //ERICif (pCurrentTD->preparationID) ! 329: //ERIC CheckpointIO(pCurrentTD->preparationID, nil); ! 330: // make sure we don't try to do another CheckpointIO later ! 331: //ERICpCurrentTD->preparationID = nil; ! 332: ! 333: if (pCurrentTD->completion.action != nil) ! 334: { ! 335: IOUSBCompletion completion; ! 336: // zero out callback first then call it ! 337: completion = pCurrentTD->completion; ! 338: pCurrentTD->completion.action = nil; ! 339: complete(completion, ! 340: TranslateStatusToUSBError(transferStatus), ! 341: bufferSizeRemaining); ! 342: bufferSizeRemaining = 0; ! 343: return; ! 344: } ! 345: ! 346: pCurrentTD = pCurrentTD->pLogicalNext; ! 347: } ! 348: } ! 349: ! 350: // FIXME add page size to param list ! 351: UInt32 AppleOHCI::findBufferRemaining (OHCIGeneralTransferDescriptorPtr pCurrentTD) ! 352: { ! 353: UInt32 pageSize; ! 354: UInt32 pageMask; ! 355: UInt32 bufferSizeRemaining; ! 356: ! 357: ! 358: pageSize = pOHCIUIMData->pageSize; ! 359: pageMask = ~(pageSize - 1); ! 360: ! 361: if (pCurrentTD->currentBufferPtr == 0) ! 362: { ! 363: bufferSizeRemaining = 0; ! 364: } ! 365: else if ((OSSwapInt32(pCurrentTD->bufferEnd) & (pageMask)) == ! 366: (OSSwapInt32(pCurrentTD->currentBufferPtr)& (pageMask))) ! 367: { ! 368: // we're on the same page ! 369: bufferSizeRemaining = ! 370: (OSSwapInt32 (pCurrentTD->bufferEnd) & ~pageMask) - ! 371: (OSSwapInt32 (pCurrentTD->currentBufferPtr) & ~pageMask) + 1; ! 372: } ! 373: else ! 374: { ! 375: bufferSizeRemaining = ! 376: ((OSSwapInt32(pCurrentTD->bufferEnd) & ~pageMask) + 1) + ! 377: (pageSize - (OSSwapInt32(pCurrentTD->currentBufferPtr) & ~pageMask)); ! 378: } ! 379: ! 380: return (bufferSizeRemaining); ! 381: } ! 382: ! 383: ! 384: IOReturn AppleOHCI::OHCIUIMControlInitialize(void) ! 385: { ! 386: OHCIRegistersPtr pOHCIRegisters; ! 387: OHCIEndpointDescriptorPtr pED, pED2; ! 388: ! 389: ! 390: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters; ! 391: ! 392: // Create ED mark it skipped and assign it to ControlTail ! 393: pED = OHCIUIMAllocateED(); ! 394: pED->flags = OSSwapInt32 (kOHCIEDControl_K); ! 395: pED->nextED = 0; // End of list ! 396: ! 397: pOHCIUIMData->pControlTail = (UInt32) pED; ! 398: ! 399: // Create ED mark it skipped and assign it to control head ! 400: pED2 = OHCIUIMAllocateED(); ! 401: pED2->flags = OSSwapInt32 (kOHCIEDControl_K); ! 402: pOHCIUIMData->pControlHead = (UInt32) pED2; ! 403: pOHCIRegisters->hcControlHeadED = OSSwapInt32 ((UInt32) pED2->pPhysical); ! 404: ! 405: // have bulk head ED point to Control tail ED ! 406: pED2->nextED = OSSwapInt32 ((UInt32) pED->pPhysical); ! 407: pED2->pLogicalNext = pED; ! 408: return (kIOReturnSuccess); ! 409: } ! 410: ! 411: IOReturn AppleOHCI::OHCIUIMBulkInitialize (void) ! 412: { ! 413: OHCIRegistersPtr pOHCIRegisters; ! 414: OHCIEndpointDescriptorPtr pED, pED2; ! 415: ! 416: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters; ! 417: ! 418: // Create ED mark it skipped and assign it to bulkTail ! 419: pED = OHCIUIMAllocateED(); ! 420: pED->flags = OSSwapInt32 (kOHCIEDControl_K); ! 421: pED->nextED = 0; // End of list ! 422: pOHCIUIMData->pBulkTail = (UInt32) pED; ! 423: ! 424: // Create ED mark it skipped and assign it to bulk head ! 425: pED2 = OHCIUIMAllocateED(); ! 426: pED2->flags = OSSwapInt32 (kOHCIEDControl_K); ! 427: pOHCIUIMData->pBulkHead = (UInt32) pED2; ! 428: pOHCIRegisters->hcBulkHeadED = OSSwapInt32 ((UInt32) pED2->pPhysical); ! 429: ! 430: // have bulk head ED point to Bulk tail ED ! 431: pED2->nextED = OSSwapInt32 ((UInt32) pED->pPhysical); ! 432: pED2->pLogicalNext = pED; ! 433: return (kIOReturnSuccess); ! 434: ! 435: } ! 436: ! 437: IOReturn AppleOHCI::OHCIUIMIsochronousInitialize(void) ! 438: { ! 439: OHCIRegistersPtr pOHCIRegisters; ! 440: OHCIEndpointDescriptorPtr pED, pED2; ! 441: ! 442: ! 443: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters; ! 444: ! 445: // Create ED mark it skipped and assign it to isoch Tail ! 446: pED = OHCIUIMAllocateED(); ! 447: pED->flags = OSSwapInt32 (kOHCIEDControl_K); ! 448: pED->nextED = 0; // End of list ! 449: pOHCIUIMData->pIsochTail = (UInt32) pED; ! 450: ! 451: // Create ED mark it skipped and assign it to isoch head ! 452: pED2 = OHCIUIMAllocateED(); ! 453: pED2->flags = OSSwapInt32 (kOHCIEDControl_K); ! 454: pOHCIUIMData->pIsochHead = (UInt32) pED2; ! 455: ! 456: ! 457: // have iso head ED point to iso tail ED ! 458: pED2->nextED = OSSwapInt32 ((UInt32) pED->pPhysical); ! 459: pED2->pLogicalNext = pED; ! 460: pOHCIUIMData->isochBandwidthAvail = kUSBMaxIsocFrameReqCount; ! 461: ! 462: return (kIOReturnSuccess); ! 463: } ! 464: ! 465: //Initializes the HCCA Interrupt list with statically ! 466: //disabled ED's to form the Interrupt polling queues ! 467: IOReturn AppleOHCI::OHCIUIMInterruptInitialize (void) ! 468: { ! 469: OHCIRegistersPtr pOHCIRegisters; ! 470: OHCIIntHeadPtr pInterruptHead; ! 471: IOReturn status = 0; ! 472: UInt32 dummyControl; ! 473: int i, p, q, z; ! 474: OHCIEndpointDescriptorPtr pED, pIsochHead; ! 475: ! 476: ! 477: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters; ! 478: pInterruptHead = pOHCIUIMData->pInterruptHead; ! 479: ! 480: // create UInt32 with same dword0 for use with searching and ! 481: // tracking, skip should be set, and open area should be marked ! 482: dummyControl = kOHCIEDControl_K; ! 483: dummyControl |= 0; //should be kOHCIFakeED ! 484: dummyControl = OSSwapInt32 (dummyControl); ! 485: pIsochHead = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pIsochHead; ! 486: ! 487: // do 31 times ! 488: // change to 65 and make isoch head the last one.????? ! 489: for (i = 0; i < 63; i++) ! 490: { ! 491: // allocate Endpoint descriptor ! 492: pED = OHCIUIMAllocateED(); ! 493: if (pED == nil) ! 494: { ! 495: return (kIOReturnNoMemory); ! 496: } ! 497: // mark skipped,some how mark as a False endpoint zzzzz ! 498: else ! 499: { ! 500: pED->flags = dummyControl; ! 501: pED->nextED = 0; // End of list ! 502: pInterruptHead[i].pHead = pED; ! 503: pInterruptHead[i].pHeadPhysical = pED->pPhysical; ! 504: pInterruptHead[i].nodeBandwidth = 0; ! 505: } ! 506: ! 507: if (i < 32) ! 508: ((UInt32 *)pOHCIUIMData->pHCCA)[i] = ! 509: (UInt32) OSSwapInt32 ((UInt32) pInterruptHead[i].pHeadPhysical); ! 510: } ! 511: ! 512: p = 0; ! 513: q = 32; ! 514: // FIXME? ERIC ! 515: for (i = 0; i < (32 +16 + 8 + 4 + 2); i++) ! 516: { ! 517: if (i < q/2+p) ! 518: z = i + q; ! 519: else ! 520: z = i + q/2; ! 521: if (i == p+q-1) ! 522: { ! 523: p = p + q; ! 524: q = q/2; ! 525: } ! 526: // point endpoint descriptor to corresponding 8ms descriptor ! 527: pED = pInterruptHead[i].pHead; ! 528: pED->nextED = OSSwapInt32 (pInterruptHead[z].pHeadPhysical); ! 529: pED->pLogicalNext = pInterruptHead[z].pHead; ! 530: pInterruptHead[i].pTail = (OHCIEndpointDescriptorPtr) pED->pLogicalNext; ! 531: } ! 532: i = 62; ! 533: pED = pInterruptHead[i].pHead; ! 534: pED->nextED = OSSwapInt32 (pIsochHead->pPhysical); ! 535: pED->pLogicalNext = pOHCIUIMData->pIsochHead; ! 536: pInterruptHead[i].pTail = (OHCIEndpointDescriptorPtr) pED->pLogicalNext; ! 537: ! 538: // point Isochronous head to last endpoint ! 539: return (status); ! 540: } ! 541: ! 542: //////////////////////////////////////////////////////////////////////////////// ! 543: // ! 544: // UInt32 OHCIUIMGetLogicalAddress ! 545: // Given the physical address, return the virtual address ! 546: // ! 547: ! 548: UInt32 AppleOHCI::OHCIUIMGetLogicalAddress (UInt32 pPhysicalAddress) ! 549: { ! 550: OHCIPhysicalLogicalPtr pPhysicalLogical; ! 551: UInt32 LogicalAddress = nil; ! 552: ! 553: if (pPhysicalAddress == 0) ! 554: return(0); ! 555: ! 556: pPhysicalLogical = pOHCIUIMData->pPhysicalLogical; ! 557: ! 558: while (pPhysicalLogical != nil) { ! 559: if (pPhysicalAddress <= pPhysicalLogical->PhysicalEnd ! 560: && pPhysicalAddress >= pPhysicalLogical->PhysicalStart) ! 561: { ! 562: LogicalAddress = pPhysicalLogical->LogicalStart + ! 563: (pPhysicalAddress - pPhysicalLogical->PhysicalStart); ! 564: pPhysicalLogical = nil; ! 565: } else { ! 566: pPhysicalLogical = (OHCIPhysicalLogicalPtr) pPhysicalLogical->pNext; ! 567: } ! 568: } ! 569: ! 570: if ( LogicalAddress == nil) ! 571: IOLog("OHCIUIM: LogicalAddress(0x%lx) == nil !\n", pPhysicalAddress); ! 572: ! 573: return (LogicalAddress); ! 574: ! 575: } ! 576: ! 577: ! 578: UInt32 AppleOHCI::OHCIUIMGetPhysicalAddress(UInt32 LogicalAddress, ! 579: UInt32 count) ! 580: { ! 581: OHCIPhysicalLogicalPtr pPhysicalLogical; ! 582: UInt32 PhysicalAddress = nil; ! 583: ! 584: if (LogicalAddress == 0) ! 585: return(0); ! 586: ! 587: pPhysicalLogical = pOHCIUIMData->pPhysicalLogical; ! 588: ! 589: while (pPhysicalLogical != nil) { ! 590: if (LogicalAddress <= pPhysicalLogical->LogicalEnd ! 591: && LogicalAddress >= pPhysicalLogical->LogicalStart) ! 592: { ! 593: PhysicalAddress = pPhysicalLogical->PhysicalStart ! 594: + (LogicalAddress - pPhysicalLogical->LogicalStart); ! 595: pPhysicalLogical = nil; ! 596: } else { ! 597: pPhysicalLogical = pPhysicalLogical->pNext; ! 598: } ! 599: } ! 600: ! 601: if (PhysicalAddress == nil) ! 602: PhysicalAddress = OHCIUIMCreatePhysicalAddress(LogicalAddress, count); ! 603: ! 604: return (PhysicalAddress); ! 605: } ! 606: ! 607: /* ! 608: * OHCIUIMCreatePhysicalAddress: ! 609: * Currently this function only creates a one entry OHCIPhysicalLogical ! 610: * entry. This is because it is assuming contiguous memory. ! 611: * ! 612: */ ! 613: UInt32 AppleOHCI::OHCIUIMCreatePhysicalAddress(UInt32 pLogicalAddress, ! 614: UInt32 count) ! 615: ! 616: { ! 617: UInt32 pageSize; ! 618: OHCIPhysicalLogicalPtr pPhysicalLogical; ! 619: OHCIPhysicalLogicalPtr p; ! 620: ! 621: pPhysicalLogical = pOHCIUIMData->pPhysicalLogical; ! 622: pageSize = pOHCIUIMData->pageSize; ! 623: ! 624: // zzz do we deallocate this? ! 625: p = (OHCIPhysicalLogicalPtr) IOMalloc(sizeof (OHCIPhysicalLogical)); ! 626: ! 627: p->LogicalStart = pLogicalAddress; ! 628: p->PhysicalStart = kvtophys((vm_offset_t)pLogicalAddress); ! 629: p->LogicalEnd = p->LogicalStart + count * pageSize-1; ! 630: p->PhysicalEnd = p->PhysicalStart + count * pageSize-1; ! 631: p->pNext = pOHCIUIMData->pPhysicalLogical; ! 632: ! 633: pOHCIUIMData->pPhysicalLogical = p; ! 634: ! 635: return (p->PhysicalStart); ! 636: } ! 637: ! 638: //Allocate ! 639: IOReturn AppleOHCI::OHCIUIMAllocateMemory (int num_of_TDs, ! 640: int num_of_EDs, ! 641: int num_of_ITDs) ! 642: { ! 643: Ptr p; ! 644: UInt32 physical; ! 645: int tdsPerPage, pagesTD, ! 646: edsPerPage, pagesED, ! 647: itdsPerPage, pagesITD; ! 648: UInt32 pageSize; ! 649: OHCIEndpointDescriptorPtr FreeED, FreeEDCurrent; ! 650: OHCIGeneralTransferDescriptorPtr FreeTD, FreeTDCurrent; ! 651: OHCIIsochTransferDescriptorPtr FreeITD, FreeITDCurrent; ! 652: int i,j; ! 653: ! 654: ! 655: pageSize = pOHCIUIMData->pageSize; ! 656: ! 657: tdsPerPage = pageSize / sizeof (OHCIGeneralTransferDescriptor); ! 658: pagesTD = (num_of_TDs + (tdsPerPage - 1)) / tdsPerPage; ! 659: edsPerPage = pageSize / sizeof (OHCIEndpointDescriptor); ! 660: pagesED = (num_of_EDs + (edsPerPage - 1)) / edsPerPage; ! 661: itdsPerPage = pageSize / sizeof (OHCIIsochTransferDescriptor); ! 662: pagesITD = (num_of_ITDs + (itdsPerPage - 1)) / itdsPerPage; ! 663: ! 664: p = (Ptr)IOMalloc( (pagesED + pagesTD + pagesITD + 1) * pageSize); ! 665: ! 666: if (!p) ! 667: return(kIOReturnNoMemory); ! 668: ! 669: for(i=0; i<(pagesED + pagesTD + pagesITD + 1) * pageSize/4; i++) ! 670: ((UInt32 *)p)[i] = 0x12345678; ! 671: // bzero(p, ((pagesED + pagesTD + pagesITD + 1) * pageSize)); ! 672: ! 673: pOHCIUIMData->pDataAllocation = p; ! 674: // page align and 16 byte align (page align automagically ! 675: // makes it 16 byte aligned) ! 676: p = (Ptr) (((UInt32) p + (pageSize - 1)) & ~(pageSize - 1)); ! 677: //bzero(p, ((pagesED) * pageSize)); ! 678: ! 679: ! 680: // create a list of unused ED's, filling in Virtual address, ! 681: // physicaladdress and virtual next physical next. ! 682: FreeED = (OHCIEndpointDescriptorPtr) p; ! 683: FreeEDCurrent = FreeED; ! 684: pOHCIUIMData->pFreeED = FreeED; ! 685: ! 686: for (i = 0 ; i < pagesED ; i++) ! 687: { ! 688: physical = kvtophys(FreeEDCurrent); ! 689: for (j = 0; j < edsPerPage; j++) ! 690: { ! 691: // create EDs ! 692: FreeEDCurrent[j].pPhysical = ! 693: physical + (j * sizeof (OHCIEndpointDescriptor)); ! 694: FreeEDCurrent[j].pLogicalNext = (&FreeEDCurrent[j+1]); ! 695: } ! 696: if (i != (pagesED - 1)) ! 697: { ! 698: FreeEDCurrent[j-1].pLogicalNext = ((UInt32) FreeEDCurrent + pageSize); ! 699: } ! 700: else ! 701: { ! 702: FreeEDCurrent[j-1].pLogicalNext = nil; ! 703: pOHCIUIMData->pLastFreeED = &FreeEDCurrent[j-1]; ! 704: } ! 705: ! 706: // goto next page ! 707: FreeEDCurrent = (OHCIEndpointDescriptorPtr) ! 708: ((UInt32) FreeEDCurrent + pageSize); ! 709: //physical += pageSize; ! 710: } ! 711: ! 712: FreeTD = (OHCIGeneralTransferDescriptorPtr) FreeEDCurrent; ! 713: FreeTDCurrent = FreeTD; ! 714: pOHCIUIMData->pFreeTD = FreeTD; ! 715: for (i = 0; i < pagesTD; i++) ! 716: { ! 717: physical = OHCIUIMGetPhysicalAddress((UInt32) FreeTDCurrent, 1); ! 718: for (j = 0; j < tdsPerPage; j++) ! 719: { ! 720: //create TDs ! 721: FreeTDCurrent[j].pPhysical = ! 722: physical + (j * sizeof (OHCIGeneralTransferDescriptor)); ! 723: FreeTDCurrent[j].pLogicalNext = (UInt32) (&FreeTDCurrent[j+1]); ! 724: } ! 725: if (i != (pagesTD - 1)) ! 726: { ! 727: FreeTDCurrent[j-1].pLogicalNext = ((UInt32) FreeTDCurrent + pageSize); ! 728: } ! 729: else ! 730: { ! 731: FreeTDCurrent[j-1].pLogicalNext = nil; ! 732: pOHCIUIMData->pLastFreeTD = &FreeTDCurrent[j-1]; ! 733: } ! 734: ! 735: // goto next page ! 736: FreeTDCurrent = (OHCIGeneralTransferDescriptorPtr) ! 737: ((UInt32) FreeTDCurrent + pageSize); ! 738: //physical += pageSize; ! 739: } ! 740: ! 741: // set up freeitd queue ! 742: FreeITD = (OHCIIsochTransferDescriptorPtr) FreeTDCurrent; ! 743: FreeITDCurrent = FreeITD; ! 744: pOHCIUIMData->pFreeITD = FreeITD; ! 745: for (i = 0; i < pagesITD; i++) ! 746: { ! 747: //physical = kvtophys(FreeITDCurrent); ! 748: physical = OHCIUIMGetPhysicalAddress((UInt32) FreeITDCurrent, 1); ! 749: for (j = 0; j < itdsPerPage; j++) ! 750: { ! 751: // create TDs ! 752: FreeITDCurrent[j].pPhysical = ! 753: physical + (j * sizeof (OHCIIsochTransferDescriptor)); ! 754: FreeITDCurrent[j].pLogicalNext = (&FreeITDCurrent[j+1]); ! 755: } ! 756: if (i != (pagesITD - 1)) ! 757: { ! 758: FreeITDCurrent[j-1].pLogicalNext = ! 759: (OHCIIsochTransferDescriptorPtr)((UInt32) FreeITDCurrent + pageSize); ! 760: } ! 761: else ! 762: { ! 763: FreeITDCurrent[j-1].pLogicalNext = nil; ! 764: pOHCIUIMData->pLastFreeITD = &FreeITDCurrent[j-1]; ! 765: } ! 766: ! 767: // goto next page ! 768: FreeITDCurrent = (OHCIIsochTransferDescriptorPtr) ! 769: ((UInt32) FreeITDCurrent + pageSize); ! 770: //physical += pageSize; ! 771: } ! 772: ! 773: // create a list of unused buffers????? ! 774: ! 775: return (kIOReturnSuccess); ! 776: } ! 777: ! 778: OHCIIsochTransferDescriptorPtr AppleOHCI::OHCIUIMAllocateITD(void) ! 779: { ! 780: OHCIIsochTransferDescriptorPtr temp; ! 781: ! 782: // pop a TD off of FreeTD list ! 783: // if FreeTD == NIL return nil ! 784: // should we check if ED is full and if not access that???? ! 785: temp = pOHCIUIMData->pFreeITD; ! 786: ! 787: if (temp != nil) ! 788: { ! 789: pOHCIUIMData->pFreeITD = temp->pLogicalNext; ! 790: } ! 791: else ! 792: { ! 793: IOLog("%s: Out of Isoch Transfer Descriptors!\n", getName()); ! 794: return nil; ! 795: } ! 796: ! 797: temp->pLogicalNext = nil; ! 798: ! 799: return (temp); ! 800: } ! 801: ! 802: OHCIGeneralTransferDescriptorPtr AppleOHCI::OHCIUIMAllocateTD(void) ! 803: ! 804: { ! 805: OHCIGeneralTransferDescriptorPtr freeTD; ! 806: ! 807: // pop a TD off of FreeTD list ! 808: //if FreeTD == NIL return nil ! 809: // should we check if ED is full and if not access that???? ! 810: freeTD = pOHCIUIMData->pFreeTD; ! 811: ! 812: if (freeTD == nil) ! 813: { ! 814: int j; ! 815: int tdsPerPage; ! 816: UInt32 physical; ! 817: OHCIGeneralTransferDescriptorPtr FreeTDCurrent; ! 818: UInt8 * p = (UInt8 *)IOMallocAligned(pOHCIUIMData->pageSize, ! 819: pOHCIUIMData->pageSize); ! 820: if(p == NULL) { ! 821: IOLog("%s: Out of Transfer Descriptors!\n", getName()); ! 822: return NULL; ! 823: } ! 824: ! 825: //bzero(p, pOHCIUIMData->pageSize); ! 826: ! 827: tdsPerPage = pOHCIUIMData->pageSize / sizeof (OHCIGeneralTransferDescriptor); ! 828: pOHCIUIMData->pFreeTD = FreeTDCurrent = (OHCIGeneralTransferDescriptorPtr)p; ! 829: physical = OHCIUIMGetPhysicalAddress((UInt32) FreeTDCurrent, 1); ! 830: for (j = 0; j < tdsPerPage-1; j++) ! 831: { ! 832: //create TDs ! 833: FreeTDCurrent[j].pPhysical = ! 834: physical + (j * sizeof (OHCIGeneralTransferDescriptor)); ! 835: FreeTDCurrent[j].pLogicalNext = &FreeTDCurrent[j+1]; ! 836: } ! 837: FreeTDCurrent[j].pPhysical = ! 838: physical + (j * sizeof (OHCIGeneralTransferDescriptor)); ! 839: FreeTDCurrent[j].pLogicalNext = nil; ! 840: pOHCIUIMData->pLastFreeTD = &FreeTDCurrent[j]; ! 841: freeTD = pOHCIUIMData->pFreeTD; ! 842: } ! 843: pOHCIUIMData->pFreeTD = freeTD->pLogicalNext; ! 844: freeTD->pLogicalNext = nil; ! 845: return (freeTD); ! 846: } ! 847: ! 848: OHCIEndpointDescriptorPtr AppleOHCI::OHCIUIMAllocateED(void) ! 849: { ! 850: OHCIEndpointDescriptorPtr freeED; ! 851: ! 852: // Pop a ED off the FreeED list ! 853: // If FreeED == nil return Error ! 854: freeED = pOHCIUIMData->pFreeED; ! 855: ! 856: if (freeED == nil) ! 857: { ! 858: int j; ! 859: int edsPerPage; ! 860: UInt32 physical; ! 861: OHCIEndpointDescriptorPtr FreeEDCurrent; ! 862: UInt8 * p = (UInt8 *)IOMallocAligned(pOHCIUIMData->pageSize, ! 863: pOHCIUIMData->pageSize); ! 864: if(p == NULL) ! 865: { ! 866: IOLog("%s: Out of Endpoint Descriptors!\n", getName()); ! 867: return NULL; ! 868: } ! 869: ! 870: //bzero(p, pOHCIUIMData->pageSize); ! 871: ! 872: edsPerPage = pOHCIUIMData->pageSize / sizeof (OHCIEndpointDescriptor); ! 873: physical = kvtophys((vm_offset_t)p); ! 874: pOHCIUIMData->pFreeED = FreeEDCurrent = (OHCIEndpointDescriptorPtr)p; ! 875: for (j = 0; j < edsPerPage-1; j++) ! 876: { ! 877: // create EDs ! 878: FreeEDCurrent[j].pPhysical = ! 879: physical + (j * sizeof (OHCIEndpointDescriptor)); ! 880: FreeEDCurrent[j].pLogicalNext = (&FreeEDCurrent[j+1]); ! 881: } ! 882: FreeEDCurrent[j].pPhysical = ! 883: physical + (j * sizeof (OHCIEndpointDescriptor)); ! 884: FreeEDCurrent[j].pLogicalNext = nil; ! 885: pOHCIUIMData->pLastFreeED = &FreeEDCurrent[j]; ! 886: freeED = pOHCIUIMData->pFreeED; ! 887: } ! 888: pOHCIUIMData->pFreeED = (OHCIEndpointDescriptorPtr) freeED->pLogicalNext; ! 889: freeED->pLogicalNext = nil; ! 890: return (freeED); ! 891: } ! 892: ! 893: IOReturn AppleOHCI::OHCIUIMDeallocateITD (OHCIIsochTransferDescriptorPtr pTD) ! 894: { ! 895: UInt32 physical; ! 896: ! 897: // zero out all unnecessary fields ! 898: physical = pTD->pPhysical; ! 899: //bzero(pTD, sizeof(*pTD)); ! 900: pTD->pLogicalNext = NULL; ! 901: pTD->pPhysical = physical; ! 902: if (pOHCIUIMData->pFreeITD) ! 903: { ! 904: pOHCIUIMData->pLastFreeITD->pLogicalNext = pTD; ! 905: pOHCIUIMData->pLastFreeITD = pTD; ! 906: } ! 907: else ! 908: { ! 909: // list is currently empty ! 910: pOHCIUIMData->pLastFreeITD = pTD; ! 911: pOHCIUIMData->pFreeITD = pTD; ! 912: } ! 913: return (kIOReturnSuccess); ! 914: } ! 915: ! 916: ! 917: IOReturn AppleOHCI::OHCIUIMDeallocateTD (OHCIGeneralTransferDescriptorPtr pTD) ! 918: { ! 919: UInt32 physical; ! 920: ! 921: //zero out all unnecessary fields ! 922: physical = pTD->pPhysical; ! 923: //bzero(pTD, sizeof(*pTD)); ! 924: pTD->pLogicalNext = nil; ! 925: pTD->pPhysical = physical; ! 926: ! 927: if (pOHCIUIMData->pFreeTD){ ! 928: pOHCIUIMData->pLastFreeTD->pLogicalNext = pTD; ! 929: pOHCIUIMData->pLastFreeTD = pTD; ! 930: } else { ! 931: // list is currently empty ! 932: pOHCIUIMData->pLastFreeTD = pTD; ! 933: pOHCIUIMData->pFreeTD = pTD; ! 934: } ! 935: return (kIOReturnSuccess); ! 936: } ! 937: ! 938: IOReturn AppleOHCI::OHCIUIMDeallocateED (OHCIEndpointDescriptorPtr pED) ! 939: { ! 940: UInt32 physical; ! 941: ! 942: //zero out all unnecessary fields ! 943: physical = pED->pPhysical; ! 944: //bzero(pED, sizeof(*pED)); ! 945: pED->pPhysical = physical; ! 946: pED->pLogicalNext = nil; ! 947: ! 948: if (pOHCIUIMData->pFreeED){ ! 949: pOHCIUIMData->pLastFreeED->pLogicalNext = pED; ! 950: pOHCIUIMData->pLastFreeED = pED; ! 951: } else { ! 952: // list is currently empty ! 953: pOHCIUIMData->pLastFreeED = pED; ! 954: pOHCIUIMData->pFreeED = pED; ! 955: } ! 956: return (kIOReturnSuccess); ! 957: } ! 958: ! 959: int GetEDType(OHCIEndpointDescriptorPtr pED) ! 960: { ! 961: return ((OSSwapInt32(pED->flags) & kOHCIEDControl_F) ! 962: >> kOHCIEDControl_FPhase); ! 963: } ! 964: ! 965: ! 966: IOReturn AppleOHCI::RemoveAllTDs (OHCIEndpointDescriptorPtr pED) ! 967: { ! 968: RemoveTDs(pED); ! 969: ! 970: if (GetEDType(pED) == kOHCIEDFormatGeneralTD) { ! 971: // remove the last "dummy" TD ! 972: OHCIUIMDeallocateTD( ! 973: (OHCIGeneralTransferDescriptorPtr) pED->pLogicalTailP); ! 974: } ! 975: else ! 976: { ! 977: OHCIUIMDeallocateITD( ! 978: (OHCIIsochTransferDescriptorPtr) pED->pLogicalTailP); ! 979: } ! 980: pED->pLogicalTailP = nil; ! 981: ! 982: return (0); ! 983: } ! 984: ! 985: ! 986: //removes all but the last of the TDs ! 987: IOReturn AppleOHCI::RemoveTDs(OHCIEndpointDescriptorPtr pED) ! 988: { ! 989: OHCIGeneralTransferDescriptorPtr pCurrentTD, lastTD; ! 990: UInt32 bufferSizeRemaining = 0; ! 991: OHCIIsochTransferDescriptorPtr pITD, pITDLast; ! 992: ! 993: if (GetEDType(pED) == kOHCIEDFormatGeneralTD) ! 994: { ! 995: //process and deallocate GTD's ! 996: pCurrentTD = (OHCIGeneralTransferDescriptorPtr) ! 997: (OSSwapInt32(pED->tdQueueHeadPtr) & kOHCIHeadPMask); ! 998: pCurrentTD = (OHCIGeneralTransferDescriptorPtr) ! 999: OHCIUIMGetLogicalAddress ((UInt32) pCurrentTD); ! 1000: ! 1001: lastTD = (OHCIGeneralTransferDescriptorPtr) pED->pLogicalTailP; ! 1002: pED->pLogicalHeadP = pED->pLogicalTailP; ! 1003: ! 1004: while (pCurrentTD != lastTD) ! 1005: { ! 1006: if (pCurrentTD == nil) ! 1007: return (-1); ! 1008: ! 1009: //take out TD from list ! 1010: pED->tdQueueHeadPtr = pCurrentTD->nextTD; ! 1011: pED->pLogicalHeadP = pCurrentTD->pLogicalNext; ! 1012: ! 1013: bufferSizeRemaining += findBufferRemaining(pCurrentTD); ! 1014: ! 1015: if (pCurrentTD->completion.action != nil) ! 1016: { ! 1017: IOUSBCompletion completion; ! 1018: // zero out callback first then call it ! 1019: completion = pCurrentTD->completion; ! 1020: pCurrentTD->completion.action = nil; ! 1021: complete(completion, ! 1022: kIOReturnAborted, ! 1023: bufferSizeRemaining); ! 1024: bufferSizeRemaining = 0; ! 1025: } ! 1026: ! 1027: OHCIUIMDeallocateTD(pCurrentTD); ! 1028: pCurrentTD = (OHCIGeneralTransferDescriptorPtr) pED->pLogicalHeadP; ! 1029: } ! 1030: } ! 1031: else ! 1032: { ! 1033: UInt32 phys; ! 1034: phys = (OSReadLittleInt32(&pED->tdQueueHeadPtr, 0) & kOHCIHeadPMask); ! 1035: pITD = (OHCIIsochTransferDescriptorPtr) ! 1036: OHCIUIMGetLogicalAddress (phys); ! 1037: pITDLast = (OHCIIsochTransferDescriptorPtr)pED->pLogicalTailP; ! 1038: ! 1039: while (pITD != pITDLast) ! 1040: { ! 1041: OHCIIsochTransferDescriptorPtr pPrevITD; ! 1042: if (pITD == nil) ! 1043: return (-1); ! 1044: ProcessCompletedITD (pITD, kIOReturnAborted); ! 1045: pPrevITD = pITD; ! 1046: pITD = pITD->pLogicalNext; ! 1047: // deallocate td ! 1048: OHCIUIMDeallocateITD(pPrevITD); ! 1049: } ! 1050: } ! 1051: ! 1052: return (0); ! 1053: } ! 1054: ! 1055: void ProcessCompletedITD (OHCIIsochTransferDescriptorPtr pITD, IOReturn status) ! 1056: { ! 1057: ! 1058: IOUSBIsocFrame * pFrames; ! 1059: int i; ! 1060: int frameCount; ! 1061: ! 1062: //print_itd(pITD); ! 1063: pFrames = pITD->pIsocFrame; ! 1064: frameCount = (OSReadLittleInt32(&pITD->flags, 0) & kOHCIITDControl_FC) >> ! 1065: kOHCIITDControl_FCPhase; ! 1066: for (i=0; i <= frameCount; i++) ! 1067: { ! 1068: UInt16 offset = OSReadLittleInt16(&pITD->offset[i], 0); ! 1069: if ( ((offset & kOHCIITDPSW_CCNA) >> kOHCIITDPSW_CCNAPhase) == ! 1070: kOHCIITDOffsetConditionNotAccessed) ! 1071: { ! 1072: pFrames[pITD->frameNum + i].frActCount = 0; ! 1073: pFrames[pITD->frameNum + i].frStatus = ! 1074: kOHCIITDConditionNotAccessedReturn; ! 1075: } ! 1076: else ! 1077: { ! 1078: pFrames[pITD->frameNum + i].frStatus = ! 1079: (offset & kOHCIITDPSW_CC) >> kOHCIITDOffset_CCPhase; ! 1080: // Successful isoch transmit sets the size field to zero, ! 1081: // successful receive sets size to actual packet size received. ! 1082: if(kIOReturnSuccess == pFrames[pITD->frameNum + i].frStatus && ! 1083: pITD->pType == kOHCIIsochronousOutType) ! 1084: pFrames[pITD->frameNum + i].frActCount = ! 1085: pFrames[pITD->frameNum + i].frReqCount; ! 1086: else ! 1087: pFrames[pITD->frameNum + i].frActCount = ! 1088: offset & kOHCIITDPSW_Size; ! 1089: } ! 1090: } ! 1091: // call callback ! 1092: if (pITD->completion.action) ! 1093: { ! 1094: IOUSBIsocCompletionAction pHandler; ! 1095: pHandler = pITD->completion.action; ! 1096: pITD->completion.action = nil; ! 1097: //zero out handler first than call it ! 1098: (*pHandler) (pITD->completion.target, pITD->completion.parameter, ! 1099: status, pFrames); ! 1100: } ! 1101: } ! 1102: ! 1103: ! 1104: IOReturn ! 1105: AppleOHCI::DoDoneQueueProcessing(OHCIGeneralTransferDescriptorPtr pHCDoneTD, ! 1106: IOUSBCompletionAction safeAction) ! 1107: { ! 1108: UInt32 control, transferStatus; ! 1109: long bufferSizeRemaining; ! 1110: OHCIGeneralTransferDescriptorPtr prevTD, nextTD; ! 1111: UInt32 PhysAddr; ! 1112: UInt32 pageSize; ! 1113: UInt32 pageMask; ! 1114: OHCIEndpointDescriptorPtr tempED; ! 1115: OHCIRegistersPtr pOHCIRegisters; ! 1116: OHCIIsochTransferDescriptorPtr pITD; ! 1117: ! 1118: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters; ! 1119: ! 1120: if(pHCDoneTD == nil) ! 1121: /* This should not happen */ ! 1122: return(kIOReturnSuccess); ! 1123: ! 1124: pageSize = pOHCIUIMData->pageSize; ! 1125: pageMask = ~(pageSize - 1); ! 1126: ! 1127: /* Reverse the done queue use only the virtual Address fields */ ! 1128: prevTD = 0; ! 1129: while (pHCDoneTD != nil) ! 1130: { ! 1131: PhysAddr = OSSwapInt32(pHCDoneTD->nextTD) & kOHCIHeadPMask; ! 1132: nextTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress(PhysAddr); ! 1133: pHCDoneTD->pLogicalNext = prevTD; ! 1134: prevTD = pHCDoneTD; ! 1135: pHCDoneTD = nextTD; ! 1136: } ! 1137: pHCDoneTD = prevTD; /* New qHead */ ! 1138: ! 1139: while (pHCDoneTD != nil) ! 1140: { ! 1141: #if (DEBUGGING_LEVEL > 2) ! 1142: DEBUGLOG("\tdone queue: processing..."); print_td(pHCDoneTD); ! 1143: #endif ! 1144: IOReturn errStatus; ! 1145: // find the next one ! 1146: nextTD = pHCDoneTD->pLogicalNext; ! 1147: ! 1148: control = OSSwapInt32(pHCDoneTD->flags); ! 1149: transferStatus = (control & kOHCIGTDControl_CC) ! 1150: >> kOHCIGTDControl_CCPhase; ! 1151: errStatus = TranslateStatusToUSBError(transferStatus); ! 1152: if (pOHCIUIMData->OptiOn && (pHCDoneTD->pType == kOHCIOptiLSBug)) ! 1153: { ! 1154: // clear any bad errors ! 1155: tempED = (OHCIEndpointDescriptorPtr) pHCDoneTD->pEndpoint; ! 1156: pHCDoneTD->flags = pHCDoneTD->flags ! 1157: & OSSwapInt32(kOHCIGTDClearErrorMask); ! 1158: tempED->tdQueueHeadPtr &= OSSwapInt32(kOHCIHeadPMask); ! 1159: pHCDoneTD->nextTD = tempED->tdQueueTailPtr & OSSwapInt32(kOHCIHeadPMask); ! 1160: tempED->tdQueueTailPtr = OSSwapInt32(pHCDoneTD->pPhysical); ! 1161: pOHCIRegisters->hcCommandStatus = ! 1162: OSSwapInt32 (kOHCIHcCommandStatus_CLF); ! 1163: ! 1164: // For CMD Buffer Underrun Errata ! 1165: } ! 1166: else if ((transferStatus == kOHCIGTDConditionBufferUnderrun) && ! 1167: (pHCDoneTD->pType == kOHCIBulkTransferOutType) && ! 1168: (pOHCIUIMData->errataBits & kErrataRetryBufferUnderruns)) ! 1169: { ! 1170: tempED = (OHCIEndpointDescriptorPtr) pHCDoneTD->pEndpoint; ! 1171: pHCDoneTD->flags = pHCDoneTD->flags ! 1172: & OSSwapInt32(kOHCIGTDClearErrorMask); ! 1173: pHCDoneTD->nextTD = tempED->tdQueueHeadPtr & OSSwapInt32(kOHCIHeadPMask); ! 1174: pHCDoneTD->pLogicalNext = (OHCIGeneralTransferDescriptorPtr) ! 1175: OHCIUIMGetLogicalAddress (OSSwapInt32(tempED->tdQueueHeadPtr) ! 1176: & kOHCIHeadPMask); ! 1177: ! 1178: tempED->tdQueueHeadPtr = OSSwapInt32(pHCDoneTD->pPhysical) ! 1179: | (tempED->tdQueueHeadPtr & OSSwapInt32( kOHCIEDToggleBitMask)); ! 1180: pOHCIRegisters->hcCommandStatus = ! 1181: OSSwapInt32(kOHCIHcCommandStatus_BLF); ! 1182: ! 1183: } ! 1184: else if (pHCDoneTD->pType == kOHCIIsochronousInType || ! 1185: pHCDoneTD->pType == kOHCIIsochronousOutType) ! 1186: { ! 1187: // cast to a isoc type ! 1188: pITD = (OHCIIsochTransferDescriptorPtr) pHCDoneTD; ! 1189: ProcessCompletedITD(pITD, errStatus); ! 1190: // deallocate td ! 1191: OHCIUIMDeallocateITD(pITD); ! 1192: } ! 1193: else ! 1194: { ! 1195: bufferSizeRemaining = findBufferRemaining (pHCDoneTD); ! 1196: if (pHCDoneTD->completion.action != nil) ! 1197: { ! 1198: IOUSBCompletion completion; ! 1199: completion = pHCDoneTD->completion; ! 1200: if(!safeAction || (safeAction == completion.action)) { ! 1201: // zero out callback first then call it ! 1202: pHCDoneTD->completion.action = nil; ! 1203: complete(completion, errStatus, bufferSizeRemaining); ! 1204: OHCIUIMDeallocateTD(pHCDoneTD); ! 1205: } ! 1206: else { ! 1207: if(_pendingHead) ! 1208: _pendingTail->pLogicalNext = pHCDoneTD; ! 1209: else ! 1210: _pendingHead = pHCDoneTD; ! 1211: _pendingTail = pHCDoneTD; ! 1212: } ! 1213: } ! 1214: else if (errStatus != kIOReturnSuccess) { ! 1215: doCallback(pHCDoneTD, errStatus, bufferSizeRemaining); ! 1216: OHCIUIMDeallocateTD(pHCDoneTD); ! 1217: } ! 1218: } ! 1219: pHCDoneTD = nextTD; /* New qHead */ ! 1220: } ! 1221: ! 1222: return(kIOReturnSuccess); ! 1223: } ! 1224: ! 1225: ! 1226: ! 1227: ! 1228: void AppleOHCI::UIMProcessDoneQueue(IOUSBCompletionAction safeAction) ! 1229: { ! 1230: OHCIRegistersPtr pOHCIRegisters = pOHCIUIMData->pOHCIRegisters; ! 1231: UInt32 interruptStatus; ! 1232: UInt32 PhysAddr; ! 1233: OHCIGeneralTransferDescriptorPtr pHCDoneTD; ! 1234: ! 1235: ! 1236: // check if the OHCI has written the DoneHead yet ! 1237: interruptStatus = OSSwapInt32(pOHCIRegisters->hcInterruptStatus); ! 1238: if( (interruptStatus & kOHCIHcInterrupt_WDH) == 0) ! 1239: { ! 1240: return; ! 1241: } ! 1242: ! 1243: // get the pointer to the list (logical address) ! 1244: PhysAddr = (UInt32) OSSwapInt32(*(UInt32 *)(pOHCIUIMData->pHCCA + 0x84)); ! 1245: PhysAddr &= kOHCIHeadPMask; // mask off interrupt bits ! 1246: pHCDoneTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress(PhysAddr); ! 1247: // write to 0 to the HCCA DoneHead ptr so we won't look at it anymore. ! 1248: *(UInt32 *)(pOHCIUIMData->pHCCA + 0x84) = 0L; ! 1249: ! 1250: // Since we have a copy of the queue to process, we can let the host update it again. ! 1251: pOHCIRegisters->hcInterruptStatus = OSSwapInt32(kOHCIHcInterrupt_WDH); ! 1252: ! 1253: DoDoneQueueProcessing(pHCDoneTD, safeAction); ! 1254: return; ! 1255: } ! 1256: ! 1257: void AppleOHCI::finishPending() ! 1258: { ! 1259: while(_pendingHead) { ! 1260: OHCIGeneralTransferDescriptorPtr next = _pendingHead->pLogicalNext; ! 1261: long bufferSizeRemaining = findBufferRemaining (_pendingHead); ! 1262: UInt32 transferStatus = (OSReadLittleInt32(&_pendingHead->flags, 0) & ! 1263: kOHCIGTDControl_CC) >> kOHCIGTDControl_CCPhase; ! 1264: ! 1265: IOUSBCompletion completion; ! 1266: // zero out callback first then call it ! 1267: completion = _pendingHead->completion; ! 1268: _pendingHead->completion.action = nil; ! 1269: complete(completion, ! 1270: TranslateStatusToUSBError(transferStatus), ! 1271: bufferSizeRemaining); ! 1272: OHCIUIMDeallocateTD(_pendingHead); ! 1273: _pendingHead = next; ! 1274: } ! 1275: } ! 1276: ! 1277: UInt32 AppleOHCI::GetBandwidthAvailable() ! 1278: { ! 1279: return pOHCIUIMData->isochBandwidthAvail; ! 1280: } ! 1281: ! 1282: UInt64 AppleOHCI::GetFrameNumber() ! 1283: { ! 1284: ! 1285: UInt64 bigFrameNumber; ! 1286: UInt16 framenumber16; ! 1287: ! 1288: framenumber16 = OSReadLittleInt16(pOHCIUIMData->pHCCA, 0x80); ! 1289: bigFrameNumber = pOHCIUIMData->frameNumber + framenumber16; ! 1290: return bigFrameNumber; ! 1291: } ! 1292: ! 1293: UInt32 AppleOHCI::GetFrameNumber32() ! 1294: { ! 1295: UInt16 framenumber16; ! 1296: UInt32 largishFrameNumber; ! 1297: framenumber16 = OSReadLittleInt16(pOHCIUIMData->pHCCA, 0x80); ! 1298: largishFrameNumber = ((UInt32)pOHCIUIMData->frameNumber) + framenumber16; ! 1299: return largishFrameNumber; ! 1300: } ! 1301: ! 1302: ! 1303: // #ifdef DEBUG ! 1304: void AppleOHCI::dumpRegs(void) ! 1305: { ! 1306: UInt32 lvalue; ! 1307: ! 1308: #if 0 ! 1309: /*device->*/configRead16(cwVendorID, &ivalue); ! 1310: /*device->*/configRead16(cwDeviceID, &ivalue); ! 1311: IOLog("OHCI: cwVendorID=%x cwDeviceID=%x\n", ivalue, ivalue2); ! 1312: #else ! 1313: lvalue = _device->configRead32(cwVendorID); ! 1314: IOLog("OHCI: cwVendorID=%lx\n", lvalue); ! 1315: #endif ! 1316: lvalue = _device->configRead32(clClassCodeAndRevID); ! 1317: IOLog("OHCI: clClassCodeAndRevID=%lx\n", lvalue); ! 1318: lvalue = _device->configRead32(clHeaderAndLatency); ! 1319: IOLog("OHCI: clHeaderAndLatency=%lx\n", lvalue); ! 1320: lvalue = _device->configRead32(clBaseAddressZero); ! 1321: IOLog("OHCI: clBaseAddressZero=%lx\n", lvalue); ! 1322: lvalue = _device->configRead32(clBaseAddressOne); ! 1323: IOLog("OHCI: clBaseAddressOne=%lx\n", lvalue); ! 1324: lvalue = _device->configRead32(clExpansionRomAddr); ! 1325: IOLog("OHCI: clExpansionRomAddr=%lx\n", lvalue); ! 1326: lvalue = _device->configRead32(clLatGntIntPinLine); ! 1327: IOLog("OHCI: clLatGntIntPinLine=%lx\n", lvalue); ! 1328: lvalue = _device->configRead32(clLatGntIntPinLine+4); ! 1329: IOLog("OHCI: clLatGntIntPinLine+4=%lx\n", lvalue); ! 1330: lvalue = _device->configRead32(cwCommand); ! 1331: IOLog("OHCI: cwCommand=%lx\n", lvalue & 0x0000ffff); ! 1332: IOLog("OHCI: cwStatus=%lx\n", lvalue & 0xffff0000); ! 1333: ! 1334: lvalue = _device->configRead32(cwCommand); ! 1335: _device->configWrite32(cwCommand, lvalue); ! 1336: _device->configWrite32(cwCommand, (lvalue & 0xffff0000) | ! 1337: (cwCommandEnableBusMaster | ! 1338: cwCommandEnableMemorySpace)); ! 1339: lvalue = _device->configRead32(cwCommand); ! 1340: IOLog("OHCI: cwCommand=%lx\n", lvalue & 0x0000ffff); ! 1341: IOLog("OHCI: cwStatus=%lx\n", lvalue & 0xffff0000); ! 1342: ! 1343: IOLog("OHCI: HcRevision=%lx\n", ! 1344: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcRevision)); ! 1345: IOLog(" HcControl=%lx\n", ! 1346: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcControl)); ! 1347: IOLog(" HcFmInterval=%lx\n", ! 1348: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcFmInterval)); ! 1349: IOLog(" hcRhDescriptorA=%lx\n", ! 1350: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcRhDescriptorA)); ! 1351: IOLog(" hcRhDescriptorB=%lx\n", ! 1352: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcRhDescriptorB)); ! 1353: } ! 1354: // #endif /* DEBUG */ ! 1355: ! 1356: IOReturn TranslateStatusToUSBError(UInt32 status) ! 1357: { ! 1358: static const UInt32 statusToErrorMap[] = { ! 1359: /* OHCI Error */ /* USB Error */ ! 1360: /* 0 */ kIOReturnSuccess, ! 1361: /* 1 */ kIOUSBPipeStalled, //kUSBCRCErr, ! 1362: /* 2 */ kIOUSBPipeStalled, //kUSBBitstufErr, ! 1363: /* 3 */ kIOUSBPipeStalled, //kUSBDataToggleErr, ! 1364: /* 4 */ kIOUSBPipeStalled, //kUSBEndpointStallErr, ! 1365: /* 5 */ kIOReturnNotResponding, //kUSBNotRespondingErr, ! 1366: /* 6 */ kIOUSBPipeStalled, //kUSBPIDCheckErr, ! 1367: /* 7 */ kIOUSBPipeStalled, //kUSBWrongPIDErr, ! 1368: /* 8 */ kIOReturnOverrun, ! 1369: /* 9 */ kIOReturnUnderrun, ! 1370: /* 10 */ kIOReturnError, //kUSBRes1Err, ! 1371: /* 11 */ kIOReturnError, //kUSBRes2Err, ! 1372: /* 12 */ kIOReturnDMAError, //kUSBBufOvrRunErr, ! 1373: /* 13 */ kIOReturnDMAError, //kUSBBufUnderRunErr ! 1374: }; ! 1375: ! 1376: if (status > 13) return(kIOReturnInternalError); ! 1377: return(statusToErrorMap[status]); ! 1378: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.