/* * 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 * 23 Nov 98 sdouglas created from objc version. * 05 Nov 99 sdouglas added UniNorth AGP based on UniNorthAGPDriver.c * by Fernando Urbina, Kent Miller. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * List of UniNorth device revisions. * Last updated 15 Dec 2004. * * UniN V1.0 - 0x00 * UniN V1.5 - 0x10 * U2 - 0x20 * Intrepid V1.0 - 0xD0 * Intrepid V1.1 - 0xD0 * Intrepid V2.0 - 0xD2 * Intrepid V2.1 - 0xD2 * U3 V1.0 - 0x30 * U3 V2.1 - 0x32 * U3 V2.2 - 0x33 * U3 V2.3 - 0xB3 * U3 Heavy V1.0 - 0x34 * U3 Heavy V1.1 - 0x35 * U3 Heavy V2.0 - 0x37 * U3 Light V1.0 - 0x38 * U3 Light V1.1 - 0x39 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define _BIG_ENDIAN 1 // for 2370035 #include #include #include #include #include #include #include #include #include #include #include #include "AppleMacRiscPCI.h" #define NO_FASTWRITE 1 #define NO_NVIDIA_FASTWRITE 1 #define ALLOC_AGP_RANGE 0 #define NO_ATIR481_FASTWRITE 1 #define kDevice_IDProperty "device-id" #define kVendor_IDProperty "vendor-id" #define kATIVendorID 0x00001002 #define kATIR481DeviceID 0x00004a48 #ifndef kIOAGPCommandValueKey #define kIOAGPCommandValueKey "IOAGPCommandValue" #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define super IOPCIBridge OSDefineMetaClassAndStructors(AppleMacRiscPCI, IOPCIBridge) OSDefineMetaClassAndStructors(AppleMacRiscVCI, AppleMacRiscPCI) OSDefineMetaClassAndStructors(AppleMacRiscAGP, AppleMacRiscPCI) OSDefineMetaClassAndStructors(AppleMacRiscHT, IOPCIBridge) OSDefineMetaClassAndStructors(AppleMacRiscPCIE, IOPCIBridge) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bool AppleMacRiscPCI::start( IOService * provider ) { IOPCIPhysicalAddress ioAddrCell; IOPhysicalAddress ioPhys; IOPhysicalAddress ioPhysLen; OSArray * array; IODeviceMemory::InitElement rangeList[ 3 ]; IORegistryEntry * bridge; OSData * busProp; IORegistryEntry *uniNRegEntry; OSData *tmpData; // Match the name of the provider to weed out the memory controller if( !IODTMatchNubWithKeys(provider, "('pci', 'vci')")) return( false); // Match the compatible property to find modern MacRISC PCI bridges if( IODTMatchNubWithKeys(provider, "('uni-north', 'u3-agp')")) configDataOffsetMask = 0x7; else configDataOffsetMask = 0x3; if( 0 == (lock = IOSimpleLockAlloc())) return( false ); ioAddrCell.physHi.bits = 0; ioAddrCell.physHi.s.space = kIOPCIIOSpace; ioAddrCell.physMid = 0; ioAddrCell.physLo = 0; ioAddrCell.lengthHi = 0; ioAddrCell.lengthLo = 0x10000; // // Disable AGP for P58/P69 U2 (v2.0) due to stablity issues // Get the Uni-N Version. uniNRegEntry = IORegistryEntry::fromPath("/uni-n", gIODTPlane); if (!uniNRegEntry) uniNRegEntry = IORegistryEntry::fromPath("/u3", gIODTPlane); if (uniNRegEntry) { tmpData = OSDynamicCast(OSData, uniNRegEntry->getProperty("device-rev")); if (tmpData) { uniNVersion = *(long *)tmpData->getBytesNoCopy(); uniNRegEntry->release(); //uniNVersion &= 0x3f; } } bridge = provider; IODTSetResolving(provider, &compareAddressCell, &nvLocation); if( ! IODTResolveAddressCell( bridge, (UInt32 *) &ioAddrCell, &ioPhys, &ioPhysLen) ) { IOLog("%s: couldn't find my base\n", getName()); return( false); } /* define more explicit ranges */ rangeList[0].start = ioPhys; rangeList[0].length = ioPhysLen; rangeList[1].start = ioPhys + 0x00800000; rangeList[1].length = 4; rangeList[2].start = ioPhys + 0x00c00000; rangeList[2].length = 4; IORangeAllocator * platformRanges; platformRanges = IOService::getPlatform()->getPhysicalRangeAllocator(); assert( platformRanges ); platformRanges->allocateRange( ioPhys, 0x01000000 ); array = IODeviceMemory::arrayFromList( rangeList, 3 ); if( !array) return( false); provider->setDeviceMemory( array ); array->release(); ioMemory = (IODeviceMemory *) array->getObject( 0 ); /* map registers */ if( (configAddrMap = provider->mapDeviceMemoryWithIndex( 1 ))) configAddr = (volatile UInt32 *) configAddrMap->getVirtualAddress(); if( (configDataMap = provider->mapDeviceMemoryWithIndex( 2 ))) configData = (volatile UInt8 *) configDataMap->getVirtualAddress(); if( !configAddr || !configData) return( false); busProp = (OSData *) bridge->getProperty("bus-range"); if( busProp) { secondaryBus = *((UInt32 *) busProp->getBytesNoCopy()); subordinateBus = *((UInt32 *) busProp->getBytesNoCopy() + 1); } return( super::start( provider)); } bool AppleMacRiscPCI::configure( IOService * provider ) { UInt32 modeSelects, addressSelects; UInt32 index; bool ok; if( getProvider()->getProperty( "DisableRDG") != 0 ) { modeSelects = configRead32( getBridgeSpace(), kMacRISCPCIModeSelect ); modeSelects |= kMacRISCPCIModeSelectRDGBit; configWrite32( getBridgeSpace(), kMacRISCPCIModeSelect, modeSelects ); } addressSelects = configRead32( getBridgeSpace(), kMacRISCPCIAddressSelect ); coarseAddressMask = addressSelects >> 16; fineAddressMask = addressSelects & 0xffff; for( index = 0; index < 15; index++ ) { if( coarseAddressMask & (1 << index)) { ok = addBridgeMemoryRange( index << 28, 0x10000000, true ); } } // if( coarseAddressMask & (1 << 15)) // F segment for( index = 0; index < 15; index++ ) { if( fineAddressMask & (1 << index)) { ok = addBridgeMemoryRange( (0xf0 | index) << 24, 0x01000000, true ); } } ok = addBridgeIORange( 0, 0x10000 ); return( super::configure( provider)); } void AppleMacRiscPCI::free() { if( configAddrMap) configAddrMap->release(); if( configDataMap) configDataMap->release(); if( lock) IOSimpleLockFree( lock); super::free(); } IODeviceMemory * AppleMacRiscPCI::ioDeviceMemory( void ) { return( ioMemory); } IODeviceMemory * AppleMacRiscVCI::ioDeviceMemory( void ) { return( 0 ); } bool AppleMacRiscVCI::configure( IOService * provider ) { addBridgeMemoryRange( 0x90000000, 0x10000000, true ); return( AppleMacRiscPCI::configure( provider)); } UInt8 AppleMacRiscPCI::firstBusNum( void ) { return( secondaryBus ); } UInt8 AppleMacRiscPCI::lastBusNum( void ) { return( subordinateBus ); } IOPCIAddressSpace AppleMacRiscPCI::getBridgeSpace( void ) { IOPCIAddressSpace space; space.bits = 0; space.s.busNum = secondaryBus; space.s.deviceNum = kPCIBridgeSelfDevice; return( space ); } inline bool AppleMacRiscPCI::setConfigSpace( IOPCIAddressSpace space, UInt8 offset ) { UInt32 addrCycle; if( space.es.registerNumExtended) return( false); offset &= 0xfc; if( space.s.busNum == secondaryBus) { if( space.s.deviceNum < kPCIBridgeSelfDevice) return( false); // primary config cycle addrCycle = ( (1 << space.s.deviceNum) | (space.s.functionNum << 8) | offset ); } else { // pass thru config cycle addrCycle = ( (space.bits) | offset | 1 ); } do { OSWriteSwapInt32( configAddr, 0, addrCycle); eieio(); } while( addrCycle != OSReadSwapInt32( configAddr, 0 )); eieio(); return( true ); } UInt32 AppleMacRiscPCI::configRead32( IOPCIAddressSpace space, UInt8 offset ) { UInt32 data; IOInterruptState ints; ints = IOSimpleLockLockDisableInterrupt( lock ); if( setConfigSpace( space, offset )) { offset = offset & configDataOffsetMask & 4; data = OSReadSwapInt32( configData, offset ); eieio(); } else data = 0xffffffff; IOSimpleLockUnlockEnableInterrupt( lock, ints ); return( data ); } void AppleMacRiscPCI::configWrite32( IOPCIAddressSpace space, UInt8 offset, UInt32 data ) { IOInterruptState ints; ints = IOSimpleLockLockDisableInterrupt( lock ); if( setConfigSpace( space, offset )) { offset = offset & configDataOffsetMask & 4; OSWriteSwapInt32( configData, offset, data ); eieio(); /* read to sync */ (void) OSReadSwapInt32( configData, offset ); eieio(); sync(); isync(); } IOSimpleLockUnlockEnableInterrupt( lock, ints ); } UInt16 AppleMacRiscPCI::configRead16( IOPCIAddressSpace space, UInt8 offset ) { UInt16 data; IOInterruptState ints; ints = IOSimpleLockLockDisableInterrupt( lock ); if( setConfigSpace( space, offset )) { offset = offset & configDataOffsetMask & 6; data = OSReadSwapInt16( configData, offset ); eieio(); } else data = 0xffff; IOSimpleLockUnlockEnableInterrupt( lock, ints ); return( data ); } void AppleMacRiscPCI::configWrite16( IOPCIAddressSpace space, UInt8 offset, UInt16 data ) { IOInterruptState ints; ints = IOSimpleLockLockDisableInterrupt( lock ); if( setConfigSpace( space, offset )) { offset = offset & configDataOffsetMask & 6; OSWriteSwapInt16( configData, offset, data ); eieio(); /* read to sync */ (void) OSReadSwapInt16( configData, offset ); eieio(); sync(); isync(); } IOSimpleLockUnlockEnableInterrupt( lock, ints ); } UInt8 AppleMacRiscPCI::configRead8( IOPCIAddressSpace space, UInt8 offset ) { UInt16 data; IOInterruptState ints; ints = IOSimpleLockLockDisableInterrupt( lock ); if( setConfigSpace( space, offset )) { offset = offset & configDataOffsetMask; data = configData[ offset ]; eieio(); } else data = 0xff; IOSimpleLockUnlockEnableInterrupt( lock, ints ); return( data ); } void AppleMacRiscPCI::configWrite8( IOPCIAddressSpace space, UInt8 offset, UInt8 data ) { IOInterruptState ints; ints = IOSimpleLockLockDisableInterrupt( lock ); if( setConfigSpace( space, offset )) { offset = offset & configDataOffsetMask; configData[ offset ] = data; eieio(); /* read to sync */ data = configData[ offset ]; eieio(); sync(); isync(); } IOSimpleLockUnlockEnableInterrupt( lock, ints ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bool AppleMacRiscHT::start( IOService * provider ) { IOPhysicalAddress ioPhysAddrs[2]; IOPhysicalAddress ioPhysLengths[2]; OSArray * array; IODeviceMemory::InitElement rangeList[ 4 ]; IODeviceMemory * md; IORegistryEntry * bridge; OSData * busProp; bridge = provider; md = provider->getDeviceMemoryWithIndex(0); if (md == 0) return 0; ioPhysAddrs[0] = md->getPhysicalAddress(); ioPhysLengths[0] = md->getLength(); md = provider->getDeviceMemoryWithIndex(1); if (md == 0) return 0; ioPhysAddrs[1] = md->getPhysicalAddress(); ioPhysLengths[1] = md->getLength(); /* define more explicit ranges */ rangeList[0].start = ioPhysAddrs[0]; rangeList[0].length = 0x01000000UL; rangeList[1].start = ioPhysAddrs[0] + 0x01000000; rangeList[1].length = 0x01000000UL; rangeList[2].start = ioPhysAddrs[0] + 0x02000000; rangeList[2].length = 0x00400000UL; rangeList[3].start = ioPhysAddrs[1]; rangeList[3].length = ioPhysLengths[1]; IORangeAllocator * platformRanges; platformRanges = IOService::getPlatform()->getPhysicalRangeAllocator(); assert( platformRanges ); platformRanges->allocateRange( ioPhysAddrs[0], ioPhysLengths[0] ); array = IODeviceMemory::arrayFromList( rangeList, 4 ); if( !array) return( false); provider->setDeviceMemory( array ); ioMemory = (IODeviceMemory *) array->getObject( 2 ); array->release(); /* map registers */ if( (configType0Map = provider->mapDeviceMemoryWithIndex( 0 ))) configType0 = (volatile UInt8 *) configType0Map->getVirtualAddress(); if( (configType1Map = provider->mapDeviceMemoryWithIndex( 1 ))) configType1 = (volatile UInt8 *) configType1Map->getVirtualAddress(); if( (configSelfMap = provider->mapDeviceMemoryWithIndex( 3 ))) configSelf = (volatile UInt8 *) configSelfMap->getVirtualAddress(); if( !configType0 || !configType1 || !configSelf) return( false); busProp = (OSData *) bridge->getProperty("bus-range"); if( busProp) primaryBus = *((UInt32 *) busProp->getBytesNoCopy()); return( super::start( provider)); } bool AppleMacRiscHT::configure( IOService * provider ) { UInt32 addressSelects; UInt32 index; bool ok; addressSelects = configRead32( getBridgeSpace(), kMacRISCHTAddressSelect ); coarseAddressMask = addressSelects >> 16; fineAddressMask = addressSelects & 0xffff; for( index = 0; index < 15; index++ ) { if( coarseAddressMask & (1 << index)) { ok = addBridgeMemoryRange( index << 28, 0x10000000, true ); } } // if( coarseAddressMask & (1 << 15)) // F segment for( index = 0; index < 15; index++ ) { if( fineAddressMask & (1 << index)) { ok = addBridgeMemoryRange( (0xf0 | index) << 24, 0x01000000, true ); } } ok = addBridgeIORange( 0, 0x10000 ); return( super::configure( provider)); } void AppleMacRiscHT::free() { if( configType0Map) configType0Map->release(); if( configType1Map) configType1Map->release(); if( configSelfMap) configSelfMap->release(); super::free(); } IODeviceMemory * AppleMacRiscHT::ioDeviceMemory( void ) { return( ioMemory); } IOPCIAddressSpace AppleMacRiscHT::getBridgeSpace( void ) { IOPCIAddressSpace space; space.bits = 0; space.s.busNum = primaryBus; space.s.deviceNum = kHTBridgeSelfDevice; return( space ); } volatile UInt8 * AppleMacRiscHT::setConfigSpace( IOPCIAddressSpace space, UInt8 offset ) { volatile UInt8 * configData; if( space.es.registerNumExtended) return( 0 ); offset &= 0xfc; if( space.s.busNum == primaryBus) { if( space.s.deviceNum == kHTBridgeSelfDevice) { // primary config cycle on self configData = configSelf + (offset << 2); } else { // primary config cycle configData = configType0 + ((space.bits & 0xffffff00) | offset); } } else { // pass thru config cycle configData = configType1 + ((space.bits & 0xffffff00) | offset); } return( configData ); } UInt32 AppleMacRiscHT::configRead32( IOPCIAddressSpace space, UInt8 offset ) { volatile UInt8 * configData; UInt32 data; configData = setConfigSpace( space, offset ); if (configData) { offset = offset & 3 & 4; data = OSReadSwapInt32( configData, offset ); eieio(); } else data = 0xffffffff; return( data ); } void AppleMacRiscHT::configWrite32( IOPCIAddressSpace space, UInt8 offset, UInt32 data ) { volatile UInt8 * configData; configData = setConfigSpace( space, offset ); if (configData) { offset = offset & 3 & 4; OSWriteSwapInt32( configData, offset, data ); eieio(); /* read to sync */ (void) OSReadSwapInt32( configData, offset ); eieio(); sync(); isync(); } } UInt16 AppleMacRiscHT::configRead16( IOPCIAddressSpace space, UInt8 offset ) { volatile UInt8 * configData; UInt16 data; configData = setConfigSpace( space, offset ); if (configData) { offset = offset & 3 & 6; data = OSReadSwapInt16( configData, offset ); eieio(); } else data = 0xffff; return( data ); } void AppleMacRiscHT::configWrite16( IOPCIAddressSpace space, UInt8 offset, UInt16 data ) { volatile UInt8 * configData; configData = setConfigSpace( space, offset ); if (configData) { offset = offset & 3 & 6; OSWriteSwapInt16( configData, offset, data ); eieio(); /* read to sync */ (void) OSReadSwapInt16( configData, offset ); eieio(); sync(); isync(); } } UInt8 AppleMacRiscHT::configRead8( IOPCIAddressSpace space, UInt8 offset ) { volatile UInt8 * configData; UInt16 data; configData = setConfigSpace( space, offset ); if (configData) { offset = offset & 3; data = configData[ offset ]; eieio(); } else data = 0xff; return( data ); } void AppleMacRiscHT::configWrite8( IOPCIAddressSpace space, UInt8 offset, UInt8 data ) { volatile UInt8 * configData; configData = setConfigSpace( space, offset ); if (configData) { offset = offset & 3; configData[ offset ] = data; eieio(); /* read to sync */ data = configData[ offset ]; eieio(); sync(); isync(); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bool AppleMacRiscPCIE::start( IOService * provider ) { IOPhysicalAddress ioPhysAddrs; IOPhysicalAddress ioPhysLengths; OSArray * array; IODeviceMemory::InitElement rangeList[ 2 ]; IODeviceMemory * md; IORegistryEntry * bridge; bridge = provider; md = provider->getDeviceMemoryWithIndex(0); if (md == 0) return 0; ioPhysAddrs = md->getPhysicalAddress(); ioPhysLengths = md->getLength(); if( 0 == (lock = IOSimpleLockAlloc())) return( false ); /* define more explicit ranges */ rangeList[0].start = ioPhysAddrs; rangeList[0].length = 0x01000000UL; rangeList[1].start = ioPhysAddrs + 0x01000000; rangeList[1].length = 0x01000000UL; IORangeAllocator * platformRanges; platformRanges = IOService::getPlatform()->getPhysicalRangeAllocator(); assert( platformRanges ); platformRanges->allocateRange( ioPhysAddrs, ioPhysLengths ); array = IODeviceMemory::arrayFromList( rangeList, 2 ); if( !array) return( false); provider->setDeviceMemory( array ); array->release(); /* map registers */ if( (hostRegsMap = provider->mapDeviceMemoryWithIndex( 0 ))) hostRegs = (volatile UInt8 *) hostRegsMap->getVirtualAddress(); if( (configAtomicMap = provider->mapDeviceMemoryWithIndex( 1 ))) configAtomic = (volatile UInt8 *) configAtomicMap->getVirtualAddress(); if( !hostRegs || !configAtomic) return( false); configAddrNA = (volatile UInt32 *)(hostRegs + 0x800000); configDataNA = (volatile UInt8 *)(hostRegs + 0xC00000); // Primary Bus is always zero. primaryBus = 0; return( super::start( provider)); } bool AppleMacRiscPCIE::configure( IOService * provider ) { UInt32 addressSelects; UInt32 index; bool ok; addressSelects = configRead32( getBridgeSpace(), kMacRISCPCIEAddressSelect ); coarseAddressMask = addressSelects >> 16; fineAddressMask = addressSelects & 0xffff; for( index = 0; index < 15; index++ ) { if( coarseAddressMask & (1 << index)) { ok = addBridgeMemoryRange( index << 28, 0x10000000, true ); } } // if( coarseAddressMask & (1 << 15)) // F segment for( index = 0; index < 15; index++ ) { if( fineAddressMask & (1 << index)) { ok = addBridgeMemoryRange( (0xf0 | index) << 24, 0x01000000, true ); } } return( super::configure( provider)); } void AppleMacRiscPCIE::free() { if( hostRegsMap) hostRegsMap->release(); if( configAtomicMap) configAtomicMap->release(); if( lock) IOSimpleLockFree( lock); super::free(); } IODeviceMemory * AppleMacRiscPCIE::ioDeviceMemory( void ) { return( 0 ); } IOPCIAddressSpace AppleMacRiscPCIE::getBridgeSpace( void ) { IOPCIAddressSpace space; space.bits = 0; space.es.busNum = primaryBus; space.es.deviceNum = kPCIEBridgeSelfDevice; return( space ); } bool AppleMacRiscPCIE::configCycleAtomic( IOPCIAddressSpace space) { if( space.es.registerNumExtended != 0) return false; return true; } volatile UInt8 * AppleMacRiscPCIE::setConfigSpace( IOPCIAddressSpace space, UInt8 offset ) { UInt32 addrCycle; volatile UInt8 * configData; offset &= 0xfc; if( configCycleAtomic(space)) { configData = configAtomic + ((space.bits & 0x00ffff00) | offset); } else { if( space.es.busNum == primaryBus) { // primary config cycle addrCycle = ( (1 << (space.es.deviceNum + 11)) | (space.es.registerNumExtended << 28) | (space.es.functionNum << 8) | offset ); } else { // pass thru config cycle addrCycle = ( ((space.bits) & 0x00ffff00) | (space.es.registerNumExtended << 28) | offset | 1 ); } do { OSWriteSwapInt32( configAddrNA, 0, addrCycle); eieio(); } while( addrCycle != OSReadSwapInt32( configAddrNA, 0 )); eieio(); configData = configDataNA; } return( configData ); } UInt32 AppleMacRiscPCIE::configRead32( IOPCIAddressSpace space, UInt8 offset ) { volatile UInt8 * configData; UInt32 data; bool atomic = configCycleAtomic(space); IOInterruptState ints = 0; if( !atomic) ints = IOSimpleLockLockDisableInterrupt( lock ); configData = setConfigSpace( space, offset ); offset = offset & 3 & 4; data = OSReadSwapInt32( configData, offset ); eieio(); if( !atomic) IOSimpleLockUnlockEnableInterrupt( lock, ints ); return( data ); } void AppleMacRiscPCIE::configWrite32( IOPCIAddressSpace space, UInt8 offset, UInt32 data ) { volatile UInt8 * configData; bool atomic = configCycleAtomic(space); IOInterruptState ints = 0; if( !atomic) ints = IOSimpleLockLockDisableInterrupt( lock ); configData = setConfigSpace( space, offset ); offset = offset & 3 & 4; OSWriteSwapInt32( configData, offset, data ); eieio(); /* read to sync */ (void) OSReadSwapInt32( configData, offset ); eieio(); sync(); isync(); if( !atomic) IOSimpleLockUnlockEnableInterrupt( lock, ints ); } UInt16 AppleMacRiscPCIE::configRead16( IOPCIAddressSpace space, UInt8 offset ) { volatile UInt8 * configData; UInt16 data; bool atomic = configCycleAtomic(space); IOInterruptState ints = 0; if( !atomic) ints = IOSimpleLockLockDisableInterrupt( lock ); configData = setConfigSpace( space, offset ); offset = offset & 3 & 6; data = OSReadSwapInt16( configData, offset ); eieio(); if( !atomic) IOSimpleLockUnlockEnableInterrupt( lock, ints ); return( data ); } void AppleMacRiscPCIE::configWrite16( IOPCIAddressSpace space, UInt8 offset, UInt16 data ) { volatile UInt8 * configData; bool atomic = configCycleAtomic(space); IOInterruptState ints = 0; if( !atomic) ints = IOSimpleLockLockDisableInterrupt( lock ); configData = setConfigSpace( space, offset ); offset = offset & 3 & 6; OSWriteSwapInt16( configData, offset, data ); eieio(); /* read to sync */ (void) OSReadSwapInt16( configData, offset ); eieio(); sync(); isync(); if( !atomic) IOSimpleLockUnlockEnableInterrupt( lock, ints ); } UInt8 AppleMacRiscPCIE::configRead8( IOPCIAddressSpace space, UInt8 offset ) { volatile UInt8 * configData; UInt16 data; bool atomic = configCycleAtomic(space); IOInterruptState ints = 0; if ( !atomic) ints = IOSimpleLockLockDisableInterrupt( lock ); configData = setConfigSpace( space, offset ); offset = offset & 3; data = configData[ offset ]; eieio(); if( !atomic) IOSimpleLockUnlockEnableInterrupt( lock, ints ); return( data ); } void AppleMacRiscPCIE::configWrite8( IOPCIAddressSpace space, UInt8 offset, UInt8 data ) { volatile UInt8 * configData; bool atomic = configCycleAtomic(space); IOInterruptState ints = 0; if( !atomic) ints = IOSimpleLockLockDisableInterrupt( lock ); configData = setConfigSpace( space, offset ); offset = offset & 3; configData[ offset ] = data; eieio(); /* read to sync */ data = configData[ offset ]; eieio(); sync(); isync(); if( !atomic) IOSimpleLockUnlockEnableInterrupt( lock, ints ); } // whatToDo for setDevicePowerState() enum { kSaveDeviceState = 0, kRestoreDeviceState = 1, kSaveBridgeState = 2, kRestoreBridgeState = 3 }; IOReturn AppleMacRiscPCIE::setDevicePowerState( IOPCIDevice * device, unsigned long whatToDo ) { if (kSaveBridgeState == whatToDo) { saveBridgeState(); } else if (kRestoreBridgeState == whatToDo) { restoreBridgeState(); } return super::setDevicePowerState(device, whatToDo); } void AppleMacRiscPCIE::saveBridgeState( void ) { UInt32 cnt; for (cnt = 0; cnt < kMacRISCPCIEBridgeRegs; cnt++) { bridgeState[cnt] = configRead32(getBridgeSpace(), cnt * 4); } } void AppleMacRiscPCIE::restoreBridgeState( void ) { UInt32 cnt; UInt32 addrCycle; IOPCIAddressSpace space = getBridgeSpace(); IOInterruptState ints = 0; // Start by restoring the PCIE primary/secondary bus numbers so that we can // can do direct access config cycles. ints = IOSimpleLockLockDisableInterrupt( lock ); addrCycle = ( (1 << (space.es.deviceNum + 11)) | (space.es.registerNumExtended << 28) | (space.es.functionNum << 8) | 18 ); do { OSWriteSwapInt32( configAddrNA, 0, addrCycle); eieio(); } while( addrCycle != OSReadSwapInt32( configAddrNA, 0 )); eieio(); OSWriteSwapInt32( configDataNA, 18, bridgeState[18] ); eieio(); IOSimpleLockUnlockEnableInterrupt( lock, ints ); // start at config space location 8 -- bytes 0-3 are // defined by the PCI Spec. as ReadOnly, and we don't // want to write anything to the Command or Status // registers until the rest of config space is set up. for (cnt = (kIOPCIConfigCommand >> 2) + 1; cnt < kMacRISCPCIEBridgeRegs; cnt++) { configWrite32(space, cnt * 4, bridgeState[cnt]); } // once the rest of the config space is restored, // turn on all the enables (,etc.) in the Command register. // NOTE - we also reset any status bits in the Status register // that may have been previously indicated by writing a '1' // to the bits indicating whatever they were indicating. configWrite32(space, kIOPCIConfigCommand, bridgeState[kIOPCIConfigCommand >> 2]); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #undef super #define super AppleMacRiscPCI /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bool AppleMacRiscAGP::configure( IOService * provider ) { if( !findPCICapability( getBridgeSpace(), kIOPCIAGPCapability, &targetAGPRegisters )) return( false ); if( false && (uniNVersion >= 0x10)) { // causes problems with nv25 SBA gartCtrl |= kGART_DIS_SBA_DET; } isU3 = IODTMatchNubWithKeys(provider, "u3-agp"); if (isU3) { uniNVersion &= 0x3f; gartCtrl |= kGART_PERF_RD; if(uniNVersion > 0x33) { /* B2B_GNT seems broken on U3 Twins */ //gartCtrl |= kGART_B2B_GNT; //gartCtrl |= kGART_FAST_DDR; } isU32 = (uniNVersion > 0x30); } return( super::configure( provider)); } IOPCIDevice * AppleMacRiscAGP::createNub( OSDictionary * from ) { IOPCIDevice * nub; IOPCIAddressSpace space; bool isAGP; UInt8 masterAGPRegisters; spaceFromProperties( from, &space); isAGP = ( (space.s.deviceNum != getBridgeSpace().s.deviceNum) && findPCICapability( space, kIOPCIAGPCapability, &masterAGPRegisters )); // more of P58/P69 AGP disable code from start if( isAGP && ((0 != getProvider()->getProperty("AAPL,noAGP")) || (uniNVersion == 0x20))) { isAGP = false; IOLog("AGP disabled on this machine\n"); } if( isAGP) { UInt64 flags; OSNumber * num; num = OSDynamicCast(OSNumber, getProperty(kIOAGPBusFlagsKey)); if (num) flags = num->unsigned64BitValue(); else flags = 0; if (isU32) flags &= ~kIOAGPGartInvalidate; else flags |= kIOAGPGartInvalidate; if ((uniNVersion < 0x08) || (isU3 && (uniNVersion < 0x33))) flags |= kIOAGPDisablePageSpans; if (isU3 && (uniNVersion < 0x34)) flags |= kIOAGPDisableUnaligned; if (uniNVersion < 0x20) flags |= kIOAGPDisableAGPWrites; if (uniNVersion == 0x30) flags |= kIOAGPDisablePCIReads | kIOAGPDisablePCIWrites; num = OSNumber::withNumber(flags, 64); nub = new IOAGPDevice; if (nub) ((IOAGPDevice *)nub)->masterAGPRegisters = masterAGPRegisters; if (num) { from->setObject(kIOAGPBusFlagsKey, num); num->release(); } } else nub = super::createNub( from ); return( nub ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ IOReturn AppleMacRiscAGP::createAGPSpace( IOAGPDevice * master, IOOptionBits options, IOPhysicalAddress * address, IOPhysicalLength * length ) { IOReturn err; IOPCIAddressSpace target = getBridgeSpace(); IOPhysicalLength agpLength; UInt64 gartPhys; OSData * data; enum { agpSpacePerPage = 4 * 1024 * 1024 }; enum { agpBytesPerGartByte = 1024 }; enum { alignLen = 4 * 1024 * 1024 - 1 }; destroyAGPSpace( master ); if (isU32 && !dummyPage) dummyPage = IOBufferMemoryDescriptor::withOptions(0, page_size, page_size); if (dummyPage) { IOPhysicalLength len; dummyPhys = dummyPage->getPhysicalSegment64(0, &len); configWrite32( target, kUniNDUMMY_PAGE, dummyPhys >> PAGE_SHIFT ); } agpCommandMask = 0xffffffff; // agpCommandMask &= ~kIOAGPSideBandAddresssing; // if (isU3) // agpCommandMask &= ~kIOAGPFastWrite; // { // // There's an nVidia NV11 ROM (revision 1017) that says that it can do fast writes, // // but can't, and can often lock the machine up when fast writes are enabled. // #define kNVIDIANV11EntryName "NVDA,NVMac" // #define kNVIDIAEntryName "NVDA," // #define kNVROMRevPropertyName "rom-revision" // #define kNVBadRevision '1017' //#if NO_NVIDIA_FASTWRITE // if( 0 == strncmp( kNVIDIAEntryName, master->getName(), strlen(kNVIDIAEntryName))) // { // agpCommandMask &= ~kIOAGPFastWrite; // NV34 systems (Q26B/Q54) has issues with this // if (!isU3) // agpCommandMask &= ~kIOAGPSideBandAddresssing; // NV34 systems (Q26B/Q54) has issues with this // } //#else /* NO_NVIDIA_FASTWRITE */ // const UInt32 badRev = kNVBadRevision; // if( (0 == strcmp( kNVIDIANV11EntryName, master->getName())) // && (data = OSDynamicCast(OSData, master->getProperty(kNVROMRevPropertyName))) // && (data->isEqualTo( &badRev, sizeof(badRev))) ) // agpCommandMask &= ~kIOAGPFastWrite; //#endif /* !NO_NVIDIA_FASTWRITE */ // } //#if NO_FASTWRITE // agpCommandMask &= ~kIOAGPFastWrite; //#endif /* !NO_FASTWRITE */ #if NO_ATIR481_FASTWRITE const UInt32 atiID = kATIVendorID; const UInt32 deviceR481ID = kATIR481DeviceID; OSData * data1; if ( (data = OSDynamicCast(OSData, master->getProperty(kVendor_IDProperty))) && (data->isEqualTo( &atiID, sizeof(atiID))) && (data1 = OSDynamicCast(OSData, master->getProperty(kDevice_IDProperty))) && (data1->isEqualTo( &deviceR481ID, sizeof(deviceR481ID))) ) { agpCommandMask &= ~kIOAGPFastWrite; // ATI R481 - disable Fast writes for R481 } #endif if ((data = OSDynamicCast(OSData, getProvider()->getProperty("AAPL,agp-clear")))) agpCommandMask &= ~*((UInt32 *)data->getBytesNoCopy()); if ((data = OSDynamicCast(OSData, getProvider()->getProperty("AAPL,agp-set")))) agpCommandSet |= *((UInt32 *)data->getBytesNoCopy()); if ((data = OSDynamicCast(OSData, master->getProperty("AAPL,agp-clear")))) agpCommandMask &= ~*((UInt32 *)data->getBytesNoCopy()); if ((data = OSDynamicCast(OSData, master->getProperty("AAPL,agp-set")))) agpCommandSet |= *((UInt32 *)data->getBytesNoCopy()); agpLength = *length; if( !agpLength) agpLength = 32 * 1024 * 1024; agpLength = (agpLength + alignLen) & ~alignLen; err = kIOReturnVMError; do { ppnum_t physPage; gartLength = agpLength / agpBytesPerGartByte; gartHandle = IOMapper::NewARTTable(gartLength, (void **) &gartArray, &physPage); if (!gartHandle) continue; gartPhys = ptoa_64(physPage); // IOMapPages( kernel_map, gartArray, gartPhys, gartLength, kIOMapInhibitCache ); bzero( (void *) gartArray, gartLength); flush_dcache( (vm_offset_t) gartArray, gartLength, false); #if ALLOC_AGP_RANGE IORangeAllocator * platformRanges = getPlatform()->getPhysicalRangeAllocator(); for( agpBaseIndex = 0xf; agpBaseIndex > 0; agpBaseIndex--) { systemBase = agpBaseIndex * 0x10000000; if( platformRanges->allocateRange( systemBase, agpLength )) { systemLength = agpLength; break; } } #else agpBaseIndex = 0; systemBase = 0; systemLength = agpLength; #endif if( !systemLength) continue; agpRange = IORangeAllocator::withRange( agpLength, 4096 ); if( !agpRange) continue; *address = systemBase; *length = systemLength; #if 0 coarseAddressMask |= (1 << agpBaseIndex); configWrite32( target, kMacRISCAddressSelect, (coarseAddressMask << 16) | fineAddressMask ); #endif UInt32 gartBaseExt = 0; if (isU3) gartBaseExt = (gartPhys >> 32); configWrite32( target, kUniNAGP_BASE, (agpBaseIndex << 28) | gartBaseExt ); configWrite32( target, kUniNGART_BASE, (gartPhys & ~PAGE_MASK) | (agpLength / agpSpacePerPage)); err = kIOReturnSuccess; } while( false ); if( kIOReturnSuccess == err) setAGPEnable( master, true, 0 ); else destroyAGPSpace( master ); return( err ); } IOReturn AppleMacRiscAGP::getAGPSpace( IOAGPDevice * master, IOPhysicalAddress * address, IOPhysicalLength * length ) { if( systemLength) { if( address) *address = systemBase; if( length) *length = systemLength; return( kIOReturnSuccess ); } else return( kIOReturnNotReady ); } IOReturn AppleMacRiscAGP::destroyAGPSpace( IOAGPDevice * master ) { setAGPEnable( master, false, 0 ); if( gartHandle) { IOMapper::FreeARTTable(gartHandle, gartLength); gartHandle = 0; gartArray = 0; } if( agpRange) { agpRange->release(); agpRange = 0; } if( systemLength) { #if ALLOC_AGP_RANGE IORangeAllocator * platformRanges = getPlatform()->getPhysicalRangeAllocator(); platformRanges->deallocate( systemBase, systemLength); #endif systemLength = 0; } return( kIOReturnSuccess ); } IORangeAllocator * AppleMacRiscAGP::getAGPRangeAllocator( IOAGPDevice * master ) { // if( agpRange) agpRange->retain(); return( agpRange ); } IOOptionBits AppleMacRiscAGP::getAGPStatus( IOAGPDevice * master, IOOptionBits options ) { IOPCIAddressSpace target = getBridgeSpace(); return( configRead32( target, kUniNINTERNAL_STATUS ) ); } inline void AppleMacRiscAGP::configSetClearMask( IOPCIAddressSpace space, UInt8 offset, UInt32 data, UInt32 mask ) { IOInterruptState ints; ints = IOSimpleLockLockDisableInterrupt( lock ); if( setConfigSpace( space, offset )) { offset = offset & configDataOffsetMask & 4; OSWriteSwapInt32( configData, offset, data | mask ); eieio(); /* read to sync */ (void) OSReadSwapInt32( configData, offset ); eieio(); sync(); isync(); OSWriteSwapInt32( configData, offset, data ); eieio(); /* read to sync */ (void) OSReadSwapInt32( configData, offset ); eieio(); sync(); isync(); } IOSimpleLockUnlockEnableInterrupt( lock, ints ); } IOReturn AppleMacRiscAGP::commitAGPMemory( IOAGPDevice * master, IOMemoryDescriptor * memory, IOByteCount agpOffset, IOOptionBits options ) { IOPCIAddressSpace target = getBridgeSpace(); IOReturn err = kIOReturnSuccess; UInt32 offset = 0; addr64_t phys64; IOByteCount len; IOByteCount agpFlushStart, flushLength; // ok = agpRange->allocate( memory->getLength(), &agpOffset ); assert( agpOffset < systemLength ); agpOffset /= (page_size / 4); agpFlushStart = agpOffset; while( (phys64 = memory->getPhysicalSegment64(offset, &len))) { offset += len; len = (len + PAGE_MASK) & ~PAGE_MASK; while( len > 0) { if (isU3) OSWriteBigInt32( gartArray, agpOffset, (((UInt32)(phys64 >> PAGE_SHIFT)) | 0x80000000)); else OSWriteLittleInt32( gartArray, agpOffset, ((phys64 & ~PAGE_MASK) | 1)); agpOffset += 4; phys64 += page_size; len -= page_size; } } // Just to be paranoid, I want to feed nice happy values to flush_dcache. // I want the start address to be cache line aligned, and I want the size // to be a multiple of cache line size. For now I'm going to assume that // any CPU hooked to an AGP chipset using this driver has a 32-byte cache // line size. Ugh. agpFlushStart &= ~31; // Round down to cache line boundary flushLength = (agpOffset - agpFlushStart); // Round up to 32 bytes, which hopefully is safe since we pushed the start // down to a 32-byte boundary first. flushLength = (flushLength + 31) & ~31; sync(); isync(); flush_dcache( ((vm_offset_t) gartArray)+agpFlushStart, flushLength, false); sync(); isync(); len = OSReadLittleInt32( gartArray, agpOffset - 4 ); sync(); isync(); if (isU32) { configSetClearMask( target, kUniNGART_CTRL, gartCtrl | kGART_EN, kGART_INV ); } else if( kIOAGPGartInvalidate & options) { configSetClearMask( target, kUniNGART_CTRL, gartCtrl | kGART_EN, kGART_INV ); configSetClearMask( target, kUniNGART_CTRL, gartCtrl | kGART_EN, kGART_2xRESET ); } return( err ); } IOReturn AppleMacRiscAGP::releaseAGPMemory( IOAGPDevice * master, IOMemoryDescriptor * memory, IOByteCount agpOffset, IOOptionBits options ) { IOPCIAddressSpace target = getBridgeSpace(); IOReturn err = kIOReturnSuccess; IOByteCount length; IOByteCount agpFlushStart, flushLength; if( !memory) return( kIOReturnBadArgument ); length = memory->getLength(); if( (agpOffset + length) > systemLength) return( kIOReturnBadArgument ); // agpRange->deallocate( agpOffset, length ); length = (length + PAGE_MASK) & ~PAGE_MASK; agpOffset /= page_size; agpFlushStart = agpOffset; while( length > 0) { gartArray[agpOffset++] = 0; length -= page_size; } agpFlushStart *= 4; agpOffset *= 4; agpFlushStart &= ~31; flushLength = (agpOffset - agpFlushStart); // Flush full cache lines // Round up to 32 bytes, which hopefully is safe since we pushed the start // down to a 32-byte boundary first. flushLength = (flushLength + 31) & ~31; sync(); isync(); flush_dcache( ((vm_offset_t) gartArray)+agpFlushStart, flushLength, false); sync(); isync(); length = OSReadLittleInt32( gartArray, agpOffset - 4 ); sync(); isync(); if (isU32) { configSetClearMask( target, kUniNGART_CTRL, gartCtrl | kGART_EN, kGART_INV ); } else if( kIOAGPGartInvalidate & options) { configSetClearMask( target, kUniNGART_CTRL, gartCtrl | kGART_EN, kGART_INV ); configSetClearMask( target, kUniNGART_CTRL, gartCtrl | kGART_EN, kGART_2xRESET ); } return( err ); } IOReturn AppleMacRiscAGP::setAGPEnable( IOAGPDevice * _master, bool enable, IOOptionBits options ) { IOReturn err = kIOReturnSuccess; IOPCIAddressSpace target = getBridgeSpace(); IOPCIAddressSpace master = _master->space; UInt32 command; UInt32 targetStatus, masterStatus; UInt8 masterAGPRegisters = _master->masterAGPRegisters; if( enable) { configWrite32( target, kUniNGART_CTRL, gartCtrl | 0); targetStatus = configRead32( target, targetAGPRegisters + kIOPCIConfigAGPStatusOffset ); masterStatus = configRead32( master, masterAGPRegisters + kIOPCIConfigAGPStatusOffset ); command = kIOAGPSideBandAddresssing | kIOAGP3Mode | kIOAGP4xDataRate | kIOAGP2xDataRate | kIOAGP1xDataRate; // Enable fast-write support for U3 Heavy/Light. if( uniNVersion == 0x34 || uniNVersion == 0x35 || uniNVersion == 0x37 || uniNVersion == 0x38 || uniNVersion == 0x39 ) command |= kIOAGPFastWrite; command &= targetStatus; command &= masterStatus; if (uniNVersion == 0x21) { command &= ~(kIOAGP4xDataRate); IOLog("AGP 4x mode disabled on this machine\n"); } command &= agpCommandMask; command |= agpCommandSet; if (isU32) _master->setProperty("AAPL,agp3-mode", (command & kIOAGP3Mode) ? kOSBooleanTrue : kOSBooleanFalse); if (isU32 && (command & kIOAGP3Mode)) { command &= ~kIOAGP4xDataRate; if( command & kIOAGP8xDataRateMode3) command &= ~kIOAGP4xDataRateMode3; else if( 0 == (command & kIOAGP4xDataRateMode3)) return( kIOReturnUnsupported ); } else { if( command & kIOAGP4xDataRate) command &= ~(kIOAGP2xDataRate | kIOAGP1xDataRate); else { if (isU3) return( kIOReturnUnsupported ); if( command & kIOAGP2xDataRate) command &= ~(kIOAGP1xDataRate); else if( 0 == (command & kIOAGP1xDataRate)) return( kIOReturnUnsupported ); } } command |= kIOAGPEnable; if( targetStatus > masterStatus) targetStatus = masterStatus; if((uniNVersion >= 0x30) && (uniNVersion <= 0x33)) // We neeed to set the REQ_DEPTH to 7 for U3 versions V1.0, V2.1, V2.2 and V2.3. command |= 0x07000000; else command |= (targetStatus & kIOAGPRequestQueueMask); _master->setProperty(kIOAGPCommandValueKey, &command, sizeof(command)); configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_EN ); configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_EN | kGART_INV ); configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_EN ); do { configWrite32( target, targetAGPRegisters + kIOPCIConfigAGPCommandOffset, command ); } while( (command & kIOAGPEnable) != (kIOAGPEnable & configRead32( target, targetAGPRegisters + kIOPCIConfigAGPCommandOffset))); do { configWrite32( master, masterAGPRegisters + kIOPCIConfigAGPCommandOffset, command ); } while( (command & kIOAGPEnable) != (kIOAGPEnable & configRead32( master, masterAGPRegisters + kIOPCIConfigAGPCommandOffset))); #if 0 configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_EN | kGART_INV ); configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_EN ); configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_EN | kGART_2xRESET); configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_EN ); #endif _master->masterState |= kIOAGPStateEnabled; } else { while( 0 == (kIOAGPIdle & configRead32( getBridgeSpace(), kUniNINTERNAL_STATUS ))) {} configWrite32( master, masterAGPRegisters + kIOPCIConfigAGPCommandOffset, 0 ); configWrite32( target, targetAGPRegisters + kIOPCIConfigAGPCommandOffset, 0 ); #if 0 configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_EN | kGART_INV ); configWrite32( target, kUniNGART_CTRL, gartCtrl | 0 ); configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_2xRESET); configWrite32( target, kUniNGART_CTRL, gartCtrl | 0 ); #endif configWrite32( target, kUniNGART_CTRL, gartCtrl | kGART_2xRESET ); _master->masterState &= ~kIOAGPStateEnabled; } return( err ); } IOReturn AppleMacRiscAGP::resetAGPDevice( IOAGPDevice * master, IOOptionBits options ) { IOReturn ret; if( master->masterState & kIOAGPStateEnablePending) { ret = setAGPEnable( master, true, 0 ); master->masterState &= ~kIOAGPStateEnablePending; } else { #if 1 ret = setAGPEnable( master, false, 0 ); ret = setAGPEnable( master, true, 0 ); #endif ret = kIOReturnSuccess; } return( ret ); } IOReturn AppleMacRiscAGP::saveDeviceState( IOPCIDevice * device, IOOptionBits options ) { IOReturn ret; IOAGPDevice * agpDev; UInt32 agpSave[3]; IOPCIAddressSpace target = getBridgeSpace(); if( (agpDev = OSDynamicCast( IOAGPDevice, device))) { if( agpDev->masterState & kIOAGPStateEnabled) setAGPEnable( agpDev, false, 0 ); agpSave[0] = configRead32( target, kUniNAGP_BASE ); agpSave[1] = configRead32( target, kUniNGART_BASE ); agpSave[2] = configRead32( target, targetAGPRegisters + kIOPCIConfigAGPCommandOffset ); } ret = super::saveDeviceState( device, options); if( agpDev && (ret == kIOReturnSuccess)) { agpDev->savedConfig[ 16 ] = agpSave[0]; agpDev->savedConfig[ 17 ] = agpSave[1]; agpDev->savedConfig[ 18 ] = agpSave[2]; } return( ret ); } IOReturn AppleMacRiscAGP::restoreDeviceState( IOPCIDevice * device, IOOptionBits options ) { IOReturn ret; IOAGPDevice * agpDev; UInt32 agpSave[3]; IOPCIAddressSpace target = getBridgeSpace(); agpDev = OSDynamicCast( IOAGPDevice, device); if( agpDev && device->savedConfig) { agpSave[0] = agpDev->savedConfig[ 16 ]; agpSave[1] = agpDev->savedConfig[ 17 ]; agpSave[2] = agpDev->savedConfig[ 18 ]; } ret = super::restoreDeviceState( device, options); if( agpDev && (kIOReturnSuccess == ret)) { configWrite32( target, kUniNAGP_BASE, agpSave[0] ); configWrite32( target, kUniNGART_BASE, agpSave[1] ); // soon, grasshopper if( kIOAGPEnable & agpSave[2]) agpDev->masterState |= kIOAGPStateEnablePending; else agpDev->masterState &= ~kIOAGPStateEnablePending; } return( ret ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */