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 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 0);
54 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 1);
55 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 2);
56 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 3);
57 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 4);
58 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
59 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
60 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
61 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
62 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
63 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
64 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
66 static IOPlatformExpert
* gIOPlatform
;
67 static OSDictionary
* gIOInterruptControllers
;
68 static IOLock
* gIOInterruptControllersLock
;
70 OSSymbol
* gPlatformInterruptControllerName
;
72 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
74 bool IOPlatformExpert::attach( IOService
* provider
)
77 if( !super::attach( provider
))
83 bool IOPlatformExpert::start( IOService
* provider
)
85 IORangeAllocator
* physicalRanges
;
86 OSData
* busFrequency
;
88 if (!super::start(provider
))
91 gIOInterruptControllers
= OSDictionary::withCapacity(1);
92 gIOInterruptControllersLock
= IOLockAlloc();
94 // Correct the bus frequency in the device tree.
95 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
96 provider
->setProperty("clock-frequency", busFrequency
);
97 busFrequency
->release();
99 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
101 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
102 IORangeAllocator::kLocking
);
103 assert(physicalRanges
);
104 setProperty("Platform Memory Ranges", physicalRanges
);
109 PMInstantiatePowerDomains();
111 return( configure(provider
) );
114 bool IOPlatformExpert::configure( IOService
* provider
)
120 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
123 while( (dict
= OSDynamicCast( OSDictionary
,
124 topLevel
->getAnyObject()))) {
126 topLevel
->removeObject( dict
);
127 nub
= createNub( dict
);
132 nub
->registerService();
139 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
143 nub
= new IOPlatformDevice
;
145 if( !nub
->init( from
)) {
153 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
154 OSString
* name
, OSString
** matched
= 0 ) const
156 return( nub
->IORegistryEntry::compareName( name
, matched
));
159 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
161 return( kIOReturnSuccess
);
164 long IOPlatformExpert::getBootROMType(void)
166 return _peBootROMType
;
169 long IOPlatformExpert::getChipSetType(void)
171 return _peChipSetType
;
174 long IOPlatformExpert::getMachineType(void)
176 return _peMachineType
;
179 void IOPlatformExpert::setBootROMType(long peBootROMType
)
181 _peBootROMType
= peBootROMType
;
184 void IOPlatformExpert::setChipSetType(long peChipSetType
)
186 _peChipSetType
= peChipSetType
;
189 void IOPlatformExpert::setMachineType(long peMachineType
)
191 _peMachineType
= peMachineType
;
194 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
199 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
204 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
206 return(OSDynamicCast(IORangeAllocator
,
207 getProperty("Platform Memory Ranges")));
210 int (*PE_halt_restart
)(unsigned int type
) = 0;
212 int IOPlatformExpert::haltRestart(unsigned int type
)
214 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
218 void IOPlatformExpert::sleepKernel(void)
224 intState
= ml_set_interrupts_enabled(false);
226 for (cnt
= 0; cnt
< 10000; cnt
++) {
230 ml_set_interrupts_enabled(intState
);
232 // PE_initialize_console(0, kPEDisableScreen);
236 // PE_initialize_console(0, kPEEnableScreen);
240 long IOPlatformExpert::getGMTTimeOfDay(void)
245 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
250 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
252 return( PE_current_console( consoleInfo
));
255 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
258 return( PE_initialize_console( consoleInfo
, op
));
261 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
263 IOLockLock(gIOInterruptControllersLock
);
265 gIOInterruptControllers
->setObject(name
, interruptController
);
267 thread_wakeup(gIOInterruptControllers
);
269 IOLockUnlock(gIOInterruptControllersLock
);
271 return kIOReturnSuccess
;
274 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
279 IOLockLock(gIOInterruptControllersLock
);
281 object
= gIOInterruptControllers
->getObject(name
);
283 if (object
== 0) assert_wait(gIOInterruptControllers
, THREAD_UNINT
);
285 IOLockUnlock(gIOInterruptControllersLock
);
287 if (object
!= 0) break;
292 return OSDynamicCast(IOInterruptController
, object
);
296 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
298 IOCPUInterruptController
*controller
;
300 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
301 if (controller
) controller
->setCPUInterruptProperties(service
);
304 bool IOPlatformExpert::atInterruptLevel(void)
306 return ml_at_interrupt_context();
309 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
315 //*********************************************************************************
318 //*********************************************************************************
320 void IOPlatformExpert::PMLog(const char * who
,unsigned long event
,unsigned long param1
, unsigned long param2
)
322 if( gIOKitDebug
& kIOLogPower
) {
323 kprintf("%s %02d %08x %08x\n",who
,event
,param1
,param2
);
324 // IOLog("%s %02d %08x %08x\n",who,event,param1,param2);
329 //*********************************************************************************
330 // PMInstantiatePowerDomains
332 // In this vanilla implementation, a Root Power Domain is instantiated.
333 // All other objects which register will be children of this Root.
334 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
335 // in a platform-specific subclass.
336 //*********************************************************************************
338 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
340 root
= new IOPMrootDomain
;
348 //*********************************************************************************
351 // In this vanilla implementation, all callers are made children of the root power domain.
352 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
353 //*********************************************************************************
355 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
357 root
->addPowerChild ( theDevice
);
360 //*********************************************************************************
363 //*********************************************************************************
365 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
367 return ((_pePMFeatures
& featureMask
) != 0);
370 //*********************************************************************************
373 //*********************************************************************************
375 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
377 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
380 //*********************************************************************************
381 // numBatteriesSupported
383 //*********************************************************************************
385 int IOPlatformExpert::numBatteriesSupported (void)
387 return (_peNumBatteriesSupported
);
390 //*********************************************************************************
393 // This method is called by the instantiated sublass of the platform expert to
394 // determine how a device should be inserted into the Power Domain. The subclass
395 // provides an XML power tree description against which a device is matched based
396 // on class and provider. If a match is found this routine returns true in addition
397 // to flagging the description tree at the appropriate node that a device has been
398 // registered for the given service.
399 //*********************************************************************************
401 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
404 unsigned int numPowerTreeNodes
;
405 OSDictionary
* entry
;
406 OSDictionary
* matchingDictionary
;
407 OSDictionary
* providerDictionary
;
408 OSDictionary
* deviceDictionary
;
409 OSDictionary
* nubDictionary
;
411 bool nodeFound
= false;
412 bool continueSearch
= false;
413 bool deviceMatch
= false;
414 bool providerMatch
= false;
415 bool multiParentMatch
= false;
417 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
420 numPowerTreeNodes
= inSubTree
->getCount ();
422 // iterate through the power tree to find a home for this device
424 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
426 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
428 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
429 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
431 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
432 if ( matchingDictionary
) {
434 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
435 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
436 deviceDictionary
->release ();
440 providerMatch
= true; // we indicate a match if there is no nub or provider
441 if ( theNub
&& providerDictionary
) {
442 providerMatch
= false;
443 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
444 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
445 nubDictionary
->release ();
449 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
450 if (deviceMatch
&& providerMatch
) {
451 if (NULL
!= multipleParentKeyValue
) {
452 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
453 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
457 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
459 // if the power tree specifies a provider dictionary but theNub is
460 // NULL then we cannot match with this entry.
462 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
465 // if this node is THE ONE...then register the device
468 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
470 if ( kIOLogPower
& gIOKitDebug
)
471 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
473 numInstancesRegistered
++;
475 // determine if we need to search for additional nodes for this item
476 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
482 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
484 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
485 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
486 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
489 if ( false == continueSearch
)
493 return ( nodeFound
);
496 //*********************************************************************************
497 // RegisterServiceInTree
499 // Register a device at the specified node of our power tree.
500 //*********************************************************************************
502 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
504 IOService
* aService
;
505 bool registered
= false;
507 unsigned int numChildren
;
508 OSDictionary
* child
;
510 // make sure someone is not already registered here
512 if ( NULL
== theTreeNode
->getObject ("service") ) {
514 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
516 // 1. CHILDREN ------------------
518 // we registered the node in the tree...now if the node has children
519 // registered we must tell this service to add them.
521 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
522 numChildren
= children
->getCount ();
523 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
524 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
525 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
526 theService
->addPowerChild (aService
);
531 // 2. PARENT --------------------
533 // also we must notify the parent of this node (if a registered service
534 // exists there) of a new child.
536 if ( theTreeParentNode
) {
537 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
538 if (aService
!= theProvider
)
539 aService
->addPowerChild (theService
);
549 //*********************************************************************************
550 // printDictionaryKeys
552 // Print the keys for the given dictionary and selected contents.
553 //*********************************************************************************
554 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
556 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
563 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
567 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
569 // if this is the IOClass key, print it's contents
571 if ( mkey
->isEqualTo ("IOClass") ) {
572 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
573 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
576 // if this is an IOProviderClass key print it
578 if ( mkey
->isEqualTo ("IOProviderClass") ) {
579 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
580 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
584 // also print IONameMatch keys
585 if ( mkey
->isEqualTo ("IONameMatch") ) {
586 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
587 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
590 // also print IONameMatched keys
592 if ( mkey
->isEqualTo ("IONameMatched") ) {
593 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
594 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
600 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
602 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
604 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
610 if ( mkey
->isEqualTo ("name") ) {
613 getCStringForObject (inDictionary
->getObject ("name"), nameStr
);
614 if (strlen(nameStr
) > 0)
615 IOLog ("%s name is %s\n", inMsg
, nameStr
);
618 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
626 static void getCStringForObject (OSObject
* inObj
, char * outStr
)
631 if ( (NULL
== inObj
) || (NULL
== outStr
))
634 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
636 if ((0 == strcmp(objString
,"OSString")) || (0 == strcmp (objString
, "OSSymbol")))
637 strcpy (outStr
, ((OSString
*)inObj
)->getCStringNoCopy());
639 else if (0 == strcmp(objString
,"OSData")) {
640 len
= ((OSData
*)inObj
)->getLength();
641 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
642 if (buffer
&& (len
> 0)) {
643 for (i
=0; i
< len
; i
++) {
644 outStr
[i
] = buffer
[i
];
651 /* IOPMPanicOnShutdownHang
652 * - Called from a timer installed by PEHaltRestart
654 static void IOPMPanicOnShutdownHang(thread_call_param_t p0
, thread_call_param_t p1
)
658 /* 30 seconds has elapsed - resume shutdown */
659 gIOPlatform
->haltRestart(type
);
666 * Callouts from BSD for machine name & model
669 boolean_t
PEGetMachineName( char * name
, int maxLength
)
672 return( gIOPlatform
->getMachineName( name
, maxLength
));
677 boolean_t
PEGetModelName( char * name
, int maxLength
)
680 return( gIOPlatform
->getModelName( name
, maxLength
));
685 int PEGetPlatformEpoch(void)
688 return( gIOPlatform
->getBootROMType());
693 int PEHaltRestart(unsigned int type
)
695 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
696 bool noWaitForResponses
;
697 AbsoluteTime deadline
;
698 thread_call_t shutdown_hang
;
700 /* Notify IOKit PM clients of shutdown/restart
701 Clients subscribe to this message with a call to
702 IOService::registerInterest()
705 /* Spawn a thread that will panic in 30 seconds.
706 If all goes well the machine will be off by the time
709 shutdown_hang
= thread_call_allocate( &IOPMPanicOnShutdownHang
, (thread_call_param_t
) type
);
710 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
711 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
713 noWaitForResponses
= pmRootDomain
->tellChangeDown2(type
);
714 /* This notification should have few clients who all do
715 their work synchronously.
717 In this "shutdown notification" context we don't give
718 drivers the option of working asynchronously and responding
719 later. PM internals make it very hard to wait for asynchronous
720 replies. In fact, it's a bad idea to even be calling
721 tellChangeDown2 from here at all.
724 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
728 long PEGetGMTTimeOfDay(void)
731 return( gIOPlatform
->getGMTTimeOfDay());
736 void PESetGMTTimeOfDay(long secs
)
739 gIOPlatform
->setGMTTimeOfDay(secs
);
744 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
746 publishResource("IONVRAM");
749 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
750 bool waitForFunction
,
751 void *param1
, void *param2
,
752 void *param3
, void *param4
)
754 IOService
*service
, *_resources
;
756 if (waitForFunction
) {
757 _resources
= waitForService(resourceMatching(functionName
));
759 _resources
= resources();
761 if (_resources
== 0) return kIOReturnUnsupported
;
763 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
764 if (service
== 0) return kIOReturnUnsupported
;
766 return service
->callPlatformFunction(functionName
, waitForFunction
,
767 param1
, param2
, param3
, param4
);
771 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
774 #define super IOPlatformExpert
776 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
778 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
779 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
780 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
781 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
782 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
783 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
784 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
785 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
787 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
789 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
792 if( !super::probe( provider
, score
))
795 // check machine types
796 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
802 bool IODTPlatformExpert::configure( IOService
* provider
)
804 if( !super::configure( provider
))
807 processTopLevel( provider
);
812 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
816 nub
= new IOPlatformDevice
;
818 if( !nub
->init( from
, gIODTPlane
)) {
826 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
828 IORegistryEntry
* next
;
833 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
835 if( 0 == (nub
= createNub( next
)))
838 nub
->attach( parent
);
839 nub
->registerService();
847 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* root
)
850 IORegistryEntry
* next
;
851 IORegistryEntry
* cpus
;
852 IORegistryEntry
* options
;
855 kids
= IODTFindMatchingEntries( root
, 0, deleteList() );
857 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
858 next
->detachAll( gIODTPlane
);
863 // Publish an IODTNVRAM class on /options.
864 options
= root
->childFromPath("options", gIODTPlane
);
866 dtNVRAM
= new IODTNVRAM
;
868 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
872 dtNVRAM
->attach(this);
873 dtNVRAM
->registerService();
879 cpus
= root
->childFromPath( "cpus", gIODTPlane
);
881 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
883 // publish top level, minus excludeList
884 createNubs( this, IODTFindMatchingEntries( root
, kIODTExclusive
, excludeList()));
887 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
889 if( nub
->getDeviceMemory())
890 return( kIOReturnSuccess
);
892 IODTResolveAddressing( nub
, "reg", 0);
894 return( kIOReturnSuccess
);
897 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
898 OSString
* name
, OSString
** matched
) const
900 return( IODTCompareNubName( nub
, name
, matched
)
901 || super::compareNubName( nub
, name
, matched
) );
904 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
914 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
916 str
= (const char *) prop
->getBytesNoCopy();
918 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
919 str
+= strlen( "AAPL," );
922 while( (c
= *str
++)) {
923 if( (c
== '/') || (c
== ' '))
927 if( len
>= maxLength
)
937 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
943 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
947 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
952 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
954 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
956 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
958 super::registerNVRAMController(nvram
);
961 int IODTPlatformExpert::haltRestart(unsigned int type
)
963 if (dtNVRAM
) dtNVRAM
->sync();
965 return super::haltRestart(type
);
968 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
971 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
972 else return kIOReturnNotReady
;
975 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
978 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
979 else return kIOReturnNotReady
;
982 IOReturn
IODTPlatformExpert::readNVRAMProperty(
983 IORegistryEntry
* entry
,
984 const OSSymbol
** name
, OSData
** value
)
986 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
987 else return kIOReturnNotReady
;
990 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
991 IORegistryEntry
* entry
,
992 const OSSymbol
* name
, OSData
* value
)
994 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
995 else return kIOReturnNotReady
;
998 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1001 #define super IOService
1003 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1005 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1006 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1007 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1008 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1010 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1012 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1013 OSString
** matched
= 0 ) const
1015 return( IODTCompareNubName( this, name
, matched
));
1019 IOPlatformExpertDevice::initWithArgs(
1020 void * dtTop
, void * p2
, void * p3
, void * p4
)
1022 IORegistryEntry
* dt
= 0;
1023 void * argsData
[ 4 ];
1026 // dtTop may be zero on non- device tree systems
1027 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1028 ok
= super::init( dt
, gIODTPlane
);
1035 workLoop
= IOWorkLoop::workLoop();
1039 argsData
[ 0 ] = dtTop
;
1044 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1049 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1054 void IOPlatformExpertDevice::free()
1057 workLoop
->release();
1060 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1063 #define super IOService
1065 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1067 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1068 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1069 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1070 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1072 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1074 bool IOPlatformDevice::compareName( OSString
* name
,
1075 OSString
** matched
= 0 ) const
1077 return( ((IOPlatformExpert
*)getProvider())->
1078 compareNubName( this, name
, matched
));
1081 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1086 IOReturn
IOPlatformDevice::getResources( void )
1088 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1091 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1093 /*********************************************************************
1094 * IOPanicPlatform class
1096 * If no legitimate IOPlatformDevice matches, this one does and panics
1097 * the kernel with a suitable message.
1098 *********************************************************************/
1100 class IOPanicPlatform
: IOPlatformExpert
{
1101 OSDeclareDefaultStructors(IOPanicPlatform
);
1104 bool start(IOService
* provider
);
1108 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1111 bool IOPanicPlatform::start(IOService
* provider
) {
1112 const char * platform_name
= "(unknown platform name)";
1114 if (provider
) platform_name
= provider
->getName();
1116 panic("Unable to find driver for this platform: \"%s\".\n",