2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
27 #include <IOKit/IOCPU.h>
28 #include <IOKit/IODeviceTreeSupport.h>
29 #include <IOKit/IOKitDebug.h>
30 #include <IOKit/IOMapper.h>
31 #include <IOKit/IOMessage.h>
32 #include <IOKit/IONVRAM.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IORangeAllocator.h>
35 #include <IOKit/IOWorkLoop.h>
36 #include <IOKit/pwr_mgt/RootDomain.h>
37 #include <IOKit/IOKitKeys.h>
38 #include <IOKit/IOTimeStamp.h>
40 #include <IOKit/system.h>
42 #include <libkern/c++/OSContainers.h>
45 #include <machine/machine_routines.h>
46 #include <pexpert/pexpert.h>
49 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
50 static void getCStringForObject (OSObject
* inObj
, char * outStr
);
52 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
54 #define super IOService
56 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
58 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
60 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
61 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 2);
62 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 3);
63 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 4);
64 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
65 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
66 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
67 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
68 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
69 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
70 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
72 static IOPlatformExpert
* gIOPlatform
;
73 static OSDictionary
* gIOInterruptControllers
;
74 static IOLock
* gIOInterruptControllersLock
;
76 OSSymbol
* gPlatformInterruptControllerName
;
78 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
80 bool IOPlatformExpert::attach( IOService
* provider
)
83 if( !super::attach( provider
))
89 bool IOPlatformExpert::start( IOService
* provider
)
91 IORangeAllocator
* physicalRanges
;
92 OSData
* busFrequency
;
95 if (!super::start(provider
))
98 // Override the mapper present flag is requested by boot arguments.
99 if (PE_parse_boot_arg("dart", &debugFlags
) && (debugFlags
== 0))
100 removeProperty(kIOPlatformMapperPresentKey
);
102 // Register the presence or lack thereof a system
103 // PCI address mapper with the IOMapper class
104 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
106 gIOInterruptControllers
= OSDictionary::withCapacity(1);
107 gIOInterruptControllersLock
= IOLockAlloc();
109 // Correct the bus frequency in the device tree.
110 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
111 provider
->setProperty("clock-frequency", busFrequency
);
112 busFrequency
->release();
114 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
116 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
117 IORangeAllocator::kLocking
);
118 assert(physicalRanges
);
119 setProperty("Platform Memory Ranges", physicalRanges
);
124 PMInstantiatePowerDomains();
126 // Parse the serial-number data and publish a user-readable string
127 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
128 if (mydata
!= NULL
) {
129 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
130 if (serNoString
!= NULL
) {
131 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
132 serNoString
->release();
136 return( configure(provider
) );
139 bool IOPlatformExpert::configure( IOService
* provider
)
145 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
148 while( (dict
= OSDynamicCast( OSDictionary
,
149 topLevel
->getAnyObject()))) {
151 topLevel
->removeObject( dict
);
152 nub
= createNub( dict
);
157 nub
->registerService();
164 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
168 nub
= new IOPlatformDevice
;
170 if( !nub
->init( from
)) {
178 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
179 OSString
* name
, OSString
** matched
) const
181 return( nub
->IORegistryEntry::compareName( name
, matched
));
184 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
186 return( kIOReturnSuccess
);
189 long IOPlatformExpert::getBootROMType(void)
191 return _peBootROMType
;
194 long IOPlatformExpert::getChipSetType(void)
196 return _peChipSetType
;
199 long IOPlatformExpert::getMachineType(void)
201 return _peMachineType
;
204 void IOPlatformExpert::setBootROMType(long peBootROMType
)
206 _peBootROMType
= peBootROMType
;
209 void IOPlatformExpert::setChipSetType(long peChipSetType
)
211 _peChipSetType
= peChipSetType
;
214 void IOPlatformExpert::setMachineType(long peMachineType
)
216 _peMachineType
= peMachineType
;
219 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
224 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
229 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
234 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
236 return(OSDynamicCast(IORangeAllocator
,
237 getProperty("Platform Memory Ranges")));
240 int (*PE_halt_restart
)(unsigned int type
) = 0;
242 int IOPlatformExpert::haltRestart(unsigned int type
)
244 IOPMrootDomain
*rd
= getPMRootDomain();
247 if(rd
) b
= (OSBoolean
*)OSDynamicCast(OSBoolean
, rd
->getProperty(OSString::withCString("StallSystemAtHalt")));
249 if (type
== kPEHangCPU
) while (1);
251 if (kOSBooleanTrue
== b
) {
252 // Stall shutdown for 5 minutes, and if no outside force has removed our power, continue with
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 /* IOPMPanicOnShutdownHang
729 * - Called from a timer installed by PEHaltRestart
731 static void IOPMPanicOnShutdownHang(thread_call_param_t p0
, thread_call_param_t p1
)
735 /* 30 seconds has elapsed - resume shutdown */
736 gIOPlatform
->haltRestart(type
);
743 * Callouts from BSD for machine name & model
746 boolean_t
PEGetMachineName( char * name
, int maxLength
)
749 return( gIOPlatform
->getMachineName( name
, maxLength
));
754 boolean_t
PEGetModelName( char * name
, int maxLength
)
757 return( gIOPlatform
->getModelName( name
, maxLength
));
762 int PEGetPlatformEpoch(void)
765 return( gIOPlatform
->getBootROMType());
770 int PEHaltRestart(unsigned int type
)
772 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
773 bool noWaitForResponses
;
774 AbsoluteTime deadline
;
775 thread_call_t shutdown_hang
;
777 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
)
779 /* Notify IOKit PM clients of shutdown/restart
780 Clients subscribe to this message with a call to
781 IOService::registerInterest()
784 /* Spawn a thread that will panic in 30 seconds.
785 If all goes well the machine will be off by the time
788 shutdown_hang
= thread_call_allocate( &IOPMPanicOnShutdownHang
, (thread_call_param_t
) type
);
789 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
790 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
792 noWaitForResponses
= pmRootDomain
->tellChangeDown2(type
);
793 /* This notification should have few clients who all do
794 their work synchronously.
796 In this "shutdown notification" context we don't give
797 drivers the option of working asynchronously and responding
798 later. PM internals make it very hard to wait for asynchronous
799 replies. In fact, it's a bad idea to even be calling
800 tellChangeDown2 from here at all.
804 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
808 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
810 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
814 long PEGetGMTTimeOfDay(void)
817 return( gIOPlatform
->getGMTTimeOfDay());
822 void PESetGMTTimeOfDay(long secs
)
825 gIOPlatform
->setGMTTimeOfDay(secs
);
830 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
832 publishResource("IONVRAM");
835 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
836 bool waitForFunction
,
837 void *param1
, void *param2
,
838 void *param3
, void *param4
)
840 IOService
*service
, *_resources
;
842 if (waitForFunction
) {
843 _resources
= waitForService(resourceMatching(functionName
));
845 _resources
= resources();
847 if (_resources
== 0) return kIOReturnUnsupported
;
849 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
850 if (service
== 0) return kIOReturnUnsupported
;
852 return service
->callPlatformFunction(functionName
, waitForFunction
,
853 param1
, param2
, param3
, param4
);
856 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
861 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
864 #define super IOPlatformExpert
866 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
868 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
869 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
870 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
871 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
872 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
873 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
874 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
875 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
877 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
879 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
882 if( !super::probe( provider
, score
))
885 // check machine types
886 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
892 bool IODTPlatformExpert::configure( IOService
* provider
)
894 if( !super::configure( provider
))
897 processTopLevel( provider
);
902 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
906 nub
= new IOPlatformDevice
;
908 if( !nub
->init( from
, gIODTPlane
)) {
916 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
918 IORegistryEntry
* next
;
923 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
925 if( 0 == (nub
= createNub( next
)))
928 nub
->attach( parent
);
929 nub
->registerService();
937 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* rootEntry
)
940 IORegistryEntry
* next
;
941 IORegistryEntry
* cpus
;
942 IORegistryEntry
* options
;
945 kids
= IODTFindMatchingEntries( rootEntry
, 0, deleteList() );
947 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
948 next
->detachAll( gIODTPlane
);
953 // Publish an IODTNVRAM class on /options.
954 options
= rootEntry
->childFromPath("options", gIODTPlane
);
956 dtNVRAM
= new IODTNVRAM
;
958 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
962 dtNVRAM
->attach(this);
963 dtNVRAM
->registerService();
969 cpus
= rootEntry
->childFromPath( "cpus", gIODTPlane
);
971 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
973 // publish top level, minus excludeList
974 createNubs( this, IODTFindMatchingEntries( rootEntry
, kIODTExclusive
, excludeList()));
977 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
979 if( nub
->getDeviceMemory())
980 return( kIOReturnSuccess
);
982 IODTResolveAddressing( nub
, "reg", 0);
984 return( kIOReturnSuccess
);
987 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
988 OSString
* name
, OSString
** matched
) const
990 return( IODTCompareNubName( nub
, name
, matched
)
991 || super::compareNubName( nub
, name
, matched
) );
994 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
1004 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
1006 str
= (const char *) prop
->getBytesNoCopy();
1008 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
1009 str
+= strlen( "AAPL," );
1012 while( (c
= *str
++)) {
1013 if( (c
== '/') || (c
== ' '))
1017 if( len
>= maxLength
)
1027 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1033 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1037 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1042 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1044 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1046 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1048 super::registerNVRAMController(nvram
);
1051 int IODTPlatformExpert::haltRestart(unsigned int type
)
1053 if (dtNVRAM
) dtNVRAM
->sync();
1055 return super::haltRestart(type
);
1058 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1061 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1062 else return kIOReturnNotReady
;
1065 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1068 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1069 else return kIOReturnNotReady
;
1072 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1073 IORegistryEntry
* entry
,
1074 const OSSymbol
** name
, OSData
** value
)
1076 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1077 else return kIOReturnNotReady
;
1080 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1081 IORegistryEntry
* entry
,
1082 const OSSymbol
* name
, OSData
* value
)
1084 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1085 else return kIOReturnNotReady
;
1088 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1090 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1094 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1095 IOByteCount offset
, UInt8
* buffer
,
1098 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1100 else return kIOReturnNotReady
;
1103 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1104 IOByteCount offset
, UInt8
* buffer
,
1107 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1109 else return kIOReturnNotReady
;
1112 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1114 IOByteCount lengthSaved
= 0;
1116 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1118 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1123 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1124 UInt8
* serialNumber
;
1125 unsigned int serialNumberSize
;
1126 unsigned short pos
= 0;
1130 if (myProperty
!= NULL
) {
1131 serialNumberSize
= myProperty
->getLength();
1132 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1133 temp
= (char*)serialNumber
;
1134 if (serialNumberSize
> 0) {
1135 // check to see if this is a CTO serial number...
1136 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1138 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1139 memcpy(SerialNo
, serialNumber
+ 12, 8);
1140 memcpy(&SerialNo
[8], serialNumber
, 3);
1142 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1144 } else { // just a normal serial number
1145 memcpy(SerialNo
, serialNumber
+ 13, 8);
1146 memcpy(&SerialNo
[8], serialNumber
, 3);
1149 return OSString::withCString(SerialNo
);
1156 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1159 #define super IOService
1161 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1163 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1164 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1165 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1166 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1168 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1170 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1171 OSString
** matched
) const
1173 return( IODTCompareNubName( this, name
, matched
));
1177 IOPlatformExpertDevice::initWithArgs(
1178 void * dtTop
, void * p2
, void * p3
, void * p4
)
1180 IORegistryEntry
* dt
= 0;
1181 void * argsData
[ 4 ];
1184 // dtTop may be zero on non- device tree systems
1185 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1186 ok
= super::init( dt
, gIODTPlane
);
1193 workLoop
= IOWorkLoop::workLoop();
1197 argsData
[ 0 ] = dtTop
;
1202 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1207 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1212 void IOPlatformExpertDevice::free()
1215 workLoop
->release();
1218 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1221 #define super IOService
1223 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1225 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1226 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1227 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1228 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1230 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1232 bool IOPlatformDevice::compareName( OSString
* name
,
1233 OSString
** matched
) const
1235 return( ((IOPlatformExpert
*)getProvider())->
1236 compareNubName( this, name
, matched
));
1239 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1244 IOReturn
IOPlatformDevice::getResources( void )
1246 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1249 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1251 /*********************************************************************
1252 * IOPanicPlatform class
1254 * If no legitimate IOPlatformDevice matches, this one does and panics
1255 * the kernel with a suitable message.
1256 *********************************************************************/
1258 class IOPanicPlatform
: IOPlatformExpert
{
1259 OSDeclareDefaultStructors(IOPanicPlatform
);
1262 bool start(IOService
* provider
);
1266 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1269 bool IOPanicPlatform::start(IOService
* provider
) {
1270 const char * platform_name
= "(unknown platform name)";
1272 if (provider
) platform_name
= provider
->getName();
1274 panic("Unable to find driver for this platform: \"%s\".\n",