2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
29 #include <IOKit/IOCPU.h>
30 #include <IOKit/IODeviceTreeSupport.h>
31 #include <IOKit/IOKitDebug.h>
32 #include <IOKit/IOMapper.h>
33 #include <IOKit/IOMessage.h>
34 #include <IOKit/IONVRAM.h>
35 #include <IOKit/IOPlatformExpert.h>
36 #include <IOKit/IORangeAllocator.h>
37 #include <IOKit/IOWorkLoop.h>
38 #include <IOKit/pwr_mgt/RootDomain.h>
39 #include <IOKit/IOKitKeys.h>
41 #include <IOKit/system.h>
43 #include <libkern/c++/OSContainers.h>
47 #include <machine/machine_routines.h>
48 #include <pexpert/pexpert.h>
51 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
);
52 static void getCStringForObject (OSObject
* inObj
, char * outStr
);
54 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
56 #define super IOService
58 OSDefineMetaClassAndStructors(IOPlatformExpert
, IOService
)
60 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 0);
62 OSMetaClassDefineReservedUsed(IOPlatformExpert
, 1);
63 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 2);
64 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 3);
65 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 4);
66 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 5);
67 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 6);
68 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 7);
69 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 8);
70 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 9);
71 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 10);
72 OSMetaClassDefineReservedUnused(IOPlatformExpert
, 11);
74 static IOPlatformExpert
* gIOPlatform
;
75 static OSDictionary
* gIOInterruptControllers
;
76 static IOLock
* gIOInterruptControllersLock
;
78 OSSymbol
* gPlatformInterruptControllerName
;
80 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
82 bool IOPlatformExpert::attach( IOService
* provider
)
85 if( !super::attach( provider
))
91 bool IOPlatformExpert::start( IOService
* provider
)
93 IORangeAllocator
* physicalRanges
;
94 OSData
* busFrequency
;
96 if (!super::start(provider
))
99 // Register the presence or lack thereof a system
100 // PCI address mapper with the IOMapper class
103 IORegistryEntry
* regEntry
= IORegistryEntry::fromPath("/u3/dart", gIODTPlane
);
105 regEntry
= IORegistryEntry::fromPath("/dart", gIODTPlane
);
108 if (!PE_parse_boot_arg("dart", &debugFlags
) || debugFlags
)
109 setProperty(kIOPlatformMapperPresentKey
, kOSBooleanTrue
);
114 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
116 gIOInterruptControllers
= OSDictionary::withCapacity(1);
117 gIOInterruptControllersLock
= IOLockAlloc();
119 // Correct the bus frequency in the device tree.
120 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
121 provider
->setProperty("clock-frequency", busFrequency
);
122 busFrequency
->release();
124 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
126 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
127 IORangeAllocator::kLocking
);
128 assert(physicalRanges
);
129 setProperty("Platform Memory Ranges", physicalRanges
);
134 PMInstantiatePowerDomains();
136 // Parse the serial-number data and publish a user-readable string
137 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
138 if (mydata
!= NULL
) {
139 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
140 if (serNoString
!= NULL
) {
141 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
142 serNoString
->release();
146 return( configure(provider
) );
149 bool IOPlatformExpert::configure( IOService
* provider
)
155 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
158 while( (dict
= OSDynamicCast( OSDictionary
,
159 topLevel
->getAnyObject()))) {
161 topLevel
->removeObject( dict
);
162 nub
= createNub( dict
);
167 nub
->registerService();
174 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
178 nub
= new IOPlatformDevice
;
180 if( !nub
->init( from
)) {
188 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
189 OSString
* name
, OSString
** matched
) const
191 return( nub
->IORegistryEntry::compareName( name
, matched
));
194 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
196 return( kIOReturnSuccess
);
199 long IOPlatformExpert::getBootROMType(void)
201 return _peBootROMType
;
204 long IOPlatformExpert::getChipSetType(void)
206 return _peChipSetType
;
209 long IOPlatformExpert::getMachineType(void)
211 return _peMachineType
;
214 void IOPlatformExpert::setBootROMType(long peBootROMType
)
216 _peBootROMType
= peBootROMType
;
219 void IOPlatformExpert::setChipSetType(long peChipSetType
)
221 _peChipSetType
= peChipSetType
;
224 void IOPlatformExpert::setMachineType(long peMachineType
)
226 _peMachineType
= peMachineType
;
229 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
234 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
239 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
244 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
246 return(OSDynamicCast(IORangeAllocator
,
247 getProperty("Platform Memory Ranges")));
250 int (*PE_halt_restart
)(unsigned int type
) = 0;
252 int IOPlatformExpert::haltRestart(unsigned int type
)
254 if (type
== kPEHangCPU
) while (1);
256 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
260 void IOPlatformExpert::sleepKernel(void)
266 intState
= ml_set_interrupts_enabled(false);
268 for (cnt
= 0; cnt
< 10000; cnt
++) {
272 ml_set_interrupts_enabled(intState
);
274 // PE_initialize_console(0, kPEDisableScreen);
278 // PE_initialize_console(0, kPEEnableScreen);
282 long IOPlatformExpert::getGMTTimeOfDay(void)
287 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
292 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
294 return( PE_current_console( consoleInfo
));
297 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
300 return( PE_initialize_console( consoleInfo
, op
));
303 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
305 IOLockLock(gIOInterruptControllersLock
);
307 gIOInterruptControllers
->setObject(name
, interruptController
);
309 IOLockWakeup(gIOInterruptControllersLock
,
310 gIOInterruptControllers
, /* one-thread */ false);
312 IOLockUnlock(gIOInterruptControllersLock
);
314 return kIOReturnSuccess
;
317 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
321 IOLockLock(gIOInterruptControllersLock
);
324 object
= gIOInterruptControllers
->getObject(name
);
329 IOLockSleep(gIOInterruptControllersLock
,
330 gIOInterruptControllers
, THREAD_UNINT
);
333 IOLockUnlock(gIOInterruptControllersLock
);
334 return OSDynamicCast(IOInterruptController
, object
);
338 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
340 IOCPUInterruptController
*controller
;
342 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
343 if (controller
) controller
->setCPUInterruptProperties(service
);
346 bool IOPlatformExpert::atInterruptLevel(void)
348 return ml_at_interrupt_context();
351 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
357 //*********************************************************************************
360 //*********************************************************************************
362 void IOPlatformExpert::PMLog(const char * who
,unsigned long event
,unsigned long param1
, unsigned long param2
)
364 if( gIOKitDebug
& kIOLogPower
) {
365 kprintf("%s %02d %08x %08x\n",who
,event
,param1
,param2
);
366 // IOLog("%s %02d %08x %08x\n",who,event,param1,param2);
371 //*********************************************************************************
372 // PMInstantiatePowerDomains
374 // In this vanilla implementation, a Root Power Domain is instantiated.
375 // All other objects which register will be children of this Root.
376 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
377 // in a platform-specific subclass.
378 //*********************************************************************************
380 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
382 root
= new IOPMrootDomain
;
390 //*********************************************************************************
393 // In this vanilla implementation, all callers are made children of the root power domain.
394 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
395 //*********************************************************************************
397 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
399 root
->addPowerChild ( theDevice
);
402 //*********************************************************************************
405 //*********************************************************************************
407 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
409 return ((_pePMFeatures
& featureMask
) != 0);
412 //*********************************************************************************
415 //*********************************************************************************
417 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
419 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
422 //*********************************************************************************
423 // numBatteriesSupported
425 //*********************************************************************************
427 int IOPlatformExpert::numBatteriesSupported (void)
429 return (_peNumBatteriesSupported
);
432 //*********************************************************************************
435 // This method is called by the instantiated sublass of the platform expert to
436 // determine how a device should be inserted into the Power Domain. The subclass
437 // provides an XML power tree description against which a device is matched based
438 // on class and provider. If a match is found this routine returns true in addition
439 // to flagging the description tree at the appropriate node that a device has been
440 // registered for the given service.
441 //*********************************************************************************
443 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
446 unsigned int numPowerTreeNodes
;
447 OSDictionary
* entry
;
448 OSDictionary
* matchingDictionary
;
449 OSDictionary
* providerDictionary
;
450 OSDictionary
* deviceDictionary
;
451 OSDictionary
* nubDictionary
;
453 bool nodeFound
= false;
454 bool continueSearch
= false;
455 bool deviceMatch
= false;
456 bool providerMatch
= false;
457 bool multiParentMatch
= false;
459 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
462 numPowerTreeNodes
= inSubTree
->getCount ();
464 // iterate through the power tree to find a home for this device
466 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
468 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
470 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
471 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
473 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
474 if ( matchingDictionary
) {
476 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
477 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
478 deviceDictionary
->release ();
482 providerMatch
= true; // we indicate a match if there is no nub or provider
483 if ( theNub
&& providerDictionary
) {
484 providerMatch
= false;
485 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
486 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
487 nubDictionary
->release ();
491 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
492 if (deviceMatch
&& providerMatch
) {
493 if (NULL
!= multipleParentKeyValue
) {
494 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
495 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
499 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
501 // if the power tree specifies a provider dictionary but theNub is
502 // NULL then we cannot match with this entry.
504 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
507 // if this node is THE ONE...then register the device
510 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
512 if ( kIOLogPower
& gIOKitDebug
)
513 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
515 numInstancesRegistered
++;
517 // determine if we need to search for additional nodes for this item
518 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
524 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
526 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
527 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
528 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
531 if ( false == continueSearch
)
535 return ( nodeFound
);
538 //*********************************************************************************
539 // RegisterServiceInTree
541 // Register a device at the specified node of our power tree.
542 //*********************************************************************************
544 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
546 IOService
* aService
;
547 bool registered
= false;
549 unsigned int numChildren
;
550 OSDictionary
* child
;
552 // make sure someone is not already registered here
554 if ( NULL
== theTreeNode
->getObject ("service") ) {
556 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
558 // 1. CHILDREN ------------------
560 // we registered the node in the tree...now if the node has children
561 // registered we must tell this service to add them.
563 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
564 numChildren
= children
->getCount ();
565 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
566 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
567 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
568 theService
->addPowerChild (aService
);
573 // 2. PARENT --------------------
575 // also we must notify the parent of this node (if a registered service
576 // exists there) of a new child.
578 if ( theTreeParentNode
) {
579 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
580 if (aService
!= theProvider
)
581 aService
->addPowerChild (theService
);
591 //*********************************************************************************
592 // printDictionaryKeys
594 // Print the keys for the given dictionary and selected contents.
595 //*********************************************************************************
596 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
598 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
605 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
609 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
611 // if this is the IOClass key, print it's contents
613 if ( mkey
->isEqualTo ("IOClass") ) {
614 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
615 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
618 // if this is an IOProviderClass key print it
620 if ( mkey
->isEqualTo ("IOProviderClass") ) {
621 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
622 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
626 // also print IONameMatch keys
627 if ( mkey
->isEqualTo ("IONameMatch") ) {
628 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
629 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
632 // also print IONameMatched keys
634 if ( mkey
->isEqualTo ("IONameMatched") ) {
635 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
636 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
642 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
644 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
646 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
652 if ( mkey
->isEqualTo ("name") ) {
655 getCStringForObject (inDictionary
->getObject ("name"), nameStr
);
656 if (strlen(nameStr
) > 0)
657 IOLog ("%s name is %s\n", inMsg
, nameStr
);
660 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
668 static void getCStringForObject (OSObject
* inObj
, char * outStr
)
673 if ( (NULL
== inObj
) || (NULL
== outStr
))
676 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
678 if ((0 == strcmp(objString
,"OSString")) || (0 == strcmp (objString
, "OSSymbol")))
679 strcpy (outStr
, ((OSString
*)inObj
)->getCStringNoCopy());
681 else if (0 == strcmp(objString
,"OSData")) {
682 len
= ((OSData
*)inObj
)->getLength();
683 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
684 if (buffer
&& (len
> 0)) {
685 for (i
=0; i
< len
; i
++) {
686 outStr
[i
] = buffer
[i
];
693 /* IOPMPanicOnShutdownHang
694 * - Called from a timer installed by PEHaltRestart
696 static void IOPMPanicOnShutdownHang(thread_call_param_t p0
, thread_call_param_t p1
)
700 /* 30 seconds has elapsed - resume shutdown */
701 gIOPlatform
->haltRestart(type
);
708 * Callouts from BSD for machine name & model
711 boolean_t
PEGetMachineName( char * name
, int maxLength
)
714 return( gIOPlatform
->getMachineName( name
, maxLength
));
719 boolean_t
PEGetModelName( char * name
, int maxLength
)
722 return( gIOPlatform
->getModelName( name
, maxLength
));
727 int PEGetPlatformEpoch(void)
730 return( gIOPlatform
->getBootROMType());
735 int PEHaltRestart(unsigned int type
)
737 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
738 bool noWaitForResponses
;
739 AbsoluteTime deadline
;
740 thread_call_t shutdown_hang
;
742 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
)
744 /* Notify IOKit PM clients of shutdown/restart
745 Clients subscribe to this message with a call to
746 IOService::registerInterest()
749 /* Spawn a thread that will panic in 30 seconds.
750 If all goes well the machine will be off by the time
753 shutdown_hang
= thread_call_allocate( &IOPMPanicOnShutdownHang
, (thread_call_param_t
) type
);
754 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
755 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
757 noWaitForResponses
= pmRootDomain
->tellChangeDown2(type
);
758 /* This notification should have few clients who all do
759 their work synchronously.
761 In this "shutdown notification" context we don't give
762 drivers the option of working asynchronously and responding
763 later. PM internals make it very hard to wait for asynchronous
764 replies. In fact, it's a bad idea to even be calling
765 tellChangeDown2 from here at all.
769 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
773 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
775 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
779 long PEGetGMTTimeOfDay(void)
782 return( gIOPlatform
->getGMTTimeOfDay());
787 void PESetGMTTimeOfDay(long secs
)
790 gIOPlatform
->setGMTTimeOfDay(secs
);
795 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
797 publishResource("IONVRAM");
800 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
801 bool waitForFunction
,
802 void *param1
, void *param2
,
803 void *param3
, void *param4
)
805 IOService
*service
, *_resources
;
807 if (waitForFunction
) {
808 _resources
= waitForService(resourceMatching(functionName
));
810 _resources
= resources();
812 if (_resources
== 0) return kIOReturnUnsupported
;
814 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
815 if (service
== 0) return kIOReturnUnsupported
;
817 return service
->callPlatformFunction(functionName
, waitForFunction
,
818 param1
, param2
, param3
, param4
);
821 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
826 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
829 #define super IOPlatformExpert
831 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
833 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
834 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
835 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
836 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
837 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
838 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
839 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
840 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
842 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
844 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
847 if( !super::probe( provider
, score
))
850 // check machine types
851 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
857 bool IODTPlatformExpert::configure( IOService
* provider
)
859 if( !super::configure( provider
))
862 processTopLevel( provider
);
867 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
871 nub
= new IOPlatformDevice
;
873 if( !nub
->init( from
, gIODTPlane
)) {
881 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
883 IORegistryEntry
* next
;
888 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
890 if( 0 == (nub
= createNub( next
)))
893 nub
->attach( parent
);
894 nub
->registerService();
902 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* root
)
905 IORegistryEntry
* next
;
906 IORegistryEntry
* cpus
;
907 IORegistryEntry
* options
;
910 kids
= IODTFindMatchingEntries( root
, 0, deleteList() );
912 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
913 next
->detachAll( gIODTPlane
);
918 // Publish an IODTNVRAM class on /options.
919 options
= root
->childFromPath("options", gIODTPlane
);
921 dtNVRAM
= new IODTNVRAM
;
923 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
927 dtNVRAM
->attach(this);
928 dtNVRAM
->registerService();
934 cpus
= root
->childFromPath( "cpus", gIODTPlane
);
936 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
938 // publish top level, minus excludeList
939 createNubs( this, IODTFindMatchingEntries( root
, kIODTExclusive
, excludeList()));
942 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
944 if( nub
->getDeviceMemory())
945 return( kIOReturnSuccess
);
947 IODTResolveAddressing( nub
, "reg", 0);
949 return( kIOReturnSuccess
);
952 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
953 OSString
* name
, OSString
** matched
) const
955 return( IODTCompareNubName( nub
, name
, matched
)
956 || super::compareNubName( nub
, name
, matched
) );
959 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
969 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
971 str
= (const char *) prop
->getBytesNoCopy();
973 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
974 str
+= strlen( "AAPL," );
977 while( (c
= *str
++)) {
978 if( (c
== '/') || (c
== ' '))
982 if( len
>= maxLength
)
992 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
998 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1002 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1007 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1009 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1011 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1013 super::registerNVRAMController(nvram
);
1016 int IODTPlatformExpert::haltRestart(unsigned int type
)
1018 if (dtNVRAM
) dtNVRAM
->sync();
1020 return super::haltRestart(type
);
1023 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1026 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1027 else return kIOReturnNotReady
;
1030 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1033 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1034 else return kIOReturnNotReady
;
1037 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1038 IORegistryEntry
* entry
,
1039 const OSSymbol
** name
, OSData
** value
)
1041 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1042 else return kIOReturnNotReady
;
1045 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1046 IORegistryEntry
* entry
,
1047 const OSSymbol
* name
, OSData
* value
)
1049 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1050 else return kIOReturnNotReady
;
1053 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1055 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1059 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1060 IOByteCount offset
, UInt8
* buffer
,
1063 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1065 else return kIOReturnNotReady
;
1068 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1069 IOByteCount offset
, UInt8
* buffer
,
1072 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1074 else return kIOReturnNotReady
;
1077 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1079 IOByteCount lengthSaved
= 0;
1081 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1083 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1088 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1089 UInt8
* serialNumber
;
1090 unsigned int serialNumberSize
;
1095 if (myProperty
!= NULL
) {
1096 serialNumberSize
= myProperty
->getLength();
1097 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1098 temp
= serialNumber
;
1099 if (serialNumberSize
> 0) {
1100 // check to see if this is a CTO serial number...
1101 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1103 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1104 memcpy(SerialNo
, serialNumber
+ 12, 8);
1105 memcpy(&SerialNo
[8], serialNumber
, 3);
1107 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1109 } else { // just a normal serial number
1110 memcpy(SerialNo
, serialNumber
+ 13, 8);
1111 memcpy(&SerialNo
[8], serialNumber
, 3);
1114 return OSString::withCString(SerialNo
);
1121 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1124 #define super IOService
1126 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1128 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1129 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1130 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1131 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1133 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1135 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1136 OSString
** matched
) const
1138 return( IODTCompareNubName( this, name
, matched
));
1142 IOPlatformExpertDevice::initWithArgs(
1143 void * dtTop
, void * p2
, void * p3
, void * p4
)
1145 IORegistryEntry
* dt
= 0;
1146 void * argsData
[ 4 ];
1149 // dtTop may be zero on non- device tree systems
1150 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1151 ok
= super::init( dt
, gIODTPlane
);
1158 workLoop
= IOWorkLoop::workLoop();
1162 argsData
[ 0 ] = dtTop
;
1167 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1172 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1177 void IOPlatformExpertDevice::free()
1180 workLoop
->release();
1183 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1186 #define super IOService
1188 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1190 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1191 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1192 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1193 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1195 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1197 bool IOPlatformDevice::compareName( OSString
* name
,
1198 OSString
** matched
) const
1200 return( ((IOPlatformExpert
*)getProvider())->
1201 compareNubName( this, name
, matched
));
1204 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1209 IOReturn
IOPlatformDevice::getResources( void )
1211 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1214 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1216 /*********************************************************************
1217 * IOPanicPlatform class
1219 * If no legitimate IOPlatformDevice matches, this one does and panics
1220 * the kernel with a suitable message.
1221 *********************************************************************/
1223 class IOPanicPlatform
: IOPlatformExpert
{
1224 OSDeclareDefaultStructors(IOPanicPlatform
);
1227 bool start(IOService
* provider
);
1231 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1234 bool IOPanicPlatform::start(IOService
* provider
) {
1235 const char * platform_name
= "(unknown platform name)";
1237 if (provider
) platform_name
= provider
->getName();
1239 panic("Unable to find driver for this platform: \"%s\".\n",