1/* 2 * Copyright (c) 1998-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. 30 * 31 * HISTORY 32 * 23 Nov 98 sdouglas created. 33 */ 34 35#include <IOKit/system.h> 36extern "C" { 37#include <pexpert/pexpert.h> 38} 39 40#include <libkern/c++/OSContainers.h> 41#include <IOKit/IOLib.h> 42#include <IOKit/IODeviceTreeSupport.h> 43#include <IOKit/IODeviceMemory.h> 44#include <IOKit/IOPlatformExpert.h> 45 46#include <IOKit/pci/IOPCIDevice.h> 47 48#include <IOKit/IOBufferMemoryDescriptor.h> 49 50#include <IOKit/platform/AppleMacIO.h> 51 52#include <IOKit/ppc/IODBDMA.h> 53 54#include <IOKit/assert.h> 55 56/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 57 58#define super IOService 59 60OSDefineMetaClassAndAbstractStructors(AppleMacIO, IOService); 61OSMetaClassDefineReservedUnused(AppleMacIO, 0); 62OSMetaClassDefineReservedUnused(AppleMacIO, 1); 63OSMetaClassDefineReservedUnused(AppleMacIO, 2); 64OSMetaClassDefineReservedUnused(AppleMacIO, 3); 65 66/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 67 68bool AppleMacIO::start( IOService * provider ) 69{ 70 IOPCIDevice *pciNub = (IOPCIDevice *)provider; 71 72 if( !super::start( provider)) 73 return( false); 74 75 // Make sure memory space is on. 76 pciNub->setMemoryEnable(true); 77 78 fNub = provider; 79 fMemory = provider->mapDeviceMemoryWithIndex( 0 ); 80 if( 0 == fMemory) 81 IOLog("%s: unexpected ranges\n", getName()); 82 else if( !selfTest()) 83 IOLog("Warning: AppleMacIO self test fails\n"); 84 PMinit(); // initialize for power management 85 temporaryPowerClampOn(); // hold power on till we get children 86 return( true); 87} 88 89 90IOService * AppleMacIO::createNub( IORegistryEntry * from ) 91{ 92 IOService * nub; 93 94 nub = new AppleMacIODevice; 95 96 if( nub && !nub->init( from, gIODTPlane )) { 97 nub->free(); 98 nub = 0; 99 } 100 101 return( nub); 102} 103 104void AppleMacIO::processNub(IOService * /*nub*/) 105{ 106} 107 108const char * AppleMacIO::deleteList ( void ) 109{ 110 return( "('sd', 'st', 'disk', 'tape', 'pram', 'rtc', 'mouse')" ); 111} 112 113const char * AppleMacIO::excludeList( void ) 114{ 115 return( 0 ); 116} 117 118void AppleMacIO::publishBelow( IORegistryEntry * root ) 119{ 120 OSCollectionIterator * kids; 121 IORegistryEntry * next; 122 IOService * nub; 123 124 // infanticide 125 kids = IODTFindMatchingEntries( root, kIODTRecursive, deleteList() ); 126 if( kids) { 127 while( (next = (IORegistryEntry *)kids->getNextObject())) { 128 next->detachAll( gIODTPlane); 129 } 130 kids->release(); 131 } 132 133 // publish everything below, minus excludeList 134 kids = IODTFindMatchingEntries( root, kIODTRecursive | kIODTExclusive, 135 excludeList()); 136 if( kids) { 137 while( (next = (IORegistryEntry *)kids->getNextObject())) { 138 139 if( 0 == (nub = createNub( next ))) 140 continue; 141 142 nub->attach( this ); 143 144 processNub(nub); 145 146 nub->registerService(); 147 } 148 kids->release(); 149 } 150} 151 152bool AppleMacIO::compareNubName( const IOService * nub, 153 OSString * name, OSString ** matched ) const 154{ 155 return( IODTCompareNubName( nub, name, matched ) 156 || nub->IORegistryEntry::compareName( name, matched ) ); 157} 158 159IOReturn AppleMacIO::getNubResources( IOService * nub ) 160{ 161 if( nub->getDeviceMemory()) 162 return( kIOReturnSuccess ); 163 164 IODTResolveAddressing( nub, "reg", fNub->getDeviceMemoryWithIndex(0) ); 165 166 return( kIOReturnSuccess); 167} 168 169bool AppleMacIO::selfTest( void ) 170{ 171 IODBDMADescriptor *dmaDescriptors; 172 UInt32 dmaDescriptorsPhys; 173 UInt32 i; 174 UInt32 status; 175 IODBDMADescriptor *dmaDesc; 176 IOBufferMemoryDescriptor *buffer; 177 volatile IODBDMAChannelRegisters *ioBaseDMA; 178 bool ok = false; 179 enum { kTestChannel = 0x8000 }; 180 181 ioBaseDMA = (volatile IODBDMAChannelRegisters *) 182 (((UInt32)fMemory->getVirtualAddress()) 183 + kTestChannel ); 184 185 do { 186 buffer = IOBufferMemoryDescriptor::withCapacity(page_size, kIODirectionOutIn, true); 187 dmaDescriptors = (IODBDMADescriptor*)buffer->getBytesNoCopy(); 188 189 if (!dmaDescriptors) 190 continue; 191 192 if ( (UInt32)dmaDescriptors & (page_size - 1) ) { 193 IOLog("AppleMacIO::%s() - DMA Descriptor memory not page aligned!!", __FUNCTION__); 194 continue; 195 } 196 197 bzero( dmaDescriptors, page_size ); 198 199 IODBDMAReset( ioBaseDMA ); 200 201 dmaDesc = dmaDescriptors; 202 203 IOMakeDBDMADescriptor( dmaDesc, 204 kdbdmaNop, 205 kdbdmaKeyStream0, 206 kdbdmaIntNever, 207 kdbdmaBranchNever, 208 kdbdmaWaitNever, 209 0, 210 0 ); 211 212 dmaDesc++; 213 214 dmaDescriptorsPhys = (UInt32) (buffer->getPhysicalSegment(0, NULL, 0)); 215 216 IOMakeDBDMADescriptorDep( dmaDesc, 217 kdbdmaStoreQuad, 218 kdbdmaKeySystem, 219 kdbdmaIntNever, 220 kdbdmaBranchNever, 221 kdbdmaWaitNever, 222 4, 223 dmaDescriptorsPhys+16*sizeof(IODBDMADescriptor), 224 0x12345678 ); 225 226 dmaDesc++; 227 228 IOMakeDBDMADescriptor( dmaDesc, 229 kdbdmaStop, 230 kdbdmaKeyStream0, 231 kdbdmaIntNever, 232 kdbdmaBranchNever, 233 kdbdmaWaitNever, 234 0, 235 0 ); 236 237 238 for ( i = 0; (!ok) && (i < 3); i++ ) 239 { 240 dmaDescriptors[16].operation = 0; 241 242 IOSetDBDMACommandPtr( ioBaseDMA, dmaDescriptorsPhys ); 243 IODBDMAContinue( ioBaseDMA ); 244 245 IODelay( 200 ); 246 247 status = IOGetDBDMAChannelStatus( ioBaseDMA ); 248 249 if ( ((status & kdbdmaActive) == 0) 250 && ((status & kdbdmaDead) == 0) 251 && (OSReadSwapInt32( &dmaDescriptors[16].operation, 0 ) == 0x12345678 )) 252 ok = true; 253 } 254 255 IODBDMAReset( ioBaseDMA ); 256 257 } while (false); 258 259 if (buffer) 260 buffer->release(); 261 262 return ok; 263} 264 265/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 266 267#undef super 268#define super IOService 269 270OSDefineMetaClassAndStructors(AppleMacIODevice, IOService); 271OSMetaClassDefineReservedUnused(AppleMacIODevice, 0); 272OSMetaClassDefineReservedUnused(AppleMacIODevice, 1); 273OSMetaClassDefineReservedUnused(AppleMacIODevice, 2); 274OSMetaClassDefineReservedUnused(AppleMacIODevice, 3); 275 276/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 277 278bool AppleMacIODevice::compareName( OSString * name, 279 OSString ** matched ) const 280{ 281 return (IODTCompareNubName(this, name, matched) || 282 IORegistryEntry::compareName(name, matched)); 283} 284 285IOService * AppleMacIODevice::matchLocation( IOService * /* client */ ) 286{ 287 return this; 288} 289 290IOReturn AppleMacIODevice::getResources( void ) 291{ 292 IOService *macIO = this; 293 294 if (getDeviceMemory() != 0) return kIOReturnSuccess; 295 296 while (macIO && ((macIO = macIO->getProvider()) != 0)) 297 if (strcmp("mac-io", macIO->getName()) == 0) break; 298 299 if (macIO == 0) return kIOReturnError; 300 301 IODTResolveAddressing(this, "reg", macIO->getDeviceMemoryWithIndex(0)); 302 303 return kIOReturnSuccess; 304} 305 306