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>
38 #include <IOKit/system.h>
40 #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
;
93 if (!super::start(provider
))
96 // Register the presence or lack thereof a system
97 // PCI address mapper with the IOMapper class
100 IORegistryEntry
* regEntry
= IORegistryEntry::fromPath("/u3/dart", gIODTPlane
);
102 regEntry
= IORegistryEntry::fromPath("/dart", gIODTPlane
);
105 if (!PE_parse_boot_arg("dart", &debugFlags
) || debugFlags
)
106 setProperty(kIOPlatformMapperPresentKey
, kOSBooleanTrue
);
111 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey
));
113 gIOInterruptControllers
= OSDictionary::withCapacity(1);
114 gIOInterruptControllersLock
= IOLockAlloc();
116 // Correct the bus frequency in the device tree.
117 busFrequency
= OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo
.bus_clock_rate_hz
, 4);
118 provider
->setProperty("clock-frequency", busFrequency
);
119 busFrequency
->release();
121 gPlatformInterruptControllerName
= (OSSymbol
*)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
123 physicalRanges
= IORangeAllocator::withRange(0xffffffff, 1, 16,
124 IORangeAllocator::kLocking
);
125 assert(physicalRanges
);
126 setProperty("Platform Memory Ranges", physicalRanges
);
131 PMInstantiatePowerDomains();
133 // Parse the serial-number data and publish a user-readable string
134 OSData
* mydata
= (OSData
*) (provider
->getProperty("serial-number"));
135 if (mydata
!= NULL
) {
136 OSString
*serNoString
= createSystemSerialNumberString(mydata
);
137 if (serNoString
!= NULL
) {
138 provider
->setProperty(kIOPlatformSerialNumberKey
, serNoString
);
139 serNoString
->release();
143 return( configure(provider
) );
146 bool IOPlatformExpert::configure( IOService
* provider
)
152 topLevel
= OSDynamicCast( OSSet
, getProperty("top-level"));
155 while( (dict
= OSDynamicCast( OSDictionary
,
156 topLevel
->getAnyObject()))) {
158 topLevel
->removeObject( dict
);
159 nub
= createNub( dict
);
164 nub
->registerService();
171 IOService
* IOPlatformExpert::createNub( OSDictionary
* from
)
175 nub
= new IOPlatformDevice
;
177 if( !nub
->init( from
)) {
185 bool IOPlatformExpert::compareNubName( const IOService
* nub
,
186 OSString
* name
, OSString
** matched
) const
188 return( nub
->IORegistryEntry::compareName( name
, matched
));
191 IOReturn
IOPlatformExpert::getNubResources( IOService
* nub
)
193 return( kIOReturnSuccess
);
196 long IOPlatformExpert::getBootROMType(void)
198 return _peBootROMType
;
201 long IOPlatformExpert::getChipSetType(void)
203 return _peChipSetType
;
206 long IOPlatformExpert::getMachineType(void)
208 return _peMachineType
;
211 void IOPlatformExpert::setBootROMType(long peBootROMType
)
213 _peBootROMType
= peBootROMType
;
216 void IOPlatformExpert::setChipSetType(long peChipSetType
)
218 _peChipSetType
= peChipSetType
;
221 void IOPlatformExpert::setMachineType(long peMachineType
)
223 _peMachineType
= peMachineType
;
226 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
231 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
236 OSString
* IOPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
)
241 IORangeAllocator
* IOPlatformExpert::getPhysicalRangeAllocator(void)
243 return(OSDynamicCast(IORangeAllocator
,
244 getProperty("Platform Memory Ranges")));
247 int (*PE_halt_restart
)(unsigned int type
) = 0;
249 int IOPlatformExpert::haltRestart(unsigned int type
)
251 IOPMrootDomain
*rd
= getPMRootDomain();
254 if(rd
) b
= (OSBoolean
*)OSDynamicCast(OSBoolean
, rd
->getProperty(OSString::withCString("StallSystemAtHalt")));
256 if (type
== kPEHangCPU
) while (1);
258 if (kOSBooleanTrue
== b
) {
259 // Stall shutdown for 5 minutes, and if no outside force has removed our power, continue with
262 type
= kPERestartCPU
;
265 if (PE_halt_restart
) return (*PE_halt_restart
)(type
);
269 void IOPlatformExpert::sleepKernel(void)
275 intState
= ml_set_interrupts_enabled(false);
277 for (cnt
= 0; cnt
< 10000; cnt
++) {
281 ml_set_interrupts_enabled(intState
);
283 // PE_initialize_console(0, kPEDisableScreen);
287 // PE_initialize_console(0, kPEEnableScreen);
291 long IOPlatformExpert::getGMTTimeOfDay(void)
296 void IOPlatformExpert::setGMTTimeOfDay(long secs
)
301 IOReturn
IOPlatformExpert::getConsoleInfo( PE_Video
* consoleInfo
)
303 return( PE_current_console( consoleInfo
));
306 IOReturn
IOPlatformExpert::setConsoleInfo( PE_Video
* consoleInfo
,
309 return( PE_initialize_console( consoleInfo
, op
));
312 IOReturn
IOPlatformExpert::registerInterruptController(OSSymbol
*name
, IOInterruptController
*interruptController
)
314 IOLockLock(gIOInterruptControllersLock
);
316 gIOInterruptControllers
->setObject(name
, interruptController
);
318 IOLockWakeup(gIOInterruptControllersLock
,
319 gIOInterruptControllers
, /* one-thread */ false);
321 IOLockUnlock(gIOInterruptControllersLock
);
323 return kIOReturnSuccess
;
326 IOInterruptController
*IOPlatformExpert::lookUpInterruptController(OSSymbol
*name
)
330 IOLockLock(gIOInterruptControllersLock
);
333 object
= gIOInterruptControllers
->getObject(name
);
338 IOLockSleep(gIOInterruptControllersLock
,
339 gIOInterruptControllers
, THREAD_UNINT
);
342 IOLockUnlock(gIOInterruptControllersLock
);
343 return OSDynamicCast(IOInterruptController
, object
);
347 void IOPlatformExpert::setCPUInterruptProperties(IOService
*service
)
349 IOCPUInterruptController
*controller
;
351 controller
= OSDynamicCast(IOCPUInterruptController
, waitForService(serviceMatching("IOCPUInterruptController")));
352 if (controller
) controller
->setCPUInterruptProperties(service
);
355 bool IOPlatformExpert::atInterruptLevel(void)
357 return ml_at_interrupt_context();
360 bool IOPlatformExpert::platformAdjustService(IOService */
*service*/
)
366 //*********************************************************************************
369 //*********************************************************************************
371 void IOPlatformExpert::PMLog(const char * who
,unsigned long event
,unsigned long param1
, unsigned long param2
)
373 if( gIOKitDebug
& kIOLogPower
) {
374 kprintf("%s %02d %08x %08x\n",who
,event
,param1
,param2
);
375 // IOLog("%s %02d %08x %08x\n",who,event,param1,param2);
380 //*********************************************************************************
381 // PMInstantiatePowerDomains
383 // In this vanilla implementation, a Root Power Domain is instantiated.
384 // All other objects which register will be children of this Root.
385 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
386 // in a platform-specific subclass.
387 //*********************************************************************************
389 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
391 root
= new IOPMrootDomain
;
399 //*********************************************************************************
402 // In this vanilla implementation, all callers are made children of the root power domain.
403 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
404 //*********************************************************************************
406 void IOPlatformExpert::PMRegisterDevice(IOService
* theNub
, IOService
* theDevice
)
408 root
->addPowerChild ( theDevice
);
411 //*********************************************************************************
414 //*********************************************************************************
416 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask
)
418 return ((_pePMFeatures
& featureMask
) != 0);
421 //*********************************************************************************
424 //*********************************************************************************
426 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask
)
428 return ((_pePrivPMFeatures
& privFeatureMask
) != 0);
431 //*********************************************************************************
432 // numBatteriesSupported
434 //*********************************************************************************
436 int IOPlatformExpert::numBatteriesSupported (void)
438 return (_peNumBatteriesSupported
);
441 //*********************************************************************************
444 // This method is called by the instantiated sublass of the platform expert to
445 // determine how a device should be inserted into the Power Domain. The subclass
446 // provides an XML power tree description against which a device is matched based
447 // on class and provider. If a match is found this routine returns true in addition
448 // to flagging the description tree at the appropriate node that a device has been
449 // registered for the given service.
450 //*********************************************************************************
452 bool IOPlatformExpert::CheckSubTree (OSArray
* inSubTree
, IOService
* theNub
, IOService
* theDevice
, OSDictionary
* theParent
)
455 unsigned int numPowerTreeNodes
;
456 OSDictionary
* entry
;
457 OSDictionary
* matchingDictionary
;
458 OSDictionary
* providerDictionary
;
459 OSDictionary
* deviceDictionary
;
460 OSDictionary
* nubDictionary
;
462 bool nodeFound
= false;
463 bool continueSearch
= false;
464 bool deviceMatch
= false;
465 bool providerMatch
= false;
466 bool multiParentMatch
= false;
468 if ( (NULL
== theDevice
) || (NULL
== inSubTree
) )
471 numPowerTreeNodes
= inSubTree
->getCount ();
473 // iterate through the power tree to find a home for this device
475 for ( i
= 0; i
< numPowerTreeNodes
; i
++ ) {
477 entry
= (OSDictionary
*) inSubTree
->getObject (i
);
479 matchingDictionary
= (OSDictionary
*) entry
->getObject ("device");
480 providerDictionary
= (OSDictionary
*) entry
->getObject ("provider");
482 deviceMatch
= true; // if no matching dictionary, this is not a criteria and so must match
483 if ( matchingDictionary
) {
485 if ( NULL
!= (deviceDictionary
= theDevice
->dictionaryWithProperties ())) {
486 deviceMatch
= deviceDictionary
->isEqualTo ( matchingDictionary
, matchingDictionary
);
487 deviceDictionary
->release ();
491 providerMatch
= true; // we indicate a match if there is no nub or provider
492 if ( theNub
&& providerDictionary
) {
493 providerMatch
= false;
494 if ( NULL
!= (nubDictionary
= theNub
->dictionaryWithProperties ()) ) {
495 providerMatch
= nubDictionary
->isEqualTo ( providerDictionary
, providerDictionary
);
496 nubDictionary
->release ();
500 multiParentMatch
= true; // again we indicate a match if there is no multi-parent node
501 if (deviceMatch
&& providerMatch
) {
502 if (NULL
!= multipleParentKeyValue
) {
503 OSNumber
* aNumber
= (OSNumber
*) entry
->getObject ("multiple-parent");
504 multiParentMatch
= (NULL
!= aNumber
) ? multipleParentKeyValue
->isEqualTo (aNumber
) : false;
508 nodeFound
= (deviceMatch
&& providerMatch
&& multiParentMatch
);
510 // if the power tree specifies a provider dictionary but theNub is
511 // NULL then we cannot match with this entry.
513 if ( theNub
== NULL
&& providerDictionary
!= NULL
)
516 // if this node is THE ONE...then register the device
519 if (RegisterServiceInTree (theDevice
, entry
, theParent
, theNub
) ) {
521 if ( kIOLogPower
& gIOKitDebug
)
522 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
524 numInstancesRegistered
++;
526 // determine if we need to search for additional nodes for this item
527 multipleParentKeyValue
= (OSNumber
*) entry
->getObject ("multiple-parent");
533 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
535 if ( continueSearch
&& (NULL
!= (children
= (OSArray
*) entry
->getObject ("children"))) ) {
536 nodeFound
= CheckSubTree ( children
, theNub
, theDevice
, entry
);
537 continueSearch
= ( (false == nodeFound
) || (NULL
!= multipleParentKeyValue
) );
540 if ( false == continueSearch
)
544 return ( nodeFound
);
547 //*********************************************************************************
548 // RegisterServiceInTree
550 // Register a device at the specified node of our power tree.
551 //*********************************************************************************
553 bool IOPlatformExpert::RegisterServiceInTree (IOService
* theService
, OSDictionary
* theTreeNode
, OSDictionary
* theTreeParentNode
, IOService
* theProvider
)
555 IOService
* aService
;
556 bool registered
= false;
558 unsigned int numChildren
;
559 OSDictionary
* child
;
561 // make sure someone is not already registered here
563 if ( NULL
== theTreeNode
->getObject ("service") ) {
565 if ( theTreeNode
->setObject ("service", OSDynamicCast ( OSObject
, theService
)) ) {
567 // 1. CHILDREN ------------------
569 // we registered the node in the tree...now if the node has children
570 // registered we must tell this service to add them.
572 if ( NULL
!= (children
= (OSArray
*) theTreeNode
->getObject ("children")) ) {
573 numChildren
= children
->getCount ();
574 for ( unsigned int i
= 0; i
< numChildren
; i
++ ) {
575 if ( NULL
!= (child
= (OSDictionary
*) children
->getObject (i
)) ) {
576 if ( NULL
!= (aService
= (IOService
*) child
->getObject ("service")) )
577 theService
->addPowerChild (aService
);
582 // 2. PARENT --------------------
584 // also we must notify the parent of this node (if a registered service
585 // exists there) of a new child.
587 if ( theTreeParentNode
) {
588 if ( NULL
!= (aService
= (IOService
*) theTreeParentNode
->getObject ("service")) )
589 if (aService
!= theProvider
)
590 aService
->addPowerChild (theService
);
600 //*********************************************************************************
601 // printDictionaryKeys
603 // Print the keys for the given dictionary and selected contents.
604 //*********************************************************************************
605 void printDictionaryKeys (OSDictionary
* inDictionary
, char * inMsg
)
607 OSCollectionIterator
* mcoll
= OSCollectionIterator::withCollection (inDictionary
);
614 mkey
= OSDynamicCast (OSSymbol
, mcoll
->getNextObject ());
618 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
620 // if this is the IOClass key, print it's contents
622 if ( mkey
->isEqualTo ("IOClass") ) {
623 ioClass
= (OSString
*) inDictionary
->getObject ("IOClass");
624 if ( ioClass
) IOLog ("%s IOClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
627 // if this is an IOProviderClass key print it
629 if ( mkey
->isEqualTo ("IOProviderClass") ) {
630 ioClass
= (OSString
*) inDictionary
->getObject ("IOProviderClass");
631 if ( ioClass
) IOLog ("%s IOProviderClass is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
635 // also print IONameMatch keys
636 if ( mkey
->isEqualTo ("IONameMatch") ) {
637 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatch");
638 if ( ioClass
) IOLog ("%s IONameMatch is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
641 // also print IONameMatched keys
643 if ( mkey
->isEqualTo ("IONameMatched") ) {
644 ioClass
= (OSString
*) inDictionary
->getObject ("IONameMatched");
645 if ( ioClass
) IOLog ("%s IONameMatched is %s\n", inMsg
, ioClass
->getCStringNoCopy () );
651 if ( mkey
->isEqualTo ("AAPL,clock-id") ) {
653 cstr
= getCStringForObject (inDictionary
->getObject ("AAPL,clock-id"));
655 kprintf (" ===> AAPL,clock-id is %s\n", cstr
);
661 if ( mkey
->isEqualTo ("name") ) {
664 getCStringForObject (inDictionary
->getObject ("name"), nameStr
);
665 if (strlen(nameStr
) > 0)
666 IOLog ("%s name is %s\n", inMsg
, nameStr
);
669 mkey
= (OSSymbol
*) mcoll
->getNextObject ();
677 static void getCStringForObject (OSObject
* inObj
, char * outStr
)
682 if ( (NULL
== inObj
) || (NULL
== outStr
))
685 char * objString
= (char *) (inObj
->getMetaClass())->getClassName();
687 if ((0 == strcmp(objString
,"OSString")) || (0 == strcmp (objString
, "OSSymbol")))
688 strcpy (outStr
, ((OSString
*)inObj
)->getCStringNoCopy());
690 else if (0 == strcmp(objString
,"OSData")) {
691 len
= ((OSData
*)inObj
)->getLength();
692 buffer
= (char *)((OSData
*)inObj
)->getBytesNoCopy();
693 if (buffer
&& (len
> 0)) {
694 for (i
=0; i
< len
; i
++) {
695 outStr
[i
] = buffer
[i
];
702 /* IOPMPanicOnShutdownHang
703 * - Called from a timer installed by PEHaltRestart
705 static void IOPMPanicOnShutdownHang(thread_call_param_t p0
, thread_call_param_t p1
)
709 /* 30 seconds has elapsed - resume shutdown */
710 gIOPlatform
->haltRestart(type
);
717 * Callouts from BSD for machine name & model
720 boolean_t
PEGetMachineName( char * name
, int maxLength
)
723 return( gIOPlatform
->getMachineName( name
, maxLength
));
728 boolean_t
PEGetModelName( char * name
, int maxLength
)
731 return( gIOPlatform
->getModelName( name
, maxLength
));
736 int PEGetPlatformEpoch(void)
739 return( gIOPlatform
->getBootROMType());
744 int PEHaltRestart(unsigned int type
)
746 IOPMrootDomain
*pmRootDomain
= IOService::getPMRootDomain();
747 bool noWaitForResponses
;
748 AbsoluteTime deadline
;
749 thread_call_t shutdown_hang
;
751 if(type
== kPEHaltCPU
|| type
== kPERestartCPU
)
753 /* Notify IOKit PM clients of shutdown/restart
754 Clients subscribe to this message with a call to
755 IOService::registerInterest()
758 /* Spawn a thread that will panic in 30 seconds.
759 If all goes well the machine will be off by the time
762 shutdown_hang
= thread_call_allocate( &IOPMPanicOnShutdownHang
, (thread_call_param_t
) type
);
763 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
764 thread_call_enter1_delayed( shutdown_hang
, 0, deadline
);
766 noWaitForResponses
= pmRootDomain
->tellChangeDown2(type
);
767 /* This notification should have few clients who all do
768 their work synchronously.
770 In this "shutdown notification" context we don't give
771 drivers the option of working asynchronously and responding
772 later. PM internals make it very hard to wait for asynchronous
773 replies. In fact, it's a bad idea to even be calling
774 tellChangeDown2 from here at all.
778 if (gIOPlatform
) return gIOPlatform
->haltRestart(type
);
782 UInt32
PESavePanicInfo(UInt8
*buffer
, UInt32 length
)
784 if (gIOPlatform
!= 0) return gIOPlatform
->savePanicInfo(buffer
, length
);
788 long PEGetGMTTimeOfDay(void)
791 return( gIOPlatform
->getGMTTimeOfDay());
796 void PESetGMTTimeOfDay(long secs
)
799 gIOPlatform
->setGMTTimeOfDay(secs
);
804 void IOPlatformExpert::registerNVRAMController(IONVRAMController
* caller
)
806 publishResource("IONVRAM");
809 IOReturn
IOPlatformExpert::callPlatformFunction(const OSSymbol
*functionName
,
810 bool waitForFunction
,
811 void *param1
, void *param2
,
812 void *param3
, void *param4
)
814 IOService
*service
, *_resources
;
816 if (waitForFunction
) {
817 _resources
= waitForService(resourceMatching(functionName
));
819 _resources
= resources();
821 if (_resources
== 0) return kIOReturnUnsupported
;
823 service
= OSDynamicCast(IOService
, _resources
->getProperty(functionName
));
824 if (service
== 0) return kIOReturnUnsupported
;
826 return service
->callPlatformFunction(functionName
, waitForFunction
,
827 param1
, param2
, param3
, param4
);
830 IOByteCount
IOPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
835 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
838 #define super IOPlatformExpert
840 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert
, IOPlatformExpert
)
842 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 0);
843 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 1);
844 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 2);
845 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 3);
846 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 4);
847 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 5);
848 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 6);
849 OSMetaClassDefineReservedUnused(IODTPlatformExpert
, 7);
851 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
853 IOService
* IODTPlatformExpert::probe( IOService
* provider
,
856 if( !super::probe( provider
, score
))
859 // check machine types
860 if( !provider
->compareNames( getProperty( gIONameMatchKey
) ))
866 bool IODTPlatformExpert::configure( IOService
* provider
)
868 if( !super::configure( provider
))
871 processTopLevel( provider
);
876 IOService
* IODTPlatformExpert::createNub( IORegistryEntry
* from
)
880 nub
= new IOPlatformDevice
;
882 if( !nub
->init( from
, gIODTPlane
)) {
890 bool IODTPlatformExpert::createNubs( IOService
* parent
, OSIterator
* iter
)
892 IORegistryEntry
* next
;
897 while( (next
= (IORegistryEntry
*) iter
->getNextObject())) {
899 if( 0 == (nub
= createNub( next
)))
902 nub
->attach( parent
);
903 nub
->registerService();
911 void IODTPlatformExpert::processTopLevel( IORegistryEntry
* root
)
914 IORegistryEntry
* next
;
915 IORegistryEntry
* cpus
;
916 IORegistryEntry
* options
;
919 kids
= IODTFindMatchingEntries( root
, 0, deleteList() );
921 while( (next
= (IORegistryEntry
*)kids
->getNextObject())) {
922 next
->detachAll( gIODTPlane
);
927 // Publish an IODTNVRAM class on /options.
928 options
= root
->childFromPath("options", gIODTPlane
);
930 dtNVRAM
= new IODTNVRAM
;
932 if (!dtNVRAM
->init(options
, gIODTPlane
)) {
936 dtNVRAM
->attach(this);
937 dtNVRAM
->registerService();
943 cpus
= root
->childFromPath( "cpus", gIODTPlane
);
945 createNubs( this, IODTFindMatchingEntries( cpus
, kIODTExclusive
, 0));
947 // publish top level, minus excludeList
948 createNubs( this, IODTFindMatchingEntries( root
, kIODTExclusive
, excludeList()));
951 IOReturn
IODTPlatformExpert::getNubResources( IOService
* nub
)
953 if( nub
->getDeviceMemory())
954 return( kIOReturnSuccess
);
956 IODTResolveAddressing( nub
, "reg", 0);
958 return( kIOReturnSuccess
);
961 bool IODTPlatformExpert::compareNubName( const IOService
* nub
,
962 OSString
* name
, OSString
** matched
) const
964 return( IODTCompareNubName( nub
, name
, matched
)
965 || super::compareNubName( nub
, name
, matched
) );
968 bool IODTPlatformExpert::getModelName( char * name
, int maxLength
)
978 prop
= (OSData
*) getProvider()->getProperty( gIODTCompatibleKey
);
980 str
= (const char *) prop
->getBytesNoCopy();
982 if( 0 == strncmp( str
, "AAPL,", strlen( "AAPL," ) ))
983 str
+= strlen( "AAPL," );
986 while( (c
= *str
++)) {
987 if( (c
== '/') || (c
== ' '))
991 if( len
>= maxLength
)
1001 bool IODTPlatformExpert::getMachineName( char * name
, int maxLength
)
1007 prop
= (OSData
*) getProvider()->getProperty( gIODTModelKey
);
1011 strncpy( name
, (const char *) prop
->getBytesNoCopy(), maxLength
);
1016 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1018 void IODTPlatformExpert::registerNVRAMController( IONVRAMController
* nvram
)
1020 if (dtNVRAM
) dtNVRAM
->registerNVRAMController(nvram
);
1022 super::registerNVRAMController(nvram
);
1025 int IODTPlatformExpert::haltRestart(unsigned int type
)
1027 if (dtNVRAM
) dtNVRAM
->sync();
1029 return super::haltRestart(type
);
1032 IOReturn
IODTPlatformExpert::readXPRAM(IOByteCount offset
, UInt8
* buffer
,
1035 if (dtNVRAM
) return dtNVRAM
->readXPRAM(offset
, buffer
, length
);
1036 else return kIOReturnNotReady
;
1039 IOReturn
IODTPlatformExpert::writeXPRAM(IOByteCount offset
, UInt8
* buffer
,
1042 if (dtNVRAM
) return dtNVRAM
->writeXPRAM(offset
, buffer
, length
);
1043 else return kIOReturnNotReady
;
1046 IOReturn
IODTPlatformExpert::readNVRAMProperty(
1047 IORegistryEntry
* entry
,
1048 const OSSymbol
** name
, OSData
** value
)
1050 if (dtNVRAM
) return dtNVRAM
->readNVRAMProperty(entry
, name
, value
);
1051 else return kIOReturnNotReady
;
1054 IOReturn
IODTPlatformExpert::writeNVRAMProperty(
1055 IORegistryEntry
* entry
,
1056 const OSSymbol
* name
, OSData
* value
)
1058 if (dtNVRAM
) return dtNVRAM
->writeNVRAMProperty(entry
, name
, value
);
1059 else return kIOReturnNotReady
;
1062 OSDictionary
*IODTPlatformExpert::getNVRAMPartitions(void)
1064 if (dtNVRAM
) return dtNVRAM
->getNVRAMPartitions();
1068 IOReturn
IODTPlatformExpert::readNVRAMPartition(const OSSymbol
* partitionID
,
1069 IOByteCount offset
, UInt8
* buffer
,
1072 if (dtNVRAM
) return dtNVRAM
->readNVRAMPartition(partitionID
, offset
,
1074 else return kIOReturnNotReady
;
1077 IOReturn
IODTPlatformExpert::writeNVRAMPartition(const OSSymbol
* partitionID
,
1078 IOByteCount offset
, UInt8
* buffer
,
1081 if (dtNVRAM
) return dtNVRAM
->writeNVRAMPartition(partitionID
, offset
,
1083 else return kIOReturnNotReady
;
1086 IOByteCount
IODTPlatformExpert::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
1088 IOByteCount lengthSaved
= 0;
1090 if (dtNVRAM
) lengthSaved
= dtNVRAM
->savePanicInfo(buffer
, length
);
1092 if (lengthSaved
== 0) lengthSaved
= super::savePanicInfo(buffer
, length
);
1097 OSString
* IODTPlatformExpert::createSystemSerialNumberString(OSData
* myProperty
) {
1098 UInt8
* serialNumber
;
1099 unsigned int serialNumberSize
;
1104 if (myProperty
!= NULL
) {
1105 serialNumberSize
= myProperty
->getLength();
1106 serialNumber
= (UInt8
*)(myProperty
->getBytesNoCopy());
1107 temp
= serialNumber
;
1108 if (serialNumberSize
> 0) {
1109 // check to see if this is a CTO serial number...
1110 while (pos
< serialNumberSize
&& temp
[pos
] != '-') pos
++;
1112 if (pos
< serialNumberSize
) { // there was a hyphen, so it's a CTO serial number
1113 memcpy(SerialNo
, serialNumber
+ 12, 8);
1114 memcpy(&SerialNo
[8], serialNumber
, 3);
1116 memcpy(&SerialNo
[12], serialNumber
+ 3, 8);
1118 } else { // just a normal serial number
1119 memcpy(SerialNo
, serialNumber
+ 13, 8);
1120 memcpy(&SerialNo
[8], serialNumber
, 3);
1123 return OSString::withCString(SerialNo
);
1130 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1133 #define super IOService
1135 OSDefineMetaClassAndStructors(IOPlatformExpertDevice
, IOService
)
1137 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 0);
1138 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 1);
1139 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 2);
1140 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice
, 3);
1142 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1144 bool IOPlatformExpertDevice::compareName( OSString
* name
,
1145 OSString
** matched
) const
1147 return( IODTCompareNubName( this, name
, matched
));
1151 IOPlatformExpertDevice::initWithArgs(
1152 void * dtTop
, void * p2
, void * p3
, void * p4
)
1154 IORegistryEntry
* dt
= 0;
1155 void * argsData
[ 4 ];
1158 // dtTop may be zero on non- device tree systems
1159 if( dtTop
&& (dt
= IODeviceTreeAlloc( dtTop
)))
1160 ok
= super::init( dt
, gIODTPlane
);
1167 workLoop
= IOWorkLoop::workLoop();
1171 argsData
[ 0 ] = dtTop
;
1176 setProperty("IOPlatformArgs", (void *)argsData
, sizeof( argsData
));
1181 IOWorkLoop
*IOPlatformExpertDevice::getWorkLoop() const
1186 void IOPlatformExpertDevice::free()
1189 workLoop
->release();
1192 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1195 #define super IOService
1197 OSDefineMetaClassAndStructors(IOPlatformDevice
, IOService
)
1199 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 0);
1200 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 1);
1201 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 2);
1202 OSMetaClassDefineReservedUnused(IOPlatformDevice
, 3);
1204 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1206 bool IOPlatformDevice::compareName( OSString
* name
,
1207 OSString
** matched
) const
1209 return( ((IOPlatformExpert
*)getProvider())->
1210 compareNubName( this, name
, matched
));
1213 IOService
* IOPlatformDevice::matchLocation( IOService
* /* client */ )
1218 IOReturn
IOPlatformDevice::getResources( void )
1220 return( ((IOPlatformExpert
*)getProvider())->getNubResources( this ));
1223 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1225 /*********************************************************************
1226 * IOPanicPlatform class
1228 * If no legitimate IOPlatformDevice matches, this one does and panics
1229 * the kernel with a suitable message.
1230 *********************************************************************/
1232 class IOPanicPlatform
: IOPlatformExpert
{
1233 OSDeclareDefaultStructors(IOPanicPlatform
);
1236 bool start(IOService
* provider
);
1240 OSDefineMetaClassAndStructors(IOPanicPlatform
, IOPlatformExpert
);
1243 bool IOPanicPlatform::start(IOService
* provider
) {
1244 const char * platform_name
= "(unknown platform name)";
1246 if (provider
) platform_name
= provider
->getName();
1248 panic("Unable to find driver for this platform: \"%s\".\n",