2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
29 #include <IOKit/system.h>
30 #include <IOKit/IOPlatformExpert.h>
31 #include <IOKit/IOCPU.h>
32 #include <IOKit/IODeviceTreeSupport.h>
33 #include <IOKit/IORangeAllocator.h>
34 #include <IOKit/IONVRAM.h>
35 #include <IOKit/IOKitDebug.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/pwr_mgt/RootDomain.h>
38 #include <IOKit/IOMessage.h>
39 #include <libkern/c++/OSContainers.h>
43 #include <machine/machine_routines.h>
44 #include <pexpert/pexpert.h>
47 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
48 static void getCStringForObject (OSObject
* inObj
, char * outStr
);
50 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
52 #define super IOService
54 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
56 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
58 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 1);
59 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 2);
60 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 3);
61 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 4);
62 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
63 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
64 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
65 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
66 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
67 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
68 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
70 static IOPlatformExpert
* gIOPlatform
;
71 static OSDictionary
* gIOInterruptControllers
;
72 static IOLock
* gIOInterruptControllersLock
;
74 OSSymbol
* gPlatformInterruptControllerName
;
76 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
78 bool IOPlatformExpert::attach( IOService
* provider
)
81 if( !super::attach( provider
))
87 bool IOPlatformExpert::start( IOService
* provider
)
89 IORangeAllocator
* physicalRanges
;
90 OSData
* busFrequency
;
92 if (!super::start(provider
))
95 gIOInterruptControllers
= OSDictionary::withCapacity(1);
96 gIOInterruptControllersLock
= IOLockAlloc();
98 // Correct the bus frequency in the device tree.
99 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
100 provider
->setProperty("clock-frequency", busFrequency
);
101 busFrequency
->release();
103 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
105 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
106 IORangeAllocator::kLocking
);
107 assert(physicalRanges
);
108 setProperty("Platform Memory Ranges", physicalRanges
);
113 PMInstantiatePowerDomains();
115 return( configure(provider
) );
118 bool IOPlatformExpert::configure( IOService
* provider
)
124 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
127 while( (dict
= OSDynamicCast( OSDictionary
,
128 topLevel
->getAnyObject()))) {
130 topLevel
->removeObject( dict
);
131 nub
= createNub( dict
);
136 nub
->registerService();
143 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
147 nub
= new IOPlatformDevice
;
149 if( !nub
->init( from
)) {
157 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
158 OSString
* name
, OSString
** matched
= 0 ) const
160 return( nub
->IORegistryEntry::compareName( name
, matched
));
163 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
165 return( kIOReturnSuccess
);
168 long IOPlatformExpert::getBootROMType(void)
170 return _peBootROMType
;
173 long IOPlatformExpert::getChipSetType(void)
175 return _peChipSetType
;
178 long IOPlatformExpert::getMachineType(void)
180 return _peMachineType
;
183 void IOPlatformExpert::setBootROMType(long peBootROMType
)
185 _peBootROMType
= peBootROMType
;
188 void IOPlatformExpert::setChipSetType(long peChipSetType
)
190 _peChipSetType
= peChipSetType
;
193 void IOPlatformExpert::setMachineType(long peMachineType
)
195 _peMachineType
= peMachineType
;
198 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
203 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
208 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
210 return(OSDynamicCast(IORangeAllocator
,
211 getProperty("Platform Memory Ranges")));
214 int (*PE_halt_restart
)(unsigned int type
) = 0;
216 int IOPlatformExpert::haltRestart(unsigned int type
)
218 if (type
== kPEHangCPU
) while (1);
220 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
224 void IOPlatformExpert::sleepKernel(void)
230 intState
= ml_set_interrupts_enabled(false);
232 for (cnt
= 0; cnt
< 10000; cnt
++) {
236 ml_set_interrupts_enabled(intState
);
238 // PE_initialize_console(0, kPEDisableScreen);
242 // PE_initialize_console(0, kPEEnableScreen);
246 long IOPlatformExpert::getGMTTimeOfDay(void)
251 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
256 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
258 return( PE_current_console( consoleInfo
));
261 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
264 return( PE_initialize_console( consoleInfo
, op
));
267 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
269 IOLockLock(gIOInterruptControllersLock
);
271 gIOInterruptControllers
->setObject(name
, interruptController
);
273 IOLockWakeup(gIOInterruptControllersLock
,
274 gIOInterruptControllers
, /* one-thread */ false);
276 IOLockUnlock(gIOInterruptControllersLock
);
278 return kIOReturnSuccess
;
281 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
285 IOLockLock(gIOInterruptControllersLock
);
288 object
= gIOInterruptControllers
->getObject(name
);
293 IOLockSleep(gIOInterruptControllersLock
,
294 gIOInterruptControllers
, THREAD_UNINT
);
297 IOLockUnlock(gIOInterruptControllersLock
);
298 return OSDynamicCast(IOInterruptController
, object
);
302 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
304 IOCPUInterruptController
*controller
;
306 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
307 if (controller
) controller
->setCPUInterruptProperties(service
);
310 bool IOPlatformExpert::atInterruptLevel(void)
312 return ml_at_interrupt_context();
315 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
321 //*********************************************************************************
324 //*********************************************************************************
326 void IOPlatformExpert::PMLog(const char * who
,unsigned long event
,unsigned long param1
, unsigned long param2
)
328 if( gIOKitDebug
& kIOLogPower
) {
329 kprintf("%s %02d %08x %08x\n",who
,event
,param1
,param2
);
330 // IOLog("%s %02d %08x %08x\n",who,event,param1,param2);
335 //*********************************************************************************
336 // PMInstantiatePowerDomains
338 // In this vanilla implementation, a Root Power Domain is instantiated.
339 // All other objects which register will be children of this Root.
340 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
341 // in a platform-specific subclass.
342 //*********************************************************************************
344 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
346 root
= new IOPMrootDomain
;
354 //*********************************************************************************
357 // In this vanilla implementation, all callers are made children of the root power domain.
358 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
359 //*********************************************************************************
361 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
363 root
->addPowerChild ( theDevice
);
366 //*********************************************************************************
369 //*********************************************************************************
371 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
373 return ((_pePMFeatures
& featureMask
) != 0);
376 //*********************************************************************************
379 //*********************************************************************************
381 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
383 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
386 //*********************************************************************************
387 // numBatteriesSupported
389 //*********************************************************************************
391 int IOPlatformExpert::numBatteriesSupported (void)
393 return (_peNumBatteriesSupported
);
396 //*********************************************************************************
399 // This method is called by the instantiated sublass of the platform expert to
400 // determine how a device should be inserted into the Power Domain. The subclass
401 // provides an XML power tree description against which a device is matched based
402 // on class and provider. If a match is found this routine returns true in addition
403 // to flagging the description tree at the appropriate node that a device has been
404 // registered for the given service.
405 //*********************************************************************************
407 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
410 unsigned int numPowerTreeNodes
;
411 OSDictionary
* entry
;
412 OSDictionary
* matchingDictionary
;
413 OSDictionary
* providerDictionary
;
414 OSDictionary
* deviceDictionary
;
415 OSDictionary
* nubDictionary
;
417 bool nodeFound
= false;
418 bool continueSearch
= false;
419 bool deviceMatch
= false;
420 bool providerMatch
= false;
421 bool multiParentMatch
= false;
423 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
426 numPowerTreeNodes
= inSubTree
->getCount ();
428 // iterate through the power tree to find a home for this device
430 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
432 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
434 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
435 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
437 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
438 if ( matchingDictionary
) {
440 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
441 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
442 deviceDictionary
->release ();
446 providerMatch
= true; // we indicate a match if there is no nub or provider
447 if ( theNub
&& providerDictionary
) {
448 providerMatch
= false;
449 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
450 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
451 nubDictionary
->release ();
455 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
456 if (deviceMatch
&& providerMatch
) {
457 if (NULL
!= multipleParentKeyValue
) {
458 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
459 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
463 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
465 // if the power tree specifies a provider dictionary but theNub is
466 // NULL then we cannot match with this entry.
468 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
471 // if this node is THE ONE...then register the device
474 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
476 if ( kIOLogPower
& gIOKitDebug
)
477 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
479 numInstancesRegistered
++;
481 // determine if we need to search for additional nodes for this item
482 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
488 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
490 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
491 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
492 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
495 if ( false == continueSearch
)
499 return ( nodeFound
);
502 //*********************************************************************************
503 // RegisterServiceInTree
505 // Register a device at the specified node of our power tree.
506 //*********************************************************************************
508 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
510 IOService
* aService
;
511 bool registered
= false;
513 unsigned int numChildren
;
514 OSDictionary
* child
;
516 // make sure someone is not already registered here
518 if ( NULL
== theTreeNode
->getObject ("service") ) {
520 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
522 // 1. CHILDREN ------------------
524 // we registered the node in the tree...now if the node has children
525 // registered we must tell this service to add them.
527 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
528 numChildren
= children
->getCount ();
529 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
530 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
531 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
532 theService
->addPowerChild (aService
);
537 // 2. PARENT --------------------
539 // also we must notify the parent of this node (if a registered service
540 // exists there) of a new child.
542 if ( theTreeParentNode
) {
543 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
544 if (aService
!= theProvider
)
545 aService
->addPowerChild (theService
);
555 //*********************************************************************************
556 // printDictionaryKeys
558 // Print the keys for the given dictionary and selected contents.
559 //*********************************************************************************
560 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
562 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
569 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
573 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
575 // if this is the IOClass key, print it's contents
577 if ( mkey
->isEqualTo ("IOClass") ) {
578 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
579 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
582 // if this is an IOProviderClass key print it
584 if ( mkey
->isEqualTo ("IOProviderClass") ) {
585 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
586 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
590 // also print IONameMatch keys
591 if ( mkey
->isEqualTo ("IONameMatch") ) {
592 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
593 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
596 // also print IONameMatched keys
598 if ( mkey
->isEqualTo ("IONameMatched") ) {
599 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
600 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
606 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
608 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
610 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
616 if ( mkey
->isEqualTo ("name") ) {
619 getCStringForObject (inDictionary
->getObject ("name"), nameStr
);
620 if (strlen(nameStr
) > 0)
621 IOLog ("%s name is %s\n", inMsg
, nameStr
);
624 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
632 static void getCStringForObject (OSObject
* inObj
, char * outStr
)
637 if ( (NULL
== inObj
) || (NULL
== outStr
))
640 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
642 if ((0 == strcmp(objString
,"OSString")) || (0 == strcmp (objString
, "OSSymbol")))
643 strcpy (outStr
, ((OSString
*)inObj
)->getCStringNoCopy());
645 else if (0 == strcmp(objString
,"OSData")) {
646 len
= ((OSData
*)inObj
)->getLength();
647 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
648 if (buffer
&& (len
> 0)) {
649 for (i
=0; i
< len
; i
++) {
650 outStr
[i
] = buffer
[i
];
657 /* IOPMPanicOnShutdownHang
658 * - Called from a timer installed by PEHaltRestart
660 static void IOPMPanicOnShutdownHang(thread_call_param_t p0
, thread_call_param_t p1
)
664 /* 30 seconds has elapsed - resume shutdown */
665 gIOPlatform
->haltRestart(type
);
672 * Callouts from BSD for machine name & model
675 boolean_t
PEGetMachineName( char * name
, int maxLength
)
678 return( gIOPlatform
->getMachineName( name
, maxLength
));
683 boolean_t
PEGetModelName( char * name
, int maxLength
)
686 return( gIOPlatform
->getModelName( name
, maxLength
));
691 int PEGetPlatformEpoch(void)
694 return( gIOPlatform
->getBootROMType());
699 int PEHaltRestart(unsigned int type
)
701 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
702 bool noWaitForResponses
;
703 AbsoluteTime deadline
;
704 thread_call_t shutdown_hang
;
706 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
)
708 /* Notify IOKit PM clients of shutdown/restart
709 Clients subscribe to this message with a call to
710 IOService::registerInterest()
713 /* Spawn a thread that will panic in 30 seconds.
714 If all goes well the machine will be off by the time
717 shutdown_hang
= thread_call_allocate( &IOPMPanicOnShutdownHang
, (thread_call_param_t
) type
);
718 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
719 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
721 noWaitForResponses
= pmRootDomain
->tellChangeDown2(type
);
722 /* This notification should have few clients who all do
723 their work synchronously.
725 In this "shutdown notification" context we don't give
726 drivers the option of working asynchronously and responding
727 later. PM internals make it very hard to wait for asynchronous
728 replies. In fact, it's a bad idea to even be calling
729 tellChangeDown2 from here at all.
733 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
737 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
739 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
743 long PEGetGMTTimeOfDay(void)
746 return( gIOPlatform
->getGMTTimeOfDay());
751 void PESetGMTTimeOfDay(long secs
)
754 gIOPlatform
->setGMTTimeOfDay(secs
);
759 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
761 publishResource("IONVRAM");
764 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
765 bool waitForFunction
,
766 void *param1
, void *param2
,
767 void *param3
, void *param4
)
769 IOService
*service
, *_resources
;
771 if (waitForFunction
) {
772 _resources
= waitForService(resourceMatching(functionName
));
774 _resources
= resources();
776 if (_resources
== 0) return kIOReturnUnsupported
;
778 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
779 if (service
== 0) return kIOReturnUnsupported
;
781 return service
->callPlatformFunction(functionName
, waitForFunction
,
782 param1
, param2
, param3
, param4
);
785 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
790 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
793 #define super IOPlatformExpert
795 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
797 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
798 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
799 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
800 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
801 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
802 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
803 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
804 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
806 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
808 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
811 if( !super::probe( provider
, score
))
814 // check machine types
815 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
821 bool IODTPlatformExpert::configure( IOService
* provider
)
823 if( !super::configure( provider
))
826 processTopLevel( provider
);
831 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
835 nub
= new IOPlatformDevice
;
837 if( !nub
->init( from
, gIODTPlane
)) {
845 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
847 IORegistryEntry
* next
;
852 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
854 if( 0 == (nub
= createNub( next
)))
857 nub
->attach( parent
);
858 nub
->registerService();
866 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* root
)
869 IORegistryEntry
* next
;
870 IORegistryEntry
* cpus
;
871 IORegistryEntry
* options
;
874 kids
= IODTFindMatchingEntries( root
, 0, deleteList() );
876 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
877 next
->detachAll( gIODTPlane
);
882 // Publish an IODTNVRAM class on /options.
883 options
= root
->childFromPath("options", gIODTPlane
);
885 dtNVRAM
= new IODTNVRAM
;
887 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
891 dtNVRAM
->attach(this);
892 dtNVRAM
->registerService();
898 cpus
= root
->childFromPath( "cpus", gIODTPlane
);
900 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
902 // publish top level, minus excludeList
903 createNubs( this, IODTFindMatchingEntries( root
, kIODTExclusive
, excludeList()));
906 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
908 if( nub
->getDeviceMemory())
909 return( kIOReturnSuccess
);
911 IODTResolveAddressing( nub
, "reg", 0);
913 return( kIOReturnSuccess
);
916 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
917 OSString
* name
, OSString
** matched
) const
919 return( IODTCompareNubName( nub
, name
, matched
)
920 || super::compareNubName( nub
, name
, matched
) );
923 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
933 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
935 str
= (const char *) prop
->getBytesNoCopy();
937 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
938 str
+= strlen( "AAPL," );
941 while( (c
= *str
++)) {
942 if( (c
== '/') || (c
== ' '))
946 if( len
>= maxLength
)
956 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
962 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
966 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
971 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
973 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
975 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
977 super::registerNVRAMController(nvram
);
980 int IODTPlatformExpert::haltRestart(unsigned int type
)
982 if (dtNVRAM
) dtNVRAM
->sync();
984 return super::haltRestart(type
);
987 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
990 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
991 else return kIOReturnNotReady
;
994 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
997 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
998 else return kIOReturnNotReady
;
1001 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1002 IORegistryEntry
* entry
,
1003 const OSSymbol
** name
, OSData
** value
)
1005 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1006 else return kIOReturnNotReady
;
1009 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1010 IORegistryEntry
* entry
,
1011 const OSSymbol
* name
, OSData
* value
)
1013 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1014 else return kIOReturnNotReady
;
1017 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1019 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1023 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1024 IOByteCount offset
, UInt8
* buffer
,
1027 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1029 else return kIOReturnNotReady
;
1032 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1033 IOByteCount offset
, UInt8
* buffer
,
1036 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1038 else return kIOReturnNotReady
;
1041 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1043 IOByteCount lengthSaved
= 0;
1045 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1047 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1052 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1055 #define super IOService
1057 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1059 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1060 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1061 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1062 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1064 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1066 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1067 OSString
** matched
= 0 ) const
1069 return( IODTCompareNubName( this, name
, matched
));
1073 IOPlatformExpertDevice::initWithArgs(
1074 void * dtTop
, void * p2
, void * p3
, void * p4
)
1076 IORegistryEntry
* dt
= 0;
1077 void * argsData
[ 4 ];
1080 // dtTop may be zero on non- device tree systems
1081 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1082 ok
= super::init( dt
, gIODTPlane
);
1089 workLoop
= IOWorkLoop::workLoop();
1093 argsData
[ 0 ] = dtTop
;
1098 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1103 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1108 void IOPlatformExpertDevice::free()
1111 workLoop
->release();
1114 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1117 #define super IOService
1119 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1121 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1122 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1123 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1124 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1126 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1128 bool IOPlatformDevice::compareName( OSString
* name
,
1129 OSString
** matched
= 0 ) const
1131 return( ((IOPlatformExpert
*)getProvider())->
1132 compareNubName( this, name
, matched
));
1135 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1140 IOReturn
IOPlatformDevice::getResources( void )
1142 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1145 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1147 /*********************************************************************
1148 * IOPanicPlatform class
1150 * If no legitimate IOPlatformDevice matches, this one does and panics
1151 * the kernel with a suitable message.
1152 *********************************************************************/
1154 class IOPanicPlatform
: IOPlatformExpert
{
1155 OSDeclareDefaultStructors(IOPanicPlatform
);
1158 bool start(IOService
* provider
);
1162 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1165 bool IOPanicPlatform::start(IOService
* provider
) {
1166 const char * platform_name
= "(unknown platform name)";
1168 if (provider
) platform_name
= provider
->getName();
1170 panic("Unable to find driver for this platform: \"%s\".\n",