Source to iokit/Drivers/usb/drvAppleOHCI/AppleOHCI.cpp
/*
* Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* The contents of this file constitute Original Code as defined in and
* are subject to the Apple Public Source License Version 1.1 (the
* "License"). You may not use this file except in compliance with the
* License. Please obtain a copy of the License at
* http://www.apple.com/publicsource and read it before using this file.
*
* This Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
*
* HISTORY
*
*/
#include <libkern/OSByteOrder.h>
#include <IOKit/IOMemoryCursor.h>
#include "AppleOHCI.h"
#include <IOKit/usb/USB.h>
#define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme
#define DEBUGLOG kprintf
#define nil (0)
#define super IOUSBController
#define self this
#define NUM_BUFFER_PAGES 9 // 54
#define NUM_TDS 255 // 1500
#define NUM_EDS 256 // 1500
#define NUM_ITDS 192 // 1300
// TDs per page == 85
// EDs per page == 128
// ITDs per page == 64
static int GetEDType(OHCIEndpointDescriptorPtr pED);
static void ProcessCompletedITD (OHCIIsochTransferDescriptorPtr pITD, IOReturn status);
extern void print_td(OHCIGeneralTransferDescriptorPtr pTD);
extern void print_itd(OHCIIsochTransferDescriptorPtr x);
static IOReturn TranslateStatusToUSBError(UInt32 status);
OSDefineMetaClassAndStructors(AppleOHCI, IOUSBController)
bool AppleOHCI::init(OSDictionary * propTable)
{
if (!super::init(propTable)) return false;
_intLock = IOLockAlloc();
if (!_intLock)
return(false);
pOHCIUIMData = (OHCIUIMDataPtr) IOMalloc(sizeof(OHCIUIMData));
if (!pOHCIUIMData)
{
IOLog("%s: Unable to allocate memory (1)\n", getName());
return(false);
}
bzero( pOHCIUIMData, sizeof(OHCIUIMData));
return (true);
}
void AppleOHCI::SetVendorInfo(void)
{
OSData *vendProp, *deviceProp, *revisionProp;
// get this chips vendID, deviceID, revisionID
vendProp = (OSData *) _device->getProperty( "vendor-id" );
if (vendProp)
_vendorID = *((UInt32 *) vendProp->getBytesNoCopy());
deviceProp = (OSData *) _device->getProperty( "device-id" );
if (deviceProp)
_deviceID = *((UInt32 *) deviceProp->getBytesNoCopy());
revisionProp = (OSData *) _device->getProperty( "revision-id" );
if (revisionProp)
_revisionID = *((UInt32 *) revisionProp->getBytesNoCopy());
}
IOReturn AppleOHCI::UIMInitialize(IOService * provider)
{
/* UInt16 ivalue, ivalue2; */
IOReturn err = 0;
OHCIRegistersPtr pOHCIRegisters;
UInt32 lvalue;
#if (DEBUGGING_LEVEL > 0)
IOLog("%s: initializing UIM\n", getName());
#endif
_device = OSDynamicCast(IOPCIDevice, provider);
if(_device == NULL)
return kIOReturnBadArgument;
do {
if (!(_deviceBase = provider->mapDeviceMemoryWithIndex(0)))
{
IOLog("%s: unable to get device memory\n", getName());
break;
}
IOLog("%s: config @ %lx (%lx)\n", getName(),
_deviceBase->getVirtualAddress(),
_deviceBase->getPhysicalAddress());
SetVendorInfo();
interruptSource = IOInterruptEventSource::
interruptEventSource(this, &OHCIUIMInterruptHandler, _device);
if (!interruptSource
|| (_workLoop->addEventSource(interruptSource) != kIOReturnSuccess))
continue;
_genCursor =
IONaturalMemoryCursor::withSpecification(PAGE_SIZE, PAGE_SIZE);
if(!_genCursor)
continue;
_isoCursor =
IONaturalMemoryCursor::withSpecification(kUSBMaxIsocFrameReqCount,
kUSBMaxIsocFrameReqCount);
if(!_isoCursor)
continue;
/*
* Initialize my data and the hardware
*/
pOHCIUIMData->errataBits = GetErrataBits(_vendorID, _deviceID, _revisionID);
#if (DEBUGGING_LEVEL > 0)
IOLog("%s: errata bits=%lx\n", getName(), pOHCIUIMData->errataBits);
#endif
pOHCIUIMData->pageSize = PAGE_SIZE;
pOHCIUIMData->pOHCIRegisters = pOHCIRegisters =
(OHCIRegistersPtr) _deviceBase->getVirtualAddress();
#if (DEBUGGING_LEVEL > 2)
dumpRegs();
#endif
// enable the card
lvalue = _device->configRead32(cwCommand);
_device->configWrite32(cwCommand, (lvalue & 0xffff0000) |
(cwCommandEnableBusMaster |
cwCommandEnableMemorySpace));
// Allocate TDs, EDs; FIXME get real numbers to use, CPU specific.
if ((err = OHCIUIMAllocateMemory(NUM_TDS, NUM_EDS, NUM_ITDS)))
continue;
pOHCIRegisters->hcControlCurrentED = 0;
pOHCIRegisters->hcControlHeadED = 0;
pOHCIRegisters->hcDoneHead = 0;
IOSync();
// Set up HCCA.
IOPhysicalAddress physAddr;
pOHCIUIMData->pHCCA = (Ptr) IOMallocContiguous(kHCCAsize, kHCCAalignment, &physAddr);
if (!pOHCIUIMData->pHCCA)
{
IOLog("%s: Unable to allocate memory (2)\n", getName());
err = kIOReturnNoMemory;
continue;
}
OSWriteLittleInt32(&pOHCIRegisters->hcHCCA, 0, physAddr);
IOSync();
// Set the HC to write the donehead to the HCCA, and enable interrupts
pOHCIRegisters->hcInterruptStatus = OSSwapInt32(kOHCIHcInterrupt_WDH);
IOSync();
// Enable the interrupt delivery.
_workLoop->enableAllInterrupts();
// Initialize the Root Hub registers
OHCIRootHubPower(1 /* kOn */);
IOSync();
pOHCIUIMData->rootHubFuncAddress = 1;
// set up Interrupt transfer tree
if ((err = OHCIUIMIsochronousInitialize())) continue;
if ((err = OHCIUIMInterruptInitialize())) continue;
if ((err = OHCIUIMBulkInitialize())) continue;
if ((err = OHCIUIMControlInitialize())) continue;
// Set up hcFmInterval.
UInt32 hcFSMPS; // in register hcFmInterval
UInt32 hcFI; // in register hcFmInterval
UInt32 hcPS; // in register hcPeriodicStart
hcFI = OSReadLittleInt32(&pOHCIRegisters->hcFmInterval, 0) & kOHCIHcFmInterval_FI;
// this formula is from the OHCI spec, section 5.4
hcFSMPS = ((((hcFI-kOHCIMax_OverHead) * 6)/7) << kOHCIHcFmInterval_FSMPSPhase);
hcPS = (hcFI * 9) / 10; // per spec- 90%
OSWriteLittleInt32(&pOHCIRegisters->hcFmInterval, 0, hcFI | hcFSMPS);
OSWriteLittleInt32(&pOHCIRegisters->hcPeriodicStart, 0, hcPS);
IOSync();
// Just so we all start from the same place, reset the OHCI.
pOHCIRegisters->hcControl =
OSSwapInt32 ((kOHCIFunctionalState_Reset
<< kOHCIHcControl_HCFSPhase));
IOSync();
// Set OHCI to operational state and enable processing of control list.
pOHCIRegisters->hcControl =
OSSwapInt32 ((kOHCIFunctionalState_Operational
<< kOHCIHcControl_HCFSPhase)
| kOHCIHcControl_CLE | kOHCIHcControl_BLE
| kOHCIHcControl_PLE | kOHCIHcControl_IE);
IOSync();
pOHCIRegisters->hcInterruptEnable =
OSSwapInt32 (kOHCIHcInterrupt_MIE | kOHCIDefaultInterrupts);
IOSync();
if (pOHCIUIMData->errataBits & kErrataLSHSOpti)
OptiLSHSFix();
//naga (*pOHCIUIMData->interruptEnabler)(pOHCIUIMData->interruptSetMember, nil);
return(kIOReturnSuccess);
} while (false);
IOLog("%s: Error occurred (%d)\n", getName(), err);
UIMFinalize();
if (interruptSource) interruptSource->release();
return(err);
}
IOReturn AppleOHCI::UIMFinalize(void)
{
OHCIRegistersPtr pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
IOLog ("UIMFinalize (shutting down HW)\n");
// Disable All OHCI Interrupts
pOHCIRegisters->hcInterruptDisable = kOHCIHcInterrupt_MIE;
IOSync();
// Place the USB bus into the Reset State
pOHCIRegisters->hcControl = OSSwapInt32((kOHCIFunctionalState_Reset
<< kOHCIHcControl_HCFSPhase));
IOSync();
// need to wait at least 1ms here
IOSleep(2);
// Take away the controllers ability be a bus master.
_device->configWrite32(cwCommand, cwCommandEnableMemorySpace);
// Clear all Processing Registers
pOHCIRegisters->hcHCCA = 0;
pOHCIRegisters->hcPeriodCurrentED = 0;
pOHCIRegisters->hcControlHeadED = 0;
pOHCIRegisters->hcControlCurrentED = 0;
pOHCIRegisters->hcBulkHeadED = 0;
pOHCIRegisters->hcBulkCurrentED = 0;
pOHCIRegisters->hcDoneHead = 0;
IOSync();
// turn off the global power
// FIXME check for per-port vs. Global power control
OHCIRootHubPower(0 /* kOff */);
IOSync();
//status = OHCIUIMFinalizeOHCIUIMData ((OHCIUIMDataPtr) pOHCIUIMData);
IOLog("OHCIUIMFinalize Exit\n");
return(kIOReturnSuccess);
}
/*
* got an error on a TD with no completion routine.
* Search for a later TD on the same end point which does have one,
* so we can tell upper layes of the error.
*/
void AppleOHCI::doCallback(OHCIGeneralTransferDescriptorPtr nextTD,
UInt32 transferStatus,
UInt32 bufferSizeRemaining)
{
OHCIGeneralTransferDescriptorPtr pCurrentTD;
OHCIEndpointDescriptorPtr pED;
UInt32 PhysAddr;
pED = (OHCIEndpointDescriptorPtr) nextTD->pEndpoint;
PhysAddr = (UInt32) OSSwapInt32(pED->tdQueueHeadPtr) & kOHCIHeadPMask;
nextTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress(PhysAddr);
pCurrentTD = nextTD;
if(pCurrentTD == nil) {
IOLog("No transfer descriptors in AppleOHCI::doCallback!\n");
return;
}
while (pCurrentTD->pLogicalNext != nil)
{
bufferSizeRemaining += findBufferRemaining (pCurrentTD);
// make sure this TD won't be added to any future buffer
// remaining calculations
pCurrentTD->currentBufferPtr = 0;
//ERICif (pCurrentTD->preparationID)
//ERIC CheckpointIO(pCurrentTD->preparationID, nil);
// make sure we don't try to do another CheckpointIO later
//ERICpCurrentTD->preparationID = nil;
if (pCurrentTD->completion.action != nil)
{
IOUSBCompletion completion;
// zero out callback first then call it
completion = pCurrentTD->completion;
pCurrentTD->completion.action = nil;
complete(completion,
TranslateStatusToUSBError(transferStatus),
bufferSizeRemaining);
bufferSizeRemaining = 0;
return;
}
pCurrentTD = pCurrentTD->pLogicalNext;
}
}
// FIXME add page size to param list
UInt32 AppleOHCI::findBufferRemaining (OHCIGeneralTransferDescriptorPtr pCurrentTD)
{
UInt32 pageSize;
UInt32 pageMask;
UInt32 bufferSizeRemaining;
pageSize = pOHCIUIMData->pageSize;
pageMask = ~(pageSize - 1);
if (pCurrentTD->currentBufferPtr == 0)
{
bufferSizeRemaining = 0;
}
else if ((OSSwapInt32(pCurrentTD->bufferEnd) & (pageMask)) ==
(OSSwapInt32(pCurrentTD->currentBufferPtr)& (pageMask)))
{
// we're on the same page
bufferSizeRemaining =
(OSSwapInt32 (pCurrentTD->bufferEnd) & ~pageMask) -
(OSSwapInt32 (pCurrentTD->currentBufferPtr) & ~pageMask) + 1;
}
else
{
bufferSizeRemaining =
((OSSwapInt32(pCurrentTD->bufferEnd) & ~pageMask) + 1) +
(pageSize - (OSSwapInt32(pCurrentTD->currentBufferPtr) & ~pageMask));
}
return (bufferSizeRemaining);
}
IOReturn AppleOHCI::OHCIUIMControlInitialize(void)
{
OHCIRegistersPtr pOHCIRegisters;
OHCIEndpointDescriptorPtr pED, pED2;
pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
// Create ED mark it skipped and assign it to ControlTail
pED = OHCIUIMAllocateED();
pED->flags = OSSwapInt32 (kOHCIEDControl_K);
pED->nextED = 0; // End of list
pOHCIUIMData->pControlTail = (UInt32) pED;
// Create ED mark it skipped and assign it to control head
pED2 = OHCIUIMAllocateED();
pED2->flags = OSSwapInt32 (kOHCIEDControl_K);
pOHCIUIMData->pControlHead = (UInt32) pED2;
pOHCIRegisters->hcControlHeadED = OSSwapInt32 ((UInt32) pED2->pPhysical);
// have bulk head ED point to Control tail ED
pED2->nextED = OSSwapInt32 ((UInt32) pED->pPhysical);
pED2->pLogicalNext = pED;
return (kIOReturnSuccess);
}
IOReturn AppleOHCI::OHCIUIMBulkInitialize (void)
{
OHCIRegistersPtr pOHCIRegisters;
OHCIEndpointDescriptorPtr pED, pED2;
pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
// Create ED mark it skipped and assign it to bulkTail
pED = OHCIUIMAllocateED();
pED->flags = OSSwapInt32 (kOHCIEDControl_K);
pED->nextED = 0; // End of list
pOHCIUIMData->pBulkTail = (UInt32) pED;
// Create ED mark it skipped and assign it to bulk head
pED2 = OHCIUIMAllocateED();
pED2->flags = OSSwapInt32 (kOHCIEDControl_K);
pOHCIUIMData->pBulkHead = (UInt32) pED2;
pOHCIRegisters->hcBulkHeadED = OSSwapInt32 ((UInt32) pED2->pPhysical);
// have bulk head ED point to Bulk tail ED
pED2->nextED = OSSwapInt32 ((UInt32) pED->pPhysical);
pED2->pLogicalNext = pED;
return (kIOReturnSuccess);
}
IOReturn AppleOHCI::OHCIUIMIsochronousInitialize(void)
{
OHCIRegistersPtr pOHCIRegisters;
OHCIEndpointDescriptorPtr pED, pED2;
pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
// Create ED mark it skipped and assign it to isoch Tail
pED = OHCIUIMAllocateED();
pED->flags = OSSwapInt32 (kOHCIEDControl_K);
pED->nextED = 0; // End of list
pOHCIUIMData->pIsochTail = (UInt32) pED;
// Create ED mark it skipped and assign it to isoch head
pED2 = OHCIUIMAllocateED();
pED2->flags = OSSwapInt32 (kOHCIEDControl_K);
pOHCIUIMData->pIsochHead = (UInt32) pED2;
// have iso head ED point to iso tail ED
pED2->nextED = OSSwapInt32 ((UInt32) pED->pPhysical);
pED2->pLogicalNext = pED;
pOHCIUIMData->isochBandwidthAvail = kUSBMaxIsocFrameReqCount;
return (kIOReturnSuccess);
}
//Initializes the HCCA Interrupt list with statically
//disabled ED's to form the Interrupt polling queues
IOReturn AppleOHCI::OHCIUIMInterruptInitialize (void)
{
OHCIRegistersPtr pOHCIRegisters;
OHCIIntHeadPtr pInterruptHead;
IOReturn status = 0;
UInt32 dummyControl;
int i, p, q, z;
OHCIEndpointDescriptorPtr pED, pIsochHead;
pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
pInterruptHead = pOHCIUIMData->pInterruptHead;
// create UInt32 with same dword0 for use with searching and
// tracking, skip should be set, and open area should be marked
dummyControl = kOHCIEDControl_K;
dummyControl |= 0; //should be kOHCIFakeED
dummyControl = OSSwapInt32 (dummyControl);
pIsochHead = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pIsochHead;
// do 31 times
// change to 65 and make isoch head the last one.?????
for (i = 0; i < 63; i++)
{
// allocate Endpoint descriptor
pED = OHCIUIMAllocateED();
if (pED == nil)
{
return (kIOReturnNoMemory);
}
// mark skipped,some how mark as a False endpoint zzzzz
else
{
pED->flags = dummyControl;
pED->nextED = 0; // End of list
pInterruptHead[i].pHead = pED;
pInterruptHead[i].pHeadPhysical = pED->pPhysical;
pInterruptHead[i].nodeBandwidth = 0;
}
if (i < 32)
((UInt32 *)pOHCIUIMData->pHCCA)[i] =
(UInt32) OSSwapInt32 ((UInt32) pInterruptHead[i].pHeadPhysical);
}
p = 0;
q = 32;
// FIXME? ERIC
for (i = 0; i < (32 +16 + 8 + 4 + 2); i++)
{
if (i < q/2+p)
z = i + q;
else
z = i + q/2;
if (i == p+q-1)
{
p = p + q;
q = q/2;
}
// point endpoint descriptor to corresponding 8ms descriptor
pED = pInterruptHead[i].pHead;
pED->nextED = OSSwapInt32 (pInterruptHead[z].pHeadPhysical);
pED->pLogicalNext = pInterruptHead[z].pHead;
pInterruptHead[i].pTail = (OHCIEndpointDescriptorPtr) pED->pLogicalNext;
}
i = 62;
pED = pInterruptHead[i].pHead;
pED->nextED = OSSwapInt32 (pIsochHead->pPhysical);
pED->pLogicalNext = pOHCIUIMData->pIsochHead;
pInterruptHead[i].pTail = (OHCIEndpointDescriptorPtr) pED->pLogicalNext;
// point Isochronous head to last endpoint
return (status);
}
////////////////////////////////////////////////////////////////////////////////
//
// UInt32 OHCIUIMGetLogicalAddress
// Given the physical address, return the virtual address
//
UInt32 AppleOHCI::OHCIUIMGetLogicalAddress (UInt32 pPhysicalAddress)
{
OHCIPhysicalLogicalPtr pPhysicalLogical;
UInt32 LogicalAddress = nil;
if (pPhysicalAddress == 0)
return(0);
pPhysicalLogical = pOHCIUIMData->pPhysicalLogical;
while (pPhysicalLogical != nil) {
if (pPhysicalAddress <= pPhysicalLogical->PhysicalEnd
&& pPhysicalAddress >= pPhysicalLogical->PhysicalStart)
{
LogicalAddress = pPhysicalLogical->LogicalStart +
(pPhysicalAddress - pPhysicalLogical->PhysicalStart);
pPhysicalLogical = nil;
} else {
pPhysicalLogical = (OHCIPhysicalLogicalPtr) pPhysicalLogical->pNext;
}
}
if ( LogicalAddress == nil)
IOLog("OHCIUIM: LogicalAddress(0x%lx) == nil !\n", pPhysicalAddress);
return (LogicalAddress);
}
UInt32 AppleOHCI::OHCIUIMGetPhysicalAddress(UInt32 LogicalAddress,
UInt32 count)
{
OHCIPhysicalLogicalPtr pPhysicalLogical;
UInt32 PhysicalAddress = nil;
if (LogicalAddress == 0)
return(0);
pPhysicalLogical = pOHCIUIMData->pPhysicalLogical;
while (pPhysicalLogical != nil) {
if (LogicalAddress <= pPhysicalLogical->LogicalEnd
&& LogicalAddress >= pPhysicalLogical->LogicalStart)
{
PhysicalAddress = pPhysicalLogical->PhysicalStart
+ (LogicalAddress - pPhysicalLogical->LogicalStart);
pPhysicalLogical = nil;
} else {
pPhysicalLogical = pPhysicalLogical->pNext;
}
}
if (PhysicalAddress == nil)
PhysicalAddress = OHCIUIMCreatePhysicalAddress(LogicalAddress, count);
return (PhysicalAddress);
}
/*
* OHCIUIMCreatePhysicalAddress:
* Currently this function only creates a one entry OHCIPhysicalLogical
* entry. This is because it is assuming contiguous memory.
*
*/
UInt32 AppleOHCI::OHCIUIMCreatePhysicalAddress(UInt32 pLogicalAddress,
UInt32 count)
{
UInt32 pageSize;
OHCIPhysicalLogicalPtr pPhysicalLogical;
OHCIPhysicalLogicalPtr p;
pPhysicalLogical = pOHCIUIMData->pPhysicalLogical;
pageSize = pOHCIUIMData->pageSize;
// zzz do we deallocate this?
p = (OHCIPhysicalLogicalPtr) IOMalloc(sizeof (OHCIPhysicalLogical));
p->LogicalStart = pLogicalAddress;
p->PhysicalStart = kvtophys((vm_offset_t)pLogicalAddress);
p->LogicalEnd = p->LogicalStart + count * pageSize-1;
p->PhysicalEnd = p->PhysicalStart + count * pageSize-1;
p->pNext = pOHCIUIMData->pPhysicalLogical;
pOHCIUIMData->pPhysicalLogical = p;
return (p->PhysicalStart);
}
//Allocate
IOReturn AppleOHCI::OHCIUIMAllocateMemory (int num_of_TDs,
int num_of_EDs,
int num_of_ITDs)
{
Ptr p;
UInt32 physical;
int tdsPerPage, pagesTD,
edsPerPage, pagesED,
itdsPerPage, pagesITD;
UInt32 pageSize;
OHCIEndpointDescriptorPtr FreeED, FreeEDCurrent;
OHCIGeneralTransferDescriptorPtr FreeTD, FreeTDCurrent;
OHCIIsochTransferDescriptorPtr FreeITD, FreeITDCurrent;
int i,j;
pageSize = pOHCIUIMData->pageSize;
tdsPerPage = pageSize / sizeof (OHCIGeneralTransferDescriptor);
pagesTD = (num_of_TDs + (tdsPerPage - 1)) / tdsPerPage;
edsPerPage = pageSize / sizeof (OHCIEndpointDescriptor);
pagesED = (num_of_EDs + (edsPerPage - 1)) / edsPerPage;
itdsPerPage = pageSize / sizeof (OHCIIsochTransferDescriptor);
pagesITD = (num_of_ITDs + (itdsPerPage - 1)) / itdsPerPage;
p = (Ptr)IOMalloc( (pagesED + pagesTD + pagesITD + 1) * pageSize);
if (!p)
return(kIOReturnNoMemory);
for(i=0; i<(pagesED + pagesTD + pagesITD + 1) * pageSize/4; i++)
((UInt32 *)p)[i] = 0x12345678;
// bzero(p, ((pagesED + pagesTD + pagesITD + 1) * pageSize));
pOHCIUIMData->pDataAllocation = p;
// page align and 16 byte align (page align automagically
// makes it 16 byte aligned)
p = (Ptr) (((UInt32) p + (pageSize - 1)) & ~(pageSize - 1));
//bzero(p, ((pagesED) * pageSize));
// create a list of unused ED's, filling in Virtual address,
// physicaladdress and virtual next physical next.
FreeED = (OHCIEndpointDescriptorPtr) p;
FreeEDCurrent = FreeED;
pOHCIUIMData->pFreeED = FreeED;
for (i = 0 ; i < pagesED ; i++)
{
physical = kvtophys(FreeEDCurrent);
for (j = 0; j < edsPerPage; j++)
{
// create EDs
FreeEDCurrent[j].pPhysical =
physical + (j * sizeof (OHCIEndpointDescriptor));
FreeEDCurrent[j].pLogicalNext = (&FreeEDCurrent[j+1]);
}
if (i != (pagesED - 1))
{
FreeEDCurrent[j-1].pLogicalNext = ((UInt32) FreeEDCurrent + pageSize);
}
else
{
FreeEDCurrent[j-1].pLogicalNext = nil;
pOHCIUIMData->pLastFreeED = &FreeEDCurrent[j-1];
}
// goto next page
FreeEDCurrent = (OHCIEndpointDescriptorPtr)
((UInt32) FreeEDCurrent + pageSize);
//physical += pageSize;
}
FreeTD = (OHCIGeneralTransferDescriptorPtr) FreeEDCurrent;
FreeTDCurrent = FreeTD;
pOHCIUIMData->pFreeTD = FreeTD;
for (i = 0; i < pagesTD; i++)
{
physical = OHCIUIMGetPhysicalAddress((UInt32) FreeTDCurrent, 1);
for (j = 0; j < tdsPerPage; j++)
{
//create TDs
FreeTDCurrent[j].pPhysical =
physical + (j * sizeof (OHCIGeneralTransferDescriptor));
FreeTDCurrent[j].pLogicalNext = (UInt32) (&FreeTDCurrent[j+1]);
}
if (i != (pagesTD - 1))
{
FreeTDCurrent[j-1].pLogicalNext = ((UInt32) FreeTDCurrent + pageSize);
}
else
{
FreeTDCurrent[j-1].pLogicalNext = nil;
pOHCIUIMData->pLastFreeTD = &FreeTDCurrent[j-1];
}
// goto next page
FreeTDCurrent = (OHCIGeneralTransferDescriptorPtr)
((UInt32) FreeTDCurrent + pageSize);
//physical += pageSize;
}
// set up freeitd queue
FreeITD = (OHCIIsochTransferDescriptorPtr) FreeTDCurrent;
FreeITDCurrent = FreeITD;
pOHCIUIMData->pFreeITD = FreeITD;
for (i = 0; i < pagesITD; i++)
{
//physical = kvtophys(FreeITDCurrent);
physical = OHCIUIMGetPhysicalAddress((UInt32) FreeITDCurrent, 1);
for (j = 0; j < itdsPerPage; j++)
{
// create TDs
FreeITDCurrent[j].pPhysical =
physical + (j * sizeof (OHCIIsochTransferDescriptor));
FreeITDCurrent[j].pLogicalNext = (&FreeITDCurrent[j+1]);
}
if (i != (pagesITD - 1))
{
FreeITDCurrent[j-1].pLogicalNext =
(OHCIIsochTransferDescriptorPtr)((UInt32) FreeITDCurrent + pageSize);
}
else
{
FreeITDCurrent[j-1].pLogicalNext = nil;
pOHCIUIMData->pLastFreeITD = &FreeITDCurrent[j-1];
}
// goto next page
FreeITDCurrent = (OHCIIsochTransferDescriptorPtr)
((UInt32) FreeITDCurrent + pageSize);
//physical += pageSize;
}
// create a list of unused buffers?????
return (kIOReturnSuccess);
}
OHCIIsochTransferDescriptorPtr AppleOHCI::OHCIUIMAllocateITD(void)
{
OHCIIsochTransferDescriptorPtr temp;
// pop a TD off of FreeTD list
// if FreeTD == NIL return nil
// should we check if ED is full and if not access that????
temp = pOHCIUIMData->pFreeITD;
if (temp != nil)
{
pOHCIUIMData->pFreeITD = temp->pLogicalNext;
}
else
{
IOLog("%s: Out of Isoch Transfer Descriptors!\n", getName());
return nil;
}
temp->pLogicalNext = nil;
return (temp);
}
OHCIGeneralTransferDescriptorPtr AppleOHCI::OHCIUIMAllocateTD(void)
{
OHCIGeneralTransferDescriptorPtr freeTD;
// pop a TD off of FreeTD list
//if FreeTD == NIL return nil
// should we check if ED is full and if not access that????
freeTD = pOHCIUIMData->pFreeTD;
if (freeTD == nil)
{
int j;
int tdsPerPage;
UInt32 physical;
OHCIGeneralTransferDescriptorPtr FreeTDCurrent;
UInt8 * p = (UInt8 *)IOMallocAligned(pOHCIUIMData->pageSize,
pOHCIUIMData->pageSize);
if(p == NULL) {
IOLog("%s: Out of Transfer Descriptors!\n", getName());
return NULL;
}
//bzero(p, pOHCIUIMData->pageSize);
tdsPerPage = pOHCIUIMData->pageSize / sizeof (OHCIGeneralTransferDescriptor);
pOHCIUIMData->pFreeTD = FreeTDCurrent = (OHCIGeneralTransferDescriptorPtr)p;
physical = OHCIUIMGetPhysicalAddress((UInt32) FreeTDCurrent, 1);
for (j = 0; j < tdsPerPage-1; j++)
{
//create TDs
FreeTDCurrent[j].pPhysical =
physical + (j * sizeof (OHCIGeneralTransferDescriptor));
FreeTDCurrent[j].pLogicalNext = &FreeTDCurrent[j+1];
}
FreeTDCurrent[j].pPhysical =
physical + (j * sizeof (OHCIGeneralTransferDescriptor));
FreeTDCurrent[j].pLogicalNext = nil;
pOHCIUIMData->pLastFreeTD = &FreeTDCurrent[j];
freeTD = pOHCIUIMData->pFreeTD;
}
pOHCIUIMData->pFreeTD = freeTD->pLogicalNext;
freeTD->pLogicalNext = nil;
return (freeTD);
}
OHCIEndpointDescriptorPtr AppleOHCI::OHCIUIMAllocateED(void)
{
OHCIEndpointDescriptorPtr freeED;
// Pop a ED off the FreeED list
// If FreeED == nil return Error
freeED = pOHCIUIMData->pFreeED;
if (freeED == nil)
{
int j;
int edsPerPage;
UInt32 physical;
OHCIEndpointDescriptorPtr FreeEDCurrent;
UInt8 * p = (UInt8 *)IOMallocAligned(pOHCIUIMData->pageSize,
pOHCIUIMData->pageSize);
if(p == NULL)
{
IOLog("%s: Out of Endpoint Descriptors!\n", getName());
return NULL;
}
//bzero(p, pOHCIUIMData->pageSize);
edsPerPage = pOHCIUIMData->pageSize / sizeof (OHCIEndpointDescriptor);
physical = kvtophys((vm_offset_t)p);
pOHCIUIMData->pFreeED = FreeEDCurrent = (OHCIEndpointDescriptorPtr)p;
for (j = 0; j < edsPerPage-1; j++)
{
// create EDs
FreeEDCurrent[j].pPhysical =
physical + (j * sizeof (OHCIEndpointDescriptor));
FreeEDCurrent[j].pLogicalNext = (&FreeEDCurrent[j+1]);
}
FreeEDCurrent[j].pPhysical =
physical + (j * sizeof (OHCIEndpointDescriptor));
FreeEDCurrent[j].pLogicalNext = nil;
pOHCIUIMData->pLastFreeED = &FreeEDCurrent[j];
freeED = pOHCIUIMData->pFreeED;
}
pOHCIUIMData->pFreeED = (OHCIEndpointDescriptorPtr) freeED->pLogicalNext;
freeED->pLogicalNext = nil;
return (freeED);
}
IOReturn AppleOHCI::OHCIUIMDeallocateITD (OHCIIsochTransferDescriptorPtr pTD)
{
UInt32 physical;
// zero out all unnecessary fields
physical = pTD->pPhysical;
//bzero(pTD, sizeof(*pTD));
pTD->pLogicalNext = NULL;
pTD->pPhysical = physical;
if (pOHCIUIMData->pFreeITD)
{
pOHCIUIMData->pLastFreeITD->pLogicalNext = pTD;
pOHCIUIMData->pLastFreeITD = pTD;
}
else
{
// list is currently empty
pOHCIUIMData->pLastFreeITD = pTD;
pOHCIUIMData->pFreeITD = pTD;
}
return (kIOReturnSuccess);
}
IOReturn AppleOHCI::OHCIUIMDeallocateTD (OHCIGeneralTransferDescriptorPtr pTD)
{
UInt32 physical;
//zero out all unnecessary fields
physical = pTD->pPhysical;
//bzero(pTD, sizeof(*pTD));
pTD->pLogicalNext = nil;
pTD->pPhysical = physical;
if (pOHCIUIMData->pFreeTD){
pOHCIUIMData->pLastFreeTD->pLogicalNext = pTD;
pOHCIUIMData->pLastFreeTD = pTD;
} else {
// list is currently empty
pOHCIUIMData->pLastFreeTD = pTD;
pOHCIUIMData->pFreeTD = pTD;
}
return (kIOReturnSuccess);
}
IOReturn AppleOHCI::OHCIUIMDeallocateED (OHCIEndpointDescriptorPtr pED)
{
UInt32 physical;
//zero out all unnecessary fields
physical = pED->pPhysical;
//bzero(pED, sizeof(*pED));
pED->pPhysical = physical;
pED->pLogicalNext = nil;
if (pOHCIUIMData->pFreeED){
pOHCIUIMData->pLastFreeED->pLogicalNext = pED;
pOHCIUIMData->pLastFreeED = pED;
} else {
// list is currently empty
pOHCIUIMData->pLastFreeED = pED;
pOHCIUIMData->pFreeED = pED;
}
return (kIOReturnSuccess);
}
int GetEDType(OHCIEndpointDescriptorPtr pED)
{
return ((OSSwapInt32(pED->flags) & kOHCIEDControl_F)
>> kOHCIEDControl_FPhase);
}
IOReturn AppleOHCI::RemoveAllTDs (OHCIEndpointDescriptorPtr pED)
{
RemoveTDs(pED);
if (GetEDType(pED) == kOHCIEDFormatGeneralTD) {
// remove the last "dummy" TD
OHCIUIMDeallocateTD(
(OHCIGeneralTransferDescriptorPtr) pED->pLogicalTailP);
}
else
{
OHCIUIMDeallocateITD(
(OHCIIsochTransferDescriptorPtr) pED->pLogicalTailP);
}
pED->pLogicalTailP = nil;
return (0);
}
//removes all but the last of the TDs
IOReturn AppleOHCI::RemoveTDs(OHCIEndpointDescriptorPtr pED)
{
OHCIGeneralTransferDescriptorPtr pCurrentTD, lastTD;
UInt32 bufferSizeRemaining = 0;
OHCIIsochTransferDescriptorPtr pITD, pITDLast;
if (GetEDType(pED) == kOHCIEDFormatGeneralTD)
{
//process and deallocate GTD's
pCurrentTD = (OHCIGeneralTransferDescriptorPtr)
(OSSwapInt32(pED->tdQueueHeadPtr) & kOHCIHeadPMask);
pCurrentTD = (OHCIGeneralTransferDescriptorPtr)
OHCIUIMGetLogicalAddress ((UInt32) pCurrentTD);
lastTD = (OHCIGeneralTransferDescriptorPtr) pED->pLogicalTailP;
pED->pLogicalHeadP = pED->pLogicalTailP;
while (pCurrentTD != lastTD)
{
if (pCurrentTD == nil)
return (-1);
//take out TD from list
pED->tdQueueHeadPtr = pCurrentTD->nextTD;
pED->pLogicalHeadP = pCurrentTD->pLogicalNext;
bufferSizeRemaining += findBufferRemaining(pCurrentTD);
if (pCurrentTD->completion.action != nil)
{
IOUSBCompletion completion;
// zero out callback first then call it
completion = pCurrentTD->completion;
pCurrentTD->completion.action = nil;
complete(completion,
kIOReturnAborted,
bufferSizeRemaining);
bufferSizeRemaining = 0;
}
OHCIUIMDeallocateTD(pCurrentTD);
pCurrentTD = (OHCIGeneralTransferDescriptorPtr) pED->pLogicalHeadP;
}
}
else
{
UInt32 phys;
phys = (OSReadLittleInt32(&pED->tdQueueHeadPtr, 0) & kOHCIHeadPMask);
pITD = (OHCIIsochTransferDescriptorPtr)
OHCIUIMGetLogicalAddress (phys);
pITDLast = (OHCIIsochTransferDescriptorPtr)pED->pLogicalTailP;
while (pITD != pITDLast)
{
OHCIIsochTransferDescriptorPtr pPrevITD;
if (pITD == nil)
return (-1);
ProcessCompletedITD (pITD, kIOReturnAborted);
pPrevITD = pITD;
pITD = pITD->pLogicalNext;
// deallocate td
OHCIUIMDeallocateITD(pPrevITD);
}
}
return (0);
}
void ProcessCompletedITD (OHCIIsochTransferDescriptorPtr pITD, IOReturn status)
{
IOUSBIsocFrame * pFrames;
int i;
int frameCount;
//print_itd(pITD);
pFrames = pITD->pIsocFrame;
frameCount = (OSReadLittleInt32(&pITD->flags, 0) & kOHCIITDControl_FC) >>
kOHCIITDControl_FCPhase;
for (i=0; i <= frameCount; i++)
{
UInt16 offset = OSReadLittleInt16(&pITD->offset[i], 0);
if ( ((offset & kOHCIITDPSW_CCNA) >> kOHCIITDPSW_CCNAPhase) ==
kOHCIITDOffsetConditionNotAccessed)
{
pFrames[pITD->frameNum + i].frActCount = 0;
pFrames[pITD->frameNum + i].frStatus =
kOHCIITDConditionNotAccessedReturn;
}
else
{
pFrames[pITD->frameNum + i].frStatus =
(offset & kOHCIITDPSW_CC) >> kOHCIITDOffset_CCPhase;
// Successful isoch transmit sets the size field to zero,
// successful receive sets size to actual packet size received.
if(kIOReturnSuccess == pFrames[pITD->frameNum + i].frStatus &&
pITD->pType == kOHCIIsochronousOutType)
pFrames[pITD->frameNum + i].frActCount =
pFrames[pITD->frameNum + i].frReqCount;
else
pFrames[pITD->frameNum + i].frActCount =
offset & kOHCIITDPSW_Size;
}
}
// call callback
if (pITD->completion.action)
{
IOUSBIsocCompletionAction pHandler;
pHandler = pITD->completion.action;
pITD->completion.action = nil;
//zero out handler first than call it
(*pHandler) (pITD->completion.target, pITD->completion.parameter,
status, pFrames);
}
}
IOReturn
AppleOHCI::DoDoneQueueProcessing(OHCIGeneralTransferDescriptorPtr pHCDoneTD,
IOUSBCompletionAction safeAction)
{
UInt32 control, transferStatus;
long bufferSizeRemaining;
OHCIGeneralTransferDescriptorPtr prevTD, nextTD;
UInt32 PhysAddr;
UInt32 pageSize;
UInt32 pageMask;
OHCIEndpointDescriptorPtr tempED;
OHCIRegistersPtr pOHCIRegisters;
OHCIIsochTransferDescriptorPtr pITD;
pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
if(pHCDoneTD == nil)
/* This should not happen */
return(kIOReturnSuccess);
pageSize = pOHCIUIMData->pageSize;
pageMask = ~(pageSize - 1);
/* Reverse the done queue use only the virtual Address fields */
prevTD = 0;
while (pHCDoneTD != nil)
{
PhysAddr = OSSwapInt32(pHCDoneTD->nextTD) & kOHCIHeadPMask;
nextTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress(PhysAddr);
pHCDoneTD->pLogicalNext = prevTD;
prevTD = pHCDoneTD;
pHCDoneTD = nextTD;
}
pHCDoneTD = prevTD; /* New qHead */
while (pHCDoneTD != nil)
{
#if (DEBUGGING_LEVEL > 2)
DEBUGLOG("\tdone queue: processing..."); print_td(pHCDoneTD);
#endif
IOReturn errStatus;
// find the next one
nextTD = pHCDoneTD->pLogicalNext;
control = OSSwapInt32(pHCDoneTD->flags);
transferStatus = (control & kOHCIGTDControl_CC)
>> kOHCIGTDControl_CCPhase;
errStatus = TranslateStatusToUSBError(transferStatus);
if (pOHCIUIMData->OptiOn && (pHCDoneTD->pType == kOHCIOptiLSBug))
{
// clear any bad errors
tempED = (OHCIEndpointDescriptorPtr) pHCDoneTD->pEndpoint;
pHCDoneTD->flags = pHCDoneTD->flags
& OSSwapInt32(kOHCIGTDClearErrorMask);
tempED->tdQueueHeadPtr &= OSSwapInt32(kOHCIHeadPMask);
pHCDoneTD->nextTD = tempED->tdQueueTailPtr & OSSwapInt32(kOHCIHeadPMask);
tempED->tdQueueTailPtr = OSSwapInt32(pHCDoneTD->pPhysical);
pOHCIRegisters->hcCommandStatus =
OSSwapInt32 (kOHCIHcCommandStatus_CLF);
// For CMD Buffer Underrun Errata
}
else if ((transferStatus == kOHCIGTDConditionBufferUnderrun) &&
(pHCDoneTD->pType == kOHCIBulkTransferOutType) &&
(pOHCIUIMData->errataBits & kErrataRetryBufferUnderruns))
{
tempED = (OHCIEndpointDescriptorPtr) pHCDoneTD->pEndpoint;
pHCDoneTD->flags = pHCDoneTD->flags
& OSSwapInt32(kOHCIGTDClearErrorMask);
pHCDoneTD->nextTD = tempED->tdQueueHeadPtr & OSSwapInt32(kOHCIHeadPMask);
pHCDoneTD->pLogicalNext = (OHCIGeneralTransferDescriptorPtr)
OHCIUIMGetLogicalAddress (OSSwapInt32(tempED->tdQueueHeadPtr)
& kOHCIHeadPMask);
tempED->tdQueueHeadPtr = OSSwapInt32(pHCDoneTD->pPhysical)
| (tempED->tdQueueHeadPtr & OSSwapInt32( kOHCIEDToggleBitMask));
pOHCIRegisters->hcCommandStatus =
OSSwapInt32(kOHCIHcCommandStatus_BLF);
}
else if (pHCDoneTD->pType == kOHCIIsochronousInType ||
pHCDoneTD->pType == kOHCIIsochronousOutType)
{
// cast to a isoc type
pITD = (OHCIIsochTransferDescriptorPtr) pHCDoneTD;
ProcessCompletedITD(pITD, errStatus);
// deallocate td
OHCIUIMDeallocateITD(pITD);
}
else
{
bufferSizeRemaining = findBufferRemaining (pHCDoneTD);
if (pHCDoneTD->completion.action != nil)
{
IOUSBCompletion completion;
completion = pHCDoneTD->completion;
if(!safeAction || (safeAction == completion.action)) {
// zero out callback first then call it
pHCDoneTD->completion.action = nil;
complete(completion, errStatus, bufferSizeRemaining);
OHCIUIMDeallocateTD(pHCDoneTD);
}
else {
if(_pendingHead)
_pendingTail->pLogicalNext = pHCDoneTD;
else
_pendingHead = pHCDoneTD;
_pendingTail = pHCDoneTD;
}
}
else if (errStatus != kIOReturnSuccess) {
doCallback(pHCDoneTD, errStatus, bufferSizeRemaining);
OHCIUIMDeallocateTD(pHCDoneTD);
}
}
pHCDoneTD = nextTD; /* New qHead */
}
return(kIOReturnSuccess);
}
void AppleOHCI::UIMProcessDoneQueue(IOUSBCompletionAction safeAction)
{
OHCIRegistersPtr pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
UInt32 interruptStatus;
UInt32 PhysAddr;
OHCIGeneralTransferDescriptorPtr pHCDoneTD;
// check if the OHCI has written the DoneHead yet
interruptStatus = OSSwapInt32(pOHCIRegisters->hcInterruptStatus);
if( (interruptStatus & kOHCIHcInterrupt_WDH) == 0)
{
return;
}
// get the pointer to the list (logical address)
PhysAddr = (UInt32) OSSwapInt32(*(UInt32 *)(pOHCIUIMData->pHCCA + 0x84));
PhysAddr &= kOHCIHeadPMask; // mask off interrupt bits
pHCDoneTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress(PhysAddr);
// write to 0 to the HCCA DoneHead ptr so we won't look at it anymore.
*(UInt32 *)(pOHCIUIMData->pHCCA + 0x84) = 0L;
// Since we have a copy of the queue to process, we can let the host update it again.
pOHCIRegisters->hcInterruptStatus = OSSwapInt32(kOHCIHcInterrupt_WDH);
DoDoneQueueProcessing(pHCDoneTD, safeAction);
return;
}
void AppleOHCI::finishPending()
{
while(_pendingHead) {
OHCIGeneralTransferDescriptorPtr next = _pendingHead->pLogicalNext;
long bufferSizeRemaining = findBufferRemaining (_pendingHead);
UInt32 transferStatus = (OSReadLittleInt32(&_pendingHead->flags, 0) &
kOHCIGTDControl_CC) >> kOHCIGTDControl_CCPhase;
IOUSBCompletion completion;
// zero out callback first then call it
completion = _pendingHead->completion;
_pendingHead->completion.action = nil;
complete(completion,
TranslateStatusToUSBError(transferStatus),
bufferSizeRemaining);
OHCIUIMDeallocateTD(_pendingHead);
_pendingHead = next;
}
}
UInt32 AppleOHCI::GetBandwidthAvailable()
{
return pOHCIUIMData->isochBandwidthAvail;
}
UInt64 AppleOHCI::GetFrameNumber()
{
UInt64 bigFrameNumber;
UInt16 framenumber16;
framenumber16 = OSReadLittleInt16(pOHCIUIMData->pHCCA, 0x80);
bigFrameNumber = pOHCIUIMData->frameNumber + framenumber16;
return bigFrameNumber;
}
UInt32 AppleOHCI::GetFrameNumber32()
{
UInt16 framenumber16;
UInt32 largishFrameNumber;
framenumber16 = OSReadLittleInt16(pOHCIUIMData->pHCCA, 0x80);
largishFrameNumber = ((UInt32)pOHCIUIMData->frameNumber) + framenumber16;
return largishFrameNumber;
}
// #ifdef DEBUG
void AppleOHCI::dumpRegs(void)
{
UInt32 lvalue;
#if 0
/*device->*/configRead16(cwVendorID, &ivalue);
/*device->*/configRead16(cwDeviceID, &ivalue);
IOLog("OHCI: cwVendorID=%x cwDeviceID=%x\n", ivalue, ivalue2);
#else
lvalue = _device->configRead32(cwVendorID);
IOLog("OHCI: cwVendorID=%lx\n", lvalue);
#endif
lvalue = _device->configRead32(clClassCodeAndRevID);
IOLog("OHCI: clClassCodeAndRevID=%lx\n", lvalue);
lvalue = _device->configRead32(clHeaderAndLatency);
IOLog("OHCI: clHeaderAndLatency=%lx\n", lvalue);
lvalue = _device->configRead32(clBaseAddressZero);
IOLog("OHCI: clBaseAddressZero=%lx\n", lvalue);
lvalue = _device->configRead32(clBaseAddressOne);
IOLog("OHCI: clBaseAddressOne=%lx\n", lvalue);
lvalue = _device->configRead32(clExpansionRomAddr);
IOLog("OHCI: clExpansionRomAddr=%lx\n", lvalue);
lvalue = _device->configRead32(clLatGntIntPinLine);
IOLog("OHCI: clLatGntIntPinLine=%lx\n", lvalue);
lvalue = _device->configRead32(clLatGntIntPinLine+4);
IOLog("OHCI: clLatGntIntPinLine+4=%lx\n", lvalue);
lvalue = _device->configRead32(cwCommand);
IOLog("OHCI: cwCommand=%lx\n", lvalue & 0x0000ffff);
IOLog("OHCI: cwStatus=%lx\n", lvalue & 0xffff0000);
lvalue = _device->configRead32(cwCommand);
_device->configWrite32(cwCommand, lvalue);
_device->configWrite32(cwCommand, (lvalue & 0xffff0000) |
(cwCommandEnableBusMaster |
cwCommandEnableMemorySpace));
lvalue = _device->configRead32(cwCommand);
IOLog("OHCI: cwCommand=%lx\n", lvalue & 0x0000ffff);
IOLog("OHCI: cwStatus=%lx\n", lvalue & 0xffff0000);
IOLog("OHCI: HcRevision=%lx\n",
OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcRevision));
IOLog(" HcControl=%lx\n",
OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcControl));
IOLog(" HcFmInterval=%lx\n",
OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcFmInterval));
IOLog(" hcRhDescriptorA=%lx\n",
OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcRhDescriptorA));
IOLog(" hcRhDescriptorB=%lx\n",
OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcRhDescriptorB));
}
// #endif /* DEBUG */
IOReturn TranslateStatusToUSBError(UInt32 status)
{
static const UInt32 statusToErrorMap[] = {
/* OHCI Error */ /* USB Error */
/* 0 */ kIOReturnSuccess,
/* 1 */ kIOUSBPipeStalled, //kUSBCRCErr,
/* 2 */ kIOUSBPipeStalled, //kUSBBitstufErr,
/* 3 */ kIOUSBPipeStalled, //kUSBDataToggleErr,
/* 4 */ kIOUSBPipeStalled, //kUSBEndpointStallErr,
/* 5 */ kIOReturnNotResponding, //kUSBNotRespondingErr,
/* 6 */ kIOUSBPipeStalled, //kUSBPIDCheckErr,
/* 7 */ kIOUSBPipeStalled, //kUSBWrongPIDErr,
/* 8 */ kIOReturnOverrun,
/* 9 */ kIOReturnUnderrun,
/* 10 */ kIOReturnError, //kUSBRes1Err,
/* 11 */ kIOReturnError, //kUSBRes2Err,
/* 12 */ kIOReturnDMAError, //kUSBBufOvrRunErr,
/* 13 */ kIOReturnDMAError, //kUSBBufUnderRunErr
};
if (status > 13) return(kIOReturnInternalError);
return(statusToErrorMap[status]);
}