]>
Commit | Line | Data |
---|---|---|
1c79356b A |
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 | } |