/* * Copyright (c) 2003 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@ */ #include #include #include #include "IOACPIInlineIO.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define super IOPlatformDevice OSDefineMetaClassAndStructors( IOACPIPlatformDevice, IOPlatformDevice ) OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 0 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 1 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 2 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 3 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 4 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 5 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 6 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 7 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 8 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 9 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 10 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 11 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 12 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 13 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 14 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 15 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 16 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 17 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 18 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 19 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 20 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 21 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 22 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 23 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 24 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 25 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 26 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 27 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 28 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 29 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 30 ); OSMetaClassDefineReservedUnused( IOACPIPlatformDevice, 31 ); //--------------------------------------------------------------------------- // Supported IOPM power states. Not to be confused with ACPI power states. // Do not expose this definition. This gives us flexibility to change the // mapping between ACPI and PM power states in the future. enum { kIOACPIPlatformDevicePMStateOff = 0, kIOACPIPlatformDevicePMStateDoze = 1, kIOACPIPlatformDevicePMStateOn = 2, kIOACPIPlatformDevicePMStateCount = 3 }; static IOPMPowerState powerStates[ kIOACPIPlatformDevicePMStateCount ] = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 0, IOPMSoftSleep, IOPMSoftSleep, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 0, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } }; // Power flags. enum { kPowerManagementInited = 0x01, kSystemWakeCapability = 0x02, kInRushCurrentLoad = 0x04 }; // Per state power flags that describe the features of each supported // ACPI power state. enum { kPowerStateHas_PSx = 0x01, kPowerStateHas_PRx = 0x02 }; //static const char * _SxD[4] = { "_S0D", "_S1D", "_S2D", "_S3D" }; static const char * _PRx[4] = { "_PR0", "_PR1", "_PR2", "_PR3" }; static const char * _PSx[4] = { "_PS0", "_PS1", "_PS2", "_PS3" }; //--------------------------------------------------------------------------- bool IOACPIPlatformDevice::init( IOService * platform, void * handle, OSDictionary * properties ) { if ( super::init( properties ) != true ) return false; _deviceHandle = handle; _deviceType = kTypeDevice; _platform = OSDynamicCast( IOACPIPlatformExpert, platform ); _sleepPowerState = kIOACPIDevicePowerStateD3; _powerStateFlags = IONew( UInt32, kIOACPIDevicePowerStateCount ); if ( _powerStateFlags == 0 ) return false; // All arguments may be zero with the exception of platform. if ( _platform == 0 ) return false; return true; } //--------------------------------------------------------------------------- void IOACPIPlatformDevice::free( void ) { if ( _powerStateFlags ) { IODelete( _powerStateFlags, UInt32, kIOACPIDevicePowerStateCount ); } super::free(); } //--------------------------------------------------------------------------- bool IOACPIPlatformDevice::attachToParent( IORegistryEntry * parent, const IORegistryPlane * plane ) { bool success = super::attachToParent( parent, plane ); if ( success && ( plane == gIOACPIPlane ) ) { _acpiParent = OSDynamicCast( IOService, parent ); if ( _acpiParent == 0 ) _acpiParent = _platform; initACPIPowerManagement( _acpiParent ); } return success; } //--------------------------------------------------------------------------- void IOACPIPlatformDevice::detachFromParent( IORegistryEntry * parent, const IORegistryPlane * plane ) { if ( plane == gIOACPIPlane ) { stopACPIPowerManagement( _acpiParent ); } super::detachFromParent( parent, plane ); } //--------------------------------------------------------------------------- bool IOACPIPlatformDevice::initACPIPowerManagement( IOService * powerParent ) { if ( _powerFlags & kPowerManagementInited ) return true; if ( validateObject( "_PRW" ) == kIOReturnSuccess ) _powerFlags |= kSystemWakeCapability; if ( validateObject( "_IRC" ) == kIOReturnSuccess ) _powerFlags |= kInRushCurrentLoad; // Probe each power state. for ( long i = kIOACPIDevicePowerStateD0; i < kIOACPIDevicePowerStateCount; i++ ) { _powerStateFlags[i] = 0; // Power state supported if _PSx exists. if ( validateObject( _PSx[i] ) == kIOReturnSuccess ) { _powerStateFlags[i] |= kPowerStateHas_PSx; } // Devices can also be power managed through power resource // control. if ( validateObject( _PRx[i] ) == kIOReturnSuccess ) { _powerStateFlags[i] |= kPowerStateHas_PRx; } } // Does this device support power management? If so, add the // device to the power tree. if ( _powerStateFlags[ kIOACPIDevicePowerStateD0 ] ) { PMinit(); // Serve as both power management "policy maker" and // "controlling driver". registerPowerDriver( this, (IOPMPowerState *) powerStates, kIOACPIPlatformDevicePMStateCount ); // Join the PM tree. This triggers a call to the platform's // PMRegisterDevice() function that knows where to insert the // device in the power plane. powerParent->joinPMtree( this ); } _powerFlags |= kPowerManagementInited; return true; } //--------------------------------------------------------------------------- void IOACPIPlatformDevice::stopACPIPowerManagement( IOService * powerParent ) { if ( _powerFlags & kPowerManagementInited ) { PMstop(); } } //--------------------------------------------------------------------------- void * IOACPIPlatformDevice::getDeviceHandle( void ) const { return _deviceHandle; } UInt32 IOACPIPlatformDevice::getDeviceType( void ) const { return _deviceType; } void IOACPIPlatformDevice::setDeviceType( UInt32 deviceType ) { _deviceType = deviceType; } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::validateObject( const OSSymbol * objectName ) { return _platform->validateObject( this, objectName ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::validateObject( const char * objectName ) { return _platform->validateObject( this, objectName ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::evaluateObject( const OSSymbol * objectName, OSObject ** result, OSObject * params[], UInt32 paramCount, IOOptionBits options ) { return _platform->evaluateObject( this, objectName, result, params, paramCount, options ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::evaluateObject( const char * objectName, OSObject ** result, OSObject * params[], UInt32 paramCount, IOOptionBits options ) { return _platform->evaluateObject( this, objectName, result, params, paramCount, options ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::evaluateInteger( const OSSymbol * objectName, UInt64 * resultInt64, OSObject * params[], IOItemCount paramCount, IOOptionBits options ) { IOReturn ret; OSObject * obj = 0; ret = evaluateObject( objectName, &obj, params, paramCount, options ); if ( ret == kIOReturnSuccess ) { OSNumber * num; if ((num = OSDynamicCast(OSNumber, obj))) *resultInt64 = num->unsigned64BitValue(); else ret = kIOReturnBadArgument; } if (obj) obj->release(); return ret; } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::evaluateInteger( const char * objectName, UInt64 * resultInt64, OSObject * params[], IOItemCount paramCount, IOOptionBits options ) { IOReturn ret; OSObject * obj = 0; ret = evaluateObject( objectName, &obj, params, paramCount, options ); if ( ret == kIOReturnSuccess ) { OSNumber * num; if ((num = OSDynamicCast(OSNumber, obj))) *resultInt64 = num->unsigned64BitValue(); else ret = kIOReturnBadArgument; } if (obj) obj->release(); return ret; } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::evaluateInteger( const OSSymbol * objectName, UInt32 * resultInt32, OSObject * params[], IOItemCount paramCount, IOOptionBits options ) { IOReturn ret; OSObject * obj = 0; ret = evaluateObject( objectName, &obj, params, paramCount, options ); if ( ret == kIOReturnSuccess ) { OSNumber * num; if ((num = OSDynamicCast(OSNumber, obj))) *resultInt32 = num->unsigned32BitValue(); else ret = kIOReturnBadArgument; } if (obj) obj->release(); return ret; } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::evaluateInteger( const char * objectName, UInt32 * resultInt32, OSObject * params[], IOItemCount paramCount, IOOptionBits options ) { IOReturn ret; OSObject * obj = 0; ret = evaluateObject( objectName, &obj, params, paramCount, options ); if ( ret == kIOReturnSuccess ) { OSNumber * num; if ((num = OSDynamicCast(OSNumber, obj))) *resultInt32 = num->unsigned32BitValue(); else ret = kIOReturnBadArgument; } if (obj) obj->release(); return ret; } //--------------------------------------------------------------------------- const OSData * IOACPIPlatformDevice::getACPITableData( const char * tableName, UInt32 tableInstance ) const { return _platform->getACPITableData( tableName, tableInstance ); } //--------------------------------------------------------------------------- UInt32 IOACPIPlatformDevice::getDeviceStatus( void ) const { UInt32 status; IOACPIPlatformDevice * me = (IOACPIPlatformDevice *) this; if ( kIOReturnSuccess == me->evaluateInteger( gIOACPIDeviceStatusKey, &status ) ) return status; else return 0x0F; } //--------------------------------------------------------------------------- SInt32 IOACPIPlatformDevice::installInterruptForFixedEvent( UInt32 event ) { return _platform->installDeviceInterruptForFixedEvent( this, event ); } //--------------------------------------------------------------------------- SInt32 IOACPIPlatformDevice::installInterruptForGPE( UInt32 gpeNumber, void * gpeBlockDevice, IOOptionBits options ) { return _platform->installDeviceInterruptForGPE( this, gpeNumber, gpeBlockDevice, options ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::acquireGlobalLock( UInt32 * lockToken, const mach_timespec_t * timeout ) { return _platform->acquireGlobalLock( this, lockToken, timeout ); } void IOACPIPlatformDevice::releaseGlobalLock( UInt32 lockToken ) { _platform->releaseGlobalLock( this, lockToken ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::registerAddressSpaceHandler( IOACPIAddressSpaceID spaceID, IOACPIAddressSpaceHandler handler, void * context, IOOptionBits options ) { return _platform->registerAddressSpaceHandler( this, spaceID, handler, context, options ); } void IOACPIPlatformDevice::unregisterAddressSpaceHandler( IOACPIAddressSpaceID spaceID, IOACPIAddressSpaceHandler handler, IOOptionBits options ) { _platform->unregisterAddressSpaceHandler( this, spaceID, handler, options ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::readAddressSpace( UInt64 * value, UInt32 spaceID, IOACPIAddress address, UInt32 bitWidth, UInt32 bitOffset, IOOptionBits options ) { return _platform->readAddressSpace( value, spaceID, address, bitWidth, bitOffset, options ); } IOReturn IOACPIPlatformDevice::writeAddressSpace( UInt64 value, UInt32 spaceID, IOACPIAddress address, UInt32 bitWidth, UInt32 bitOffset, IOOptionBits options ) { return _platform->writeAddressSpace( value, spaceID, address, bitWidth, bitOffset, options ); } //--------------------------------------------------------------------------- bool IOACPIPlatformDevice::getPathComponent( char * path, int * length, const IORegistryPlane * plane ) const { return super::getPathComponent(path, length, plane); } //--------------------------------------------------------------------------- bool IOACPIPlatformDevice::compareName( OSString * name, OSString ** matched ) const { return ( _platform->compareNubName( this, name, matched ) ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::getResources( void ) { return ( _platform->getNubResources( this ) ); } //--------------------------------------------------------------------------- bool IOACPIPlatformDevice::hasSystemWakeCapability( void ) const { return ( _powerFlags & kSystemWakeCapability ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::setSystemWakeCapabilityEnable( bool enable ) { return _platform->setDeviceWakeEnable( this, enable ); } //--------------------------------------------------------------------------- bool IOACPIPlatformDevice::hasACPIPowerStateSupport( UInt32 powerState ) const { if ( powerState >= kIOACPIDevicePowerStateCount ) return false; return ( _powerStateFlags[powerState] != 0 ); } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::setACPIPowerManagementEnable( bool enable, UInt32 powerState, IOOptionBits options ) { return kIOReturnUnsupported; } //--------------------------------------------------------------------------- IOReturn IOACPIPlatformDevice::setPowerState( unsigned long stateIndex, IOService * whatDevice ) { UInt32 powerState; //kprintf("%s: setPowerState %d (%p)\n", getName(), stateIndex, whatDevice); switch ( stateIndex ) { case kIOACPIPlatformDevicePMStateOff: powerState = _sleepPowerState; break; default: powerState = kIOACPIDevicePowerStateD0; break; } _platform->setDevicePowerState( this, powerState ); return IOPMAckImplied; } //--------------------------------------------------------------------------- // FIXME: verify that the range is tagged as I/O? UInt32 IOACPIPlatformDevice::ioRead32( UInt16 offset, IOMemoryMap * map ) { UInt32 value; UInt16 base = 0; if (map) base = map->getPhysicalAddress(); value = inl( base + offset ); return (value); } UInt16 IOACPIPlatformDevice::ioRead16( UInt16 offset, IOMemoryMap * map ) { UInt16 value; UInt16 base = 0; if (map) base = map->getPhysicalAddress(); value = inw( base + offset ); return (value); } UInt8 IOACPIPlatformDevice::ioRead8( UInt16 offset, IOMemoryMap * map ) { UInt32 value; UInt16 base = 0; if (map) base = map->getPhysicalAddress(); value = inb( base + offset ); return (value); } void IOACPIPlatformDevice::ioWrite32( UInt16 offset, UInt32 value, IOMemoryMap * map ) { UInt16 base = 0; if (map) base = map->getPhysicalAddress(); outl( base + offset, value ); } void IOACPIPlatformDevice::ioWrite16( UInt16 offset, UInt16 value, IOMemoryMap * map ) { UInt16 base = 0; if (map) base = map->getPhysicalAddress(); outw( base + offset, value ); } void IOACPIPlatformDevice::ioWrite8( UInt16 offset, UInt8 value, IOMemoryMap * map ) { UInt16 base = 0; if (map) base = map->getPhysicalAddress(); outb( base + offset, value ); }