]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOPlatformExpert.cpp
xnu-792.17.14.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPlatformExpert.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * HISTORY
30 */
31
1c79356b
A
32#include <IOKit/IOCPU.h>
33#include <IOKit/IODeviceTreeSupport.h>
de355530 34#include <IOKit/IOKitDebug.h>
55e303ae
A
35#include <IOKit/IOMapper.h>
36#include <IOKit/IOMessage.h>
37#include <IOKit/IONVRAM.h>
38#include <IOKit/IOPlatformExpert.h>
39#include <IOKit/IORangeAllocator.h>
1c79356b
A
40#include <IOKit/IOWorkLoop.h>
41#include <IOKit/pwr_mgt/RootDomain.h>
55e303ae 42#include <IOKit/IOKitKeys.h>
91447636 43#include <IOKit/IOTimeStamp.h>
55e303ae
A
44
45#include <IOKit/system.h>
46
1c79356b
A
47#include <libkern/c++/OSContainers.h>
48
1c79356b
A
49extern "C" {
50#include <machine/machine_routines.h>
51#include <pexpert/pexpert.h>
52}
53
54void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg);
55static void getCStringForObject (OSObject * inObj, char * outStr);
56
57/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
58
59#define super IOService
60
61OSDefineMetaClassAndStructors(IOPlatformExpert, IOService)
62
9bccf70c
A
63OSMetaClassDefineReservedUsed(IOPlatformExpert, 0);
64
55e303ae 65OSMetaClassDefineReservedUsed(IOPlatformExpert, 1);
1c79356b
A
66OSMetaClassDefineReservedUnused(IOPlatformExpert, 2);
67OSMetaClassDefineReservedUnused(IOPlatformExpert, 3);
68OSMetaClassDefineReservedUnused(IOPlatformExpert, 4);
69OSMetaClassDefineReservedUnused(IOPlatformExpert, 5);
70OSMetaClassDefineReservedUnused(IOPlatformExpert, 6);
71OSMetaClassDefineReservedUnused(IOPlatformExpert, 7);
72OSMetaClassDefineReservedUnused(IOPlatformExpert, 8);
73OSMetaClassDefineReservedUnused(IOPlatformExpert, 9);
74OSMetaClassDefineReservedUnused(IOPlatformExpert, 10);
75OSMetaClassDefineReservedUnused(IOPlatformExpert, 11);
76
77static IOPlatformExpert * gIOPlatform;
fa4905b1
A
78static OSDictionary * gIOInterruptControllers;
79static IOLock * gIOInterruptControllersLock;
1c79356b
A
80
81OSSymbol * gPlatformInterruptControllerName;
82
83/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
84
85bool IOPlatformExpert::attach( IOService * provider )
86{
87
88 if( !super::attach( provider ))
89 return( false);
90
91 return( true);
92}
93
94bool IOPlatformExpert::start( IOService * provider )
95{
96 IORangeAllocator * physicalRanges;
97 OSData * busFrequency;
3a60a9f5 98 uint32_t debugFlags;
1c79356b
A
99
100 if (!super::start(provider))
101 return false;
3a60a9f5
A
102
103 // Override the mapper present flag is requested by boot arguments.
104 if (PE_parse_boot_arg("dart", &debugFlags) && (debugFlags == 0))
105 removeProperty(kIOPlatformMapperPresentKey);
106
55e303ae
A
107 // Register the presence or lack thereof a system
108 // PCI address mapper with the IOMapper class
55e303ae 109 IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey));
1c79356b 110
fa4905b1
A
111 gIOInterruptControllers = OSDictionary::withCapacity(1);
112 gIOInterruptControllersLock = IOLockAlloc();
113
1c79356b
A
114 // Correct the bus frequency in the device tree.
115 busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4);
116 provider->setProperty("clock-frequency", busFrequency);
117 busFrequency->release();
118
119 gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
120
121 physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16,
122 IORangeAllocator::kLocking);
123 assert(physicalRanges);
124 setProperty("Platform Memory Ranges", physicalRanges);
125
126 setPlatform( this );
127 gIOPlatform = this;
128
129 PMInstantiatePowerDomains();
130
55e303ae
A
131 // Parse the serial-number data and publish a user-readable string
132 OSData* mydata = (OSData*) (provider->getProperty("serial-number"));
133 if (mydata != NULL) {
134 OSString *serNoString = createSystemSerialNumberString(mydata);
135 if (serNoString != NULL) {
136 provider->setProperty(kIOPlatformSerialNumberKey, serNoString);
137 serNoString->release();
138 }
139 }
140
1c79356b
A
141 return( configure(provider) );
142}
143
144bool IOPlatformExpert::configure( IOService * provider )
145{
146 OSSet * topLevel;
147 OSDictionary * dict;
148 IOService * nub;
149
150 topLevel = OSDynamicCast( OSSet, getProperty("top-level"));
151
152 if( topLevel) {
153 while( (dict = OSDynamicCast( OSDictionary,
154 topLevel->getAnyObject()))) {
155 dict->retain();
156 topLevel->removeObject( dict );
157 nub = createNub( dict );
158 if( 0 == nub)
159 continue;
160 dict->release();
161 nub->attach( this );
162 nub->registerService();
163 }
164 }
165
166 return( true );
167}
168
169IOService * IOPlatformExpert::createNub( OSDictionary * from )
170{
171 IOService * nub;
172
173 nub = new IOPlatformDevice;
174 if(nub) {
175 if( !nub->init( from )) {
176 nub->release();
177 nub = 0;
178 }
179 }
180 return( nub);
181}
182
183bool IOPlatformExpert::compareNubName( const IOService * nub,
55e303ae 184 OSString * name, OSString ** matched ) const
1c79356b
A
185{
186 return( nub->IORegistryEntry::compareName( name, matched ));
187}
188
189IOReturn IOPlatformExpert::getNubResources( IOService * nub )
190{
191 return( kIOReturnSuccess );
192}
193
194long IOPlatformExpert::getBootROMType(void)
195{
196 return _peBootROMType;
197}
198
199long IOPlatformExpert::getChipSetType(void)
200{
201 return _peChipSetType;
202}
203
204long IOPlatformExpert::getMachineType(void)
205{
206 return _peMachineType;
207}
208
209void IOPlatformExpert::setBootROMType(long peBootROMType)
210{
211 _peBootROMType = peBootROMType;
212}
213
214void IOPlatformExpert::setChipSetType(long peChipSetType)
215{
216 _peChipSetType = peChipSetType;
217}
218
219void IOPlatformExpert::setMachineType(long peMachineType)
220{
221 _peMachineType = peMachineType;
222}
223
224bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
225{
226 return( false );
227}
228
229bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
230{
231 return( false );
232}
233
55e303ae
A
234OSString* IOPlatformExpert::createSystemSerialNumberString(OSData* myProperty)
235{
236 return NULL;
237}
238
1c79356b
A
239IORangeAllocator * IOPlatformExpert::getPhysicalRangeAllocator(void)
240{
241 return(OSDynamicCast(IORangeAllocator,
242 getProperty("Platform Memory Ranges")));
243}
244
245int (*PE_halt_restart)(unsigned int type) = 0;
246
247int IOPlatformExpert::haltRestart(unsigned int type)
248{
8f6c56a5
A
249 IOPMrootDomain *rd = getPMRootDomain();
250 OSBoolean *b = 0;
251
252 if(rd) b = (OSBoolean *)OSDynamicCast(OSBoolean, rd->getProperty(OSString::withCString("StallSystemAtHalt")));
5d5c5d0d 253
8f6c56a5 254 if (type == kPEHangCPU) while (1);
5d5c5d0d 255
8f6c56a5
A
256 if (kOSBooleanTrue == b) {
257 // Stall shutdown for 5 minutes, and if no outside force has removed our power, continue with
258 // a reboot.
259 IOSleep(1000*60*5);
4a249263
A
260 type = kPERestartCPU;
261 }
9bccf70c 262
1c79356b
A
263 if (PE_halt_restart) return (*PE_halt_restart)(type);
264 else return -1;
265}
266
267void IOPlatformExpert::sleepKernel(void)
268{
269#if 0
270 long cnt;
271 boolean_t intState;
272
273 intState = ml_set_interrupts_enabled(false);
274
275 for (cnt = 0; cnt < 10000; cnt++) {
276 IODelay(1000);
277 }
278
279 ml_set_interrupts_enabled(intState);
280#else
281// PE_initialize_console(0, kPEDisableScreen);
282
283 IOCPUSleepKernel();
284
285// PE_initialize_console(0, kPEEnableScreen);
286#endif
287}
288
289long IOPlatformExpert::getGMTTimeOfDay(void)
290{
291 return(0);
292}
293
294void IOPlatformExpert::setGMTTimeOfDay(long secs)
295{
296}
297
298
299IOReturn IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo )
300{
301 return( PE_current_console( consoleInfo));
302}
303
304IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
305 unsigned int op)
306{
307 return( PE_initialize_console( consoleInfo, op ));
308}
309
310IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
311{
fa4905b1
A
312 IOLockLock(gIOInterruptControllersLock);
313
314 gIOInterruptControllers->setObject(name, interruptController);
315
9bccf70c
A
316 IOLockWakeup(gIOInterruptControllersLock,
317 gIOInterruptControllers, /* one-thread */ false);
318
fa4905b1 319 IOLockUnlock(gIOInterruptControllersLock);
1c79356b
A
320
321 return kIOReturnSuccess;
322}
323
324IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
325{
fa4905b1 326 OSObject *object;
1c79356b 327
9bccf70c 328 IOLockLock(gIOInterruptControllersLock);
fa4905b1 329 while (1) {
fa4905b1
A
330
331 object = gIOInterruptControllers->getObject(name);
332
9bccf70c
A
333 if (object != 0)
334 break;
fa4905b1 335
9bccf70c
A
336 IOLockSleep(gIOInterruptControllersLock,
337 gIOInterruptControllers, THREAD_UNINT);
fa4905b1 338 }
1c79356b 339
9bccf70c 340 IOLockUnlock(gIOInterruptControllersLock);
fa4905b1 341 return OSDynamicCast(IOInterruptController, object);
1c79356b
A
342}
343
344
345void IOPlatformExpert::setCPUInterruptProperties(IOService *service)
346{
347 IOCPUInterruptController *controller;
348
349 controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
350 if (controller) controller->setCPUInterruptProperties(service);
351}
352
353bool IOPlatformExpert::atInterruptLevel(void)
354{
355 return ml_at_interrupt_context();
356}
357
358bool IOPlatformExpert::platformAdjustService(IOService */*service*/)
359{
360 return true;
361}
362
363
364//*********************************************************************************
365// PMLog
366//
367//*********************************************************************************
368
91447636
A
369void IOPlatformExpert::
370PMLog(const char *who, unsigned long event,
371 unsigned long param1, unsigned long param2)
1c79356b 372{
91447636
A
373 UInt32 debugFlags = gIOKitDebug;
374
375 if (debugFlags & kIOLogPower) {
376
377 uint32_t nows, nowus;
378 clock_get_system_microtime(&nows, &nowus);
379 nowus += (nows % 1000) * 1000000;
380
381 kprintf("pm%u %x %.30s %d %x %x\n",
382 nowus, (unsigned) current_thread(), who, // Identity
383 (int) event, param1, param2); // Args
384
385 if (debugFlags & kIOLogTracePower) {
386 static const UInt32 sStartStopBitField[] =
387 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
388
389 // Arcane formula from Hacker's Delight by Warren
390 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
391 UInt32 sgnevent = ((long) event >> 31);
392 UInt32 absevent = sgnevent ^ (event + sgnevent);
393 UInt32 code = IODBG_POWER(absevent);
394
395 UInt32 bit = 1 << (absevent & 0x1f);
396 if (absevent < sizeof(sStartStopBitField) * 8
397 && (sStartStopBitField[absevent >> 5] & bit) ) {
398 // Or in the START or END bits, Start = 1 & END = 2
399 // If sgnevent == 0 then START - 0 => START
400 // else if sgnevent == -1 then START - -1 => END
401 code |= DBG_FUNC_START - sgnevent;
402 }
403
404 // Record the timestamp, wish I had a this pointer
405 IOTimeStampConstant(code, (UInt32) who, event, param1, param2);
406 }
1c79356b
A
407 }
408}
409
410
411//*********************************************************************************
412// PMInstantiatePowerDomains
413//
414// In this vanilla implementation, a Root Power Domain is instantiated.
415// All other objects which register will be children of this Root.
416// Where this is inappropriate, PMInstantiatePowerDomains is overridden
417// in a platform-specific subclass.
418//*********************************************************************************
419
420void IOPlatformExpert::PMInstantiatePowerDomains ( void )
421{
422 root = new IOPMrootDomain;
423 root->init();
424 root->attach(this);
425 root->start(this);
426 root->youAreRoot();
427}
428
429
430//*********************************************************************************
431// PMRegisterDevice
432//
433// In this vanilla implementation, all callers are made children of the root power domain.
434// Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
435//*********************************************************************************
436
437void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
438{
439 root->addPowerChild ( theDevice );
440}
441
442//*********************************************************************************
443// hasPMFeature
444//
445//*********************************************************************************
446
447bool IOPlatformExpert::hasPMFeature (unsigned long featureMask)
448{
449 return ((_pePMFeatures & featureMask) != 0);
450}
451
452//*********************************************************************************
453// hasPrivPMFeature
454//
455//*********************************************************************************
456
457bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask)
458{
459 return ((_pePrivPMFeatures & privFeatureMask) != 0);
460}
461
462//*********************************************************************************
463// numBatteriesSupported
464//
465//*********************************************************************************
466
467int IOPlatformExpert::numBatteriesSupported (void)
468{
469 return (_peNumBatteriesSupported);
470}
471
472//*********************************************************************************
473// CheckSubTree
474//
475// This method is called by the instantiated sublass of the platform expert to
476// determine how a device should be inserted into the Power Domain. The subclass
477// provides an XML power tree description against which a device is matched based
478// on class and provider. If a match is found this routine returns true in addition
479// to flagging the description tree at the appropriate node that a device has been
480// registered for the given service.
481//*********************************************************************************
482
483bool IOPlatformExpert::CheckSubTree (OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent)
484{
485 unsigned int i;
486 unsigned int numPowerTreeNodes;
487 OSDictionary * entry;
488 OSDictionary * matchingDictionary;
489 OSDictionary * providerDictionary;
490 OSDictionary * deviceDictionary;
491 OSDictionary * nubDictionary;
492 OSArray * children;
493 bool nodeFound = false;
494 bool continueSearch = false;
495 bool deviceMatch = false;
496 bool providerMatch = false;
497 bool multiParentMatch = false;
498
499 if ( (NULL == theDevice) || (NULL == inSubTree) )
500 return false;
501
502 numPowerTreeNodes = inSubTree->getCount ();
503
504 // iterate through the power tree to find a home for this device
505
506 for ( i = 0; i < numPowerTreeNodes; i++ ) {
507
508 entry = (OSDictionary *) inSubTree->getObject (i);
509
510 matchingDictionary = (OSDictionary *) entry->getObject ("device");
511 providerDictionary = (OSDictionary *) entry->getObject ("provider");
512
513 deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match
514 if ( matchingDictionary ) {
515 deviceMatch = false;
516 if ( NULL != (deviceDictionary = theDevice->dictionaryWithProperties ())) {
517 deviceMatch = deviceDictionary->isEqualTo ( matchingDictionary, matchingDictionary );
518 deviceDictionary->release ();
519 }
520 }
521
522 providerMatch = true; // we indicate a match if there is no nub or provider
523 if ( theNub && providerDictionary ) {
524 providerMatch = false;
525 if ( NULL != (nubDictionary = theNub->dictionaryWithProperties ()) ) {
526 providerMatch = nubDictionary->isEqualTo ( providerDictionary, providerDictionary );
527 nubDictionary->release ();
528 }
529 }
530
531 multiParentMatch = true; // again we indicate a match if there is no multi-parent node
532 if (deviceMatch && providerMatch) {
533 if (NULL != multipleParentKeyValue) {
534 OSNumber * aNumber = (OSNumber *) entry->getObject ("multiple-parent");
535 multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo (aNumber) : false;
536 }
537 }
538
539 nodeFound = (deviceMatch && providerMatch && multiParentMatch);
540
541 // if the power tree specifies a provider dictionary but theNub is
542 // NULL then we cannot match with this entry.
543
544 if ( theNub == NULL && providerDictionary != NULL )
545 nodeFound = false;
546
547 // if this node is THE ONE...then register the device
548
549 if ( nodeFound ) {
550 if (RegisterServiceInTree (theDevice, entry, theParent, theNub) ) {
551
552 if ( kIOLogPower & gIOKitDebug)
553 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
554
555 numInstancesRegistered++;
556
557 // determine if we need to search for additional nodes for this item
558 multipleParentKeyValue = (OSNumber *) entry->getObject ("multiple-parent");
559 }
560 else
561 nodeFound = false;
562 }
563
564 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
565
566 if ( continueSearch && (NULL != (children = (OSArray *) entry->getObject ("children"))) ) {
567 nodeFound = CheckSubTree ( children, theNub, theDevice, entry );
568 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
569 }
570
571 if ( false == continueSearch )
572 break;
573 }
574
575 return ( nodeFound );
576}
577
578//*********************************************************************************
579// RegisterServiceInTree
580//
581// Register a device at the specified node of our power tree.
582//*********************************************************************************
583
584bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
585{
586 IOService * aService;
587 bool registered = false;
588 OSArray * children;
589 unsigned int numChildren;
590 OSDictionary * child;
591
592 // make sure someone is not already registered here
593
594 if ( NULL == theTreeNode->getObject ("service") ) {
595
596 if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) {
597
598 // 1. CHILDREN ------------------
599
600 // we registered the node in the tree...now if the node has children
601 // registered we must tell this service to add them.
602
603 if ( NULL != (children = (OSArray *) theTreeNode->getObject ("children")) ) {
604 numChildren = children->getCount ();
605 for ( unsigned int i = 0; i < numChildren; i++ ) {
606 if ( NULL != (child = (OSDictionary *) children->getObject (i)) ) {
607 if ( NULL != (aService = (IOService *) child->getObject ("service")) )
608 theService->addPowerChild (aService);
609 }
610 }
611 }
612
613 // 2. PARENT --------------------
614
615 // also we must notify the parent of this node (if a registered service
616 // exists there) of a new child.
617
618 if ( theTreeParentNode ) {
619 if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) )
620 if (aService != theProvider)
621 aService->addPowerChild (theService);
622 }
623
624 registered = true;
625 }
626 }
627
628 return registered;
629}
630
631//*********************************************************************************
632// printDictionaryKeys
633//
634// Print the keys for the given dictionary and selected contents.
635//*********************************************************************************
636void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg)
637{
638 OSCollectionIterator * mcoll = OSCollectionIterator::withCollection (inDictionary);
639 OSSymbol * mkey;
640 OSString * ioClass;
641 unsigned int i = 0;
642
643 mcoll->reset ();
644
645 mkey = OSDynamicCast (OSSymbol, mcoll->getNextObject ());
646
647 while (mkey) {
648
649 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
650
651 // if this is the IOClass key, print it's contents
652
653 if ( mkey->isEqualTo ("IOClass") ) {
654 ioClass = (OSString *) inDictionary->getObject ("IOClass");
655 if ( ioClass ) IOLog ("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
656 }
657
658 // if this is an IOProviderClass key print it
659
660 if ( mkey->isEqualTo ("IOProviderClass") ) {
661 ioClass = (OSString *) inDictionary->getObject ("IOProviderClass");
662 if ( ioClass ) IOLog ("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
663
664 }
665
666 // also print IONameMatch keys
667 if ( mkey->isEqualTo ("IONameMatch") ) {
668 ioClass = (OSString *) inDictionary->getObject ("IONameMatch");
669 if ( ioClass ) IOLog ("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy () );
670 }
671
672 // also print IONameMatched keys
673
674 if ( mkey->isEqualTo ("IONameMatched") ) {
675 ioClass = (OSString *) inDictionary->getObject ("IONameMatched");
676 if ( ioClass ) IOLog ("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy () );
677 }
678
679#if 0
680 // print clock-id
681
682 if ( mkey->isEqualTo ("AAPL,clock-id") ) {
683 char * cstr;
684 cstr = getCStringForObject (inDictionary->getObject ("AAPL,clock-id"));
685 if (cstr)
686 kprintf (" ===> AAPL,clock-id is %s\n", cstr );
687 }
688#endif
689
690 // print name
691
692 if ( mkey->isEqualTo ("name") ) {
693 char nameStr[64];
694 nameStr[0] = 0;
695 getCStringForObject (inDictionary->getObject ("name"), nameStr );
696 if (strlen(nameStr) > 0)
697 IOLog ("%s name is %s\n", inMsg, nameStr);
698 }
699
700 mkey = (OSSymbol *) mcoll->getNextObject ();
701
702 i++;
703 }
704
705 mcoll->release ();
706}
707
708static void getCStringForObject (OSObject * inObj, char * outStr)
709{
710 char * buffer;
711 unsigned int len, i;
712
713 if ( (NULL == inObj) || (NULL == outStr))
714 return;
715
716 char * objString = (char *) (inObj->getMetaClass())->getClassName();
717
718 if ((0 == strcmp(objString,"OSString")) || (0 == strcmp (objString, "OSSymbol")))
719 strcpy (outStr, ((OSString *)inObj)->getCStringNoCopy());
720
721 else if (0 == strcmp(objString,"OSData")) {
722 len = ((OSData *)inObj)->getLength();
723 buffer = (char *)((OSData *)inObj)->getBytesNoCopy();
724 if (buffer && (len > 0)) {
725 for (i=0; i < len; i++) {
726 outStr[i] = buffer[i];
727 }
728 outStr[len] = 0;
729 }
730 }
731}
732
8f6c56a5 733/* IOPMPanicOnShutdownHang
fa4905b1
A
734 * - Called from a timer installed by PEHaltRestart
735 */
8f6c56a5 736static void IOPMPanicOnShutdownHang(thread_call_param_t p0, thread_call_param_t p1)
fa4905b1
A
737{
738 int type = (int)p0;
739
740 /* 30 seconds has elapsed - resume shutdown */
8f6c56a5 741 gIOPlatform->haltRestart(type);
fa4905b1
A
742}
743
744
1c79356b
A
745extern "C" {
746
747/*
748 * Callouts from BSD for machine name & model
749 */
750
751boolean_t PEGetMachineName( char * name, int maxLength )
752{
753 if( gIOPlatform)
754 return( gIOPlatform->getMachineName( name, maxLength ));
755 else
756 return( false );
757}
758
759boolean_t PEGetModelName( char * name, int maxLength )
760{
761 if( gIOPlatform)
762 return( gIOPlatform->getModelName( name, maxLength ));
763 else
764 return( false );
765}
766
767int PEGetPlatformEpoch(void)
768{
769 if( gIOPlatform)
770 return( gIOPlatform->getBootROMType());
771 else
772 return( -1 );
773}
774
775int PEHaltRestart(unsigned int type)
776{
fa4905b1
A
777 IOPMrootDomain *pmRootDomain = IOService::getPMRootDomain();
778 bool noWaitForResponses;
779 AbsoluteTime deadline;
780 thread_call_t shutdown_hang;
781
8f6c56a5 782 if(type == kPEHaltCPU || type == kPERestartCPU)
9bccf70c
A
783 {
784 /* Notify IOKit PM clients of shutdown/restart
785 Clients subscribe to this message with a call to
786 IOService::registerInterest()
787 */
788
789 /* Spawn a thread that will panic in 30 seconds.
790 If all goes well the machine will be off by the time
791 the timer expires.
792 */
8f6c56a5 793 shutdown_hang = thread_call_allocate( &IOPMPanicOnShutdownHang, (thread_call_param_t) type);
9bccf70c
A
794 clock_interval_to_deadline( 30, kSecondScale, &deadline );
795 thread_call_enter1_delayed( shutdown_hang, 0, deadline );
796
8f6c56a5 797 noWaitForResponses = pmRootDomain->tellChangeDown2(type);
9bccf70c
A
798 /* This notification should have few clients who all do
799 their work synchronously.
800
801 In this "shutdown notification" context we don't give
802 drivers the option of working asynchronously and responding
803 later. PM internals make it very hard to wait for asynchronous
804 replies. In fact, it's a bad idea to even be calling
805 tellChangeDown2 from here at all.
806 */
807 }
fa4905b1 808
1c79356b
A
809 if (gIOPlatform) return gIOPlatform->haltRestart(type);
810 else return -1;
811}
812
9bccf70c
A
813UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length)
814{
815 if (gIOPlatform != 0) return gIOPlatform->savePanicInfo(buffer, length);
816 else return 0;
817}
818
1c79356b
A
819long PEGetGMTTimeOfDay(void)
820{
821 if( gIOPlatform)
8f6c56a5
A
822 return( gIOPlatform->getGMTTimeOfDay());
823 else
824 return( 0 );
1c79356b
A
825}
826
827void PESetGMTTimeOfDay(long secs)
828{
829 if( gIOPlatform)
8f6c56a5 830 gIOPlatform->setGMTTimeOfDay(secs);
1c79356b
A
831}
832
833} /* extern "C" */
834
835void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
836{
837 publishResource("IONVRAM");
838}
839
840IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
841 bool waitForFunction,
842 void *param1, void *param2,
843 void *param3, void *param4)
844{
845 IOService *service, *_resources;
846
847 if (waitForFunction) {
848 _resources = waitForService(resourceMatching(functionName));
849 } else {
850 _resources = resources();
851 }
852 if (_resources == 0) return kIOReturnUnsupported;
853
854 service = OSDynamicCast(IOService, _resources->getProperty(functionName));
855 if (service == 0) return kIOReturnUnsupported;
856
857 return service->callPlatformFunction(functionName, waitForFunction,
858 param1, param2, param3, param4);
859}
860
9bccf70c
A
861IOByteCount IOPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
862{
863 return 0;
864}
1c79356b
A
865
866/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
867
868#undef super
869#define super IOPlatformExpert
870
871OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
872
873OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
874OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
875OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
876OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
877OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
878OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
879OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
880OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
881
882/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
883
884IOService * IODTPlatformExpert::probe( IOService * provider,
885 SInt32 * score )
886{
887 if( !super::probe( provider, score))
888 return( 0 );
889
890 // check machine types
891 if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
892 return( 0 );
893
894 return( this);
895}
896
897bool IODTPlatformExpert::configure( IOService * provider )
898{
899 if( !super::configure( provider))
900 return( false);
901
902 processTopLevel( provider );
903
904 return( true );
905}
906
907IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
908{
909 IOService * nub;
910
911 nub = new IOPlatformDevice;
912 if( nub) {
913 if( !nub->init( from, gIODTPlane )) {
914 nub->free();
915 nub = 0;
916 }
917 }
918 return( nub);
919}
920
921bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
922{
923 IORegistryEntry * next;
924 IOService * nub;
925 bool ok = true;
926
927 if( iter) {
928 while( (next = (IORegistryEntry *) iter->getNextObject())) {
929
930 if( 0 == (nub = createNub( next )))
931 continue;
932
933 nub->attach( parent );
934 nub->registerService();
935 }
936 iter->release();
937 }
938
939 return( ok );
940}
941
91447636 942void IODTPlatformExpert::processTopLevel( IORegistryEntry * rootEntry )
1c79356b
A
943{
944 OSIterator * kids;
945 IORegistryEntry * next;
946 IORegistryEntry * cpus;
947 IORegistryEntry * options;
948
949 // infanticide
91447636 950 kids = IODTFindMatchingEntries( rootEntry, 0, deleteList() );
1c79356b
A
951 if( kids) {
952 while( (next = (IORegistryEntry *)kids->getNextObject())) {
953 next->detachAll( gIODTPlane);
954 }
955 kids->release();
956 }
957
958 // Publish an IODTNVRAM class on /options.
91447636 959 options = rootEntry->childFromPath("options", gIODTPlane);
1c79356b
A
960 if (options) {
961 dtNVRAM = new IODTNVRAM;
962 if (dtNVRAM) {
963 if (!dtNVRAM->init(options, gIODTPlane)) {
964 dtNVRAM->release();
965 dtNVRAM = 0;
966 } else {
967 dtNVRAM->attach(this);
968 dtNVRAM->registerService();
969 }
970 }
971 }
972
973 // Publish the cpus.
91447636 974 cpus = rootEntry->childFromPath( "cpus", gIODTPlane);
1c79356b
A
975 if ( cpus)
976 createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
977
978 // publish top level, minus excludeList
91447636 979 createNubs( this, IODTFindMatchingEntries( rootEntry, kIODTExclusive, excludeList()));
1c79356b
A
980}
981
982IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
983{
984 if( nub->getDeviceMemory())
985 return( kIOReturnSuccess );
986
987 IODTResolveAddressing( nub, "reg", 0);
988
989 return( kIOReturnSuccess);
990}
991
992bool IODTPlatformExpert::compareNubName( const IOService * nub,
993 OSString * name, OSString ** matched ) const
994{
995 return( IODTCompareNubName( nub, name, matched )
996 || super::compareNubName( nub, name, matched) );
997}
998
999bool IODTPlatformExpert::getModelName( char * name, int maxLength )
1000{
1001 OSData * prop;
1002 const char * str;
1003 int len;
1004 char c;
1005 bool ok = false;
1006
1007 maxLength--;
1008
1009 prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
1010 if( prop ) {
1011 str = (const char *) prop->getBytesNoCopy();
1012
1013 if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) ))
1014 str += strlen( "AAPL," );
1015
1016 len = 0;
1017 while( (c = *str++)) {
1018 if( (c == '/') || (c == ' '))
1019 c = '-';
1020
1021 name[ len++ ] = c;
1022 if( len >= maxLength)
1023 break;
1024 }
1025
1026 name[ len ] = 0;
1027 ok = true;
1028 }
1029 return( ok );
1030}
1031
1032bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
1033{
1034 OSData * prop;
1035 bool ok = false;
1036
1037 maxLength--;
1038 prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
1039 ok = (0 != prop);
1040
1041 if( ok )
1042 strncpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
1043
1044 return( ok );
1045}
1046
1047/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1048
1049void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
1050{
1051 if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram);
1052
1053 super::registerNVRAMController(nvram);
1054}
1055
1056int IODTPlatformExpert::haltRestart(unsigned int type)
1057{
1058 if (dtNVRAM) dtNVRAM->sync();
1059
1060 return super::haltRestart(type);
1061}
1062
1063IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
1064 IOByteCount length)
1065{
1066 if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length);
1067 else return kIOReturnNotReady;
1068}
1069
1070IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
1071 IOByteCount length)
1072{
1073 if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length);
1074 else return kIOReturnNotReady;
1075}
1076
1077IOReturn IODTPlatformExpert::readNVRAMProperty(
1078 IORegistryEntry * entry,
1079 const OSSymbol ** name, OSData ** value )
1080{
1081 if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value);
1082 else return kIOReturnNotReady;
1083}
1084
1085IOReturn IODTPlatformExpert::writeNVRAMProperty(
1086 IORegistryEntry * entry,
1087 const OSSymbol * name, OSData * value )
1088{
1089 if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value);
1090 else return kIOReturnNotReady;
1091}
1092
d52fe63f
A
1093OSDictionary *IODTPlatformExpert::getNVRAMPartitions(void)
1094{
1095 if (dtNVRAM) return dtNVRAM->getNVRAMPartitions();
1096 else return 0;
1097}
1098
1099IOReturn IODTPlatformExpert::readNVRAMPartition(const OSSymbol * partitionID,
1100 IOByteCount offset, UInt8 * buffer,
1101 IOByteCount length)
1102{
1103 if (dtNVRAM) return dtNVRAM->readNVRAMPartition(partitionID, offset,
1104 buffer, length);
1105 else return kIOReturnNotReady;
1106}
1107
1108IOReturn IODTPlatformExpert::writeNVRAMPartition(const OSSymbol * partitionID,
1109 IOByteCount offset, UInt8 * buffer,
1110 IOByteCount length)
1111{
1112 if (dtNVRAM) return dtNVRAM->writeNVRAMPartition(partitionID, offset,
1113 buffer, length);
1114 else return kIOReturnNotReady;
1115}
1116
9bccf70c
A
1117IOByteCount IODTPlatformExpert::savePanicInfo(UInt8 *buffer, IOByteCount length)
1118{
1119 IOByteCount lengthSaved = 0;
1120
1121 if (dtNVRAM) lengthSaved = dtNVRAM->savePanicInfo(buffer, length);
1122
1123 if (lengthSaved == 0) lengthSaved = super::savePanicInfo(buffer, length);
1124
1125 return lengthSaved;
1126}
d52fe63f 1127
55e303ae
A
1128OSString* IODTPlatformExpert::createSystemSerialNumberString(OSData* myProperty) {
1129 UInt8* serialNumber;
1130 unsigned int serialNumberSize;
91447636 1131 unsigned short pos = 0;
55e303ae
A
1132 char* temp;
1133 char SerialNo[30];
1134
1135 if (myProperty != NULL) {
1136 serialNumberSize = myProperty->getLength();
1137 serialNumber = (UInt8*)(myProperty->getBytesNoCopy());
91447636 1138 temp = (char*)serialNumber;
55e303ae
A
1139 if (serialNumberSize > 0) {
1140 // check to see if this is a CTO serial number...
1141 while (pos < serialNumberSize && temp[pos] != '-') pos++;
1142
1143 if (pos < serialNumberSize) { // there was a hyphen, so it's a CTO serial number
1144 memcpy(SerialNo, serialNumber + 12, 8);
1145 memcpy(&SerialNo[8], serialNumber, 3);
1146 SerialNo[11] = '-';
1147 memcpy(&SerialNo[12], serialNumber + 3, 8);
1148 SerialNo[20] = 0;
1149 } else { // just a normal serial number
1150 memcpy(SerialNo, serialNumber + 13, 8);
1151 memcpy(&SerialNo[8], serialNumber, 3);
1152 SerialNo[11] = 0;
1153 }
1154 return OSString::withCString(SerialNo);
1155 }
1156 }
1157 return NULL;
1158}
1159
1160
1c79356b
A
1161/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1162
1163#undef super
1164#define super IOService
1165
1166OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService)
1167
1168OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
1169OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
1170OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
1171OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
1172
1173/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1174
1175bool IOPlatformExpertDevice::compareName( OSString * name,
55e303ae 1176 OSString ** matched ) const
1c79356b
A
1177{
1178 return( IODTCompareNubName( this, name, matched ));
1179}
1180
1181bool
1182IOPlatformExpertDevice::initWithArgs(
1183 void * dtTop, void * p2, void * p3, void * p4 )
1184{
1185 IORegistryEntry * dt = 0;
1186 void * argsData[ 4 ];
1187 bool ok;
1188
1189 // dtTop may be zero on non- device tree systems
1190 if( dtTop && (dt = IODeviceTreeAlloc( dtTop )))
1191 ok = super::init( dt, gIODTPlane );
1192 else
1193 ok = super::init();
1194
1195 if( !ok)
1196 return( false);
1197
1198 workLoop = IOWorkLoop::workLoop();
1199 if (!workLoop)
1200 return false;
1201
1202 argsData[ 0 ] = dtTop;
1203 argsData[ 1 ] = p2;
1204 argsData[ 2 ] = p3;
1205 argsData[ 3 ] = p4;
1206
1207 setProperty("IOPlatformArgs", (void *)argsData, sizeof( argsData));
1208
1209 return( true);
1210}
1211
1212IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const
1213{
1214 return workLoop;
1215}
1216
1217void IOPlatformExpertDevice::free()
1218{
1219 if (workLoop)
1220 workLoop->release();
1221}
1222
1223/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1224
1225#undef super
1226#define super IOService
1227
1228OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
1229
1230OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
1231OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
1232OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
1233OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
1234
1235/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1236
1237bool IOPlatformDevice::compareName( OSString * name,
55e303ae 1238 OSString ** matched ) const
1c79356b
A
1239{
1240 return( ((IOPlatformExpert *)getProvider())->
1241 compareNubName( this, name, matched ));
1242}
1243
1244IOService * IOPlatformDevice::matchLocation( IOService * /* client */ )
1245{
1246 return( this );
1247}
1248
1249IOReturn IOPlatformDevice::getResources( void )
1250{
1251 return( ((IOPlatformExpert *)getProvider())->getNubResources( this ));
1252}
1253
1254/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1255
1256/*********************************************************************
1257* IOPanicPlatform class
1258*
1259* If no legitimate IOPlatformDevice matches, this one does and panics
1260* the kernel with a suitable message.
1261*********************************************************************/
1262
1263class IOPanicPlatform : IOPlatformExpert {
1264 OSDeclareDefaultStructors(IOPanicPlatform);
1265
1266public:
1267 bool start(IOService * provider);
1268};
1269
1270
1271OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
1272
1273
1274bool IOPanicPlatform::start(IOService * provider) {
1275 const char * platform_name = "(unknown platform name)";
1276
1277 if (provider) platform_name = provider->getName();
1278
1279 panic("Unable to find driver for this platform: \"%s\".\n",
1280 platform_name);
1281
1282 return false;
1283}