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 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
49 static void getCStringForObject (OSObject
* inObj
, char * outStr
);
51 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53 #define super IOService
55 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
57 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
59 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
60 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 2);
61 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 3);
62 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 4);
63 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
64 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
65 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
66 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
67 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
68 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
69 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
71 static IOPlatformExpert
* gIOPlatform
;
72 static OSDictionary
* gIOInterruptControllers
;
73 static IOLock
* gIOInterruptControllersLock
;
75 OSSymbol
* gPlatformInterruptControllerName
;
77 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
79 bool IOPlatformExpert::attach( IOService
* provider
)
82 if( !super::attach( provider
))
88 bool IOPlatformExpert::start( IOService
* provider
)
90 IORangeAllocator
* physicalRanges
;
91 OSData
* busFrequency
;
94 if (!super::start(provider
))
97 // Override the mapper present flag is requested by boot arguments.
98 if (PE_parse_boot_arg("dart", &debugFlags
) && (debugFlags
== 0))
99 removeProperty(kIOPlatformMapperPresentKey
);
101 // Register the presence or lack thereof a system
102 // PCI address mapper with the IOMapper class
103 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
105 gIOInterruptControllers
= OSDictionary::withCapacity(1);
106 gIOInterruptControllersLock
= IOLockAlloc();
108 // Correct the bus frequency in the device tree.
109 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
110 provider
->setProperty("clock-frequency", busFrequency
);
111 busFrequency
->release();
113 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
115 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
116 IORangeAllocator::kLocking
);
117 assert(physicalRanges
);
118 setProperty("Platform Memory Ranges", physicalRanges
);
123 PMInstantiatePowerDomains();
125 // Parse the serial-number data and publish a user-readable string
126 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
127 if (mydata
!= NULL
) {
128 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
129 if (serNoString
!= NULL
) {
130 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
131 serNoString
->release();
135 return( configure(provider
) );
138 bool IOPlatformExpert::configure( IOService
* provider
)
144 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
147 while( (dict
= OSDynamicCast( OSDictionary
,
148 topLevel
->getAnyObject()))) {
150 topLevel
->removeObject( dict
);
151 nub
= createNub( dict
);
156 nub
->registerService();
163 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
167 nub
= new IOPlatformDevice
;
169 if( !nub
->init( from
)) {
177 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
178 OSString
* name
, OSString
** matched
) const
180 return( nub
->IORegistryEntry::compareName( name
, matched
));
183 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
185 return( kIOReturnSuccess
);
188 long IOPlatformExpert::getBootROMType(void)
190 return _peBootROMType
;
193 long IOPlatformExpert::getChipSetType(void)
195 return _peChipSetType
;
198 long IOPlatformExpert::getMachineType(void)
200 return _peMachineType
;
203 void IOPlatformExpert::setBootROMType(long peBootROMType
)
205 _peBootROMType
= peBootROMType
;
208 void IOPlatformExpert::setChipSetType(long peChipSetType
)
210 _peChipSetType
= peChipSetType
;
213 void IOPlatformExpert::setMachineType(long peMachineType
)
215 _peMachineType
= peMachineType
;
218 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
223 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
228 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
233 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
235 return(OSDynamicCast(IORangeAllocator
,
236 getProperty("Platform Memory Ranges")));
239 int (*PE_halt_restart
)(unsigned int type
) = 0;
241 int IOPlatformExpert::haltRestart(unsigned int type
)
243 IOPMrootDomain
*rd
= getPMRootDomain();
246 if(rd
) b
= (OSBoolean
*)OSDynamicCast(OSBoolean
, rd
->getProperty(OSString::withCString("StallSystemAtHalt")));
248 if (type
== kPEHangCPU
) while (1);
250 if (kOSBooleanTrue
== b
) {
251 // Stall shutdown for 5 minutes, and if no outside force has removed our power, continue with
254 type
= kPERestartCPU
;
257 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
261 void IOPlatformExpert::sleepKernel(void)
267 intState
= ml_set_interrupts_enabled(false);
269 for (cnt
= 0; cnt
< 10000; cnt
++) {
273 ml_set_interrupts_enabled(intState
);
275 // PE_initialize_console(0, kPEDisableScreen);
279 // PE_initialize_console(0, kPEEnableScreen);
283 long IOPlatformExpert::getGMTTimeOfDay(void)
288 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
293 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
295 return( PE_current_console( consoleInfo
));
298 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
301 return( PE_initialize_console( consoleInfo
, op
));
304 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
306 IOLockLock(gIOInterruptControllersLock
);
308 gIOInterruptControllers
->setObject(name
, interruptController
);
310 IOLockWakeup(gIOInterruptControllersLock
,
311 gIOInterruptControllers
, /* one-thread */ false);
313 IOLockUnlock(gIOInterruptControllersLock
);
315 return kIOReturnSuccess
;
318 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
322 IOLockLock(gIOInterruptControllersLock
);
325 object
= gIOInterruptControllers
->getObject(name
);
330 IOLockSleep(gIOInterruptControllersLock
,
331 gIOInterruptControllers
, THREAD_UNINT
);
334 IOLockUnlock(gIOInterruptControllersLock
);
335 return OSDynamicCast(IOInterruptController
, object
);
339 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
341 IOCPUInterruptController
*controller
;
343 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
344 if (controller
) controller
->setCPUInterruptProperties(service
);
347 bool IOPlatformExpert::atInterruptLevel(void)
349 return ml_at_interrupt_context();
352 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
358 //*********************************************************************************
361 //*********************************************************************************
363 void IOPlatformExpert::
364 PMLog(const char *who
, unsigned long event
,
365 unsigned long param1
, unsigned long param2
)
367 UInt32 debugFlags
= gIOKitDebug
;
369 if (debugFlags
& kIOLogPower
) {
371 uint32_t nows
, nowus
;
372 clock_get_system_microtime(&nows
, &nowus
);
373 nowus
+= (nows
% 1000) * 1000000;
375 kprintf("pm%u %x %.30s %d %x %x\n",
376 nowus
, (unsigned) current_thread(), who
, // Identity
377 (int) event
, param1
, param2
); // Args
379 if (debugFlags
& kIOLogTracePower
) {
380 static const UInt32 sStartStopBitField
[] =
381 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
383 // Arcane formula from Hacker's Delight by Warren
384 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
385 UInt32 sgnevent
= ((long) event
>> 31);
386 UInt32 absevent
= sgnevent
^ (event
+ sgnevent
);
387 UInt32 code
= IODBG_POWER(absevent
);
389 UInt32 bit
= 1 << (absevent
& 0x1f);
390 if (absevent
< sizeof(sStartStopBitField
) * 8
391 && (sStartStopBitField
[absevent
>> 5] & bit
) ) {
392 // Or in the START or END bits, Start = 1 & END = 2
393 // If sgnevent == 0 then START - 0 => START
394 // else if sgnevent == -1 then START - -1 => END
395 code
|= DBG_FUNC_START
- sgnevent
;
398 // Record the timestamp, wish I had a this pointer
399 IOTimeStampConstant(code
, (UInt32
) who
, event
, param1
, param2
);
405 //*********************************************************************************
406 // PMInstantiatePowerDomains
408 // In this vanilla implementation, a Root Power Domain is instantiated.
409 // All other objects which register will be children of this Root.
410 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
411 // in a platform-specific subclass.
412 //*********************************************************************************
414 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
416 root
= new IOPMrootDomain
;
424 //*********************************************************************************
427 // In this vanilla implementation, all callers are made children of the root power domain.
428 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
429 //*********************************************************************************
431 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
433 root
->addPowerChild ( theDevice
);
436 //*********************************************************************************
439 //*********************************************************************************
441 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
443 return ((_pePMFeatures
& featureMask
) != 0);
446 //*********************************************************************************
449 //*********************************************************************************
451 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
453 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
456 //*********************************************************************************
457 // numBatteriesSupported
459 //*********************************************************************************
461 int IOPlatformExpert::numBatteriesSupported (void)
463 return (_peNumBatteriesSupported
);
466 //*********************************************************************************
469 // This method is called by the instantiated sublass of the platform expert to
470 // determine how a device should be inserted into the Power Domain. The subclass
471 // provides an XML power tree description against which a device is matched based
472 // on class and provider. If a match is found this routine returns true in addition
473 // to flagging the description tree at the appropriate node that a device has been
474 // registered for the given service.
475 //*********************************************************************************
477 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
480 unsigned int numPowerTreeNodes
;
481 OSDictionary
* entry
;
482 OSDictionary
* matchingDictionary
;
483 OSDictionary
* providerDictionary
;
484 OSDictionary
* deviceDictionary
;
485 OSDictionary
* nubDictionary
;
487 bool nodeFound
= false;
488 bool continueSearch
= false;
489 bool deviceMatch
= false;
490 bool providerMatch
= false;
491 bool multiParentMatch
= false;
493 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
496 numPowerTreeNodes
= inSubTree
->getCount ();
498 // iterate through the power tree to find a home for this device
500 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
502 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
504 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
505 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
507 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
508 if ( matchingDictionary
) {
510 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
511 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
512 deviceDictionary
->release ();
516 providerMatch
= true; // we indicate a match if there is no nub or provider
517 if ( theNub
&& providerDictionary
) {
518 providerMatch
= false;
519 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
520 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
521 nubDictionary
->release ();
525 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
526 if (deviceMatch
&& providerMatch
) {
527 if (NULL
!= multipleParentKeyValue
) {
528 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
529 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
533 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
535 // if the power tree specifies a provider dictionary but theNub is
536 // NULL then we cannot match with this entry.
538 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
541 // if this node is THE ONE...then register the device
544 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
546 if ( kIOLogPower
& gIOKitDebug
)
547 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
549 numInstancesRegistered
++;
551 // determine if we need to search for additional nodes for this item
552 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
558 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
560 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
561 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
562 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
565 if ( false == continueSearch
)
569 return ( nodeFound
);
572 //*********************************************************************************
573 // RegisterServiceInTree
575 // Register a device at the specified node of our power tree.
576 //*********************************************************************************
578 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
580 IOService
* aService
;
581 bool registered
= false;
583 unsigned int numChildren
;
584 OSDictionary
* child
;
586 // make sure someone is not already registered here
588 if ( NULL
== theTreeNode
->getObject ("service") ) {
590 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
592 // 1. CHILDREN ------------------
594 // we registered the node in the tree...now if the node has children
595 // registered we must tell this service to add them.
597 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
598 numChildren
= children
->getCount ();
599 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
600 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
601 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
602 theService
->addPowerChild (aService
);
607 // 2. PARENT --------------------
609 // also we must notify the parent of this node (if a registered service
610 // exists there) of a new child.
612 if ( theTreeParentNode
) {
613 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
614 if (aService
!= theProvider
)
615 aService
->addPowerChild (theService
);
625 //*********************************************************************************
626 // printDictionaryKeys
628 // Print the keys for the given dictionary and selected contents.
629 //*********************************************************************************
630 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
632 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
639 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
643 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
645 // if this is the IOClass key, print it's contents
647 if ( mkey
->isEqualTo ("IOClass") ) {
648 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
649 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
652 // if this is an IOProviderClass key print it
654 if ( mkey
->isEqualTo ("IOProviderClass") ) {
655 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
656 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
660 // also print IONameMatch keys
661 if ( mkey
->isEqualTo ("IONameMatch") ) {
662 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
663 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
666 // also print IONameMatched keys
668 if ( mkey
->isEqualTo ("IONameMatched") ) {
669 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
670 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
676 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
678 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
680 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
686 if ( mkey
->isEqualTo ("name") ) {
689 getCStringForObject (inDictionary
->getObject ("name"), nameStr
);
690 if (strlen(nameStr
) > 0)
691 IOLog ("%s name is %s\n", inMsg
, nameStr
);
694 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
702 static void getCStringForObject (OSObject
* inObj
, char * outStr
)
707 if ( (NULL
== inObj
) || (NULL
== outStr
))
710 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
712 if ((0 == strcmp(objString
,"OSString")) || (0 == strcmp (objString
, "OSSymbol")))
713 strcpy (outStr
, ((OSString
*)inObj
)->getCStringNoCopy());
715 else if (0 == strcmp(objString
,"OSData")) {
716 len
= ((OSData
*)inObj
)->getLength();
717 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
718 if (buffer
&& (len
> 0)) {
719 for (i
=0; i
< len
; i
++) {
720 outStr
[i
] = buffer
[i
];
727 /* IOPMPanicOnShutdownHang
728 * - Called from a timer installed by PEHaltRestart
730 static void IOPMPanicOnShutdownHang(thread_call_param_t p0
, thread_call_param_t p1
)
734 /* 30 seconds has elapsed - resume shutdown */
735 gIOPlatform
->haltRestart(type
);
742 * Callouts from BSD for machine name & model
745 boolean_t
PEGetMachineName( char * name
, int maxLength
)
748 return( gIOPlatform
->getMachineName( name
, maxLength
));
753 boolean_t
PEGetModelName( char * name
, int maxLength
)
756 return( gIOPlatform
->getModelName( name
, maxLength
));
761 int PEGetPlatformEpoch(void)
764 return( gIOPlatform
->getBootROMType());
769 int PEHaltRestart(unsigned int type
)
771 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
772 bool noWaitForResponses
;
773 AbsoluteTime deadline
;
774 thread_call_t shutdown_hang
;
776 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
)
778 /* Notify IOKit PM clients of shutdown/restart
779 Clients subscribe to this message with a call to
780 IOService::registerInterest()
783 /* Spawn a thread that will panic in 30 seconds.
784 If all goes well the machine will be off by the time
787 shutdown_hang
= thread_call_allocate( &IOPMPanicOnShutdownHang
, (thread_call_param_t
) type
);
788 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
789 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
791 noWaitForResponses
= pmRootDomain
->tellChangeDown2(type
);
792 /* This notification should have few clients who all do
793 their work synchronously.
795 In this "shutdown notification" context we don't give
796 drivers the option of working asynchronously and responding
797 later. PM internals make it very hard to wait for asynchronous
798 replies. In fact, it's a bad idea to even be calling
799 tellChangeDown2 from here at all.
803 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
807 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
809 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
813 long PEGetGMTTimeOfDay(void)
816 return( gIOPlatform
->getGMTTimeOfDay());
821 void PESetGMTTimeOfDay(long secs
)
824 gIOPlatform
->setGMTTimeOfDay(secs
);
829 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
831 publishResource("IONVRAM");
834 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
835 bool waitForFunction
,
836 void *param1
, void *param2
,
837 void *param3
, void *param4
)
839 IOService
*service
, *_resources
;
841 if (waitForFunction
) {
842 _resources
= waitForService(resourceMatching(functionName
));
844 _resources
= resources();
846 if (_resources
== 0) return kIOReturnUnsupported
;
848 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
849 if (service
== 0) return kIOReturnUnsupported
;
851 return service
->callPlatformFunction(functionName
, waitForFunction
,
852 param1
, param2
, param3
, param4
);
855 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
860 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
863 #define super IOPlatformExpert
865 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
867 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
868 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
869 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
870 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
871 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
872 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
873 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
874 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
876 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
878 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
881 if( !super::probe( provider
, score
))
884 // check machine types
885 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
891 bool IODTPlatformExpert::configure( IOService
* provider
)
893 if( !super::configure( provider
))
896 processTopLevel( provider
);
901 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
905 nub
= new IOPlatformDevice
;
907 if( !nub
->init( from
, gIODTPlane
)) {
915 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
917 IORegistryEntry
* next
;
922 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
924 if( 0 == (nub
= createNub( next
)))
927 nub
->attach( parent
);
928 nub
->registerService();
936 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* rootEntry
)
939 IORegistryEntry
* next
;
940 IORegistryEntry
* cpus
;
941 IORegistryEntry
* options
;
944 kids
= IODTFindMatchingEntries( rootEntry
, 0, deleteList() );
946 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
947 next
->detachAll( gIODTPlane
);
952 // Publish an IODTNVRAM class on /options.
953 options
= rootEntry
->childFromPath("options", gIODTPlane
);
955 dtNVRAM
= new IODTNVRAM
;
957 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
961 dtNVRAM
->attach(this);
962 dtNVRAM
->registerService();
968 cpus
= rootEntry
->childFromPath( "cpus", gIODTPlane
);
970 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
972 // publish top level, minus excludeList
973 createNubs( this, IODTFindMatchingEntries( rootEntry
, kIODTExclusive
, excludeList()));
976 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
978 if( nub
->getDeviceMemory())
979 return( kIOReturnSuccess
);
981 IODTResolveAddressing( nub
, "reg", 0);
983 return( kIOReturnSuccess
);
986 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
987 OSString
* name
, OSString
** matched
) const
989 return( IODTCompareNubName( nub
, name
, matched
)
990 || super::compareNubName( nub
, name
, matched
) );
993 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
1003 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
1005 str
= (const char *) prop
->getBytesNoCopy();
1007 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
1008 str
+= strlen( "AAPL," );
1011 while( (c
= *str
++)) {
1012 if( (c
== '/') || (c
== ' '))
1016 if( len
>= maxLength
)
1026 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1032 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1036 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1041 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1043 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1045 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1047 super::registerNVRAMController(nvram
);
1050 int IODTPlatformExpert::haltRestart(unsigned int type
)
1052 if (dtNVRAM
) dtNVRAM
->sync();
1054 return super::haltRestart(type
);
1057 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1060 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1061 else return kIOReturnNotReady
;
1064 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1067 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1068 else return kIOReturnNotReady
;
1071 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1072 IORegistryEntry
* entry
,
1073 const OSSymbol
** name
, OSData
** value
)
1075 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1076 else return kIOReturnNotReady
;
1079 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1080 IORegistryEntry
* entry
,
1081 const OSSymbol
* name
, OSData
* value
)
1083 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1084 else return kIOReturnNotReady
;
1087 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1089 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1093 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1094 IOByteCount offset
, UInt8
* buffer
,
1097 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1099 else return kIOReturnNotReady
;
1102 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1103 IOByteCount offset
, UInt8
* buffer
,
1106 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1108 else return kIOReturnNotReady
;
1111 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1113 IOByteCount lengthSaved
= 0;
1115 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1117 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1122 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1123 UInt8
* serialNumber
;
1124 unsigned int serialNumberSize
;
1125 unsigned short pos
= 0;
1129 if (myProperty
!= NULL
) {
1130 serialNumberSize
= myProperty
->getLength();
1131 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1132 temp
= (char*)serialNumber
;
1133 if (serialNumberSize
> 0) {
1134 // check to see if this is a CTO serial number...
1135 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1137 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1138 memcpy(SerialNo
, serialNumber
+ 12, 8);
1139 memcpy(&SerialNo
[8], serialNumber
, 3);
1141 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1143 } else { // just a normal serial number
1144 memcpy(SerialNo
, serialNumber
+ 13, 8);
1145 memcpy(&SerialNo
[8], serialNumber
, 3);
1148 return OSString::withCString(SerialNo
);
1155 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1158 #define super IOService
1160 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1162 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1163 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1164 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1165 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1167 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1169 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1170 OSString
** matched
) const
1172 return( IODTCompareNubName( this, name
, matched
));
1176 IOPlatformExpertDevice::initWithArgs(
1177 void * dtTop
, void * p2
, void * p3
, void * p4
)
1179 IORegistryEntry
* dt
= 0;
1180 void * argsData
[ 4 ];
1183 // dtTop may be zero on non- device tree systems
1184 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1185 ok
= super::init( dt
, gIODTPlane
);
1192 workLoop
= IOWorkLoop::workLoop();
1196 argsData
[ 0 ] = dtTop
;
1201 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1206 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1211 void IOPlatformExpertDevice::free()
1214 workLoop
->release();
1217 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1220 #define super IOService
1222 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1224 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1225 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1226 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1227 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1229 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1231 bool IOPlatformDevice::compareName( OSString
* name
,
1232 OSString
** matched
) const
1234 return( ((IOPlatformExpert
*)getProvider())->
1235 compareNubName( this, name
, matched
));
1238 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1243 IOReturn
IOPlatformDevice::getResources( void )
1245 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1248 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1250 /*********************************************************************
1251 * IOPanicPlatform class
1253 * If no legitimate IOPlatformDevice matches, this one does and panics
1254 * the kernel with a suitable message.
1255 *********************************************************************/
1257 class IOPanicPlatform
: IOPlatformExpert
{
1258 OSDeclareDefaultStructors(IOPanicPlatform
);
1261 bool start(IOService
* provider
);
1265 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1268 bool IOPanicPlatform::start(IOService
* provider
) {
1269 const char * platform_name
= "(unknown platform name)";
1271 if (provider
) platform_name
= provider
->getName();
1273 panic("Unable to find driver for this platform: \"%s\".\n",