#ifndef _IOKIT_AppleUSBEHCI_H
#define _IOKIT_AppleUSBEHCI_H
#include <libkern/c++/OSData.h>
#include <IOKit/IOService.h>
#include <IOKit/IOFilterInterruptEventSource.h>
#include <IOKit/pci/IOPCIBridge.h>
#include <IOKit/pci/IOPCIDevice.h>
#include <IOKit/usb/IOUSBControllerV2.h>
#include <IOKit/usb/USB.h>
#include <IOKit/usb/USBHub.h>
#include "AppleUSBEHCIHubInfo.h"
#include "USBEHCI.h"
#include "USBEHCIRootHub.h"
#define MICROSECOND (1)
#define MILLISECOND (1000)
#ifdef __ppc__
#define IOSync eieio
#else
#define IOSync()
#endif
extern "C" {
extern int kvtophys(vm_offset_t);
extern void delay(int);
};
struct InterruptTransaction {
IOMemoryDescriptor * buf;
UInt32 bufLen;
IOUSBCompletion completion;
};
#define kMaxOutstandingTrans 4
class IONaturalMemoryCursor;
class AppleEHCIedMemoryBlock;
class AppleEHCItdMemoryBlock;
class AppleEHCIitdMemoryBlock;
class AppleEHCIsitdMemoryBlock;
class AppleEHCIListElement;
class AppleEHCIQueueHead;
class AppleEHCIIsochListElement;
class AppleEHCIIsochTransferDescriptor;
class AppleEHCISplitIsochTransferDescriptor;
typedef struct EHCIGeneralTransferDescriptor
EHCIGeneralTransferDescriptor,
*EHCIGeneralTransferDescriptorPtr;
typedef struct AppleEHCIIsochEndpointStruct
AppleEHCIIsochEndpoint,
*AppleEHCIIsochEndpointPtr;
#include "AppleEHCIListElement.h"
struct EHCIGeneralTransferDescriptor
{
EHCIGeneralTransferDescriptorSharedPtr pShared;
IOUSBCommand *command; UInt32 unused;
AppleEHCIQueueHead *pQH; UInt8 traceFlag;
UInt8 pType;
UInt8 lastTDofTransaction;
IOPhysicalAddress pPhysical;
EHCIGeneralTransferDescriptorPtr pLogicalNext;
void* logicalBuffer; UInt32 lastFrame; UInt32 lastRemaining;
};
enum{
kEHCIElementTypeBad = 0,
kEHCIElementTypeED,
kEHCIElementTypeiTD,
kEHCIElementTypeSiTD
};
enum
{
kEHCICheckForRootHubConnectionsPeriod = 30, kEHCICheckForRootHubInactivityPeriod = 30 };
struct AppleEHCIIsochEndpointStruct {
AppleEHCIIsochEndpointPtr nextEP;
AppleEHCIIsochListElement *toDoList; AppleEHCIIsochListElement *toDoEnd; AppleEHCIIsochListElement *doneQueue; AppleEHCIIsochListElement *doneEnd; UInt64 firstAvailableFrame; UInt32 maxPacketSize;
UInt32 activeTDs; IOReturn accumulatedStatus;
UInt16 inSlot; short oneMPS; short mult; short functionAddress;
short endpointNumber;
USBDeviceAddress highSpeedHub;
int highSpeedPort;
UInt8 direction;
};
class AppleUSBEHCI : public IOUSBControllerV2
{
OSDeclareDefaultStructors(AppleUSBEHCI)
private:
virtual void initForPM (IOPCIDevice *provider);
unsigned long maxCapabilityForDomainState ( IOPMPowerFlags domainState );
unsigned long initialPowerStateForDomainState ( IOPMPowerFlags domainState );
virtual IOReturn setPowerState( unsigned long, IOService* );
void showRegisters(char *s);
void printTD(EHCIGeneralTransferDescriptorPtr pTD);
void printAsyncQueue(void);
void AddIsocFramesToSchedule(AppleEHCIIsochEndpointPtr);
void ReturnIsocDoneQueue(AppleEHCIIsochEndpointPtr);
void PutTDonToDoList(AppleEHCIIsochEndpointPtr pED, AppleEHCIIsochListElement *pTD);
void PutTDonDoneQueue(AppleEHCIIsochEndpointPtr pED, AppleEHCIIsochListElement *pTD);
AppleEHCIIsochListElement *GetTDfromToDoList(AppleEHCIIsochEndpointPtr pED);
AppleEHCIIsochListElement *GetTDfromDoneQueue(AppleEHCIIsochEndpointPtr pED);
IOReturn AbortIsochEP(AppleEHCIIsochEndpointPtr);
IOReturn DeleteIsochEP(AppleEHCIIsochEndpointPtr);
protected:
IOPCIDevice * _device;
IOMemoryMap * _deviceBase;
UInt16 _vendorID;
UInt16 _deviceID;
UInt16 _revisionID;
UInt32 _errataBits; UInt32 _pageSize; EHCICapRegistersPtr _pEHCICapRegisters; EHCIRegistersPtr _pEHCIRegisters; UInt32 _dataAllocationSize; SInt32 _greatestPeriod; EHCIGeneralTransferDescriptorPtr _pFreeTD; AppleEHCIIsochTransferDescriptor *_pFreeITD; AppleEHCISplitIsochTransferDescriptor *_pFreeSITD; AppleEHCIQueueHead *_pFreeQH; EHCIGeneralTransferDescriptorPtr _pLastFreeTD; AppleEHCIIsochTransferDescriptor *_pLastFreeITD; AppleEHCISplitIsochTransferDescriptor *_pLastFreeSITD; AppleEHCIQueueHead *_pLastFreeQH; EHCIGeneralTransferDescriptorPtr _pPendingTD; AppleEHCIIsochEndpointPtr _isochEPList; AppleEHCIIsochEndpointPtr _freeIsochEPList; IOPhysicalAddress *_periodicList; AppleEHCIListElement **_logicalPeriodicList; UInt16 _periodicBandwidth[kEHCIMaxPoll]; AppleUSBEHCIHubInfoPtr _hsHubs; IOFilterInterruptEventSource * _filterInterruptSource;
UInt32 _filterInterruptCount;
UInt8 _ehciBusState;
IOLock * _intLock;
volatile AppleEHCIIsochListElement * _savedDoneQueueHead; volatile UInt32 _producerCount; volatile UInt32 _consumerCount; volatile bool _filterInterruptActive; IOSimpleLock * _wdhLock;
UInt32 _asyncAdvanceInterrupt;
UInt32 _hostErrorInterrupt;
UInt32 _portChangeInterrupt;
UInt32 _errorInterrupt;
UInt32 _completeInterrupt;
const OSSymbol *usb_remote_wakeup;
bool _unloadUIMAcrossSleep;
bool _onCardBus;
bool _remote_wakeup_occurred;
bool _idleSuspend;
bool _uimInitialized;
bool _testModeEnabled;
bool _sleepRegistersSaved;
bool _hasPCIPwrMgmt;
bool _ehciAvailable;
UInt32 _isochBandwidthAvail; UInt32 _periodicEDsInSchedule;
UInt64 _frameNumber; UInt16 _rootHubFuncAddress; struct InterruptTransaction _outstandingTrans[kMaxOutstandingTrans];
struct {
volatile UInt32 hostSystemError; volatile UInt32 unrecoverableError; volatile UInt32 ownershipChange; } _errors;
UInt32 _frameListSize;
AppleEHCIQueueHead *_AsyncHead; EHCIGeneralTransferDescriptorPtr _pendingHead, _pendingTail;
AppleEHCIedMemoryBlock *_edMBHead;
AppleEHCItdMemoryBlock *_tdMBHead;
AppleEHCIitdMemoryBlock *_itdMBHead;
AppleEHCIsitdMemoryBlock *_sitdMBHead;
AbsoluteTime _lastRootHubStatusChanged; UInt32 _savedUSBIntr; UInt32 _savedUSBCMD; UInt32 _savedPeriodicListBase; UInt32 _savedAsyncListAddr; UInt16 _outSlot;
AbsoluteTime _lastCheckedTime;
static void InterruptHandler(OSObject *owner, IOInterruptEventSource * source, int count);
static bool PrimaryInterruptFilter(OSObject *owner, IOFilterInterruptEventSource *source);
bool FilterInterrupt(int index);
void UIMRootHubStatusChange(void);
void UIMRootHubStatusChange( bool abort );
void SimulateRootHubInt(
UInt8 endpoint,
IOMemoryDescriptor * buf,
UInt32 bufLen,
IOUSBCompletion completion);
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, AppleEHCIQueueHead *pEDHead);
void returnTransactions(AppleEHCIQueueHead *pED,
EHCIGeneralTransferDescriptor *untilThisOne);
AppleEHCIQueueHead *AddEmptyCBEndPoint(
UInt8 functionAddress,
UInt8 endpointNumber,
UInt16 maxPacketSize,
UInt8 speed,
USBDeviceAddress highSpeedHub,
int highSpeedPort,
UInt8 direction,
AppleEHCIQueueHead *pED);
AppleEHCIQueueHead *FindInterruptEndpoint(
short functionNumber,
short endpointNumber,
short direction,
AppleEHCIQueueHead **pEDBack);
AppleEHCIQueueHead *AllocateQH(void);
EHCIGeneralTransferDescriptorPtr AllocateTD(void);
AppleEHCIIsochTransferDescriptor *AllocateITD(void);
AppleEHCISplitIsochTransferDescriptor *AllocateSITD(void);
AppleEHCIIsochEndpointPtr AllocateIsochEP(void);
IOReturn DeallocateIsochEP(AppleEHCIIsochEndpointPtr pEP);
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);
IOReturn scavengeAnIsocTD(AppleEHCIIsochListElement *pTD, IOUSBCompletionAction safeAction);
IOReturn scavengeAnEndpointQueue(AppleEHCIListElement *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);
AppleUSBEHCIHubInfoPtr GetHubInfo(UInt8 hubAddr, UInt8 hubPort);
AppleUSBEHCIHubInfoPtr NewHubInfo(UInt8 hubAddr, UInt8 hubPort);
IOReturn DeleteHubInfo(UInt8 hubAddr, UInt8 hubPort);
IOReturn EnterTestMode(void);
IOReturn PlacePortInMode(UInt32 port, UInt32 mode);
IOReturn LeaveTestMode(void);
void ResumeUSBBus();
void SuspendUSBBus();
void StopUSBBus();
void RestartUSBBus();
AppleEHCIIsochEndpointPtr FindIsochronousEndpoint(short functionNumber, short endpointNumber, short direction, AppleEHCIIsochEndpointPtr *pEDBack);
AppleEHCIIsochEndpointPtr CreateIsochronousEndpoint(short functionNumber, short endpointNumber, short direction, USBDeviceAddress highSpeedHub, int highSpeedPort);
IOReturn CreateHSIsochTransfer( AppleEHCIIsochEndpointPtr pEP,
IOUSBIsocCompletion completion,
UInt64 frameNumberStart,
IOMemoryDescriptor *pBuffer,
UInt32 frameCount,
IOUSBLowLatencyIsocFrame *pFrames,
UInt32 updateFrequency,
Boolean lowLatency);
IOReturn CreateHSIsochTransfer( AppleEHCIIsochEndpointPtr pEP,
IOUSBIsocCompletion completion,
UInt64 frameNumberStart,
IOMemoryDescriptor *pBuffer,
UInt32 frameCount,
IOUSBLowLatencyIsocFrame *pFrames,
UInt32 updateFrequency);
IOReturn CreateHSIsochTransfer( AppleEHCIIsochEndpointPtr pEP,
IOUSBIsocCompletion completion,
UInt64 frameNumberStart,
IOMemoryDescriptor *pBuffer,
UInt32 frameCount,
IOUSBIsocFrame *pFrames);
IOReturn CreateSplitIsochTransfer(AppleEHCIIsochEndpointPtr pEP,
IOUSBIsocCompletion completion,
UInt64 frameNumberStart,
IOMemoryDescriptor *pBuffer,
UInt32 frameCount,
IOUSBIsocFrame *pFrames, UInt32 updateFrequency = 0,
bool lowLatency = false);
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 );
IOReturn UIMInitialize(IOService * provider);
IOReturn UIMFinalize();
IOReturn UIMFinalizeForPowerDown();
IOReturn UIMInitializeForPowerUp();
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 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);
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);
virtual IOReturn callPlatformFunction(const OSSymbol *functionName,
bool waitForFunction,
void *param1, void *param2,
void *param3, void *param4);
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 UIMHubMaintenance(USBDeviceAddress highSpeedHub, UInt32 highSpeedPort, UInt32 command, UInt32 flags);
virtual IOReturn UIMSetTestMode(UInt32 mode, UInt32 port);
virtual IOReturn EnableAsyncSchedule(void);
virtual IOReturn DisableAsyncSchedule(void);
virtual IOReturn EnablePeriodicSchedule(void);
virtual IOReturn DisablePeriodicSchedule(void);
void CheckEDListForTimeouts(AppleEHCIQueueHead *head);
bool RootHubAreAllPortsDisconnected( void );
void GetNumberOfPorts(UInt8 *numPorts);
};
enum
{
kEHCISetPowerLevelSuspend = 0,
kEHCISetPowerLevelRunning = 1,
kEHCISetPowerLevelIdleSuspend = 2
};
enum
{
kEHCIBusStateOff = 0,
kEHCIBusStateSuspended = 1,
kEHCIBusStateRunning = 2
};
#endif