2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
34 #include <IOKit/IOCPU.h>
35 #include <IOKit/IODeviceTreeSupport.h>
36 #include <IOKit/IOKitDebug.h>
37 #include <IOKit/IOMapper.h>
38 #include <IOKit/IOMessage.h>
39 #include <IOKit/IONVRAM.h>
40 #include <IOKit/IOPlatformExpert.h>
41 #include <IOKit/IORangeAllocator.h>
42 #include <IOKit/IOWorkLoop.h>
43 #include <IOKit/pwr_mgt/RootDomain.h>
44 #include <IOKit/IOKitKeys.h>
45 #include <IOKit/IOTimeStamp.h>
47 #include <IOKit/system.h>
49 #include <libkern/c++/OSContainers.h>
52 #include <machine/machine_routines.h>
53 #include <pexpert/pexpert.h>
56 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
57 static void getCStringForObject (OSObject
* inObj
, char * outStr
);
59 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
61 #define super IOService
63 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
65 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
67 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
68 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 2);
69 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 3);
70 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 4);
71 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
72 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
73 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
74 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
75 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
76 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
77 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
79 static IOPlatformExpert
* gIOPlatform
;
80 static OSDictionary
* gIOInterruptControllers
;
81 static IOLock
* gIOInterruptControllersLock
;
83 OSSymbol
* gPlatformInterruptControllerName
;
85 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
87 bool IOPlatformExpert::attach( IOService
* provider
)
90 if( !super::attach( provider
))
96 bool IOPlatformExpert::start( IOService
* provider
)
98 IORangeAllocator
* physicalRanges
;
99 OSData
* busFrequency
;
102 if (!super::start(provider
))
105 // Override the mapper present flag is requested by boot arguments.
106 if (PE_parse_boot_arg("dart", &debugFlags
) && (debugFlags
== 0))
107 removeProperty(kIOPlatformMapperPresentKey
);
109 // Register the presence or lack thereof a system
110 // PCI address mapper with the IOMapper class
111 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
113 gIOInterruptControllers
= OSDictionary::withCapacity(1);
114 gIOInterruptControllersLock
= IOLockAlloc();
116 // Correct the bus frequency in the device tree.
117 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
118 provider
->setProperty("clock-frequency", busFrequency
);
119 busFrequency
->release();
121 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
123 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
124 IORangeAllocator::kLocking
);
125 assert(physicalRanges
);
126 setProperty("Platform Memory Ranges", physicalRanges
);
131 PMInstantiatePowerDomains();
133 // Parse the serial-number data and publish a user-readable string
134 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
135 if (mydata
!= NULL
) {
136 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
137 if (serNoString
!= NULL
) {
138 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
139 serNoString
->release();
143 return( configure(provider
) );
146 bool IOPlatformExpert::configure( IOService
* provider
)
152 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
155 while( (dict
= OSDynamicCast( OSDictionary
,
156 topLevel
->getAnyObject()))) {
158 topLevel
->removeObject( dict
);
159 nub
= createNub( dict
);
164 nub
->registerService();
171 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
175 nub
= new IOPlatformDevice
;
177 if( !nub
->init( from
)) {
185 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
186 OSString
* name
, OSString
** matched
) const
188 return( nub
->IORegistryEntry::compareName( name
, matched
));
191 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
193 return( kIOReturnSuccess
);
196 long IOPlatformExpert::getBootROMType(void)
198 return _peBootROMType
;
201 long IOPlatformExpert::getChipSetType(void)
203 return _peChipSetType
;
206 long IOPlatformExpert::getMachineType(void)
208 return _peMachineType
;
211 void IOPlatformExpert::setBootROMType(long peBootROMType
)
213 _peBootROMType
= peBootROMType
;
216 void IOPlatformExpert::setChipSetType(long peChipSetType
)
218 _peChipSetType
= peChipSetType
;
221 void IOPlatformExpert::setMachineType(long peMachineType
)
223 _peMachineType
= peMachineType
;
226 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
231 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
236 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
241 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
243 return(OSDynamicCast(IORangeAllocator
,
244 getProperty("Platform Memory Ranges")));
247 int (*PE_halt_restart
)(unsigned int type
) = 0;
249 int IOPlatformExpert::haltRestart(unsigned int type
)
251 IOPMrootDomain
*rd
= getPMRootDomain();
254 if(rd
) b
= (OSBoolean
*)OSDynamicCast(OSBoolean
, rd
->getProperty(OSString::withCString("StallSystemAtHalt")));
256 if (type
== kPEHangCPU
) while (1);
258 if (kOSBooleanTrue
== b
) {
259 // Stall shutdown for 5 minutes, and if no outside force has removed our power, continue with
262 type
= kPERestartCPU
;
265 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
269 void IOPlatformExpert::sleepKernel(void)
275 intState
= ml_set_interrupts_enabled(false);
277 for (cnt
= 0; cnt
< 10000; cnt
++) {
281 ml_set_interrupts_enabled(intState
);
283 // PE_initialize_console(0, kPEDisableScreen);
287 // PE_initialize_console(0, kPEEnableScreen);
291 long IOPlatformExpert::getGMTTimeOfDay(void)
296 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
301 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
303 return( PE_current_console( consoleInfo
));
306 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
309 return( PE_initialize_console( consoleInfo
, op
));
312 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
314 IOLockLock(gIOInterruptControllersLock
);
316 gIOInterruptControllers
->setObject(name
, interruptController
);
318 IOLockWakeup(gIOInterruptControllersLock
,
319 gIOInterruptControllers
, /* one-thread */ false);
321 IOLockUnlock(gIOInterruptControllersLock
);
323 return kIOReturnSuccess
;
326 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
330 IOLockLock(gIOInterruptControllersLock
);
333 object
= gIOInterruptControllers
->getObject(name
);
338 IOLockSleep(gIOInterruptControllersLock
,
339 gIOInterruptControllers
, THREAD_UNINT
);
342 IOLockUnlock(gIOInterruptControllersLock
);
343 return OSDynamicCast(IOInterruptController
, object
);
347 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
349 IOCPUInterruptController
*controller
;
351 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
352 if (controller
) controller
->setCPUInterruptProperties(service
);
355 bool IOPlatformExpert::atInterruptLevel(void)
357 return ml_at_interrupt_context();
360 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
366 //*********************************************************************************
369 //*********************************************************************************
371 void IOPlatformExpert::
372 PMLog(const char *who
, unsigned long event
,
373 unsigned long param1
, unsigned long param2
)
375 UInt32 debugFlags
= gIOKitDebug
;
377 if (debugFlags
& kIOLogPower
) {
379 uint32_t nows
, nowus
;
380 clock_get_system_microtime(&nows
, &nowus
);
381 nowus
+= (nows
% 1000) * 1000000;
383 kprintf("pm%u %x %.30s %d %x %x\n",
384 nowus
, (unsigned) current_thread(), who
, // Identity
385 (int) event
, param1
, param2
); // Args
387 if (debugFlags
& kIOLogTracePower
) {
388 static const UInt32 sStartStopBitField
[] =
389 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
391 // Arcane formula from Hacker's Delight by Warren
392 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
393 UInt32 sgnevent
= ((long) event
>> 31);
394 UInt32 absevent
= sgnevent
^ (event
+ sgnevent
);
395 UInt32 code
= IODBG_POWER(absevent
);
397 UInt32 bit
= 1 << (absevent
& 0x1f);
398 if (absevent
< sizeof(sStartStopBitField
) * 8
399 && (sStartStopBitField
[absevent
>> 5] & bit
) ) {
400 // Or in the START or END bits, Start = 1 & END = 2
401 // If sgnevent == 0 then START - 0 => START
402 // else if sgnevent == -1 then START - -1 => END
403 code
|= DBG_FUNC_START
- sgnevent
;
406 // Record the timestamp, wish I had a this pointer
407 IOTimeStampConstant(code
, (UInt32
) who
, event
, param1
, param2
);
413 //*********************************************************************************
414 // PMInstantiatePowerDomains
416 // In this vanilla implementation, a Root Power Domain is instantiated.
417 // All other objects which register will be children of this Root.
418 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
419 // in a platform-specific subclass.
420 //*********************************************************************************
422 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
424 root
= new IOPMrootDomain
;
432 //*********************************************************************************
435 // In this vanilla implementation, all callers are made children of the root power domain.
436 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
437 //*********************************************************************************
439 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
441 root
->addPowerChild ( theDevice
);
444 //*********************************************************************************
447 //*********************************************************************************
449 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
451 return ((_pePMFeatures
& featureMask
) != 0);
454 //*********************************************************************************
457 //*********************************************************************************
459 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
461 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
464 //*********************************************************************************
465 // numBatteriesSupported
467 //*********************************************************************************
469 int IOPlatformExpert::numBatteriesSupported (void)
471 return (_peNumBatteriesSupported
);
474 //*********************************************************************************
477 // This method is called by the instantiated sublass of the platform expert to
478 // determine how a device should be inserted into the Power Domain. The subclass
479 // provides an XML power tree description against which a device is matched based
480 // on class and provider. If a match is found this routine returns true in addition
481 // to flagging the description tree at the appropriate node that a device has been
482 // registered for the given service.
483 //*********************************************************************************
485 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
488 unsigned int numPowerTreeNodes
;
489 OSDictionary
* entry
;
490 OSDictionary
* matchingDictionary
;
491 OSDictionary
* providerDictionary
;
492 OSDictionary
* deviceDictionary
;
493 OSDictionary
* nubDictionary
;
495 bool nodeFound
= false;
496 bool continueSearch
= false;
497 bool deviceMatch
= false;
498 bool providerMatch
= false;
499 bool multiParentMatch
= false;
501 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
504 numPowerTreeNodes
= inSubTree
->getCount ();
506 // iterate through the power tree to find a home for this device
508 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
510 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
512 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
513 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
515 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
516 if ( matchingDictionary
) {
518 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
519 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
520 deviceDictionary
->release ();
524 providerMatch
= true; // we indicate a match if there is no nub or provider
525 if ( theNub
&& providerDictionary
) {
526 providerMatch
= false;
527 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
528 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
529 nubDictionary
->release ();
533 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
534 if (deviceMatch
&& providerMatch
) {
535 if (NULL
!= multipleParentKeyValue
) {
536 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
537 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
541 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
543 // if the power tree specifies a provider dictionary but theNub is
544 // NULL then we cannot match with this entry.
546 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
549 // if this node is THE ONE...then register the device
552 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
554 if ( kIOLogPower
& gIOKitDebug
)
555 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
557 numInstancesRegistered
++;
559 // determine if we need to search for additional nodes for this item
560 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
566 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
568 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
569 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
570 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
573 if ( false == continueSearch
)
577 return ( nodeFound
);
580 //*********************************************************************************
581 // RegisterServiceInTree
583 // Register a device at the specified node of our power tree.
584 //*********************************************************************************
586 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
588 IOService
* aService
;
589 bool registered
= false;
591 unsigned int numChildren
;
592 OSDictionary
* child
;
594 // make sure someone is not already registered here
596 if ( NULL
== theTreeNode
->getObject ("service") ) {
598 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
600 // 1. CHILDREN ------------------
602 // we registered the node in the tree...now if the node has children
603 // registered we must tell this service to add them.
605 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
606 numChildren
= children
->getCount ();
607 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
608 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
609 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
610 theService
->addPowerChild (aService
);
615 // 2. PARENT --------------------
617 // also we must notify the parent of this node (if a registered service
618 // exists there) of a new child.
620 if ( theTreeParentNode
) {
621 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
622 if (aService
!= theProvider
)
623 aService
->addPowerChild (theService
);
633 //*********************************************************************************
634 // printDictionaryKeys
636 // Print the keys for the given dictionary and selected contents.
637 //*********************************************************************************
638 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
640 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
647 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
651 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
653 // if this is the IOClass key, print it's contents
655 if ( mkey
->isEqualTo ("IOClass") ) {
656 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
657 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
660 // if this is an IOProviderClass key print it
662 if ( mkey
->isEqualTo ("IOProviderClass") ) {
663 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
664 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
668 // also print IONameMatch keys
669 if ( mkey
->isEqualTo ("IONameMatch") ) {
670 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
671 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
674 // also print IONameMatched keys
676 if ( mkey
->isEqualTo ("IONameMatched") ) {
677 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
678 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
684 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
686 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
688 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
694 if ( mkey
->isEqualTo ("name") ) {
697 getCStringForObject (inDictionary
->getObject ("name"), nameStr
);
698 if (strlen(nameStr
) > 0)
699 IOLog ("%s name is %s\n", inMsg
, nameStr
);
702 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
710 static void getCStringForObject (OSObject
* inObj
, char * outStr
)
715 if ( (NULL
== inObj
) || (NULL
== outStr
))
718 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
720 if ((0 == strcmp(objString
,"OSString")) || (0 == strcmp (objString
, "OSSymbol")))
721 strcpy (outStr
, ((OSString
*)inObj
)->getCStringNoCopy());
723 else if (0 == strcmp(objString
,"OSData")) {
724 len
= ((OSData
*)inObj
)->getLength();
725 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
726 if (buffer
&& (len
> 0)) {
727 for (i
=0; i
< len
; i
++) {
728 outStr
[i
] = buffer
[i
];
735 /* IOPMPanicOnShutdownHang
736 * - Called from a timer installed by PEHaltRestart
738 static void IOPMPanicOnShutdownHang(thread_call_param_t p0
, thread_call_param_t p1
)
742 /* 30 seconds has elapsed - resume shutdown */
743 gIOPlatform
->haltRestart(type
);
750 * Callouts from BSD for machine name & model
753 boolean_t
PEGetMachineName( char * name
, int maxLength
)
756 return( gIOPlatform
->getMachineName( name
, maxLength
));
761 boolean_t
PEGetModelName( char * name
, int maxLength
)
764 return( gIOPlatform
->getModelName( name
, maxLength
));
769 int PEGetPlatformEpoch(void)
772 return( gIOPlatform
->getBootROMType());
777 int PEHaltRestart(unsigned int type
)
779 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
780 bool noWaitForResponses
;
781 AbsoluteTime deadline
;
782 thread_call_t shutdown_hang
;
784 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
)
786 /* Notify IOKit PM clients of shutdown/restart
787 Clients subscribe to this message with a call to
788 IOService::registerInterest()
791 /* Spawn a thread that will panic in 30 seconds.
792 If all goes well the machine will be off by the time
795 shutdown_hang
= thread_call_allocate( &IOPMPanicOnShutdownHang
, (thread_call_param_t
) type
);
796 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
797 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
799 noWaitForResponses
= pmRootDomain
->tellChangeDown2(type
);
800 /* This notification should have few clients who all do
801 their work synchronously.
803 In this "shutdown notification" context we don't give
804 drivers the option of working asynchronously and responding
805 later. PM internals make it very hard to wait for asynchronous
806 replies. In fact, it's a bad idea to even be calling
807 tellChangeDown2 from here at all.
811 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
815 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
817 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
821 long PEGetGMTTimeOfDay(void)
824 return( gIOPlatform
->getGMTTimeOfDay());
829 void PESetGMTTimeOfDay(long secs
)
832 gIOPlatform
->setGMTTimeOfDay(secs
);
837 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
839 publishResource("IONVRAM");
842 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
843 bool waitForFunction
,
844 void *param1
, void *param2
,
845 void *param3
, void *param4
)
847 IOService
*service
, *_resources
;
849 if (waitForFunction
) {
850 _resources
= waitForService(resourceMatching(functionName
));
852 _resources
= resources();
854 if (_resources
== 0) return kIOReturnUnsupported
;
856 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
857 if (service
== 0) return kIOReturnUnsupported
;
859 return service
->callPlatformFunction(functionName
, waitForFunction
,
860 param1
, param2
, param3
, param4
);
863 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
868 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
871 #define super IOPlatformExpert
873 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
875 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
876 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
877 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
878 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
879 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
880 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
881 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
882 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
884 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
886 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
889 if( !super::probe( provider
, score
))
892 // check machine types
893 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
899 bool IODTPlatformExpert::configure( IOService
* provider
)
901 if( !super::configure( provider
))
904 processTopLevel( provider
);
909 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
913 nub
= new IOPlatformDevice
;
915 if( !nub
->init( from
, gIODTPlane
)) {
923 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
925 IORegistryEntry
* next
;
930 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
932 if( 0 == (nub
= createNub( next
)))
935 nub
->attach( parent
);
936 nub
->registerService();
944 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* rootEntry
)
947 IORegistryEntry
* next
;
948 IORegistryEntry
* cpus
;
949 IORegistryEntry
* options
;
952 kids
= IODTFindMatchingEntries( rootEntry
, 0, deleteList() );
954 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
955 next
->detachAll( gIODTPlane
);
960 // Publish an IODTNVRAM class on /options.
961 options
= rootEntry
->childFromPath("options", gIODTPlane
);
963 dtNVRAM
= new IODTNVRAM
;
965 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
969 dtNVRAM
->attach(this);
970 dtNVRAM
->registerService();
976 cpus
= rootEntry
->childFromPath( "cpus", gIODTPlane
);
978 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
980 // publish top level, minus excludeList
981 createNubs( this, IODTFindMatchingEntries( rootEntry
, kIODTExclusive
, excludeList()));
984 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
986 if( nub
->getDeviceMemory())
987 return( kIOReturnSuccess
);
989 IODTResolveAddressing( nub
, "reg", 0);
991 return( kIOReturnSuccess
);
994 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
995 OSString
* name
, OSString
** matched
) const
997 return( IODTCompareNubName( nub
, name
, matched
)
998 || super::compareNubName( nub
, name
, matched
) );
1001 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
1011 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
1013 str
= (const char *) prop
->getBytesNoCopy();
1015 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
1016 str
+= strlen( "AAPL," );
1019 while( (c
= *str
++)) {
1020 if( (c
== '/') || (c
== ' '))
1024 if( len
>= maxLength
)
1034 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1040 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1044 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1049 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1051 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1053 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1055 super::registerNVRAMController(nvram
);
1058 int IODTPlatformExpert::haltRestart(unsigned int type
)
1060 if (dtNVRAM
) dtNVRAM
->sync();
1062 return super::haltRestart(type
);
1065 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1068 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1069 else return kIOReturnNotReady
;
1072 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1075 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1076 else return kIOReturnNotReady
;
1079 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1080 IORegistryEntry
* entry
,
1081 const OSSymbol
** name
, OSData
** value
)
1083 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1084 else return kIOReturnNotReady
;
1087 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1088 IORegistryEntry
* entry
,
1089 const OSSymbol
* name
, OSData
* value
)
1091 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1092 else return kIOReturnNotReady
;
1095 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1097 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1101 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1102 IOByteCount offset
, UInt8
* buffer
,
1105 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1107 else return kIOReturnNotReady
;
1110 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1111 IOByteCount offset
, UInt8
* buffer
,
1114 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1116 else return kIOReturnNotReady
;
1119 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1121 IOByteCount lengthSaved
= 0;
1123 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1125 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1130 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1131 UInt8
* serialNumber
;
1132 unsigned int serialNumberSize
;
1133 unsigned short pos
= 0;
1137 if (myProperty
!= NULL
) {
1138 serialNumberSize
= myProperty
->getLength();
1139 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1140 temp
= (char*)serialNumber
;
1141 if (serialNumberSize
> 0) {
1142 // check to see if this is a CTO serial number...
1143 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1145 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1146 memcpy(SerialNo
, serialNumber
+ 12, 8);
1147 memcpy(&SerialNo
[8], serialNumber
, 3);
1149 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1151 } else { // just a normal serial number
1152 memcpy(SerialNo
, serialNumber
+ 13, 8);
1153 memcpy(&SerialNo
[8], serialNumber
, 3);
1156 return OSString::withCString(SerialNo
);
1163 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1166 #define super IOService
1168 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1170 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1171 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1172 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1173 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1175 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1177 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1178 OSString
** matched
) const
1180 return( IODTCompareNubName( this, name
, matched
));
1184 IOPlatformExpertDevice::initWithArgs(
1185 void * dtTop
, void * p2
, void * p3
, void * p4
)
1187 IORegistryEntry
* dt
= 0;
1188 void * argsData
[ 4 ];
1191 // dtTop may be zero on non- device tree systems
1192 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1193 ok
= super::init( dt
, gIODTPlane
);
1200 workLoop
= IOWorkLoop::workLoop();
1204 argsData
[ 0 ] = dtTop
;
1209 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1214 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1219 void IOPlatformExpertDevice::free()
1222 workLoop
->release();
1225 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1228 #define super IOService
1230 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1232 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1233 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1234 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1235 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1237 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1239 bool IOPlatformDevice::compareName( OSString
* name
,
1240 OSString
** matched
) const
1242 return( ((IOPlatformExpert
*)getProvider())->
1243 compareNubName( this, name
, matched
));
1246 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1251 IOReturn
IOPlatformDevice::getResources( void )
1253 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1256 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1258 /*********************************************************************
1259 * IOPanicPlatform class
1261 * If no legitimate IOPlatformDevice matches, this one does and panics
1262 * the kernel with a suitable message.
1263 *********************************************************************/
1265 class IOPanicPlatform
: IOPlatformExpert
{
1266 OSDeclareDefaultStructors(IOPanicPlatform
);
1269 bool start(IOService
* provider
);
1273 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1276 bool IOPanicPlatform::start(IOService
* provider
) {
1277 const char * platform_name
= "(unknown platform name)";
1279 if (provider
) platform_name
= provider
->getName();
1281 panic("Unable to find driver for this platform: \"%s\".\n",