]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPlatformExpert.cpp
7faa1698647e73b42b7b7cfae25b2ba81a97f786
[apple/xnu.git] / iokit / Kernel / IOPlatformExpert.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * HISTORY
24 */
25
26 #include <IOKit/system.h>
27 #include <IOKit/IOPlatformExpert.h>
28 #include <IOKit/IOCPU.h>
29 #include <IOKit/IODeviceTreeSupport.h>
30 #include <IOKit/IORangeAllocator.h>
31 #include <IOKit/IONVRAM.h>
32 #include <IOKit/IOKitDebug.h>
33 #include <IOKit/IOWorkLoop.h>
34 #include <IOKit/pwr_mgt/RootDomain.h>
35
36 #include <libkern/c++/OSContainers.h>
37
38
39 extern "C" {
40 #include <machine/machine_routines.h>
41 #include <pexpert/pexpert.h>
42 }
43
44 void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg);
45 static void getCStringForObject (OSObject * inObj, char * outStr);
46
47 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
48
49 #define super IOService
50
51 OSDefineMetaClassAndStructors(IOPlatformExpert, IOService)
52
53 OSMetaClassDefineReservedUnused(IOPlatformExpert, 0);
54 OSMetaClassDefineReservedUnused(IOPlatformExpert, 1);
55 OSMetaClassDefineReservedUnused(IOPlatformExpert, 2);
56 OSMetaClassDefineReservedUnused(IOPlatformExpert, 3);
57 OSMetaClassDefineReservedUnused(IOPlatformExpert, 4);
58 OSMetaClassDefineReservedUnused(IOPlatformExpert, 5);
59 OSMetaClassDefineReservedUnused(IOPlatformExpert, 6);
60 OSMetaClassDefineReservedUnused(IOPlatformExpert, 7);
61 OSMetaClassDefineReservedUnused(IOPlatformExpert, 8);
62 OSMetaClassDefineReservedUnused(IOPlatformExpert, 9);
63 OSMetaClassDefineReservedUnused(IOPlatformExpert, 10);
64 OSMetaClassDefineReservedUnused(IOPlatformExpert, 11);
65
66 static IOPlatformExpert * gIOPlatform;
67
68 OSSymbol * gPlatformInterruptControllerName;
69
70 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
71
72 bool IOPlatformExpert::attach( IOService * provider )
73 {
74
75 if( !super::attach( provider ))
76 return( false);
77
78 return( true);
79 }
80
81 bool IOPlatformExpert::start( IOService * provider )
82 {
83 IORangeAllocator * physicalRanges;
84 OSData * busFrequency;
85
86 if (!super::start(provider))
87 return false;
88
89 // Correct the bus frequency in the device tree.
90 busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4);
91 provider->setProperty("clock-frequency", busFrequency);
92 busFrequency->release();
93
94 gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
95
96 physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16,
97 IORangeAllocator::kLocking);
98 assert(physicalRanges);
99 setProperty("Platform Memory Ranges", physicalRanges);
100
101 setPlatform( this );
102 gIOPlatform = this;
103
104 PMInstantiatePowerDomains();
105
106 return( configure(provider) );
107 }
108
109 bool IOPlatformExpert::configure( IOService * provider )
110 {
111 OSSet * topLevel;
112 OSDictionary * dict;
113 IOService * nub;
114
115 topLevel = OSDynamicCast( OSSet, getProperty("top-level"));
116
117 if( topLevel) {
118 while( (dict = OSDynamicCast( OSDictionary,
119 topLevel->getAnyObject()))) {
120 dict->retain();
121 topLevel->removeObject( dict );
122 nub = createNub( dict );
123 if( 0 == nub)
124 continue;
125 dict->release();
126 nub->attach( this );
127 nub->registerService();
128 }
129 }
130
131 return( true );
132 }
133
134 IOService * IOPlatformExpert::createNub( OSDictionary * from )
135 {
136 IOService * nub;
137
138 nub = new IOPlatformDevice;
139 if(nub) {
140 if( !nub->init( from )) {
141 nub->release();
142 nub = 0;
143 }
144 }
145 return( nub);
146 }
147
148 bool IOPlatformExpert::compareNubName( const IOService * nub,
149 OSString * name, OSString ** matched = 0 ) const
150 {
151 return( nub->IORegistryEntry::compareName( name, matched ));
152 }
153
154 IOReturn IOPlatformExpert::getNubResources( IOService * nub )
155 {
156 return( kIOReturnSuccess );
157 }
158
159 long IOPlatformExpert::getBootROMType(void)
160 {
161 return _peBootROMType;
162 }
163
164 long IOPlatformExpert::getChipSetType(void)
165 {
166 return _peChipSetType;
167 }
168
169 long IOPlatformExpert::getMachineType(void)
170 {
171 return _peMachineType;
172 }
173
174 void IOPlatformExpert::setBootROMType(long peBootROMType)
175 {
176 _peBootROMType = peBootROMType;
177 }
178
179 void IOPlatformExpert::setChipSetType(long peChipSetType)
180 {
181 _peChipSetType = peChipSetType;
182 }
183
184 void IOPlatformExpert::setMachineType(long peMachineType)
185 {
186 _peMachineType = peMachineType;
187 }
188
189 bool IOPlatformExpert::getMachineName( char * /*name*/, int /*maxLength*/)
190 {
191 return( false );
192 }
193
194 bool IOPlatformExpert::getModelName( char * /*name*/, int /*maxLength*/)
195 {
196 return( false );
197 }
198
199 IORangeAllocator * IOPlatformExpert::getPhysicalRangeAllocator(void)
200 {
201 return(OSDynamicCast(IORangeAllocator,
202 getProperty("Platform Memory Ranges")));
203 }
204
205 int (*PE_halt_restart)(unsigned int type) = 0;
206
207 int IOPlatformExpert::haltRestart(unsigned int type)
208 {
209 if (PE_halt_restart) return (*PE_halt_restart)(type);
210 else return -1;
211 }
212
213 void IOPlatformExpert::sleepKernel(void)
214 {
215 #if 0
216 long cnt;
217 boolean_t intState;
218
219 intState = ml_set_interrupts_enabled(false);
220
221 for (cnt = 0; cnt < 10000; cnt++) {
222 IODelay(1000);
223 }
224
225 ml_set_interrupts_enabled(intState);
226 #else
227 // PE_initialize_console(0, kPEDisableScreen);
228
229 IOCPUSleepKernel();
230
231 // PE_initialize_console(0, kPEEnableScreen);
232 #endif
233 }
234
235 long IOPlatformExpert::getGMTTimeOfDay(void)
236 {
237 return(0);
238 }
239
240 void IOPlatformExpert::setGMTTimeOfDay(long secs)
241 {
242 }
243
244
245 IOReturn IOPlatformExpert::getConsoleInfo( PE_Video * consoleInfo )
246 {
247 return( PE_current_console( consoleInfo));
248 }
249
250 IOReturn IOPlatformExpert::setConsoleInfo( PE_Video * consoleInfo,
251 unsigned int op)
252 {
253 return( PE_initialize_console( consoleInfo, op ));
254 }
255
256 IOReturn IOPlatformExpert::registerInterruptController(OSSymbol *name, IOInterruptController *interruptController)
257 {
258 publishResource(name, interruptController);
259
260 return kIOReturnSuccess;
261 }
262
263 IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name)
264 {
265 IOInterruptController *interruptController;
266 IOService *service;
267
268 service = waitForService(resourceMatching(name));
269
270 interruptController = OSDynamicCast(IOInterruptController, service->getProperty(name));
271
272 return interruptController;
273 }
274
275
276 void IOPlatformExpert::setCPUInterruptProperties(IOService *service)
277 {
278 IOCPUInterruptController *controller;
279
280 controller = OSDynamicCast(IOCPUInterruptController, waitForService(serviceMatching("IOCPUInterruptController")));
281 if (controller) controller->setCPUInterruptProperties(service);
282 }
283
284 bool IOPlatformExpert::atInterruptLevel(void)
285 {
286 return ml_at_interrupt_context();
287 }
288
289 bool IOPlatformExpert::platformAdjustService(IOService */*service*/)
290 {
291 return true;
292 }
293
294
295 //*********************************************************************************
296 // PMLog
297 //
298 //*********************************************************************************
299
300 void IOPlatformExpert::PMLog(const char * who,unsigned long event,unsigned long param1, unsigned long param2)
301 {
302 if( gIOKitDebug & kIOLogPower) {
303 kprintf("%s %02d %08x %08x\n",who,event,param1,param2);
304 // IOLog("%s %02d %08x %08x\n",who,event,param1,param2);
305 }
306 }
307
308
309 //*********************************************************************************
310 // PMInstantiatePowerDomains
311 //
312 // In this vanilla implementation, a Root Power Domain is instantiated.
313 // All other objects which register will be children of this Root.
314 // Where this is inappropriate, PMInstantiatePowerDomains is overridden
315 // in a platform-specific subclass.
316 //*********************************************************************************
317
318 void IOPlatformExpert::PMInstantiatePowerDomains ( void )
319 {
320 root = new IOPMrootDomain;
321 root->init();
322 root->attach(this);
323 root->start(this);
324 root->youAreRoot();
325 }
326
327
328 //*********************************************************************************
329 // PMRegisterDevice
330 //
331 // In this vanilla implementation, all callers are made children of the root power domain.
332 // Where this is inappropriate, PMRegisterDevice is overridden in a platform-specific subclass.
333 //*********************************************************************************
334
335 void IOPlatformExpert::PMRegisterDevice(IOService * theNub, IOService * theDevice)
336 {
337 root->addPowerChild ( theDevice );
338 }
339
340 //*********************************************************************************
341 // hasPMFeature
342 //
343 //*********************************************************************************
344
345 bool IOPlatformExpert::hasPMFeature (unsigned long featureMask)
346 {
347 return ((_pePMFeatures & featureMask) != 0);
348 }
349
350 //*********************************************************************************
351 // hasPrivPMFeature
352 //
353 //*********************************************************************************
354
355 bool IOPlatformExpert::hasPrivPMFeature (unsigned long privFeatureMask)
356 {
357 return ((_pePrivPMFeatures & privFeatureMask) != 0);
358 }
359
360 //*********************************************************************************
361 // numBatteriesSupported
362 //
363 //*********************************************************************************
364
365 int IOPlatformExpert::numBatteriesSupported (void)
366 {
367 return (_peNumBatteriesSupported);
368 }
369
370 //*********************************************************************************
371 // CheckSubTree
372 //
373 // This method is called by the instantiated sublass of the platform expert to
374 // determine how a device should be inserted into the Power Domain. The subclass
375 // provides an XML power tree description against which a device is matched based
376 // on class and provider. If a match is found this routine returns true in addition
377 // to flagging the description tree at the appropriate node that a device has been
378 // registered for the given service.
379 //*********************************************************************************
380
381 bool IOPlatformExpert::CheckSubTree (OSArray * inSubTree, IOService * theNub, IOService * theDevice, OSDictionary * theParent)
382 {
383 unsigned int i;
384 unsigned int numPowerTreeNodes;
385 OSDictionary * entry;
386 OSDictionary * matchingDictionary;
387 OSDictionary * providerDictionary;
388 OSDictionary * deviceDictionary;
389 OSDictionary * nubDictionary;
390 OSArray * children;
391 bool nodeFound = false;
392 bool continueSearch = false;
393 bool deviceMatch = false;
394 bool providerMatch = false;
395 bool multiParentMatch = false;
396
397 if ( (NULL == theDevice) || (NULL == inSubTree) )
398 return false;
399
400 numPowerTreeNodes = inSubTree->getCount ();
401
402 // iterate through the power tree to find a home for this device
403
404 for ( i = 0; i < numPowerTreeNodes; i++ ) {
405
406 entry = (OSDictionary *) inSubTree->getObject (i);
407
408 matchingDictionary = (OSDictionary *) entry->getObject ("device");
409 providerDictionary = (OSDictionary *) entry->getObject ("provider");
410
411 deviceMatch = true; // if no matching dictionary, this is not a criteria and so must match
412 if ( matchingDictionary ) {
413 deviceMatch = false;
414 if ( NULL != (deviceDictionary = theDevice->dictionaryWithProperties ())) {
415 deviceMatch = deviceDictionary->isEqualTo ( matchingDictionary, matchingDictionary );
416 deviceDictionary->release ();
417 }
418 }
419
420 providerMatch = true; // we indicate a match if there is no nub or provider
421 if ( theNub && providerDictionary ) {
422 providerMatch = false;
423 if ( NULL != (nubDictionary = theNub->dictionaryWithProperties ()) ) {
424 providerMatch = nubDictionary->isEqualTo ( providerDictionary, providerDictionary );
425 nubDictionary->release ();
426 }
427 }
428
429 multiParentMatch = true; // again we indicate a match if there is no multi-parent node
430 if (deviceMatch && providerMatch) {
431 if (NULL != multipleParentKeyValue) {
432 OSNumber * aNumber = (OSNumber *) entry->getObject ("multiple-parent");
433 multiParentMatch = (NULL != aNumber) ? multipleParentKeyValue->isEqualTo (aNumber) : false;
434 }
435 }
436
437 nodeFound = (deviceMatch && providerMatch && multiParentMatch);
438
439 // if the power tree specifies a provider dictionary but theNub is
440 // NULL then we cannot match with this entry.
441
442 if ( theNub == NULL && providerDictionary != NULL )
443 nodeFound = false;
444
445 // if this node is THE ONE...then register the device
446
447 if ( nodeFound ) {
448 if (RegisterServiceInTree (theDevice, entry, theParent, theNub) ) {
449
450 if ( kIOLogPower & gIOKitDebug)
451 IOLog ("PMRegisterDevice/CheckSubTree - service registered!\n");
452
453 numInstancesRegistered++;
454
455 // determine if we need to search for additional nodes for this item
456 multipleParentKeyValue = (OSNumber *) entry->getObject ("multiple-parent");
457 }
458 else
459 nodeFound = false;
460 }
461
462 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
463
464 if ( continueSearch && (NULL != (children = (OSArray *) entry->getObject ("children"))) ) {
465 nodeFound = CheckSubTree ( children, theNub, theDevice, entry );
466 continueSearch = ( (false == nodeFound) || (NULL != multipleParentKeyValue) );
467 }
468
469 if ( false == continueSearch )
470 break;
471 }
472
473 return ( nodeFound );
474 }
475
476 //*********************************************************************************
477 // RegisterServiceInTree
478 //
479 // Register a device at the specified node of our power tree.
480 //*********************************************************************************
481
482 bool IOPlatformExpert::RegisterServiceInTree (IOService * theService, OSDictionary * theTreeNode, OSDictionary * theTreeParentNode, IOService * theProvider)
483 {
484 IOService * aService;
485 bool registered = false;
486 OSArray * children;
487 unsigned int numChildren;
488 OSDictionary * child;
489
490 // make sure someone is not already registered here
491
492 if ( NULL == theTreeNode->getObject ("service") ) {
493
494 if ( theTreeNode->setObject ("service", OSDynamicCast ( OSObject, theService)) ) {
495
496 // 1. CHILDREN ------------------
497
498 // we registered the node in the tree...now if the node has children
499 // registered we must tell this service to add them.
500
501 if ( NULL != (children = (OSArray *) theTreeNode->getObject ("children")) ) {
502 numChildren = children->getCount ();
503 for ( unsigned int i = 0; i < numChildren; i++ ) {
504 if ( NULL != (child = (OSDictionary *) children->getObject (i)) ) {
505 if ( NULL != (aService = (IOService *) child->getObject ("service")) )
506 theService->addPowerChild (aService);
507 }
508 }
509 }
510
511 // 2. PARENT --------------------
512
513 // also we must notify the parent of this node (if a registered service
514 // exists there) of a new child.
515
516 if ( theTreeParentNode ) {
517 if ( NULL != (aService = (IOService *) theTreeParentNode->getObject ("service")) )
518 if (aService != theProvider)
519 aService->addPowerChild (theService);
520 }
521
522 registered = true;
523 }
524 }
525
526 return registered;
527 }
528
529 //*********************************************************************************
530 // printDictionaryKeys
531 //
532 // Print the keys for the given dictionary and selected contents.
533 //*********************************************************************************
534 void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg)
535 {
536 OSCollectionIterator * mcoll = OSCollectionIterator::withCollection (inDictionary);
537 OSSymbol * mkey;
538 OSString * ioClass;
539 unsigned int i = 0;
540
541 mcoll->reset ();
542
543 mkey = OSDynamicCast (OSSymbol, mcoll->getNextObject ());
544
545 while (mkey) {
546
547 // kprintf ("dictionary key #%d: %s\n", i, mkey->getCStringNoCopy () );
548
549 // if this is the IOClass key, print it's contents
550
551 if ( mkey->isEqualTo ("IOClass") ) {
552 ioClass = (OSString *) inDictionary->getObject ("IOClass");
553 if ( ioClass ) IOLog ("%s IOClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
554 }
555
556 // if this is an IOProviderClass key print it
557
558 if ( mkey->isEqualTo ("IOProviderClass") ) {
559 ioClass = (OSString *) inDictionary->getObject ("IOProviderClass");
560 if ( ioClass ) IOLog ("%s IOProviderClass is %s\n", inMsg, ioClass->getCStringNoCopy () );
561
562 }
563
564 // also print IONameMatch keys
565 if ( mkey->isEqualTo ("IONameMatch") ) {
566 ioClass = (OSString *) inDictionary->getObject ("IONameMatch");
567 if ( ioClass ) IOLog ("%s IONameMatch is %s\n", inMsg, ioClass->getCStringNoCopy () );
568 }
569
570 // also print IONameMatched keys
571
572 if ( mkey->isEqualTo ("IONameMatched") ) {
573 ioClass = (OSString *) inDictionary->getObject ("IONameMatched");
574 if ( ioClass ) IOLog ("%s IONameMatched is %s\n", inMsg, ioClass->getCStringNoCopy () );
575 }
576
577 #if 0
578 // print clock-id
579
580 if ( mkey->isEqualTo ("AAPL,clock-id") ) {
581 char * cstr;
582 cstr = getCStringForObject (inDictionary->getObject ("AAPL,clock-id"));
583 if (cstr)
584 kprintf (" ===> AAPL,clock-id is %s\n", cstr );
585 }
586 #endif
587
588 // print name
589
590 if ( mkey->isEqualTo ("name") ) {
591 char nameStr[64];
592 nameStr[0] = 0;
593 getCStringForObject (inDictionary->getObject ("name"), nameStr );
594 if (strlen(nameStr) > 0)
595 IOLog ("%s name is %s\n", inMsg, nameStr);
596 }
597
598 mkey = (OSSymbol *) mcoll->getNextObject ();
599
600 i++;
601 }
602
603 mcoll->release ();
604 }
605
606 static void getCStringForObject (OSObject * inObj, char * outStr)
607 {
608 char * buffer;
609 unsigned int len, i;
610
611 if ( (NULL == inObj) || (NULL == outStr))
612 return;
613
614 char * objString = (char *) (inObj->getMetaClass())->getClassName();
615
616 if ((0 == strcmp(objString,"OSString")) || (0 == strcmp (objString, "OSSymbol")))
617 strcpy (outStr, ((OSString *)inObj)->getCStringNoCopy());
618
619 else if (0 == strcmp(objString,"OSData")) {
620 len = ((OSData *)inObj)->getLength();
621 buffer = (char *)((OSData *)inObj)->getBytesNoCopy();
622 if (buffer && (len > 0)) {
623 for (i=0; i < len; i++) {
624 outStr[i] = buffer[i];
625 }
626 outStr[len] = 0;
627 }
628 }
629 }
630
631 extern "C" {
632
633 /*
634 * Callouts from BSD for machine name & model
635 */
636
637 boolean_t PEGetMachineName( char * name, int maxLength )
638 {
639 if( gIOPlatform)
640 return( gIOPlatform->getMachineName( name, maxLength ));
641 else
642 return( false );
643 }
644
645 boolean_t PEGetModelName( char * name, int maxLength )
646 {
647 if( gIOPlatform)
648 return( gIOPlatform->getModelName( name, maxLength ));
649 else
650 return( false );
651 }
652
653 int PEGetPlatformEpoch(void)
654 {
655 if( gIOPlatform)
656 return( gIOPlatform->getBootROMType());
657 else
658 return( -1 );
659 }
660
661 int PEHaltRestart(unsigned int type)
662 {
663 if (gIOPlatform) return gIOPlatform->haltRestart(type);
664 else return -1;
665 }
666
667 long PEGetGMTTimeOfDay(void)
668 {
669 if( gIOPlatform)
670 return( gIOPlatform->getGMTTimeOfDay());
671 else
672 return( 0 );
673 }
674
675 void PESetGMTTimeOfDay(long secs)
676 {
677 if( gIOPlatform)
678 gIOPlatform->setGMTTimeOfDay(secs);
679 }
680
681 } /* extern "C" */
682
683 void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller)
684 {
685 publishResource("IONVRAM");
686 }
687
688 IOReturn IOPlatformExpert::callPlatformFunction(const OSSymbol *functionName,
689 bool waitForFunction,
690 void *param1, void *param2,
691 void *param3, void *param4)
692 {
693 IOService *service, *_resources;
694
695 if (waitForFunction) {
696 _resources = waitForService(resourceMatching(functionName));
697 } else {
698 _resources = resources();
699 }
700 if (_resources == 0) return kIOReturnUnsupported;
701
702 service = OSDynamicCast(IOService, _resources->getProperty(functionName));
703 if (service == 0) return kIOReturnUnsupported;
704
705 return service->callPlatformFunction(functionName, waitForFunction,
706 param1, param2, param3, param4);
707 }
708
709
710 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
711
712 #undef super
713 #define super IOPlatformExpert
714
715 OSDefineMetaClassAndAbstractStructors( IODTPlatformExpert, IOPlatformExpert )
716
717 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 0);
718 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 1);
719 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 2);
720 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 3);
721 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 4);
722 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 5);
723 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 6);
724 OSMetaClassDefineReservedUnused(IODTPlatformExpert, 7);
725
726 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
727
728 IOService * IODTPlatformExpert::probe( IOService * provider,
729 SInt32 * score )
730 {
731 if( !super::probe( provider, score))
732 return( 0 );
733
734 // check machine types
735 if( !provider->compareNames( getProperty( gIONameMatchKey ) ))
736 return( 0 );
737
738 return( this);
739 }
740
741 bool IODTPlatformExpert::configure( IOService * provider )
742 {
743 if( !super::configure( provider))
744 return( false);
745
746 processTopLevel( provider );
747
748 return( true );
749 }
750
751 IOService * IODTPlatformExpert::createNub( IORegistryEntry * from )
752 {
753 IOService * nub;
754
755 nub = new IOPlatformDevice;
756 if( nub) {
757 if( !nub->init( from, gIODTPlane )) {
758 nub->free();
759 nub = 0;
760 }
761 }
762 return( nub);
763 }
764
765 bool IODTPlatformExpert::createNubs( IOService * parent, OSIterator * iter )
766 {
767 IORegistryEntry * next;
768 IOService * nub;
769 bool ok = true;
770
771 if( iter) {
772 while( (next = (IORegistryEntry *) iter->getNextObject())) {
773
774 if( 0 == (nub = createNub( next )))
775 continue;
776
777 nub->attach( parent );
778 nub->registerService();
779 }
780 iter->release();
781 }
782
783 return( ok );
784 }
785
786 void IODTPlatformExpert::processTopLevel( IORegistryEntry * root )
787 {
788 OSIterator * kids;
789 IORegistryEntry * next;
790 IORegistryEntry * cpus;
791 IORegistryEntry * options;
792
793 // infanticide
794 kids = IODTFindMatchingEntries( root, 0, deleteList() );
795 if( kids) {
796 while( (next = (IORegistryEntry *)kids->getNextObject())) {
797 next->detachAll( gIODTPlane);
798 }
799 kids->release();
800 }
801
802 // Publish an IODTNVRAM class on /options.
803 options = root->childFromPath("options", gIODTPlane);
804 if (options) {
805 dtNVRAM = new IODTNVRAM;
806 if (dtNVRAM) {
807 if (!dtNVRAM->init(options, gIODTPlane)) {
808 dtNVRAM->release();
809 dtNVRAM = 0;
810 } else {
811 dtNVRAM->attach(this);
812 dtNVRAM->registerService();
813 }
814 }
815 }
816
817 // Publish the cpus.
818 cpus = root->childFromPath( "cpus", gIODTPlane);
819 if ( cpus)
820 createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));
821
822 // publish top level, minus excludeList
823 createNubs( this, IODTFindMatchingEntries( root, kIODTExclusive, excludeList()));
824 }
825
826 IOReturn IODTPlatformExpert::getNubResources( IOService * nub )
827 {
828 if( nub->getDeviceMemory())
829 return( kIOReturnSuccess );
830
831 IODTResolveAddressing( nub, "reg", 0);
832
833 return( kIOReturnSuccess);
834 }
835
836 bool IODTPlatformExpert::compareNubName( const IOService * nub,
837 OSString * name, OSString ** matched ) const
838 {
839 return( IODTCompareNubName( nub, name, matched )
840 || super::compareNubName( nub, name, matched) );
841 }
842
843 bool IODTPlatformExpert::getModelName( char * name, int maxLength )
844 {
845 OSData * prop;
846 const char * str;
847 int len;
848 char c;
849 bool ok = false;
850
851 maxLength--;
852
853 prop = (OSData *) getProvider()->getProperty( gIODTCompatibleKey );
854 if( prop ) {
855 str = (const char *) prop->getBytesNoCopy();
856
857 if( 0 == strncmp( str, "AAPL,", strlen( "AAPL," ) ))
858 str += strlen( "AAPL," );
859
860 len = 0;
861 while( (c = *str++)) {
862 if( (c == '/') || (c == ' '))
863 c = '-';
864
865 name[ len++ ] = c;
866 if( len >= maxLength)
867 break;
868 }
869
870 name[ len ] = 0;
871 ok = true;
872 }
873 return( ok );
874 }
875
876 bool IODTPlatformExpert::getMachineName( char * name, int maxLength )
877 {
878 OSData * prop;
879 bool ok = false;
880
881 maxLength--;
882 prop = (OSData *) getProvider()->getProperty( gIODTModelKey );
883 ok = (0 != prop);
884
885 if( ok )
886 strncpy( name, (const char *) prop->getBytesNoCopy(), maxLength );
887
888 return( ok );
889 }
890
891 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
892
893 void IODTPlatformExpert::registerNVRAMController( IONVRAMController * nvram )
894 {
895 if (dtNVRAM) dtNVRAM->registerNVRAMController(nvram);
896
897 super::registerNVRAMController(nvram);
898 }
899
900 int IODTPlatformExpert::haltRestart(unsigned int type)
901 {
902 if (dtNVRAM) dtNVRAM->sync();
903
904 return super::haltRestart(type);
905 }
906
907 IOReturn IODTPlatformExpert::readXPRAM(IOByteCount offset, UInt8 * buffer,
908 IOByteCount length)
909 {
910 if (dtNVRAM) return dtNVRAM->readXPRAM(offset, buffer, length);
911 else return kIOReturnNotReady;
912 }
913
914 IOReturn IODTPlatformExpert::writeXPRAM(IOByteCount offset, UInt8 * buffer,
915 IOByteCount length)
916 {
917 if (dtNVRAM) return dtNVRAM->writeXPRAM(offset, buffer, length);
918 else return kIOReturnNotReady;
919 }
920
921 IOReturn IODTPlatformExpert::readNVRAMProperty(
922 IORegistryEntry * entry,
923 const OSSymbol ** name, OSData ** value )
924 {
925 if (dtNVRAM) return dtNVRAM->readNVRAMProperty(entry, name, value);
926 else return kIOReturnNotReady;
927 }
928
929 IOReturn IODTPlatformExpert::writeNVRAMProperty(
930 IORegistryEntry * entry,
931 const OSSymbol * name, OSData * value )
932 {
933 if (dtNVRAM) return dtNVRAM->writeNVRAMProperty(entry, name, value);
934 else return kIOReturnNotReady;
935 }
936
937 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
938
939 #undef super
940 #define super IOService
941
942 OSDefineMetaClassAndStructors(IOPlatformExpertDevice, IOService)
943
944 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 0);
945 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 1);
946 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 2);
947 OSMetaClassDefineReservedUnused(IOPlatformExpertDevice, 3);
948
949 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
950
951 bool IOPlatformExpertDevice::compareName( OSString * name,
952 OSString ** matched = 0 ) const
953 {
954 return( IODTCompareNubName( this, name, matched ));
955 }
956
957 bool
958 IOPlatformExpertDevice::initWithArgs(
959 void * dtTop, void * p2, void * p3, void * p4 )
960 {
961 IORegistryEntry * dt = 0;
962 void * argsData[ 4 ];
963 bool ok;
964
965 // dtTop may be zero on non- device tree systems
966 if( dtTop && (dt = IODeviceTreeAlloc( dtTop )))
967 ok = super::init( dt, gIODTPlane );
968 else
969 ok = super::init();
970
971 if( !ok)
972 return( false);
973
974 workLoop = IOWorkLoop::workLoop();
975 if (!workLoop)
976 return false;
977
978 argsData[ 0 ] = dtTop;
979 argsData[ 1 ] = p2;
980 argsData[ 2 ] = p3;
981 argsData[ 3 ] = p4;
982
983 setProperty("IOPlatformArgs", (void *)argsData, sizeof( argsData));
984
985 return( true);
986 }
987
988 IOWorkLoop *IOPlatformExpertDevice::getWorkLoop() const
989 {
990 return workLoop;
991 }
992
993 void IOPlatformExpertDevice::free()
994 {
995 if (workLoop)
996 workLoop->release();
997 }
998
999 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1000
1001 #undef super
1002 #define super IOService
1003
1004 OSDefineMetaClassAndStructors(IOPlatformDevice, IOService)
1005
1006 OSMetaClassDefineReservedUnused(IOPlatformDevice, 0);
1007 OSMetaClassDefineReservedUnused(IOPlatformDevice, 1);
1008 OSMetaClassDefineReservedUnused(IOPlatformDevice, 2);
1009 OSMetaClassDefineReservedUnused(IOPlatformDevice, 3);
1010
1011 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1012
1013 bool IOPlatformDevice::compareName( OSString * name,
1014 OSString ** matched = 0 ) const
1015 {
1016 return( ((IOPlatformExpert *)getProvider())->
1017 compareNubName( this, name, matched ));
1018 }
1019
1020 IOService * IOPlatformDevice::matchLocation( IOService * /* client */ )
1021 {
1022 return( this );
1023 }
1024
1025 IOReturn IOPlatformDevice::getResources( void )
1026 {
1027 return( ((IOPlatformExpert *)getProvider())->getNubResources( this ));
1028 }
1029
1030 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1031
1032 /*********************************************************************
1033 * IOPanicPlatform class
1034 *
1035 * If no legitimate IOPlatformDevice matches, this one does and panics
1036 * the kernel with a suitable message.
1037 *********************************************************************/
1038
1039 class IOPanicPlatform : IOPlatformExpert {
1040 OSDeclareDefaultStructors(IOPanicPlatform);
1041
1042 public:
1043 bool start(IOService * provider);
1044 };
1045
1046
1047 OSDefineMetaClassAndStructors(IOPanicPlatform, IOPlatformExpert);
1048
1049
1050 bool IOPanicPlatform::start(IOService * provider) {
1051 const char * platform_name = "(unknown platform name)";
1052
1053 if (provider) platform_name = provider->getName();
1054
1055 panic("Unable to find driver for this platform: \"%s\".\n",
1056 platform_name);
1057
1058 return false;
1059 }