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