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/IOCPU.h>
30 #include <IOKit/IODeviceTreeSupport.h>
31 #include <IOKit/IOKitDebug.h>
32 #include <IOKit/IOMapper.h>
33 #include <IOKit/IOMessage.h>
34 #include <IOKit/IONVRAM.h>
35 #include <IOKit/IOPlatformExpert.h>
36 #include <IOKit/IORangeAllocator.h>
37 #include <IOKit/IOWorkLoop.h>
38 #include <IOKit/pwr_mgt/RootDomain.h>
40 #include <IOKit/system.h>
42 #include <libkern/c++/OSContainers.h>
46 #include <machine/machine_routines.h>
47 #include <pexpert/pexpert.h>
50 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
51 static void getCStringForObject (OSObject
* inObj
, char * outStr
);
53 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
55 #define super IOService
57 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
59 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
61 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 1);
62 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 2);
63 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 3);
64 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 4);
65 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
66 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
67 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
68 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
69 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
70 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
71 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
73 static IOPlatformExpert
* gIOPlatform
;
74 static OSDictionary
* gIOInterruptControllers
;
75 static IOLock
* gIOInterruptControllersLock
;
77 OSSymbol
* gPlatformInterruptControllerName
;
79 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
81 bool IOPlatformExpert::attach( IOService
* provider
)
84 if( !super::attach( provider
))
90 bool IOPlatformExpert::start( IOService
* provider
)
92 IORangeAllocator
* physicalRanges
;
93 OSData
* busFrequency
;
95 if (!super::start(provider
))
98 // Register the presence or lack thereof a system
99 // PCI address mapper with the IOMapper class
102 IORegistryEntry
* regEntry
= IORegistryEntry::fromPath("/u3/dart", gIODTPlane
);
104 regEntry
= IORegistryEntry::fromPath("/dart", gIODTPlane
);
107 if (!PE_parse_boot_arg("dart", &debugFlags
) || debugFlags
)
108 setProperty(kIOPlatformMapperPresentKey
, kOSBooleanTrue
);
113 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
115 gIOInterruptControllers
= OSDictionary::withCapacity(1);
116 gIOInterruptControllersLock
= IOLockAlloc();
118 // Correct the bus frequency in the device tree.
119 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
120 provider
->setProperty("clock-frequency", busFrequency
);
121 busFrequency
->release();
123 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
125 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
126 IORangeAllocator::kLocking
);
127 assert(physicalRanges
);
128 setProperty("Platform Memory Ranges", physicalRanges
);
133 PMInstantiatePowerDomains();
135 return( configure(provider
) );
138 bool IOPlatformExpert::configure( IOService
* provider
)
144 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
147 while( (dict
= OSDynamicCast( OSDictionary
,
148 topLevel
->getAnyObject()))) {
150 topLevel
->removeObject( dict
);
151 nub
= createNub( dict
);
156 nub
->registerService();
163 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
167 nub
= new IOPlatformDevice
;
169 if( !nub
->init( from
)) {
177 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
178 OSString
* name
, OSString
** matched
) const
180 return( nub
->IORegistryEntry::compareName( name
, matched
));
183 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
185 return( kIOReturnSuccess
);
188 long IOPlatformExpert::getBootROMType(void)
190 return _peBootROMType
;
193 long IOPlatformExpert::getChipSetType(void)
195 return _peChipSetType
;
198 long IOPlatformExpert::getMachineType(void)
200 return _peMachineType
;
203 void IOPlatformExpert::setBootROMType(long peBootROMType
)
205 _peBootROMType
= peBootROMType
;
208 void IOPlatformExpert::setChipSetType(long peChipSetType
)
210 _peChipSetType
= peChipSetType
;
213 void IOPlatformExpert::setMachineType(long peMachineType
)
215 _peMachineType
= peMachineType
;
218 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
223 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
228 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
230 return(OSDynamicCast(IORangeAllocator
,
231 getProperty("Platform Memory Ranges")));
234 int (*PE_halt_restart
)(unsigned int type
) = 0;
236 int IOPlatformExpert::haltRestart(unsigned int type
)
238 if (type
== kPEHangCPU
) while (1);
240 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
244 void IOPlatformExpert::sleepKernel(void)
250 intState
= ml_set_interrupts_enabled(false);
252 for (cnt
= 0; cnt
< 10000; cnt
++) {
256 ml_set_interrupts_enabled(intState
);
258 // PE_initialize_console(0, kPEDisableScreen);
262 // PE_initialize_console(0, kPEEnableScreen);
266 long IOPlatformExpert::getGMTTimeOfDay(void)
271 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
276 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
278 return( PE_current_console( consoleInfo
));
281 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
284 return( PE_initialize_console( consoleInfo
, op
));
287 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
289 IOLockLock(gIOInterruptControllersLock
);
291 gIOInterruptControllers
->setObject(name
, interruptController
);
293 IOLockWakeup(gIOInterruptControllersLock
,
294 gIOInterruptControllers
, /* one-thread */ false);
296 IOLockUnlock(gIOInterruptControllersLock
);
298 return kIOReturnSuccess
;
301 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
305 IOLockLock(gIOInterruptControllersLock
);
308 object
= gIOInterruptControllers
->getObject(name
);
313 IOLockSleep(gIOInterruptControllersLock
,
314 gIOInterruptControllers
, THREAD_UNINT
);
317 IOLockUnlock(gIOInterruptControllersLock
);
318 return OSDynamicCast(IOInterruptController
, object
);
322 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
324 IOCPUInterruptController
*controller
;
326 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
327 if (controller
) controller
->setCPUInterruptProperties(service
);
330 bool IOPlatformExpert::atInterruptLevel(void)
332 return ml_at_interrupt_context();
335 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
341 //*********************************************************************************
344 //*********************************************************************************
346 void IOPlatformExpert::PMLog(const char * who
,unsigned long event
,unsigned long param1
, unsigned long param2
)
348 if( gIOKitDebug
& kIOLogPower
) {
349 kprintf("%s %02d %08x %08x\n",who
,event
,param1
,param2
);
350 // IOLog("%s %02d %08x %08x\n",who,event,param1,param2);
355 //*********************************************************************************
356 // PMInstantiatePowerDomains
358 // In this vanilla implementation, a Root Power Domain is instantiated.
359 // All other objects which register will be children of this Root.
360 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
361 // in a platform-specific subclass.
362 //*********************************************************************************
364 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
366 root
= new IOPMrootDomain
;
374 //*********************************************************************************
377 // In this vanilla implementation, all callers are made children of the root power domain.
378 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
379 //*********************************************************************************
381 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
383 root
->addPowerChild ( theDevice
);
386 //*********************************************************************************
389 //*********************************************************************************
391 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
393 return ((_pePMFeatures
& featureMask
) != 0);
396 //*********************************************************************************
399 //*********************************************************************************
401 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
403 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
406 //*********************************************************************************
407 // numBatteriesSupported
409 //*********************************************************************************
411 int IOPlatformExpert::numBatteriesSupported (void)
413 return (_peNumBatteriesSupported
);
416 //*********************************************************************************
419 // This method is called by the instantiated sublass of the platform expert to
420 // determine how a device should be inserted into the Power Domain. The subclass
421 // provides an XML power tree description against which a device is matched based
422 // on class and provider. If a match is found this routine returns true in addition
423 // to flagging the description tree at the appropriate node that a device has been
424 // registered for the given service.
425 //*********************************************************************************
427 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
430 unsigned int numPowerTreeNodes
;
431 OSDictionary
* entry
;
432 OSDictionary
* matchingDictionary
;
433 OSDictionary
* providerDictionary
;
434 OSDictionary
* deviceDictionary
;
435 OSDictionary
* nubDictionary
;
437 bool nodeFound
= false;
438 bool continueSearch
= false;
439 bool deviceMatch
= false;
440 bool providerMatch
= false;
441 bool multiParentMatch
= false;
443 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
446 numPowerTreeNodes
= inSubTree
->getCount ();
448 // iterate through the power tree to find a home for this device
450 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
452 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
454 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
455 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
457 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
458 if ( matchingDictionary
) {
460 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
461 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
462 deviceDictionary
->release ();
466 providerMatch
= true; // we indicate a match if there is no nub or provider
467 if ( theNub
&& providerDictionary
) {
468 providerMatch
= false;
469 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
470 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
471 nubDictionary
->release ();
475 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
476 if (deviceMatch
&& providerMatch
) {
477 if (NULL
!= multipleParentKeyValue
) {
478 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
479 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
483 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
485 // if the power tree specifies a provider dictionary but theNub is
486 // NULL then we cannot match with this entry.
488 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
491 // if this node is THE ONE...then register the device
494 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
496 if ( kIOLogPower
& gIOKitDebug
)
497 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
499 numInstancesRegistered
++;
501 // determine if we need to search for additional nodes for this item
502 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
508 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
510 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
511 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
512 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
515 if ( false == continueSearch
)
519 return ( nodeFound
);
522 //*********************************************************************************
523 // RegisterServiceInTree
525 // Register a device at the specified node of our power tree.
526 //*********************************************************************************
528 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
530 IOService
* aService
;
531 bool registered
= false;
533 unsigned int numChildren
;
534 OSDictionary
* child
;
536 // make sure someone is not already registered here
538 if ( NULL
== theTreeNode
->getObject ("service") ) {
540 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
542 // 1. CHILDREN ------------------
544 // we registered the node in the tree...now if the node has children
545 // registered we must tell this service to add them.
547 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
548 numChildren
= children
->getCount ();
549 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
550 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
551 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
552 theService
->addPowerChild (aService
);
557 // 2. PARENT --------------------
559 // also we must notify the parent of this node (if a registered service
560 // exists there) of a new child.
562 if ( theTreeParentNode
) {
563 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
564 if (aService
!= theProvider
)
565 aService
->addPowerChild (theService
);
575 //*********************************************************************************
576 // printDictionaryKeys
578 // Print the keys for the given dictionary and selected contents.
579 //*********************************************************************************
580 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
582 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
589 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
593 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
595 // if this is the IOClass key, print it's contents
597 if ( mkey
->isEqualTo ("IOClass") ) {
598 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
599 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
602 // if this is an IOProviderClass key print it
604 if ( mkey
->isEqualTo ("IOProviderClass") ) {
605 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
606 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
610 // also print IONameMatch keys
611 if ( mkey
->isEqualTo ("IONameMatch") ) {
612 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
613 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
616 // also print IONameMatched keys
618 if ( mkey
->isEqualTo ("IONameMatched") ) {
619 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
620 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
626 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
628 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
630 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
636 if ( mkey
->isEqualTo ("name") ) {
639 getCStringForObject (inDictionary
->getObject ("name"), nameStr
);
640 if (strlen(nameStr
) > 0)
641 IOLog ("%s name is %s\n", inMsg
, nameStr
);
644 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
652 static void getCStringForObject (OSObject
* inObj
, char * outStr
)
657 if ( (NULL
== inObj
) || (NULL
== outStr
))
660 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
662 if ((0 == strcmp(objString
,"OSString")) || (0 == strcmp (objString
, "OSSymbol")))
663 strcpy (outStr
, ((OSString
*)inObj
)->getCStringNoCopy());
665 else if (0 == strcmp(objString
,"OSData")) {
666 len
= ((OSData
*)inObj
)->getLength();
667 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
668 if (buffer
&& (len
> 0)) {
669 for (i
=0; i
< len
; i
++) {
670 outStr
[i
] = buffer
[i
];
677 /* IOPMPanicOnShutdownHang
678 * - Called from a timer installed by PEHaltRestart
680 static void IOPMPanicOnShutdownHang(thread_call_param_t p0
, thread_call_param_t p1
)
684 /* 30 seconds has elapsed - resume shutdown */
685 gIOPlatform
->haltRestart(type
);
692 * Callouts from BSD for machine name & model
695 boolean_t
PEGetMachineName( char * name
, int maxLength
)
698 return( gIOPlatform
->getMachineName( name
, maxLength
));
703 boolean_t
PEGetModelName( char * name
, int maxLength
)
706 return( gIOPlatform
->getModelName( name
, maxLength
));
711 int PEGetPlatformEpoch(void)
714 return( gIOPlatform
->getBootROMType());
719 int PEHaltRestart(unsigned int type
)
721 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
722 bool noWaitForResponses
;
723 AbsoluteTime deadline
;
724 thread_call_t shutdown_hang
;
726 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
)
728 /* Notify IOKit PM clients of shutdown/restart
729 Clients subscribe to this message with a call to
730 IOService::registerInterest()
733 /* Spawn a thread that will panic in 30 seconds.
734 If all goes well the machine will be off by the time
737 shutdown_hang
= thread_call_allocate( &IOPMPanicOnShutdownHang
, (thread_call_param_t
) type
);
738 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
739 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
741 noWaitForResponses
= pmRootDomain
->tellChangeDown2(type
);
742 /* This notification should have few clients who all do
743 their work synchronously.
745 In this "shutdown notification" context we don't give
746 drivers the option of working asynchronously and responding
747 later. PM internals make it very hard to wait for asynchronous
748 replies. In fact, it's a bad idea to even be calling
749 tellChangeDown2 from here at all.
753 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
757 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
759 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
763 long PEGetGMTTimeOfDay(void)
766 return( gIOPlatform
->getGMTTimeOfDay());
771 void PESetGMTTimeOfDay(long secs
)
774 gIOPlatform
->setGMTTimeOfDay(secs
);
779 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
781 publishResource("IONVRAM");
784 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
785 bool waitForFunction
,
786 void *param1
, void *param2
,
787 void *param3
, void *param4
)
789 IOService
*service
, *_resources
;
791 if (waitForFunction
) {
792 _resources
= waitForService(resourceMatching(functionName
));
794 _resources
= resources();
796 if (_resources
== 0) return kIOReturnUnsupported
;
798 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
799 if (service
== 0) return kIOReturnUnsupported
;
801 return service
->callPlatformFunction(functionName
, waitForFunction
,
802 param1
, param2
, param3
, param4
);
805 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
810 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
813 #define super IOPlatformExpert
815 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
817 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
818 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
819 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
820 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
821 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
822 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
823 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
824 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
826 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
828 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
831 if( !super::probe( provider
, score
))
834 // check machine types
835 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
841 bool IODTPlatformExpert::configure( IOService
* provider
)
843 if( !super::configure( provider
))
846 processTopLevel( provider
);
851 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
855 nub
= new IOPlatformDevice
;
857 if( !nub
->init( from
, gIODTPlane
)) {
865 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
867 IORegistryEntry
* next
;
872 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
874 if( 0 == (nub
= createNub( next
)))
877 nub
->attach( parent
);
878 nub
->registerService();
886 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* root
)
889 IORegistryEntry
* next
;
890 IORegistryEntry
* cpus
;
891 IORegistryEntry
* options
;
894 kids
= IODTFindMatchingEntries( root
, 0, deleteList() );
896 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
897 next
->detachAll( gIODTPlane
);
902 // Publish an IODTNVRAM class on /options.
903 options
= root
->childFromPath("options", gIODTPlane
);
905 dtNVRAM
= new IODTNVRAM
;
907 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
911 dtNVRAM
->attach(this);
912 dtNVRAM
->registerService();
918 cpus
= root
->childFromPath( "cpus", gIODTPlane
);
920 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
922 // publish top level, minus excludeList
923 createNubs( this, IODTFindMatchingEntries( root
, kIODTExclusive
, excludeList()));
926 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
928 if( nub
->getDeviceMemory())
929 return( kIOReturnSuccess
);
931 IODTResolveAddressing( nub
, "reg", 0);
933 return( kIOReturnSuccess
);
936 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
937 OSString
* name
, OSString
** matched
) const
939 return( IODTCompareNubName( nub
, name
, matched
)
940 || super::compareNubName( nub
, name
, matched
) );
943 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
953 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
955 str
= (const char *) prop
->getBytesNoCopy();
957 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
958 str
+= strlen( "AAPL," );
961 while( (c
= *str
++)) {
962 if( (c
== '/') || (c
== ' '))
966 if( len
>= maxLength
)
976 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
982 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
986 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
991 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
993 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
995 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
997 super::registerNVRAMController(nvram
);
1000 int IODTPlatformExpert::haltRestart(unsigned int type
)
1002 if (dtNVRAM
) dtNVRAM
->sync();
1004 return super::haltRestart(type
);
1007 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1010 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1011 else return kIOReturnNotReady
;
1014 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1017 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1018 else return kIOReturnNotReady
;
1021 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1022 IORegistryEntry
* entry
,
1023 const OSSymbol
** name
, OSData
** value
)
1025 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1026 else return kIOReturnNotReady
;
1029 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1030 IORegistryEntry
* entry
,
1031 const OSSymbol
* name
, OSData
* value
)
1033 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1034 else return kIOReturnNotReady
;
1037 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1039 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1043 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1044 IOByteCount offset
, UInt8
* buffer
,
1047 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1049 else return kIOReturnNotReady
;
1052 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1053 IOByteCount offset
, UInt8
* buffer
,
1056 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1058 else return kIOReturnNotReady
;
1061 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1063 IOByteCount lengthSaved
= 0;
1065 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1067 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1072 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1075 #define super IOService
1077 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1079 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1080 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1081 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1082 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1084 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1086 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1087 OSString
** matched
) const
1089 return( IODTCompareNubName( this, name
, matched
));
1093 IOPlatformExpertDevice::initWithArgs(
1094 void * dtTop
, void * p2
, void * p3
, void * p4
)
1096 IORegistryEntry
* dt
= 0;
1097 void * argsData
[ 4 ];
1100 // dtTop may be zero on non- device tree systems
1101 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1102 ok
= super::init( dt
, gIODTPlane
);
1109 workLoop
= IOWorkLoop::workLoop();
1113 argsData
[ 0 ] = dtTop
;
1118 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1123 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1128 void IOPlatformExpertDevice::free()
1131 workLoop
->release();
1134 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1137 #define super IOService
1139 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1141 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1142 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1143 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1144 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1146 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1148 bool IOPlatformDevice::compareName( OSString
* name
,
1149 OSString
** matched
) const
1151 return( ((IOPlatformExpert
*)getProvider())->
1152 compareNubName( this, name
, matched
));
1155 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1160 IOReturn
IOPlatformDevice::getResources( void )
1162 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1165 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1167 /*********************************************************************
1168 * IOPanicPlatform class
1170 * If no legitimate IOPlatformDevice matches, this one does and panics
1171 * the kernel with a suitable message.
1172 *********************************************************************/
1174 class IOPanicPlatform
: IOPlatformExpert
{
1175 OSDeclareDefaultStructors(IOPanicPlatform
);
1178 bool start(IOService
* provider
);
1182 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1185 bool IOPanicPlatform::start(IOService
* provider
) {
1186 const char * platform_name
= "(unknown platform name)";
1188 if (provider
) platform_name
= provider
->getName();
1190 panic("Unable to find driver for this platform: \"%s\".\n",