Annotation of XNU/iokit/Drivers/usb/drvAppleOHCI/AppleOHCI.cpp, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.