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/IOCPU.h>
27 #include <IOKit/IODeviceTreeSupport.h>
28 #include <IOKit/IOKitDebug.h>
29 #include <IOKit/IOMapper.h>
30 #include <IOKit/IOMessage.h>
31 #include <IOKit/IONVRAM.h>
32 #include <IOKit/IOPlatformExpert.h>
33 #include <IOKit/IORangeAllocator.h>
34 #include <IOKit/IOWorkLoop.h>
35 #include <IOKit/pwr_mgt/RootDomain.h>
36 #include <IOKit/IOKitKeys.h>
37 #include <IOKit/IOTimeStamp.h>
39 #include <IOKit/system.h>
41 #include <libkern/c++/OSContainers.h>
44 #include <machine/machine_routines.h>
45 #include <pexpert/pexpert.h>
48 /* Delay period for UPS halt */
49 #define kUPSDelayHaltCPU_msec (1000*60*5)
51 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
52 static void getCStringForObject (OSObject
* inObj
, char * outStr
);
54 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
56 #define super IOService
58 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
60 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
62 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
63 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 2);
64 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 3);
65 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 4);
66 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
67 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
68 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
69 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
70 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
71 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
72 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
74 static IOPlatformExpert
* gIOPlatform
;
75 static OSDictionary
* gIOInterruptControllers
;
76 static IOLock
* gIOInterruptControllersLock
;
78 OSSymbol
* gPlatformInterruptControllerName
;
80 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
82 bool IOPlatformExpert::attach( IOService
* provider
)
85 if( !super::attach( provider
))
91 bool IOPlatformExpert::start( IOService
* provider
)
93 IORangeAllocator
* physicalRanges
;
94 OSData
* busFrequency
;
97 if (!super::start(provider
))
100 // Override the mapper present flag is requested by boot arguments.
101 if (PE_parse_boot_arg("dart", &debugFlags
) && (debugFlags
== 0))
102 removeProperty(kIOPlatformMapperPresentKey
);
104 // Register the presence or lack thereof a system
105 // PCI address mapper with the IOMapper class
106 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
108 gIOInterruptControllers
= OSDictionary::withCapacity(1);
109 gIOInterruptControllersLock
= IOLockAlloc();
111 // Correct the bus frequency in the device tree.
112 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
113 provider
->setProperty("clock-frequency", busFrequency
);
114 busFrequency
->release();
116 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
118 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
119 IORangeAllocator::kLocking
);
120 assert(physicalRanges
);
121 setProperty("Platform Memory Ranges", physicalRanges
);
126 PMInstantiatePowerDomains();
128 // Parse the serial-number data and publish a user-readable string
129 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
130 if (mydata
!= NULL
) {
131 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
132 if (serNoString
!= NULL
) {
133 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
134 serNoString
->release();
138 return( configure(provider
) );
141 bool IOPlatformExpert::configure( IOService
* provider
)
147 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
150 while( (dict
= OSDynamicCast( OSDictionary
,
151 topLevel
->getAnyObject()))) {
153 topLevel
->removeObject( dict
);
154 nub
= createNub( dict
);
159 nub
->registerService();
166 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
170 nub
= new IOPlatformDevice
;
172 if( !nub
->init( from
)) {
180 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
181 OSString
* name
, OSString
** matched
) const
183 return( nub
->IORegistryEntry::compareName( name
, matched
));
186 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
188 return( kIOReturnSuccess
);
191 long IOPlatformExpert::getBootROMType(void)
193 return _peBootROMType
;
196 long IOPlatformExpert::getChipSetType(void)
198 return _peChipSetType
;
201 long IOPlatformExpert::getMachineType(void)
203 return _peMachineType
;
206 void IOPlatformExpert::setBootROMType(long peBootROMType
)
208 _peBootROMType
= peBootROMType
;
211 void IOPlatformExpert::setChipSetType(long peChipSetType
)
213 _peChipSetType
= peChipSetType
;
216 void IOPlatformExpert::setMachineType(long peMachineType
)
218 _peMachineType
= peMachineType
;
221 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
226 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
231 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
236 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
238 return(OSDynamicCast(IORangeAllocator
,
239 getProperty("Platform Memory Ranges")));
242 int (*PE_halt_restart
)(unsigned int type
) = 0;
244 int IOPlatformExpert::haltRestart(unsigned int type
)
246 if (type
== kPEHangCPU
) while (1);
248 if (type
== kPEUPSDelayHaltCPU
) {
249 // Stall shutdown for 5 minutes, and if no outside force has
250 // removed our power at that point, proceed with a reboot.
251 IOSleep( kUPSDelayHaltCPU_msec
);
253 // Ideally we never reach this point.
255 type
= kPERestartCPU
;
258 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
262 void IOPlatformExpert::sleepKernel(void)
268 intState
= ml_set_interrupts_enabled(false);
270 for (cnt
= 0; cnt
< 10000; cnt
++) {
274 ml_set_interrupts_enabled(intState
);
276 // PE_initialize_console(0, kPEDisableScreen);
280 // PE_initialize_console(0, kPEEnableScreen);
284 long IOPlatformExpert::getGMTTimeOfDay(void)
289 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
294 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
296 return( PE_current_console( consoleInfo
));
299 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
302 return( PE_initialize_console( consoleInfo
, op
));
305 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
307 IOLockLock(gIOInterruptControllersLock
);
309 gIOInterruptControllers
->setObject(name
, interruptController
);
311 IOLockWakeup(gIOInterruptControllersLock
,
312 gIOInterruptControllers
, /* one-thread */ false);
314 IOLockUnlock(gIOInterruptControllersLock
);
316 return kIOReturnSuccess
;
319 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
323 IOLockLock(gIOInterruptControllersLock
);
326 object
= gIOInterruptControllers
->getObject(name
);
331 IOLockSleep(gIOInterruptControllersLock
,
332 gIOInterruptControllers
, THREAD_UNINT
);
335 IOLockUnlock(gIOInterruptControllersLock
);
336 return OSDynamicCast(IOInterruptController
, object
);
340 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
342 IOCPUInterruptController
*controller
;
344 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
345 if (controller
) controller
->setCPUInterruptProperties(service
);
348 bool IOPlatformExpert::atInterruptLevel(void)
350 return ml_at_interrupt_context();
353 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
359 //*********************************************************************************
362 //*********************************************************************************
364 void IOPlatformExpert::
365 PMLog(const char *who
, unsigned long event
,
366 unsigned long param1
, unsigned long param2
)
368 UInt32 debugFlags
= gIOKitDebug
;
370 if (debugFlags
& kIOLogPower
) {
372 uint32_t nows
, nowus
;
373 clock_get_system_microtime(&nows
, &nowus
);
374 nowus
+= (nows
% 1000) * 1000000;
376 kprintf("pm%u %x %.30s %d %x %x\n",
377 nowus
, (unsigned) current_thread(), who
, // Identity
378 (int) event
, param1
, param2
); // Args
380 if (debugFlags
& kIOLogTracePower
) {
381 static const UInt32 sStartStopBitField
[] =
382 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
384 // Arcane formula from Hacker's Delight by Warren
385 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
386 UInt32 sgnevent
= ((long) event
>> 31);
387 UInt32 absevent
= sgnevent
^ (event
+ sgnevent
);
388 UInt32 code
= IODBG_POWER(absevent
);
390 UInt32 bit
= 1 << (absevent
& 0x1f);
391 if (absevent
< sizeof(sStartStopBitField
) * 8
392 && (sStartStopBitField
[absevent
>> 5] & bit
) ) {
393 // Or in the START or END bits, Start = 1 & END = 2
394 // If sgnevent == 0 then START - 0 => START
395 // else if sgnevent == -1 then START - -1 => END
396 code
|= DBG_FUNC_START
- sgnevent
;
399 // Record the timestamp, wish I had a this pointer
400 IOTimeStampConstant(code
, (UInt32
) who
, event
, param1
, param2
);
406 //*********************************************************************************
407 // PMInstantiatePowerDomains
409 // In this vanilla implementation, a Root Power Domain is instantiated.
410 // All other objects which register will be children of this Root.
411 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
412 // in a platform-specific subclass.
413 //*********************************************************************************
415 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
417 root
= new IOPMrootDomain
;
425 //*********************************************************************************
428 // In this vanilla implementation, all callers are made children of the root power domain.
429 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
430 //*********************************************************************************
432 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
434 root
->addPowerChild ( theDevice
);
437 //*********************************************************************************
440 //*********************************************************************************
442 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
444 return ((_pePMFeatures
& featureMask
) != 0);
447 //*********************************************************************************
450 //*********************************************************************************
452 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
454 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
457 //*********************************************************************************
458 // numBatteriesSupported
460 //*********************************************************************************
462 int IOPlatformExpert::numBatteriesSupported (void)
464 return (_peNumBatteriesSupported
);
467 //*********************************************************************************
470 // This method is called by the instantiated sublass of the platform expert to
471 // determine how a device should be inserted into the Power Domain. The subclass
472 // provides an XML power tree description against which a device is matched based
473 // on class and provider. If a match is found this routine returns true in addition
474 // to flagging the description tree at the appropriate node that a device has been
475 // registered for the given service.
476 //*********************************************************************************
478 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
481 unsigned int numPowerTreeNodes
;
482 OSDictionary
* entry
;
483 OSDictionary
* matchingDictionary
;
484 OSDictionary
* providerDictionary
;
485 OSDictionary
* deviceDictionary
;
486 OSDictionary
* nubDictionary
;
488 bool nodeFound
= false;
489 bool continueSearch
= false;
490 bool deviceMatch
= false;
491 bool providerMatch
= false;
492 bool multiParentMatch
= false;
494 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
497 numPowerTreeNodes
= inSubTree
->getCount ();
499 // iterate through the power tree to find a home for this device
501 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
503 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
505 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
506 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
508 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
509 if ( matchingDictionary
) {
511 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
512 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
513 deviceDictionary
->release ();
517 providerMatch
= true; // we indicate a match if there is no nub or provider
518 if ( theNub
&& providerDictionary
) {
519 providerMatch
= false;
520 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
521 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
522 nubDictionary
->release ();
526 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
527 if (deviceMatch
&& providerMatch
) {
528 if (NULL
!= multipleParentKeyValue
) {
529 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
530 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
534 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
536 // if the power tree specifies a provider dictionary but theNub is
537 // NULL then we cannot match with this entry.
539 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
542 // if this node is THE ONE...then register the device
545 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
547 if ( kIOLogPower
& gIOKitDebug
)
548 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
550 numInstancesRegistered
++;
552 // determine if we need to search for additional nodes for this item
553 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
559 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
561 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
562 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
563 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
566 if ( false == continueSearch
)
570 return ( nodeFound
);
573 //*********************************************************************************
574 // RegisterServiceInTree
576 // Register a device at the specified node of our power tree.
577 //*********************************************************************************
579 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
581 IOService
* aService
;
582 bool registered
= false;
584 unsigned int numChildren
;
585 OSDictionary
* child
;
587 // make sure someone is not already registered here
589 if ( NULL
== theTreeNode
->getObject ("service") ) {
591 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
593 // 1. CHILDREN ------------------
595 // we registered the node in the tree...now if the node has children
596 // registered we must tell this service to add them.
598 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
599 numChildren
= children
->getCount ();
600 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
601 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
602 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
603 theService
->addPowerChild (aService
);
608 // 2. PARENT --------------------
610 // also we must notify the parent of this node (if a registered service
611 // exists there) of a new child.
613 if ( theTreeParentNode
) {
614 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
615 if (aService
!= theProvider
)
616 aService
->addPowerChild (theService
);
626 //*********************************************************************************
627 // printDictionaryKeys
629 // Print the keys for the given dictionary and selected contents.
630 //*********************************************************************************
631 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
633 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
640 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
644 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
646 // if this is the IOClass key, print it's contents
648 if ( mkey
->isEqualTo ("IOClass") ) {
649 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
650 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
653 // if this is an IOProviderClass key print it
655 if ( mkey
->isEqualTo ("IOProviderClass") ) {
656 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
657 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
661 // also print IONameMatch keys
662 if ( mkey
->isEqualTo ("IONameMatch") ) {
663 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
664 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
667 // also print IONameMatched keys
669 if ( mkey
->isEqualTo ("IONameMatched") ) {
670 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
671 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
677 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
679 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
681 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
687 if ( mkey
->isEqualTo ("name") ) {
690 getCStringForObject (inDictionary
->getObject ("name"), nameStr
);
691 if (strlen(nameStr
) > 0)
692 IOLog ("%s name is %s\n", inMsg
, nameStr
);
695 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
703 static void getCStringForObject (OSObject
* inObj
, char * outStr
)
708 if ( (NULL
== inObj
) || (NULL
== outStr
))
711 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
713 if ((0 == strcmp(objString
,"OSString")) || (0 == strcmp (objString
, "OSSymbol")))
714 strcpy (outStr
, ((OSString
*)inObj
)->getCStringNoCopy());
716 else if (0 == strcmp(objString
,"OSData")) {
717 len
= ((OSData
*)inObj
)->getLength();
718 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
719 if (buffer
&& (len
> 0)) {
720 for (i
=0; i
< len
; i
++) {
721 outStr
[i
] = buffer
[i
];
728 /* IOShutdownNotificationsTimedOut
729 * - Called from a timer installed by PEHaltRestart
731 static void IOShutdownNotificationsTimedOut(
732 thread_call_param_t p0
,
733 thread_call_param_t p1
)
737 /* 30 seconds has elapsed - resume shutdown */
738 if(gIOPlatform
) gIOPlatform
->haltRestart(type
);
745 * Callouts from BSD for machine name & model
748 boolean_t
PEGetMachineName( char * name
, int maxLength
)
751 return( gIOPlatform
->getMachineName( name
, maxLength
));
756 boolean_t
PEGetModelName( char * name
, int maxLength
)
759 return( gIOPlatform
->getModelName( name
, maxLength
));
764 int PEGetPlatformEpoch(void)
767 return( gIOPlatform
->getBootROMType());
772 int PEHaltRestart(unsigned int type
)
774 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
775 bool noWaitForResponses
;
776 AbsoluteTime deadline
;
777 thread_call_t shutdown_hang
;
778 unsigned int tell_type
;
780 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
|| type
== kPEUPSDelayHaltCPU
)
782 /* Notify IOKit PM clients of shutdown/restart
783 Clients subscribe to this message with a call to
784 IOService::registerInterest()
787 /* Spawn a thread that will panic in 30 seconds.
788 If all goes well the machine will be off by the time
791 shutdown_hang
= thread_call_allocate( &IOShutdownNotificationsTimedOut
,
792 (thread_call_param_t
) type
);
793 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
794 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
797 if( kPEUPSDelayHaltCPU
== type
) {
798 tell_type
= kPEHaltCPU
;
803 noWaitForResponses
= pmRootDomain
->tellChangeDown2(tell_type
);
804 /* This notification should have few clients who all do
805 their work synchronously.
807 In this "shutdown notification" context we don't give
808 drivers the option of working asynchronously and responding
809 later. PM internals make it very hard to wait for asynchronous
810 replies. In fact, it's a bad idea to even be calling
811 tellChangeDown2 from here at all.
815 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
819 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
821 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
825 long PEGetGMTTimeOfDay(void)
830 result
= gIOPlatform
->getGMTTimeOfDay();
835 void PESetGMTTimeOfDay(long secs
)
838 gIOPlatform
->setGMTTimeOfDay(secs
);
843 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
845 publishResource("IONVRAM");
848 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
849 bool waitForFunction
,
850 void *param1
, void *param2
,
851 void *param3
, void *param4
)
853 IOService
*service
, *_resources
;
855 if (waitForFunction
) {
856 _resources
= waitForService(resourceMatching(functionName
));
858 _resources
= resources();
860 if (_resources
== 0) return kIOReturnUnsupported
;
862 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
863 if (service
== 0) return kIOReturnUnsupported
;
865 return service
->callPlatformFunction(functionName
, waitForFunction
,
866 param1
, param2
, param3
, param4
);
869 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
874 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
877 #define super IOPlatformExpert
879 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
881 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
882 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
883 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
884 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
885 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
886 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
887 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
888 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
890 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
892 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
895 if( !super::probe( provider
, score
))
898 // check machine types
899 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
905 bool IODTPlatformExpert::configure( IOService
* provider
)
907 if( !super::configure( provider
))
910 processTopLevel( provider
);
915 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
919 nub
= new IOPlatformDevice
;
921 if( !nub
->init( from
, gIODTPlane
)) {
929 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
931 IORegistryEntry
* next
;
936 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
938 if( 0 == (nub
= createNub( next
)))
941 nub
->attach( parent
);
942 nub
->registerService();
950 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* rootEntry
)
953 IORegistryEntry
* next
;
954 IORegistryEntry
* cpus
;
955 IORegistryEntry
* options
;
958 kids
= IODTFindMatchingEntries( rootEntry
, 0, deleteList() );
960 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
961 next
->detachAll( gIODTPlane
);
966 // Publish an IODTNVRAM class on /options.
967 options
= rootEntry
->childFromPath("options", gIODTPlane
);
969 dtNVRAM
= new IODTNVRAM
;
971 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
975 dtNVRAM
->attach(this);
976 dtNVRAM
->registerService();
982 cpus
= rootEntry
->childFromPath( "cpus", gIODTPlane
);
984 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
986 // publish top level, minus excludeList
987 createNubs( this, IODTFindMatchingEntries( rootEntry
, kIODTExclusive
, excludeList()));
990 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
992 if( nub
->getDeviceMemory())
993 return( kIOReturnSuccess
);
995 IODTResolveAddressing( nub
, "reg", 0);
997 return( kIOReturnSuccess
);
1000 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
1001 OSString
* name
, OSString
** matched
) const
1003 return( IODTCompareNubName( nub
, name
, matched
)
1004 || super::compareNubName( nub
, name
, matched
) );
1007 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
1017 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
1019 str
= (const char *) prop
->getBytesNoCopy();
1021 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
1022 str
+= strlen( "AAPL," );
1025 while( (c
= *str
++)) {
1026 if( (c
== '/') || (c
== ' '))
1030 if( len
>= maxLength
)
1040 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1046 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1050 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1055 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1057 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1059 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1061 super::registerNVRAMController(nvram
);
1064 int IODTPlatformExpert::haltRestart(unsigned int type
)
1066 if (dtNVRAM
) dtNVRAM
->sync();
1068 return super::haltRestart(type
);
1071 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1074 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1075 else return kIOReturnNotReady
;
1078 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1081 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1082 else return kIOReturnNotReady
;
1085 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1086 IORegistryEntry
* entry
,
1087 const OSSymbol
** name
, OSData
** value
)
1089 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1090 else return kIOReturnNotReady
;
1093 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1094 IORegistryEntry
* entry
,
1095 const OSSymbol
* name
, OSData
* value
)
1097 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1098 else return kIOReturnNotReady
;
1101 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1103 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1107 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1108 IOByteCount offset
, UInt8
* buffer
,
1111 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1113 else return kIOReturnNotReady
;
1116 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1117 IOByteCount offset
, UInt8
* buffer
,
1120 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1122 else return kIOReturnNotReady
;
1125 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1127 IOByteCount lengthSaved
= 0;
1129 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1131 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1136 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1137 UInt8
* serialNumber
;
1138 unsigned int serialNumberSize
;
1139 unsigned short pos
= 0;
1143 if (myProperty
!= NULL
) {
1144 serialNumberSize
= myProperty
->getLength();
1145 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1146 temp
= (char*)serialNumber
;
1147 if (serialNumberSize
> 0) {
1148 // check to see if this is a CTO serial number...
1149 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1151 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1152 memcpy(SerialNo
, serialNumber
+ 12, 8);
1153 memcpy(&SerialNo
[8], serialNumber
, 3);
1155 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1157 } else { // just a normal serial number
1158 memcpy(SerialNo
, serialNumber
+ 13, 8);
1159 memcpy(&SerialNo
[8], serialNumber
, 3);
1162 return OSString::withCString(SerialNo
);
1169 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1172 #define super IOService
1174 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1176 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1177 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1178 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1179 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1181 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1183 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1184 OSString
** matched
) const
1186 return( IODTCompareNubName( this, name
, matched
));
1190 IOPlatformExpertDevice::initWithArgs(
1191 void * dtTop
, void * p2
, void * p3
, void * p4
)
1193 IORegistryEntry
* dt
= 0;
1194 void * argsData
[ 4 ];
1197 // dtTop may be zero on non- device tree systems
1198 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1199 ok
= super::init( dt
, gIODTPlane
);
1206 workLoop
= IOWorkLoop::workLoop();
1210 argsData
[ 0 ] = dtTop
;
1215 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1220 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1225 void IOPlatformExpertDevice::free()
1228 workLoop
->release();
1231 bool IOPlatformExpertDevice::attachToChild( IORegistryEntry
* child
,
1232 const IORegistryPlane
* plane
)
1234 return IOService::attachToChild( child
, plane
);
1237 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1240 #define super IOService
1242 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1244 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1245 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1246 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1247 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1249 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1251 bool IOPlatformDevice::compareName( OSString
* name
,
1252 OSString
** matched
) const
1254 return( ((IOPlatformExpert
*)getProvider())->
1255 compareNubName( this, name
, matched
));
1258 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1263 IOReturn
IOPlatformDevice::getResources( void )
1265 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1268 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1270 /*********************************************************************
1271 * IOPanicPlatform class
1273 * If no legitimate IOPlatformDevice matches, this one does and panics
1274 * the kernel with a suitable message.
1275 *********************************************************************/
1277 class IOPanicPlatform
: IOPlatformExpert
{
1278 OSDeclareDefaultStructors(IOPanicPlatform
);
1281 bool start(IOService
* provider
);
1285 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1288 bool IOPanicPlatform::start(IOService
* provider
) {
1289 const char * platform_name
= "(unknown platform name)";
1291 if (provider
) platform_name
= provider
->getName();
1293 panic("Unable to find driver for this platform: \"%s\".\n",