#ifndef _IOKIT_AppleUSBEHCI_H
#define _IOKIT_AppleUSBEHCI_H
#include <libkern/c++/OSData.h>
#include <IOKit/IOService.h>
#include <IOKit/IOFilterInterruptEventSource.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include <IOKit/IODMACommand.h>
#include <IOKit/pci/IOPCIBridge.h>
#include <IOKit/pci/IOPCIDevice.h>
#include <IOKit/usb/IOUSBControllerV3.h>
#include <IOKit/usb/IOUSBControllerListElement.h>
#include <IOKit/usb/USB.h>
#include <IOKit/usb/USBHub.h>
#include "USBEHCI.h"
#include "USBEHCIRootHub.h"
#define MICROSECOND (1)
#define MILLISECOND (1000)
#ifndef EHCI_USE_KPRINTF
#define EHCI_USE_KPRINTF 0
#endif
#ifdef __ppc__
#define IOSync eieio
#else
#define IOSync() __asm__ __volatile__ ( "mfence" : : : "memory" )
#endif
class IONaturalMemoryCursor;
class AppleEHCIedMemoryBlock;
class AppleEHCItdMemoryBlock;
class AppleEHCIitdMemoryBlock;
class AppleEHCIsitdMemoryBlock;
class AppleEHCIQueueHead;
class AppleEHCIIsochTransferDescriptor;
class AppleEHCISplitIsochTransferDescriptor;
typedef struct EHCIGeneralTransferDescriptor
EHCIGeneralTransferDescriptor,
*EHCIGeneralTransferDescriptorPtr;
#include "AppleEHCIListElement.h"
#include "AppleUSBEHCIHubInfo.h"
struct EHCIGeneralTransferDescriptor
{
EHCIGeneralTransferDescriptorSharedPtr pShared; IOUSBCommand *command; AppleEHCIQueueHead *pQH; bool traceFlag;
bool callbackOnTD; bool multiXferTransaction; bool finalXferInTransaction; USBPhysicalAddress32 pPhysical;
EHCIGeneralTransferDescriptorPtr pLogicalNext;
void* logicalBuffer; UInt32 lastFrame; UInt32 lastRemaining;
};
struct EHCIDoneQueueParams
{
EHCIGeneralTransferDescriptorPtr pHCDoneTD;
OSStatus forceErr;
IOUSBCompletionAction safeAction;
EHCIGeneralTransferDescriptorPtr stopAt;
};
enum{
kEHCIElementTypeBad = 0,
kEHCIElementTypeED,
kEHCIElementTypeiTD,
kEHCIElementTypeSiTD
};
enum
{
kEHCICheckForRootHubConnectionsPeriod = 5, kEHCICheckForRootHubInactivityPeriod = 2 };
enum
{
kUSBEHCIFSPeriodicOverhead = 10, kUSBEHCIMaxMicroframePeriodic = 180, kUSBEHCIMaxSSOUTsection = 188 };
enum{
kMaxPorts = 16
};
typedef struct AppleEHCIExtraPower
{
UInt32 version; UInt32 perPort; UInt32 aggregate; UInt32 inSleep; } AppleEHCIExtraPower;
enum {
kAppleEHCIExtraPowerVersion = 0x100
};
class AppleUSBEHCI : public IOUSBControllerV3
{
OSDeclareDefaultStructors(AppleUSBEHCI)
private:
UInt32 ExpressCardPort( IOService * provider );
void showRegisters(UInt32 level, const char *s);
void printTD(EHCIGeneralTransferDescriptorPtr pTD, int level);
void printAsyncQueue(int level, const char *str);
void AddIsocFramesToSchedule(AppleEHCIIsochEndpoint*);
IOReturn AbortIsochEP(AppleEHCIIsochEndpoint*);
IOReturn DeleteIsochEP(AppleEHCIIsochEndpoint*);
UInt8 LastScheduledSSMicroFrame(AppleEHCIIsochEndpoint* pEP);
UInt8 FirstScheduledSSMicroFrame(AppleEHCIIsochEndpoint* pEP);
static AppleEHCIExtraPower _extraPower;
protected:
IOMemoryMap * _deviceBase;
UInt16 _vendorID;
UInt16 _deviceID;
UInt16 _revisionID;
UInt32 _errataBits; EHCICapRegistersPtr _pEHCICapRegisters; EHCIRegistersPtr _pEHCIRegisters; UInt32 _dataAllocationSize; SInt32 _greatestPeriod; EHCIGeneralTransferDescriptorPtr _pFreeTD; AppleEHCIIsochTransferDescriptor *_pFreeITD; AppleEHCISplitIsochTransferDescriptor *_pFreeSITD; AppleEHCIQueueHead *_pFreeQH; EHCIGeneralTransferDescriptorPtr _pLastFreeTD; AppleEHCIIsochTransferDescriptor *_pLastFreeITD; AppleEHCISplitIsochTransferDescriptor *_pLastFreeSITD; AppleEHCIQueueHead *_pLastFreeQH; IOBufferMemoryDescriptor *_periodicListBuffer; USBPhysicalAddress32 *_periodicList; IOUSBControllerListElement **_logicalPeriodicList; UInt16 _periodicBandwidth[kEHCIMaxPoll]; AppleUSBEHCIHubInfo *_hsHubs; IOFilterInterruptEventSource * _filterInterruptSource;
UInt32 _filterInterruptCount;
UInt8 _istKeepAwayFrames; volatile IOUSBControllerIsochListElement *_savedDoneQueueHead; volatile UInt32 _producerCount; volatile UInt32 _consumerCount; volatile bool _filterInterruptActive; IOSimpleLock * _wdhLock;
IOSimpleLock * _isochScheduleLock;
UInt32 _asyncAdvanceInterrupt;
UInt32 _hostErrorInterrupt;
UInt32 _frameRolloverInterrupt;
UInt32 _portChangeInterrupt;
UInt32 _errorInterrupt;
UInt32 _completeInterrupt;
UInt32 _controlBulkTransactionsOut;
bool _uimInitialized;
bool _testModeEnabled;
bool _sleepRegistersSaved;
bool _hasPCIPwrMgmt;
bool _is64bit;
bool _inAbortIsochEP;
UInt8 _asynchScheduleUnsynchCount;
UInt8 _periodicScheduleUnsynchCount;
UInt32 _isochBandwidthAvail; UInt32 _periodicEDsInSchedule; volatile UInt64 _frameNumber; UInt16 _rootHubFuncAddress; struct {
volatile UInt32 hostSystemError; volatile UInt32 unrecoverableError; volatile UInt32 ownershipChange; UInt32 displayed;
} _errors;
UInt32 _frameListSize;
AppleEHCIQueueHead *_AsyncHead;
AppleEHCIedMemoryBlock *_edMBHead;
AppleEHCItdMemoryBlock *_tdMBHead;
AppleEHCIitdMemoryBlock *_itdMBHead;
AppleEHCIsitdMemoryBlock *_sitdMBHead;
AbsoluteTime _lastRootHubStatusChanged; UInt32 _savedUSBIntr; UInt32 _savedUSBCMD; UInt32 _physPeriodicListBase; UInt32 _savedAsyncListAddr; UInt32 _savedSuspendedPortBitmap; UInt16 _outSlot;
AbsoluteTime _lastCheckedTime; UInt32 _rhPrevStatus[kMaxPorts]; UInt32 _rhChangeBits[kMaxPorts]; bool _rhPortBeingResumed[kMaxPorts]; thread_call_t _rhResumePortTimerThread[kMaxPorts]; UInt32 _ExpressCardPort; IONotifier * _powerDownNotifier;
bool _gangedOvercurrent; bool _badExpressCardAttached;
AbsoluteTime _tempAnchorTime;
AbsoluteTime _anchorTime;
UInt64 _tempAnchorFrame;
UInt64 _anchorFrame;
UInt32 _nextDoneQueue;
struct EHCIDoneQueueParams _doneQueueParams[20];
AppleEHCIQueueHead * _disabledQHList;
static void InterruptHandler(OSObject *owner, IOInterruptEventSource * source, int count);
static bool PrimaryInterruptFilter(OSObject *owner, IOFilterInterruptEventSource *source);
bool FilterInterrupt(int index);
virtual void UIMRootHubStatusChange(void);
virtual void UIMRootHubStatusChange( bool abort );
void SetVendorInfo(void);
AppleEHCIQueueHead *MakeEmptyEndPoint(UInt8 functionAddress,
UInt8 endpointNumber,
UInt16 maxPacketSize,
UInt8 speed,
USBDeviceAddress highSpeedHub,
int highSpeedPort,
UInt8 direction);
AppleEHCIQueueHead *MakeEmptyIntEndPoint(UInt8 functionAddress,
UInt8 endpointNumber,
UInt16 maxPacketSize,
UInt8 speed,
USBDeviceAddress highSpeedHub,
int highSpeedPort,
UInt8 direction);
void linkInterruptEndpoint(AppleEHCIQueueHead *pEHCIEndpointDescriptor);
void linkAsyncEndpoint(AppleEHCIQueueHead *CBED);
void returnTransactions(AppleEHCIQueueHead *pED, EHCIGeneralTransferDescriptor *untilThisOne, IOReturn error, bool clearToggle);
AppleEHCIQueueHead *AddEmptyCBEndPoint(UInt8 functionAddress,
UInt8 endpointNumber,
UInt16 maxPacketSize,
UInt8 speed,
USBDeviceAddress highSpeedHub,
int highSpeedPort,
UInt8 direction);
AppleEHCIQueueHead *FindInterruptEndpoint(short functionNumber,
short endpointNumber,
short direction,
IOUSBControllerListElement **pLEBack);
AppleEHCIQueueHead *AllocateQH(void);
EHCIGeneralTransferDescriptorPtr AllocateTD(void);
AppleEHCIIsochTransferDescriptor *AllocateITD(void);
AppleEHCISplitIsochTransferDescriptor *AllocateSITD(void);
IOReturn allocateTDs(AppleEHCIQueueHead *pEDQueue,
IOUSBCommand* command,
IOMemoryDescriptor * CBP,
UInt32 bufferSize,
UInt16 direction,
Boolean controlTransaction);
AppleEHCIQueueHead *FindControlBulkEndpoint (short functionNumber,
short endpointNumber,
AppleEHCIQueueHead **pEDBack,
short direction);
void scavengeCompletedTransactions(IOUSBCompletionAction safeAction);
IOReturn scavengeIsocTransactions(IOUSBCompletionAction safeAction, bool reQueueTransactions);
IOReturn scavengeAnIsocTD(IOUSBControllerIsochListElement *pTD, IOUSBCompletionAction safeAction);
IOReturn scavengeAnEndpointQueue(IOUSBControllerListElement *pEDQueue, IOUSBCompletionAction safeAction);
IOReturn EHCIUIMDoDoneQueueProcessing(EHCIGeneralTransferDescriptorPtr pHCDoneTD, OSStatus forceErr, IOUSBCompletionAction safeAction, EHCIGeneralTransferDescriptorPtr stopAt);
IOReturn DeallocateTD (EHCIGeneralTransferDescriptorPtr pTD);
IOReturn DeallocateED (AppleEHCIQueueHead *pED);
void doCallback(EHCIGeneralTransferDescriptorPtr nextTD,
UInt32 transferStatus,
UInt32 bufferSizeRemaining);
IOReturn AsyncInitialize (void);
IOReturn InterruptInitialize (void);
void unlinkIntEndpoint(AppleEHCIQueueHead *pED);
void unlinkAsyncEndpoint(AppleEHCIQueueHead *pED, AppleEHCIQueueHead *pEDQueueBack);
void HaltAsyncEndpoint(AppleEHCIQueueHead *pED, AppleEHCIQueueHead *pEDBack);
void HaltInterruptEndpoint(AppleEHCIQueueHead *pED);
void waitForSOF(EHCIRegistersPtr pEHCIRegisters);
UInt16 validatePollingRate(short rawPollingRate, short speed, int *offset, UInt16 *bytesAvailable);
IOReturn EnterTestMode(void);
IOReturn PlacePortInMode(UInt32 port, UInt32 mode);
IOReturn LeaveTestMode(void);
void ResumeUSBBus();
void SuspendUSBBus();
void StopUSBBus();
void RestartUSBBus();
IOReturn AcquireOSOwnership(void);
IOReturn CreateHSIsochTransfer(AppleEHCIIsochEndpoint *pEP, IOUSBIsocCommand *command);
IOReturn CreateSplitIsochTransfer(AppleEHCIIsochEndpoint *pEP, IOUSBIsocCommand *command);
void ReturnOneTransaction(EHCIGeneralTransferDescriptor *transaction,
AppleEHCIQueueHead *pED,
AppleEHCIQueueHead *pEDBack,
IOReturn err);
UInt32 findBufferRemaining(AppleEHCIQueueHead *pED);
void UIMCheckForTimeouts(void);
#if 0
void printED(AppleEHCIQueueHead * pED);
#endif
public:
virtual bool init(OSDictionary * propTable);
virtual bool start( IOService * provider );
virtual void free();
virtual IOReturn message( UInt32 type, IOService * provider, void * argument = 0 );
virtual IOReturn powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService* );
virtual void powerChangeDone ( unsigned long fromState );
IOReturn UIMInitialize(IOService * provider);
IOReturn UIMFinalize();
IOReturn DeallocateITD (AppleEHCIIsochTransferDescriptor *pTD);
IOReturn DeallocateSITD (AppleEHCISplitIsochTransferDescriptor *pTD);
virtual IOReturn UIMCreateControlEndpoint(UInt8 functionNumber,
UInt8 endpointNumber,
UInt16 maxPacketSize,
UInt8 speed);
virtual IOReturn UIMCreateControlEndpoint(UInt8 functionNumber,
UInt8 endpointNumber,
UInt16 maxPacketSize,
UInt8 speed,
USBDeviceAddress highSpeedHub,
int highSpeedPort);
virtual IOReturn UIMCreateControlTransfer(short functionNumber,
short endpointNumber,
IOUSBCompletion completion,
void *CBP,
bool bufferRounding,
UInt32 bufferSize,
short direction);
virtual IOReturn UIMCreateControlTransfer(short functionNumber,
short endpointNumber,
IOUSBCommand* command,
IOMemoryDescriptor *CBP,
bool bufferRounding,
UInt32 bufferSize,
short direction);
virtual IOReturn UIMCreateControlTransfer(short functionNumber,
short endpointNumber,
IOUSBCompletion completion,
IOMemoryDescriptor *CBP,
bool bufferRounding,
UInt32 bufferSize,
short direction);
virtual IOReturn UIMCreateControlTransfer(short functionNumber,
short endpointNumber,
IOUSBCommand *command,
void *CBP,
bool bufferRounding,
UInt32 bufferSize,
short direction);
virtual IOReturn UIMCreateBulkEndpoint(UInt8 functionNumber,
UInt8 endpointNumber,
UInt8 direction,
UInt8 speed,
UInt8 maxPacketSize);
virtual IOReturn UIMCreateBulkEndpoint(UInt8 functionNumber,
UInt8 endpointNumber,
UInt8 direction,
UInt8 speed,
UInt16 maxPacketSize,
USBDeviceAddress highSpeedHub,
int highSpeedPort);
virtual IOReturn UIMCreateBulkTransfer(short functionNumber,
short endpointNumber,
IOUSBCompletion completion,
IOMemoryDescriptor *CBP,
bool bufferRounding,
UInt32 bufferSize,
short direction);
virtual IOReturn UIMCreateBulkTransfer(IOUSBCommand* command);
virtual IOReturn UIMCreateInterruptEndpoint(short functionAddress,
short endpointNumber,
UInt8 direction,
short speed,
UInt16 maxPacketSize,
short pollingRate);
virtual IOReturn UIMCreateInterruptEndpoint(short functionAddress,
short endpointNumber,
UInt8 direction,
short speed,
UInt16 maxPacketSize,
short pollingRate,
USBDeviceAddress highSpeedHub,
int highSpeedPort);
virtual IOReturn UIMCreateInterruptTransfer(short functionNumber,
short endpointNumber,
IOUSBCompletion completion,
IOMemoryDescriptor *CBP,
bool bufferRounding,
UInt32 bufferSize,
short direction);
virtual IOReturn UIMCreateInterruptTransfer(IOUSBCommand* command);
virtual IOReturn UIMCreateIsochEndpoint(short functionAddress,
short endpointNumber,
UInt32 maxPacketSize,
UInt8 direction);
virtual IOReturn UIMCreateIsochEndpoint(short functionAddress,
short endpointNumber,
UInt32 maxPacketSize,
UInt8 direction,
USBDeviceAddress highSpeedHub,
int highSpeedPort);
virtual IOReturn UIMCreateIsochEndpoint(short functionAddress,
short endpointNumber,
UInt32 maxPacketSize,
UInt8 direction,
USBDeviceAddress highSpeedHub,
int highSpeedPort,
UInt8 interval);
virtual IOReturn UIMCreateIsochTransfer(short functionAddress,
short endpointNumber,
IOUSBIsocCompletion completion,
UInt8 direction,
UInt64 frameStart,
IOMemoryDescriptor *pBuffer,
UInt32 frameCount,
IOUSBIsocFrame *pFrames);
virtual IOReturn UIMAbortEndpoint(short functionNumber,
short endpointNumber,
short direction);
virtual IOReturn UIMDeleteEndpoint(short functionNumber,
short endpointNumber,
short direction);
virtual IOReturn UIMClearEndpointStall(short functionNumber,
short endpointNumber,
short direction);
IOReturn HandleEndpointAbort(short functionNumber, short endpointNumber, short direction, bool clearToggle);
IOReturn GetRootHubDeviceDescriptor(IOUSBDeviceDescriptor *desc);
IOReturn GetRootHubDescriptor(IOUSBHubDescriptor *desc);
IOReturn SetRootHubDescriptor(OSData *buffer);
IOReturn GetRootHubConfDescriptor(OSData *desc);
IOReturn GetRootHubStatus(IOUSBHubStatus *status);
IOReturn SetRootHubFeature(UInt16 wValue);
IOReturn ClearRootHubFeature(UInt16 wValue);
IOReturn GetRootHubPortStatus(IOUSBHubPortStatus *status, UInt16 port);
IOReturn SetRootHubPortFeature(UInt16 wValue, UInt16 port);
IOReturn ClearRootHubPortFeature(UInt16 wValue, UInt16 port);
IOReturn GetRootHubPortState(UInt8 *state, UInt16 port);
IOReturn SetHubAddress(UInt16 wValue);
virtual UInt32 GetBandwidthAvailable();
virtual UInt64 GetFrameNumber();
virtual UInt32 GetFrameNumber32();
virtual UInt64 GetMicroFrameNumber();
virtual void PollInterrupts(IOUSBCompletionAction safeAction=0);
IOReturn EHCIRootHubPower(bool on);
IOReturn EHCIRootHubResetChangeConnection(UInt16 port);
IOReturn EHCIRootHubResetResetChange(UInt16 port);
IOReturn EHCIRootHubResetSuspendChange(UInt16 port);
IOReturn EHCIRootHubResetEnableChange(UInt16 port);
IOReturn EHCIRootHubResetOverCurrentChange(UInt16 port);
IOReturn EHCIRootHubResetPort (UInt16 port);
IOReturn EHCIRootHubPortEnable(UInt16 port, bool on);
IOReturn EHCIRootHubPortSuspend(UInt16 port, bool on);
IOReturn EHCIRootHubPortPower(UInt16 port, bool on);
IOReturn SimulateEDDelete (short endpointNumber, short direction);
IOReturn SimulateEDAbort (short endpointNumber, short direction);
IOReturn GetRootHubStringDescriptor(UInt8 index, OSData *desc);
AbsoluteTime LastRootHubPortStatusChanged( bool reset );
virtual IOReturn UIMCreateIsochTransfer(short functionAddress,
short endpointNumber,
IOUSBIsocCompletion completion,
UInt8 direction,
UInt64 frameStart,
IOMemoryDescriptor * pBuffer,
UInt32 frameCount,
IOUSBLowLatencyIsocFrame *pFrames,
UInt32 updateFrequency);
virtual IOReturn UIMCreateIsochTransfer(IOUSBIsocCommand *command);
virtual IOReturn UIMHubMaintenance(USBDeviceAddress highSpeedHub, UInt32 highSpeedPort, UInt32 command, UInt32 flags);
virtual IOReturn UIMSetTestMode(UInt32 mode, UInt32 port);
IOReturn EnableAsyncSchedule(bool waitForON);
IOReturn DisableAsyncSchedule(bool waitForOFF);
IOReturn EnablePeriodicSchedule(bool waitForON);
IOReturn DisablePeriodicSchedule(bool waitForOFF);
void CheckEDListForTimeouts(AppleEHCIQueueHead *head);
void GetNumberOfPorts(UInt8 *numPorts);
virtual IOUSBControllerIsochEndpoint* AllocateIsochEP();
virtual void ReturnIsochDoneQueue(IOUSBControllerIsochEndpoint*);
virtual IOReturn GetLowLatencyOptionsAndPhysicalMask(IOOptionBits *optionBits, mach_vm_address_t *physicalMask);
virtual IODMACommand *GetNewDMACommand();
virtual IOReturn GetFrameNumberWithTime(UInt64* frameNumber, AbsoluteTime *theTime);
static IOReturn GatedGetFrameNumberWithTime(OSObject *owner, void* arg0, void* arg1, void* arg2, void* arg3);
static void RHResumePortTimerEntry(OSObject *target, thread_call_param_t port);
void RHResumePortTimer(UInt32 port);
static IOReturn RHResumePortCompletionEntry(OSObject *target, void *param1, void *param2, void *param3, void *param4);
IOReturn RHResumePortCompletion(UInt32 port);
void CheckSleepCapability(void);
virtual IOReturn ResetControllerState(void);
virtual IOReturn RestartControllerFromReset(void);
virtual IOReturn SaveControllerStateForSleep(void);
virtual IOReturn RestoreControllerStateFromSleep(void);
virtual IOReturn DozeController(void);
virtual IOReturn WakeControllerFromDoze(void);
virtual IOReturn UIMEnableAddressEndpoints(USBDeviceAddress address, bool enable);
virtual IOReturn UIMEnableAllEndpoints(bool enable);
virtual IOReturn EnableInterruptsFromController(bool enable);
virtual UInt32 AllocateExtraRootHubPortPower(UInt32 extraPowerRequested);
virtual void ReturnExtraRootHubPortPower(UInt32 extraPowerReturned);
};
#endif