⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 appleusbohci.cpp

📁 苹果公司的OHCI USB主机协议栈的代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* * * @APPLE_LICENSE_HEADER_START@ *  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved. *  * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. *  * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. *  * @APPLE_LICENSE_HEADER_END@ */#include <libkern/OSByteOrder.h>extern "C" {#include <kern/clock.h>}#include <IOKit/IOFilterInterruptEventSource.h>#include <IOKit/IOMemoryCursor.h>#include <IOKit/IOMessage.h>#include <IOKit/pccard/IOPCCard.h>#include <IOKit/usb/USB.h>#include <IOKit/usb/IOUSBLog.h>#include "AppleUSBOHCI.h"#include "AppleUSBOHCIMemoryBlocks.h"#define DEBUGGING_LEVEL 0	// 1 = low; 2 = high; 3 = extreme#define super IOUSBController#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 == 64static int GetEDType(AppleOHCIEndpointDescriptorPtr pED);extern void print_td(AppleOHCIGeneralTransferDescriptorPtr pTD);extern void print_itd(AppleOHCIIsochTransferDescriptorPtr x);OSDefineMetaClassAndStructors(AppleUSBOHCI, IOUSBController)bool AppleUSBOHCI::init(OSDictionary * propTable){    if (!super::init(propTable))  return false;    _ohciBusState = kOHCIBusStateOff;    _ohciAvailable = true;        _intLock = IOLockAlloc();    if (!_intLock)        return(false);    _wdhLock = IOSimpleLockAlloc();    if (!_wdhLock)        return(false);    _uimInitialized = false;        // Initialize our consumer and producer counts.      //    _producerCount = 1;    _consumerCount = 1;        return (true);}boolAppleUSBOHCI::start( IOService * provider ){    UInt32	ext1;        USBLog(5,"+%s[%p]::start", getName(), this);    if( !super::start(provider))        return false;    // super::start sets _device or it fails    initForPM(_device);    // Set our initial time for root hub inactivity    //    clock_get_uptime(&_lastCheckedTime);        USBLog(5,"-%s[%p]::start", getName(), this);    return true;}void AppleUSBOHCI::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 AppleUSBOHCI::UIMInitialize(IOService * provider){    IOReturn		err = kIOReturnSuccess;    UInt32		lvalue;    IOPhysicalAddress 	hcDoneHead;    USBLog(5,"%s[%p]: initializing UIM", getName(), this);    _device = OSDynamicCast(IOPCIDevice, provider);    if(_device == NULL)        return kIOReturnBadArgument;    do {        if (!(_deviceBase = provider->mapDeviceMemoryWithIndex(0)))        {            USBError(1,"%s[%p]: unable to get device memory", getName(), this);            break;        }        USBLog(3, "%s: config @ %lx (%lx)", getName(),              (long)_deviceBase->getVirtualAddress(),              _deviceBase->getPhysicalAddress());        SetVendorInfo();        // Set up a filter interrupt source (this process both primary (thru filter function) and secondary (thru action function)        // interrupts.        //        _filterInterruptSource = IOFilterInterruptEventSource::filterInterruptEventSource(this,                                                                            AppleUSBOHCI::InterruptHandler,	                                                                            AppleUSBOHCI::PrimaryInterruptFilter,                                                                            provider );                                                                                    if ( !_filterInterruptSource )        {             USBError(1,"%s[%p]: unable to get filterInterruptEventSource", getName(), this);             break;        }                err = _workLoop->addEventSource(_filterInterruptSource);        if ( err != kIOReturnSuccess )        {             USBError(1,"%s[%p]: unable to add filter event source: 0x%x", getName(), this, err);             break;        }        _genCursor = IONaturalMemoryCursor::withSpecification(PAGE_SIZE, PAGE_SIZE);        if(!_genCursor)            break;        _isoCursor = IONaturalMemoryCursor::withSpecification(kUSBMaxIsocFrameReqCount,  kUSBMaxIsocFrameReqCount);        if(!_isoCursor)            break;        /*         * Initialize my data and the hardware         */        _errataBits = GetErrataBits(_vendorID, _deviceID, _revisionID);	if (_errataBits & kErrataLucentSuspendResume)        {            OSData	*suspendProp;            UInt32	portBitmap = 0;                        // We need to check to see if there are ports that we really should suspend            //            suspendProp     = (OSData *) provider->getProperty( "AAPL,SuspendablePorts" );            if (suspendProp)            {                // Only allow suspend on certain ports                //                portBitmap = *((UInt32 *) suspendProp->getBytesNoCopy());                _disablePortsBitmap = (0xffffffff & (~portBitmap));            }            else                _disablePortsBitmap = (0xffffffff);        }                USBLog(5,"%s: errata bits=%lx", getName(), _errataBits);        _pageSize = PAGE_SIZE;        _pOHCIRegisters = (OHCIRegistersPtr) _deviceBase->getVirtualAddress();#if (DEBUGGING_LEVEL > 2)        dumpRegs();#endif                // enable the card        lvalue = _device->configRead32(cwCommand);        _device->configWrite32(cwCommand, (lvalue & 0xffff0000) | (cwCommandEnableBusMaster | cwCommandEnableMemorySpace));        // Check to see if the hcDoneHead is not NULL.  If so, then we need to reset the controller        //        hcDoneHead = USBToHostLong(_pOHCIRegisters->hcDoneHead);        if ( hcDoneHead != NULL )        {            USBError(1,"%s[%p]::UIMInitialize Non-NULL hcDoneHead: %p", getName(), this, hcDoneHead );            // Reset it now            //            _pOHCIRegisters->hcCommandStatus = USBToHostLong(kOHCIHcCommandStatus_HCR);  // Reset OHCI            IOSleep(3);        }                _pOHCIRegisters->hcControlCurrentED = 0;        _pOHCIRegisters->hcControlHeadED = 0;        IOSync();        // Set up HCCA.        _pHCCA = (Ptr) IOMallocContiguous(kHCCAsize, kHCCAalignment, &_hccaPhysAddr);        if (!_pHCCA)        {            USBError(1,"%s[%p]: Unable to allocate memory (2)", getName(), this);            err = kIOReturnNoMemory;            break;        }        OSWriteLittleInt32(&_pOHCIRegisters->hcHCCA, 0, _hccaPhysAddr);        IOSync();      // Set the HC to write the donehead to the HCCA, and enable interrupts        _pOHCIRegisters->hcInterruptStatus = USBToHostLong(kOHCIHcInterrupt_WDH);        IOSync();	// Enable the interrupt delivery.	_workLoop->enableAllInterrupts();        _rootHubFuncAddress = 1;        // set up Interrupt transfer tree        if ((err = IsochronousInitialize()))	break;        if ((err = InterruptInitialize()))	break;	if ((err = BulkInitialize()))		break;        if ((err = ControlInitialize()))	break;        // Set up hcFmInterval.        UInt32	hcFSMPS;				// in register hcFmInterval        UInt32	hcFI;					// in register hcFmInterval        UInt32	hcPS;					// in register hcPeriodicStart                hcFI = USBToHostLong(_pOHCIRegisters->hcFmInterval) & 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%        _pOHCIRegisters->hcFmInterval = HostToUSBLong(hcFI | hcFSMPS);        _pOHCIRegisters->hcPeriodicStart = HostToUSBLong(hcPS);        IOSync();        // Work around the Philips part which does weird things when a device is plugged in at boot        //        if (_errataBits & kErrataNeedsPortPowerOff)        {            USBError(1, "%s[%p]::UIMInitialize error, turning off power to ports to clear", getName(), this);            OHCIRootHubPower(0 /* kOff */);            // No need to turn the power back on here, the reset does that anyway.        }                // Just so we all start from the same place, reset the OHCI.        _pOHCIRegisters->hcControl = HostToUSBLong ((kOHCIFunctionalState_Reset << kOHCIHcControl_HCFSPhase));        IOSync();      // Set OHCI to operational state and enable processing of control list.        _pOHCIRegisters->hcControl = HostToUSBLong ((kOHCIFunctionalState_Operational << kOHCIHcControl_HCFSPhase)					    | kOHCIHcControl_CLE | kOHCIHcControl_BLE					    | kOHCIHcControl_PLE | kOHCIHcControl_IE);        IOSync();        // Initialize the Root Hub registers	if (_errataBits & kErrataDisableOvercurrent)	    _pOHCIRegisters->hcRhDescriptorA |= USBToHostLong(kOHCIHcRhDescriptorA_NOCP);	_pOHCIRegisters->hcRhStatus = HostToUSBLong(kOHCIHcRhStatus_OCIC | kOHCIHcRhStatus_DRWE); // should be SRWE which should be identical to DRWE        IOSync();        OHCIRootHubPower(1 /* kOn */);		// enable interrupts        _pOHCIRegisters->hcInterruptEnable = HostToUSBLong (kOHCIHcInterrupt_MIE | kOHCIDefaultInterrupts);        IOSync();                if (_errataBits & kErrataLSHSOpti)            OptiLSHSFix();        _uimInitialized = true;                return(kIOReturnSuccess);    } while (false);    USBError(1, "%s[%p]::UIMInitialize error(%x)", getName(), this, err);    UIMFinalize();    if (_filterInterruptSource)     {        _filterInterruptSource->release();        _filterInterruptSource = NULL;    }    return(err);}IOReturn AppleUSBOHCI::UIMFinalize(void){    USBLog (3, "%s[%p]: @ %lx (%lx)(shutting down HW)",getName(),this,               (long)_deviceBase->getVirtualAddress(),              _deviceBase->getPhysicalAddress());    // Disable the interrupt delivery    //    _workLoop->disableAllInterrupts();    // If we are NOT being terminated, then talk to the OHCI controller and    // set up all the registers to be off    //    if ( !isInactive() )    {        // Disable All OHCI Interrupts        _pOHCIRegisters->hcInterruptDisable = HostToUSBLong(kOHCIHcInterrupt_MIE);        IOSync();            // Place the USB bus into the Reset State        _pOHCIRegisters->hcControl = HostToUSBLong((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->hcControlHeadED = 0;        _pOHCIRegisters->hcControlCurrentED = 0;        _pOHCIRegisters->hcBulkHeadED = 0;        _pOHCIRegisters->hcBulkCurrentED = 0;        IOSync();            // turn off the global power        // FIXME check for per-port vs. Global power control        OHCIRootHubPower(0 /* kOff */);		// go ahead and reset the controller	_pOHCIRegisters->hcCommandStatus = HostToUSBLong(kOHCIHcCommandStatus_HCR);  	// Reset OHCI

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -