2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
26 #include <IOKit/system.h>
27 #include <IOKit/IOPlatformExpert.h>
28 #include <IOKit/IOCPU.h>
29 #include <IOKit/IODeviceTreeSupport.h>
30 #include <IOKit/IORangeAllocator.h>
31 #include <IOKit/IONVRAM.h>
32 #include <IOKit/IOKitDebug.h>
33 #include <IOKit/IOWorkLoop.h>
34 #include <IOKit/pwr_mgt/RootDomain.h>
35 #include <IOKit/IOMessage.h>
36 #include <libkern/c++/OSContainers.h>
40 #include <machine/machine_routines.h>
41 #include <pexpert/pexpert.h>
44 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
45 static void getCStringForObject (OSObject
* inObj
, char * outStr
);
47 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49 #define super IOService
51 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
53 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
55 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 1);
56 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 2);
57 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 3);
58 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 4);
59 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
60 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
61 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
62 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
63 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
64 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
65 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
67 static IOPlatformExpert
* gIOPlatform
;
68 static OSDictionary
* gIOInterruptControllers
;
69 static IOLock
* gIOInterruptControllersLock
;
71 OSSymbol
* gPlatformInterruptControllerName
;
73 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
75 bool IOPlatformExpert::attach( IOService
* provider
)
78 if( !super::attach( provider
))
84 bool IOPlatformExpert::start( IOService
* provider
)
86 IORangeAllocator
* physicalRanges
;
87 OSData
* busFrequency
;
89 if (!super::start(provider
))
92 gIOInterruptControllers
= OSDictionary::withCapacity(1);
93 gIOInterruptControllersLock
= IOLockAlloc();
95 // Correct the bus frequency in the device tree.
96 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
97 provider
->setProperty("clock-frequency", busFrequency
);
98 busFrequency
->release();
100 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
102 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
103 IORangeAllocator::kLocking
);
104 assert(physicalRanges
);
105 setProperty("Platform Memory Ranges", physicalRanges
);
110 PMInstantiatePowerDomains();
112 return( configure(provider
) );
115 bool IOPlatformExpert::configure( IOService
* provider
)
121 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
124 while( (dict
= OSDynamicCast( OSDictionary
,
125 topLevel
->getAnyObject()))) {
127 topLevel
->removeObject( dict
);
128 nub
= createNub( dict
);
133 nub
->registerService();
140 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
144 nub
= new IOPlatformDevice
;
146 if( !nub
->init( from
)) {
154 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
155 OSString
* name
, OSString
** matched
= 0 ) const
157 return( nub
->IORegistryEntry::compareName( name
, matched
));
160 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
162 return( kIOReturnSuccess
);
165 long IOPlatformExpert::getBootROMType(void)
167 return _peBootROMType
;
170 long IOPlatformExpert::getChipSetType(void)
172 return _peChipSetType
;
175 long IOPlatformExpert::getMachineType(void)
177 return _peMachineType
;
180 void IOPlatformExpert::setBootROMType(long peBootROMType
)
182 _peBootROMType
= peBootROMType
;
185 void IOPlatformExpert::setChipSetType(long peChipSetType
)
187 _peChipSetType
= peChipSetType
;
190 void IOPlatformExpert::setMachineType(long peMachineType
)
192 _peMachineType
= peMachineType
;
195 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
200 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
205 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
207 return(OSDynamicCast(IORangeAllocator
,
208 getProperty("Platform Memory Ranges")));
211 int (*PE_halt_restart
)(unsigned int type
) = 0;
213 int IOPlatformExpert::haltRestart(unsigned int type
)
215 if (type
== kPEHangCPU
) while (1);
217 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
221 void IOPlatformExpert::sleepKernel(void)
227 intState
= ml_set_interrupts_enabled(false);
229 for (cnt
= 0; cnt
< 10000; cnt
++) {
233 ml_set_interrupts_enabled(intState
);
235 // PE_initialize_console(0, kPEDisableScreen);
239 // PE_initialize_console(0, kPEEnableScreen);
243 long IOPlatformExpert::getGMTTimeOfDay(void)
248 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
253 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
255 return( PE_current_console( consoleInfo
));
258 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
261 return( PE_initialize_console( consoleInfo
, op
));
264 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
266 IOLockLock(gIOInterruptControllersLock
);
268 gIOInterruptControllers
->setObject(name
, interruptController
);
270 IOLockWakeup(gIOInterruptControllersLock
,
271 gIOInterruptControllers
, /* one-thread */ false);
273 IOLockUnlock(gIOInterruptControllersLock
);
275 return kIOReturnSuccess
;
278 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
282 IOLockLock(gIOInterruptControllersLock
);
285 object
= gIOInterruptControllers
->getObject(name
);
290 IOLockSleep(gIOInterruptControllersLock
,
291 gIOInterruptControllers
, THREAD_UNINT
);
294 IOLockUnlock(gIOInterruptControllersLock
);
295 return OSDynamicCast(IOInterruptController
, object
);
299 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
301 IOCPUInterruptController
*controller
;
303 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
304 if (controller
) controller
->setCPUInterruptProperties(service
);
307 bool IOPlatformExpert::atInterruptLevel(void)
309 return ml_at_interrupt_context();
312 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
318 //*********************************************************************************
321 //*********************************************************************************
323 void IOPlatformExpert::PMLog(const char * who
,unsigned long event
,unsigned long param1
, unsigned long param2
)
325 if( gIOKitDebug
& kIOLogPower
) {
326 kprintf("%s %02d %08x %08x\n",who
,event
,param1
,param2
);
327 // IOLog("%s %02d %08x %08x\n",who,event,param1,param2);
332 //*********************************************************************************
333 // PMInstantiatePowerDomains
335 // In this vanilla implementation, a Root Power Domain is instantiated.
336 // All other objects which register will be children of this Root.
337 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
338 // in a platform-specific subclass.
339 //*********************************************************************************
341 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
343 root
= new IOPMrootDomain
;
351 //*********************************************************************************
354 // In this vanilla implementation, all callers are made children of the root power domain.
355 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
356 //*********************************************************************************
358 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
360 root
->addPowerChild ( theDevice
);
363 //*********************************************************************************
366 //*********************************************************************************
368 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
370 return ((_pePMFeatures
& featureMask
) != 0);
373 //*********************************************************************************
376 //*********************************************************************************
378 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
380 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
383 //*********************************************************************************
384 // numBatteriesSupported
386 //*********************************************************************************
388 int IOPlatformExpert::numBatteriesSupported (void)
390 return (_peNumBatteriesSupported
);
393 //*********************************************************************************
396 // This method is called by the instantiated sublass of the platform expert to
397 // determine how a device should be inserted into the Power Domain. The subclass
398 // provides an XML power tree description against which a device is matched based
399 // on class and provider. If a match is found this routine returns true in addition
400 // to flagging the description tree at the appropriate node that a device has been
401 // registered for the given service.
402 //*********************************************************************************
404 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
407 unsigned int numPowerTreeNodes
;
408 OSDictionary
* entry
;
409 OSDictionary
* matchingDictionary
;
410 OSDictionary
* providerDictionary
;
411 OSDictionary
* deviceDictionary
;
412 OSDictionary
* nubDictionary
;
414 bool nodeFound
= false;
415 bool continueSearch
= false;
416 bool deviceMatch
= false;
417 bool providerMatch
= false;
418 bool multiParentMatch
= false;
420 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
423 numPowerTreeNodes
= inSubTree
->getCount ();
425 // iterate through the power tree to find a home for this device
427 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
429 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
431 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
432 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
434 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
435 if ( matchingDictionary
) {
437 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
438 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
439 deviceDictionary
->release ();
443 providerMatch
= true; // we indicate a match if there is no nub or provider
444 if ( theNub
&& providerDictionary
) {
445 providerMatch
= false;
446 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
447 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
448 nubDictionary
->release ();
452 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
453 if (deviceMatch
&& providerMatch
) {
454 if (NULL
!= multipleParentKeyValue
) {
455 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
456 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
460 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
462 // if the power tree specifies a provider dictionary but theNub is
463 // NULL then we cannot match with this entry.
465 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
468 // if this node is THE ONE...then register the device
471 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
473 if ( kIOLogPower
& gIOKitDebug
)
474 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
476 numInstancesRegistered
++;
478 // determine if we need to search for additional nodes for this item
479 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
485 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
487 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
488 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
489 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
492 if ( false == continueSearch
)
496 return ( nodeFound
);
499 //*********************************************************************************
500 // RegisterServiceInTree
502 // Register a device at the specified node of our power tree.
503 //*********************************************************************************
505 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
507 IOService
* aService
;
508 bool registered
= false;
510 unsigned int numChildren
;
511 OSDictionary
* child
;
513 // make sure someone is not already registered here
515 if ( NULL
== theTreeNode
->getObject ("service") ) {
517 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
519 // 1. CHILDREN ------------------
521 // we registered the node in the tree...now if the node has children
522 // registered we must tell this service to add them.
524 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
525 numChildren
= children
->getCount ();
526 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
527 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
528 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
529 theService
->addPowerChild (aService
);
534 // 2. PARENT --------------------
536 // also we must notify the parent of this node (if a registered service
537 // exists there) of a new child.
539 if ( theTreeParentNode
) {
540 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
541 if (aService
!= theProvider
)
542 aService
->addPowerChild (theService
);
552 //*********************************************************************************
553 // printDictionaryKeys
555 // Print the keys for the given dictionary and selected contents.
556 //*********************************************************************************
557 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
559 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
566 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
570 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
572 // if this is the IOClass key, print it's contents
574 if ( mkey
->isEqualTo ("IOClass") ) {
575 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
576 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
579 // if this is an IOProviderClass key print it
581 if ( mkey
->isEqualTo ("IOProviderClass") ) {
582 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
583 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
587 // also print IONameMatch keys
588 if ( mkey
->isEqualTo ("IONameMatch") ) {
589 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
590 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
593 // also print IONameMatched keys
595 if ( mkey
->isEqualTo ("IONameMatched") ) {
596 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
597 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
603 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
605 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
607 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
613 if ( mkey
->isEqualTo ("name") ) {
616 getCStringForObject (inDictionary
->getObject ("name"), nameStr
);
617 if (strlen(nameStr
) > 0)
618 IOLog ("%s name is %s\n", inMsg
, nameStr
);
621 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
629 static void getCStringForObject (OSObject
* inObj
, char * outStr
)
634 if ( (NULL
== inObj
) || (NULL
== outStr
))
637 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
639 if ((0 == strcmp(objString
,"OSString")) || (0 == strcmp (objString
, "OSSymbol")))
640 strcpy (outStr
, ((OSString
*)inObj
)->getCStringNoCopy());
642 else if (0 == strcmp(objString
,"OSData")) {
643 len
= ((OSData
*)inObj
)->getLength();
644 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
645 if (buffer
&& (len
> 0)) {
646 for (i
=0; i
< len
; i
++) {
647 outStr
[i
] = buffer
[i
];
654 /* IOPMPanicOnShutdownHang
655 * - Called from a timer installed by PEHaltRestart
657 static void IOPMPanicOnShutdownHang(thread_call_param_t p0
, thread_call_param_t p1
)
661 /* 30 seconds has elapsed - resume shutdown */
662 gIOPlatform
->haltRestart(type
);
669 * Callouts from BSD for machine name & model
672 boolean_t
PEGetMachineName( char * name
, int maxLength
)
675 return( gIOPlatform
->getMachineName( name
, maxLength
));
680 boolean_t
PEGetModelName( char * name
, int maxLength
)
683 return( gIOPlatform
->getModelName( name
, maxLength
));
688 int PEGetPlatformEpoch(void)
691 return( gIOPlatform
->getBootROMType());
696 int PEHaltRestart(unsigned int type
)
698 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
699 bool noWaitForResponses
;
700 AbsoluteTime deadline
;
701 thread_call_t shutdown_hang
;
703 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
)
705 /* Notify IOKit PM clients of shutdown/restart
706 Clients subscribe to this message with a call to
707 IOService::registerInterest()
710 /* Spawn a thread that will panic in 30 seconds.
711 If all goes well the machine will be off by the time
714 shutdown_hang
= thread_call_allocate( &IOPMPanicOnShutdownHang
, (thread_call_param_t
) type
);
715 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
716 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
718 noWaitForResponses
= pmRootDomain
->tellChangeDown2(type
);
719 /* This notification should have few clients who all do
720 their work synchronously.
722 In this "shutdown notification" context we don't give
723 drivers the option of working asynchronously and responding
724 later. PM internals make it very hard to wait for asynchronous
725 replies. In fact, it's a bad idea to even be calling
726 tellChangeDown2 from here at all.
730 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
734 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
736 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
740 long PEGetGMTTimeOfDay(void)
743 return( gIOPlatform
->getGMTTimeOfDay());
748 void PESetGMTTimeOfDay(long secs
)
751 gIOPlatform
->setGMTTimeOfDay(secs
);
756 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
758 publishResource("IONVRAM");
761 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
762 bool waitForFunction
,
763 void *param1
, void *param2
,
764 void *param3
, void *param4
)
766 IOService
*service
, *_resources
;
768 if (waitForFunction
) {
769 _resources
= waitForService(resourceMatching(functionName
));
771 _resources
= resources();
773 if (_resources
== 0) return kIOReturnUnsupported
;
775 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
776 if (service
== 0) return kIOReturnUnsupported
;
778 return service
->callPlatformFunction(functionName
, waitForFunction
,
779 param1
, param2
, param3
, param4
);
782 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
787 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
790 #define super IOPlatformExpert
792 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
794 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
795 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
796 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
797 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
798 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
799 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
800 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
801 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
803 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
805 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
808 if( !super::probe( provider
, score
))
811 // check machine types
812 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
818 bool IODTPlatformExpert::configure( IOService
* provider
)
820 if( !super::configure( provider
))
823 processTopLevel( provider
);
828 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
832 nub
= new IOPlatformDevice
;
834 if( !nub
->init( from
, gIODTPlane
)) {
842 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
844 IORegistryEntry
* next
;
849 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
851 if( 0 == (nub
= createNub( next
)))
854 nub
->attach( parent
);
855 nub
->registerService();
863 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* root
)
866 IORegistryEntry
* next
;
867 IORegistryEntry
* cpus
;
868 IORegistryEntry
* options
;
871 kids
= IODTFindMatchingEntries( root
, 0, deleteList() );
873 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
874 next
->detachAll( gIODTPlane
);
879 // Publish an IODTNVRAM class on /options.
880 options
= root
->childFromPath("options", gIODTPlane
);
882 dtNVRAM
= new IODTNVRAM
;
884 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
888 dtNVRAM
->attach(this);
889 dtNVRAM
->registerService();
895 cpus
= root
->childFromPath( "cpus", gIODTPlane
);
897 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
899 // publish top level, minus excludeList
900 createNubs( this, IODTFindMatchingEntries( root
, kIODTExclusive
, excludeList()));
903 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
905 if( nub
->getDeviceMemory())
906 return( kIOReturnSuccess
);
908 IODTResolveAddressing( nub
, "reg", 0);
910 return( kIOReturnSuccess
);
913 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
914 OSString
* name
, OSString
** matched
) const
916 return( IODTCompareNubName( nub
, name
, matched
)
917 || super::compareNubName( nub
, name
, matched
) );
920 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
930 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
932 str
= (const char *) prop
->getBytesNoCopy();
934 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
935 str
+= strlen( "AAPL," );
938 while( (c
= *str
++)) {
939 if( (c
== '/') || (c
== ' '))
943 if( len
>= maxLength
)
953 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
959 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
963 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
968 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
970 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
972 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
974 super::registerNVRAMController(nvram
);
977 int IODTPlatformExpert::haltRestart(unsigned int type
)
979 if (dtNVRAM
) dtNVRAM
->sync();
981 return super::haltRestart(type
);
984 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
987 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
988 else return kIOReturnNotReady
;
991 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
994 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
995 else return kIOReturnNotReady
;
998 IOReturn
IODTPlatformExpert::readNVRAMProperty(
999 IORegistryEntry
* entry
,
1000 const OSSymbol
** name
, OSData
** value
)
1002 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1003 else return kIOReturnNotReady
;
1006 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1007 IORegistryEntry
* entry
,
1008 const OSSymbol
* name
, OSData
* value
)
1010 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1011 else return kIOReturnNotReady
;
1014 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1016 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1020 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1021 IOByteCount offset
, UInt8
* buffer
,
1024 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1026 else return kIOReturnNotReady
;
1029 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1030 IOByteCount offset
, UInt8
* buffer
,
1033 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1035 else return kIOReturnNotReady
;
1038 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1040 IOByteCount lengthSaved
= 0;
1042 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1044 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1049 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1052 #define super IOService
1054 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1056 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1057 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1058 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1059 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1061 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1063 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1064 OSString
** matched
= 0 ) const
1066 return( IODTCompareNubName( this, name
, matched
));
1070 IOPlatformExpertDevice::initWithArgs(
1071 void * dtTop
, void * p2
, void * p3
, void * p4
)
1073 IORegistryEntry
* dt
= 0;
1074 void * argsData
[ 4 ];
1077 // dtTop may be zero on non- device tree systems
1078 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1079 ok
= super::init( dt
, gIODTPlane
);
1086 workLoop
= IOWorkLoop::workLoop();
1090 argsData
[ 0 ] = dtTop
;
1095 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1100 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1105 void IOPlatformExpertDevice::free()
1108 workLoop
->release();
1111 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1114 #define super IOService
1116 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1118 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1119 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1120 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1121 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1123 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1125 bool IOPlatformDevice::compareName( OSString
* name
,
1126 OSString
** matched
= 0 ) const
1128 return( ((IOPlatformExpert
*)getProvider())->
1129 compareNubName( this, name
, matched
));
1132 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1137 IOReturn
IOPlatformDevice::getResources( void )
1139 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1142 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1144 /*********************************************************************
1145 * IOPanicPlatform class
1147 * If no legitimate IOPlatformDevice matches, this one does and panics
1148 * the kernel with a suitable message.
1149 *********************************************************************/
1151 class IOPanicPlatform
: IOPlatformExpert
{
1152 OSDeclareDefaultStructors(IOPanicPlatform
);
1155 bool start(IOService
* provider
);
1159 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1162 bool IOPanicPlatform::start(IOService
* provider
) {
1163 const char * platform_name
= "(unknown platform name)";
1165 if (provider
) platform_name
= provider
->getName();
1167 panic("Unable to find driver for this platform: \"%s\".\n",