]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IONDRVSupport/IONDRVLibraries.cpp
24ab2ee5cd35d7c38a57ac5c4825daac1e83e23e
[apple/xnu.git] / iokit / Families / IONDRVSupport / IONDRVLibraries.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 * Copyright (c) 1997 Apple Computer, Inc.
24 *
25 *
26 * HISTORY
27 *
28 * sdouglas 22 Oct 97 - first checked in.
29 * sdouglas 21 Jul 98 - start IOKit
30 * sdouglas 14 Dec 98 - start cpp.
31 */
32
33
34 #include <IOKit/IOLib.h>
35 #include <libkern/c++/OSContainers.h>
36 #include <IOKit/IODeviceTreeSupport.h>
37 #include <IOKit/IOPlatformExpert.h>
38 #include <IOKit/pci/IOPCIDevice.h>
39 #include <IOKit/ndrvsupport/IONDRVSupport.h>
40 #include <IOKit/ndrvsupport/IONDRVFramebuffer.h>
41
42 #include <libkern/OSByteOrder.h>
43 #include <libkern/OSAtomic.h>
44 #include <IOKit/assert.h>
45
46 #include <pexpert/pexpert.h>
47
48 #include "IOPEFLibraries.h"
49 #include "IOPEFLoader.h"
50 #include "IONDRV.h"
51
52 #include <string.h>
53
54 extern "C"
55 {
56
57 extern void *kern_os_malloc(size_t size);
58 extern void kern_os_free(void * addr);
59
60 #define LOG if(1) kprintf
61
62 #define LOGNAMEREG 0
63
64 /* NameRegistry error codes */
65 enum {
66 nrLockedErr = -2536,
67 nrNotEnoughMemoryErr = -2537,
68 nrInvalidNodeErr = -2538,
69 nrNotFoundErr = -2539,
70 nrNotCreatedErr = -2540,
71 nrNameErr = -2541,
72 nrNotSlotDeviceErr = -2542,
73 nrDataTruncatedErr = -2543,
74 nrPowerErr = -2544,
75 nrPowerSwitchAbortErr = -2545,
76 nrTypeMismatchErr = -2546,
77 nrNotModifiedErr = -2547,
78 nrOverrunErr = -2548,
79 nrResultCodeBase = -2549,
80 nrPathNotFound = -2550, /* a path component lookup failed */
81 nrPathBufferTooSmall = -2551, /* buffer for path is too small */
82 nrInvalidEntryIterationOp = -2552, /* invalid entry iteration operation */
83 nrPropertyAlreadyExists = -2553, /* property already exists */
84 nrIterationDone = -2554, /* iteration operation is done */
85 nrExitedIteratorScope = -2555, /* outer scope of iterator was exited */
86 nrTransactionAborted = -2556 /* transaction was aborted */
87 };
88
89 enum {
90 kNVRAMProperty = 0x00000020L, // matches NR
91 kRegMaximumPropertyNameLength = 31
92 };
93
94 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
95
96 UInt32 _eEndianSwap32Bit( UInt32 data )
97 {
98 return( OSReadSwapInt32(&data, 0));
99 }
100
101 UInt16 _eEndianSwap16Bit( UInt16 data )
102 {
103 return( OSReadSwapInt16(&data, 0));
104 }
105
106 OSStatus _eExpMgrConfigReadLong( RegEntryID entryID, UInt8 offset, UInt32 * value )
107 {
108 IORegistryEntry * regEntry;
109 IOPCIDevice * ioDevice;
110 UInt32 adj;
111
112 REG_ENTRY_TO_OBJ( entryID, regEntry)
113
114 ioDevice = OSDynamicCast( IOPCIDevice, regEntry );
115 if( !ioDevice)
116 ioDevice = OSDynamicCast( IOPCIDevice, regEntry->getParentEntry( gIODTPlane) );
117 if( !ioDevice)
118 return( nrNotSlotDeviceErr );
119
120 adj = ioDevice->configRead32( offset );
121 #if 0
122 IOMemoryMap * map = 0;
123 if( (offset >= kIOPCIConfigBaseAddress2)
124 && (offset <= kIOPCIConfigBaseAddress5)) {
125 if( (map = ioDevice->mapDeviceMemoryWithRegister( offset, kIOMapReference))) {
126 adj = (adj & 3) | (map->getVirtualAddress());
127 map->release();
128 }
129 }
130 #endif
131 *value = adj;
132
133 return( noErr );
134 }
135
136 OSStatus _eExpMgrConfigWriteLong( RegEntryID entryID, UInt8 offset, UInt32 value )
137 {
138
139 REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice)
140
141 ioDevice->configWrite32( offset, value);
142
143 return( noErr );
144 }
145
146
147 OSStatus _eExpMgrConfigReadWord( RegEntryID entryID, UInt8 offset, UInt16 * value )
148 {
149 IORegistryEntry * regEntry;
150 IOPCIDevice * ioDevice;
151
152 REG_ENTRY_TO_OBJ( entryID, regEntry)
153
154 ioDevice = OSDynamicCast( IOPCIDevice, regEntry );
155 if( !ioDevice)
156 ioDevice = OSDynamicCast( IOPCIDevice, regEntry->getParentEntry( gIODTPlane) );
157 if( !ioDevice)
158 return( nrNotSlotDeviceErr );
159
160 *value = ioDevice->configRead16( offset );
161
162 return( noErr );
163 }
164
165 OSStatus _eExpMgrConfigWriteWord( RegEntryID entryID, UInt8 offset, UInt16 value )
166 {
167
168 REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice)
169
170 ioDevice->configWrite16( offset, value);
171
172 return( noErr);
173 }
174
175 OSStatus _eExpMgrConfigReadByte( RegEntryID entryID, UInt8 offset, UInt8 * value )
176 {
177 IORegistryEntry * regEntry;
178 IOPCIDevice * ioDevice;
179
180 REG_ENTRY_TO_OBJ( entryID, regEntry)
181
182 ioDevice = OSDynamicCast( IOPCIDevice, regEntry );
183 if( !ioDevice)
184 ioDevice = OSDynamicCast( IOPCIDevice, regEntry->getParentEntry( gIODTPlane) );
185 if( !ioDevice)
186 return( nrNotSlotDeviceErr );
187
188 *value = ioDevice->configRead8( offset );
189
190 return( noErr );
191 }
192
193 OSStatus _eExpMgrConfigWriteByte( RegEntryID entryID, UInt8 offset, UInt8 value )
194 {
195
196 REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice)
197
198 ioDevice->configWrite8( offset, value);
199
200 return( noErr);
201 }
202
203 OSStatus _eExpMgrIOReadLong( RegEntryID entryID, UInt16 offset, UInt32 * value )
204 {
205
206 REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice)
207
208 *value = ioDevice->ioRead32( offset );
209
210 return( noErr);
211 }
212
213 OSStatus _eExpMgrIOWriteLong( RegEntryID entryID, UInt16 offset, UInt32 value )
214 {
215
216 REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice)
217
218 ioDevice->ioWrite32( offset, value );
219
220 return( noErr);
221 }
222
223 OSStatus _eExpMgrIOReadWord( RegEntryID entryID, UInt16 offset, UInt16 * value )
224 {
225 REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice)
226
227 *value = ioDevice->ioRead16( offset );
228
229 return( noErr);
230 }
231
232 OSStatus _eExpMgrIOWriteWord( RegEntryID entryID, UInt16 offset, UInt16 value )
233 {
234
235 REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice)
236
237 ioDevice->ioWrite16( offset, value );
238
239 return( noErr);
240 }
241
242 OSStatus _eExpMgrIOReadByte( RegEntryID entryID, UInt16 offset, UInt8 * value )
243 {
244 REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice)
245
246 *value = ioDevice->ioRead8( offset );
247
248 return( noErr);
249 }
250
251 OSStatus _eExpMgrIOWriteByte( RegEntryID entryID, UInt16 offset, UInt8 value )
252 {
253
254 REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice)
255
256 ioDevice->ioWrite8( offset, value );
257
258 return( noErr);
259 }
260
261 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
262
263 OSStatus _eRegistryEntryIDCopy( RegEntryID entryID, RegEntryID to )
264 {
265 bcopy( entryID, to, sizeof( RegEntryID) );
266 return( noErr);
267 }
268
269
270 OSStatus _eRegistryEntryIDInit( RegEntryID entryID )
271 {
272 MAKE_REG_ENTRY( entryID, 0);
273 return( noErr);
274 }
275
276 /*
277 * Compare EntryID's for equality or if invalid
278 *
279 * If a NULL value is given for either id1 or id2, the other id
280 * is compared with an invalid ID. If both are NULL, the id's
281 * are consided equal (result = true).
282 * note: invalid != uninitialized
283 */
284 Boolean _eRegistryEntryIDCompare( RegEntryID entryID1, RegEntryID entryID2 )
285 {
286 IORegistryEntry * regEntry1;
287 IORegistryEntry * regEntry2;
288
289 if( entryID1) {
290 REG_ENTRY_TO_OBJ_RET( entryID1, regEntry1, false)
291 } else
292 regEntry1 = 0;
293
294 if( entryID2) {
295 REG_ENTRY_TO_OBJ_RET( entryID2, regEntry2, false)
296 } else
297 regEntry2 = 0;
298
299 return( regEntry1 == regEntry2 );
300 }
301
302 OSStatus _eRegistryPropertyGetSize( void *entryID, char *propertyName,
303 UInt32 * propertySize )
304 {
305 OSStatus err = noErr;
306 OSData * prop;
307
308 REG_ENTRY_TO_PT( entryID, regEntry)
309
310 prop = (OSData *) regEntry->getProperty( propertyName);
311 if( prop)
312 *propertySize = prop->getLength();
313 else
314 err = nrNotFoundErr;
315
316 #if LOGNAMEREG
317 LOG("RegistryPropertyGetSize: %s : %d\n", propertyName, err);
318 #endif
319 return( err);
320
321 }
322
323 OSStatus _eRegistryPropertyGet(void *entryID, char *propertyName, UInt32 *propertyValue, UInt32 *propertySize)
324 {
325 OSStatus err = noErr;
326 OSData * prop;
327 UInt32 len;
328
329 REG_ENTRY_TO_PT( entryID, regEntry)
330
331 prop = OSDynamicCast( OSData, regEntry->getProperty( propertyName));
332 if( prop) {
333
334 len = *propertySize;
335 *propertySize = prop->getLength();
336 len = (len > prop->getLength()) ? prop->getLength() : len;
337 bcopy( prop->getBytesNoCopy(), propertyValue, len);
338 #if LOGNAMEREG
339 LOG("value: %08x ", *propertyValue);
340 #endif
341 } else
342 err = nrNotFoundErr;
343
344 #if LOGNAMEREG
345 LOG("RegistryPropertyGet: %s : %d\n", propertyName, err);
346 #endif
347 return( err);
348 }
349
350 OSStatus _eRegistryPropertyCreate( void *entryID, char *propertyName,
351 void * propertyValue, UInt32 propertySize )
352 {
353 OSStatus err = noErr;
354 OSData * prop;
355
356 REG_ENTRY_TO_PT( entryID, regEntry)
357
358 prop = OSData::withBytes( propertyValue, propertySize );
359
360 if( prop) {
361
362 regEntry->setProperty( propertyName, prop);
363 prop->release();
364
365 } else
366 err = nrNotCreatedErr;
367
368 #if LOGNAMEREG
369 LOG("RegistryPropertyCreate: %s : %d\n", propertyName, err);
370 #endif
371 return( err);
372 }
373
374 OSStatus _eRegistryPropertyDelete( void *entryID, char *propertyName )
375 {
376 OSStatus err = noErr;
377 OSObject * old;
378
379 REG_ENTRY_TO_PT( entryID, regEntry)
380
381 old = regEntry->getProperty(propertyName);
382 if ( old )
383 regEntry->removeProperty(propertyName);
384 else
385 err = nrNotFoundErr;
386
387 #if LOGNAMEREG
388 LOG("RegistryPropertyDelete: %s : %d\n", propertyName, err);
389 #endif
390 return( err);
391 }
392
393 void IONDRVSetNVRAMPropertyName( IORegistryEntry * regEntry,
394 const OSSymbol * sym )
395 {
396 regEntry->setProperty( "IONVRAMProperty", (OSObject *) sym );
397 }
398
399 static IOReturn IONDRVSetNVRAMPropertyValue( IORegistryEntry * regEntry,
400 const OSSymbol * name, OSData * value )
401 {
402 IOReturn err;
403 IODTPlatformExpert * platform =
404 (IODTPlatformExpert *) IOService::getPlatform();
405
406 err = platform->writeNVRAMProperty( regEntry, name, value );
407
408 return( err );
409 }
410
411 OSStatus _eRegistryPropertySet( void *entryID, char *propertyName, void * propertyValue, UInt32 propertySize )
412 {
413 OSStatus err = noErr;
414 OSData * prop;
415 const OSSymbol * sym;
416
417 REG_ENTRY_TO_PT( entryID, regEntry)
418
419 sym = OSSymbol::withCString( propertyName );
420 if( !sym)
421 return( kIOReturnNoMemory );
422
423 prop = OSDynamicCast( OSData, regEntry->getProperty( sym ));
424 if( 0 == prop)
425 err = nrNotFoundErr;
426
427 else if( (prop = OSData::withBytes( propertyValue, propertySize))) {
428 regEntry->setProperty( sym, prop);
429
430 if( (sym == (const OSSymbol *)
431 regEntry->getProperty("IONVRAMProperty")))
432 err = IONDRVSetNVRAMPropertyValue( regEntry, sym, prop );
433 prop->release();
434
435 } else
436 err = nrNotCreatedErr;
437
438 sym->release();
439
440 #if LOGNAMEREG
441 LOG("RegistryPropertySet: %s : %d\n", propertyName, err);
442 #endif
443 return( err);
444 }
445
446 OSStatus _eRegistryPropertyGetMod(void * entryID, char * propertyName,
447 UInt32 * mod)
448 {
449 const OSSymbol * sym;
450
451 REG_ENTRY_TO_PT( entryID, regEntry)
452
453 if( (sym = OSDynamicCast( OSSymbol,
454 regEntry->getProperty("IONVRAMProperty")))
455 && (0 == strcmp( propertyName, sym->getCStringNoCopy())))
456
457 *mod = kNVRAMProperty;
458 else
459 *mod = 0;
460
461 return( noErr);
462 }
463
464 OSStatus _eRegistryPropertySetMod(void *entryID, char *propertyName,
465 UInt32 mod )
466 {
467 OSStatus err = noErr;
468 OSData * data;
469 const OSSymbol * sym;
470
471 REG_ENTRY_TO_PT( entryID, regEntry)
472
473 if( (mod & kNVRAMProperty)
474 && (sym = OSSymbol::withCString( propertyName ))) {
475
476 if( (data = OSDynamicCast( OSData, regEntry->getProperty( sym))) ) {
477 err = IONDRVSetNVRAMPropertyValue( regEntry, sym, data );
478 if( kIOReturnSuccess == err)
479 IONDRVSetNVRAMPropertyName( regEntry, sym );
480 }
481 sym->release();
482 }
483
484 return( err);
485 }
486
487 OSStatus _eVSLSetDisplayConfiguration(RegEntryID * entryID,
488 char * propertyName,
489 void * configData,
490 long configDataSize)
491 {
492 IOReturn err = nrNotCreatedErr;
493 IORegistryEntry * options;
494 const OSSymbol * sym = 0;
495 OSData * data = 0;
496 enum { kMaxDisplayConfigDataSize = 64 };
497
498 if( (configDataSize > kMaxDisplayConfigDataSize)
499 || (strlen(propertyName) > kRegMaximumPropertyNameLength))
500 return( nrNotCreatedErr );
501
502 do {
503 options = IORegistryEntry::fromPath( "/options", gIODTPlane);
504 if( !options)
505 continue;
506 data = OSData::withBytes( configData, configDataSize );
507 if( !data)
508 continue;
509 sym = OSSymbol::withCString( propertyName );
510 if( !sym)
511 continue;
512 if( !options->setProperty( sym, data ))
513 continue;
514 err = kIOReturnSuccess;
515
516 } while( false );
517
518 if( options)
519 options->release();
520 if( data)
521 data->release();
522 if( sym)
523 sym->release();
524
525 return( err );
526 }
527
528 OSStatus _eRegistryPropertyIterateCreate( RegEntryID * entryID,
529 OSCollectionIterator ** cookie)
530 {
531
532 REG_ENTRY_TO_PT( entryID, regEntry)
533
534 // NB. unsynchronized. But should only happen on an owned nub!
535 // Should non OSData be filtered out?
536 *cookie = OSCollectionIterator::withCollection(
537 regEntry->getPropertyTable());
538
539 if( *cookie)
540 return( noErr);
541 else
542 return( nrNotEnoughMemoryErr);
543 }
544
545 OSStatus _eRegistryPropertyIterateDispose( OSCollectionIterator ** cookie)
546 {
547 if( *cookie) {
548 (*cookie)->release();
549 *cookie = NULL;
550 return( noErr);
551 } else
552 return( nrIterationDone);
553 }
554
555
556 OSStatus _eRegistryPropertyIterate( OSCollectionIterator ** cookie,
557 char * name, Boolean * done )
558 {
559 const OSSymbol * key;
560
561 key = (const OSSymbol *) (*cookie)->getNextObject();
562 if( key)
563 strncpy( name, key->getCStringNoCopy(), kRegMaximumPropertyNameLength);
564
565 // Seems to be differences in handling "done".
566 // ATI assumes done = true when getting the last property.
567 // The Book says done is true after last property.
568 // ATI does check err, so this will work.
569 // Control ignores err and checks done.
570
571 *done = (key == 0);
572
573 if( 0 != key)
574 return( noErr);
575 else
576 return( nrIterationDone );
577 }
578
579 OSStatus
580 _eRegistryEntryIterateCreate( IORegistryIterator ** cookie)
581 {
582 *cookie = IORegistryIterator::iterateOver( gIODTPlane );
583 if( *cookie)
584 return( noErr);
585 else
586 return( nrNotEnoughMemoryErr);
587 }
588
589 OSStatus
590 _eRegistryEntryIterateDispose( IORegistryIterator ** cookie)
591 {
592 if( *cookie) {
593 (*cookie)->release();
594 *cookie = NULL;
595 return( noErr);
596 } else
597 return( nrIterationDone);
598 }
599
600 OSStatus
601 _eRegistryEntryIterate( IORegistryIterator ** cookie,
602 UInt32 /* relationship */,
603 RegEntryID foundEntry,
604 Boolean * done)
605 {
606 IORegistryEntry * regEntry;
607
608 // TODO: check requested type of iteration
609 regEntry = (*cookie)->getNextObjectRecursive();
610
611 MAKE_REG_ENTRY( foundEntry, regEntry);
612 *done = (0 == regEntry);
613
614 #if LOGNAMEREG
615 if( regEntry)
616 LOG("RegistryEntryIterate: %s\n", regEntry->getName( gIODTPlane ));
617 #endif
618
619 if( regEntry)
620 return( noErr);
621 else
622 return( nrNotFoundErr);
623 }
624
625 OSStatus
626 _eRegistryCStrEntryToName( const RegEntryID * entryID,
627 RegEntryID parentEntry,
628 char * nameComponent,
629 Boolean * done )
630 {
631 IORegistryEntry * regEntry;
632
633 REG_ENTRY_TO_OBJ( entryID, regEntry)
634
635 strncpy( nameComponent, regEntry->getName( gIODTPlane ), kRegMaximumPropertyNameLength );
636 nameComponent[ kRegMaximumPropertyNameLength ] = 0;
637
638 regEntry = regEntry->getParentEntry( gIODTPlane );
639 if( regEntry) {
640 MAKE_REG_ENTRY( parentEntry, regEntry);
641 *done = false;
642 } else
643 *done = true;
644
645 return( noErr);
646 }
647
648 OSStatus
649 _eRegistryCStrEntryLookup( const RegEntryID * parentEntry,
650 const char * path,
651 RegEntryID newEntry)
652 {
653 IOReturn err;
654 IORegistryEntry * regEntry = 0;
655 char * buf;
656 char * cvtPath;
657 char c;
658 #define kDTRoot "Devices:device-tree:"
659 #define kMacIORoot "Devices:device-tree:pci:mac-io:"
660
661 if( parentEntry) {
662 REG_ENTRY_TO_OBJ( parentEntry, regEntry)
663 } else
664 regEntry = 0;
665
666 buf = IONew( char, 512 );
667 if( !buf)
668 return( nrNotEnoughMemoryErr );
669
670 cvtPath = buf;
671 if( ':' == path[0])
672 path++;
673 else if( 0 == strncmp( path, kMacIORoot, strlen( kMacIORoot ))) {
674 path += strlen( kMacIORoot ) - 7;
675 regEntry = 0;
676 }
677 else if( 0 == strncmp( path, kDTRoot, strlen( kDTRoot ))) {
678 path += strlen( kDTRoot ) - 1;
679 regEntry = 0;
680 }
681
682 do {
683 c = *(path++);
684 if( ':' == c)
685 c = '/';
686 *(cvtPath++) = c;
687 } while( c != 0 );
688
689 if( regEntry)
690 regEntry = regEntry->childFromPath( buf, gIODTPlane );
691 else
692 regEntry = IORegistryEntry::fromPath( buf, gIODTPlane );
693
694 if( regEntry) {
695 MAKE_REG_ENTRY( newEntry, regEntry);
696 regEntry->release();
697 err = noErr;
698 } else
699 err = nrNotFoundErr;
700
701 IODelete( buf, char, 512 );
702
703 return( err );
704 }
705
706
707 OSStatus
708 _eRegistryCStrEntryCreate( const RegEntryID * parentEntry,
709 char * name,
710 RegEntryID newEntry)
711 {
712 IORegistryEntry * newDev;
713 IORegistryEntry * parent;
714
715 REG_ENTRY_TO_OBJ( parentEntry, parent)
716
717 // NOT published
718
719 newDev = new IORegistryEntry;
720 if( newDev && (false == newDev->init()))
721 newDev = 0;
722
723 if( newDev) {
724 newDev->attachToParent( parent, gIODTPlane );
725 if( ':' == name[0])
726 name++;
727 newDev->setName( name );
728 }
729
730 MAKE_REG_ENTRY( newEntry, newDev);
731
732 if( newDev)
733 return( noErr);
734 else
735 return( nrNotCreatedErr);
736 }
737
738 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
739
740 extern "C" {
741
742 // in NDRVLibrariesAsm.s
743 extern void _eSynchronizeIO( void );
744
745 // platform expert
746 extern vm_offset_t
747 PEResidentAddress( vm_offset_t address, vm_size_t length );
748
749 };
750
751 enum {
752 kProcessorCacheModeDefault = 0,
753 kProcessorCacheModeInhibited = 1,
754 kProcessorCacheModeWriteThrough = 2,
755 kProcessorCacheModeCopyBack = 3
756 };
757
758 OSStatus _eSetProcessorCacheMode( UInt32 /* space */, void * /* addr */,
759 UInt32 /* len */, UInt32 /* mode */ )
760 {
761 #if 0
762 struct phys_entry* pp;
763 vm_offset_t spa;
764 vm_offset_t epa;
765 int wimg;
766
767 // This doesn't change any existing kernel mapping eg. BAT changes etc.
768 // but this is enough to change user level mappings for DPS etc.
769 // Should use a kernel service when one is available.
770
771 spa = kvtophys( (vm_offset_t)addr);
772 if( spa == 0) {
773 spa = PEResidentAddress( (vm_offset_t)addr, len);
774 if( spa == 0)
775 return( kIOReturnVMError);
776 }
777 epa = (len + spa + 0xfff) & 0xfffff000;
778 spa &= 0xfffff000;
779
780 switch( mode) {
781 case kProcessorCacheModeWriteThrough:
782 wimg = PTE_WIMG_WT_CACHED_COHERENT_GUARDED;
783 break;
784 case kProcessorCacheModeCopyBack:
785 wimg = PTE_WIMG_CB_CACHED_COHERENT_GUARDED;
786 break;
787 default:
788 wimg = PTE_WIMG_UNCACHED_COHERENT_GUARDED;
789 break;
790 }
791
792 while( spa < epa) {
793 pp = pmap_find_physentry(spa);
794 if (pp != PHYS_NULL)
795 pp->pte1.bits.wimg = wimg;
796 spa += PAGE_SIZE;
797 }
798 #endif
799 _eSynchronizeIO();
800 return( noErr);
801 }
802
803 char * _ePStrCopy( char *to, const char *from )
804 {
805 UInt32 len;
806 char * copy;
807
808 copy = to;
809 len = *(from++);
810 *(copy++) = len;
811 bcopy( from, copy, len);
812 return( to);
813 }
814
815 LogicalAddress _ePoolAllocateResident(ByteCount byteSize, Boolean clear)
816 {
817 LogicalAddress mem;
818
819 mem = (LogicalAddress) kern_os_malloc( (size_t) byteSize );
820 if( clear && mem)
821 memset( mem, 0, byteSize);
822
823 return( mem);
824 }
825
826 OSStatus _ePoolDeallocate( LogicalAddress address )
827 {
828 kern_os_free( (void *) address );
829 return( noErr);
830 }
831
832 UInt32 _eCurrentExecutionLevel(void)
833 {
834 return(0); // == kTaskLevel, HWInt == 6
835 }
836
837 // don't expect any callers of this
838 OSErr _eIOCommandIsComplete( UInt32 /* commandID */, OSErr result)
839 {
840 LOG("_eIOCommandIsComplete\n");
841 return( result); // !!??!!
842 }
843
844 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
845
846 #include <kern/clock.h>
847
848
849 AbsoluteTime _eUpTime( void )
850 {
851 AbsoluteTime result;
852
853 clock_get_uptime( &result);
854
855 return( result);
856 }
857
858 AbsoluteTime _eAddAbsoluteToAbsolute(AbsoluteTime left, AbsoluteTime right)
859 {
860 AbsoluteTime result = left;
861
862 ADD_ABSOLUTETIME( &left, &right);
863
864 return( result);
865 }
866
867
868 AbsoluteTime _eSubAbsoluteFromAbsolute(AbsoluteTime left, AbsoluteTime right)
869 {
870 AbsoluteTime result = left;
871
872 // !! ATI bug fix here:
873 // They expect the 64-bit result to be signed. The spec says < 0 => 0
874 // To workaround, make sure this routine takes 10 us to execute.
875 IODelay( 10);
876
877 if( CMP_ABSOLUTETIME( &result, &right) < 0) {
878 AbsoluteTime_to_scalar( &result ) = 0;
879 } else {
880 result = left;
881 SUB_ABSOLUTETIME( &result, &right);
882 }
883
884 return( result);
885 }
886
887
888 AbsoluteTime _eDurationToAbsolute( Duration theDuration)
889 {
890 AbsoluteTime result;
891
892 if( theDuration > 0) {
893 clock_interval_to_absolutetime_interval( theDuration, kMillisecondScale,
894 &result );
895
896 } else {
897 clock_interval_to_absolutetime_interval( (-theDuration), kMicrosecondScale,
898 &result );
899 }
900
901 return( result);
902 }
903
904 AbsoluteTime _eAddDurationToAbsolute( Duration duration, AbsoluteTime absolute )
905 {
906 return( _eAddAbsoluteToAbsolute(_eDurationToAbsolute( duration), absolute));
907 }
908
909 #define UnsignedWideToUInt64(x) (*(UInt64 *)(x))
910 #define UInt64ToUnsignedWide(x) (*(UnsignedWide *)(x))
911
912 AbsoluteTime _eNanosecondsToAbsolute ( UnsignedWide theNanoseconds)
913 {
914 AbsoluteTime result;
915 UInt64 nano = UnsignedWideToUInt64(&theNanoseconds);
916
917 nanoseconds_to_absolutetime( nano, &result);
918
919 return( result);
920 }
921
922 UnsignedWide _eAbsoluteToNanoseconds( AbsoluteTime absolute )
923 {
924 UnsignedWide result;
925 UInt64 nano;
926
927 absolutetime_to_nanoseconds( absolute, &nano);
928 result = UInt64ToUnsignedWide( &nano );
929
930 return( result);
931 }
932
933 Duration _eAbsoluteDeltaToDuration( AbsoluteTime left, AbsoluteTime right )
934 {
935 Duration dur;
936 AbsoluteTime result;
937 UInt64 nano;
938
939 if( CMP_ABSOLUTETIME( &left, &right) < 0)
940 return( 0);
941
942 result = left;
943 SUB_ABSOLUTETIME( &result, &right);
944 absolutetime_to_nanoseconds( result, &nano);
945
946 if( nano >= ((1ULL << 31) * 1000ULL)) {
947 // +ve milliseconds
948 if( nano >= ((1ULL << 31) * 1000ULL * 1000ULL))
949 dur = 0x7fffffff;
950 else
951 dur = nano / 1000000ULL;
952 } else {
953 // -ve microseconds
954 dur = -(nano / 1000ULL);
955 }
956
957 return( dur);
958 }
959
960
961 OSStatus _eDelayForHardware( AbsoluteTime time )
962 {
963 AbsoluteTime deadline;
964
965 clock_absolutetime_interval_to_deadline( time, &deadline );
966 clock_delay_until( deadline );
967
968 return( noErr);
969 }
970
971 OSStatus _eDelayFor( Duration theDuration )
972 {
973 #if 1
974
975 // In Marconi, DelayFor uses the old toolbox Delay routine
976 // which is based on the 60 Hz timer. Durations are not
977 // rounded up when converting to ticks. Yes, really.
978 // Some ATI drivers call DelayFor(1) 50000 times starting up.
979 // There is some 64-bit math there so we'd better reproduce
980 // the overhead of that calculation.
981
982 #define DELAY_FOR_TICK_NANO 16666666
983 #define DELAY_FOR_TICK_MILLI 17
984 #define NANO32_MILLI 4295
985
986 UnsignedWide nano;
987 AbsoluteTime abs;
988 unsigned int ms;
989
990 abs = _eDurationToAbsolute( theDuration);
991 nano = _eAbsoluteToNanoseconds( abs);
992
993 ms = (nano.lo / DELAY_FOR_TICK_NANO) * DELAY_FOR_TICK_MILLI;
994 ms += nano.hi * NANO32_MILLI;
995 if( ms)
996 IOSleep( ms);
997
998 #else
999 // Accurate, but incompatible, version
1000
1001 #define SLEEP_THRESHOLD 5000
1002
1003 if( theDuration < 0) {
1004
1005 // us duration
1006 theDuration -= theDuration;
1007 if( theDuration > SLEEP_THRESHOLD)
1008 IOSleep( (theDuration + 999) / 1000);
1009 else
1010 IODelay( theDuration);
1011
1012 } else {
1013
1014 // ms duration
1015 if( theDuration > (SLEEP_THRESHOLD / 1000))
1016 IOSleep( theDuration ); // ms
1017 else
1018 IODelay( theDuration * 1000); // us
1019 }
1020 #endif
1021
1022 return( noErr);
1023 }
1024
1025 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1026
1027 OSStatus _eCallOSTrapUniversalProc( UInt32 /* theProc */,
1028 UInt32 procInfo, UInt32 trap, UInt8 * pb )
1029 {
1030 OSStatus err = -40;
1031 struct PMgrOpParamBlock {
1032 SInt16 pmCommand;
1033 SInt16 pmLength;
1034 UInt8 * pmSBuffer;
1035 UInt8 * pmRBuffer;
1036 UInt8 pmData[4];
1037 };
1038 #define readExtSwitches 0xDC
1039
1040 if( (procInfo == 0x133822)
1041 && (trap == 0xa085) ) {
1042
1043 PMgrOpParamBlock * pmOp = (PMgrOpParamBlock *) pb;
1044
1045 if( (readExtSwitches == pmOp->pmCommand) && pmOp->pmRBuffer) {
1046 OSNumber * num = OSDynamicCast(OSNumber,
1047 IOService::getPlatform()->getProperty("AppleExtSwitchBootState"));
1048 *pmOp->pmRBuffer = (num->unsigned32BitValue() & 1);
1049 err = noErr;
1050 }
1051
1052 } else if( (procInfo == 0x133822)
1053 && (trap == 0xa092) ) {
1054
1055 UInt8 addr, reg, data;
1056
1057 addr = pb[ 2 ];
1058 reg = pb[ 3 ];
1059 pb = *( (UInt8 **) ((UInt32) pb + 8));
1060 data = pb[ 1 ];
1061 (*PE_write_IIC)( addr, reg, data );
1062 err = noErr;
1063 }
1064 return( err);
1065 }
1066
1067 const UInt32 * _eGetKeys( void )
1068 {
1069 static const UInt32 zeros[] = { 0, 0, 0, 0 };
1070
1071 return( zeros);
1072 }
1073
1074 UInt32 _eGetIndADB( void * adbInfo, UInt32 /* index */)
1075 {
1076 bzero( adbInfo, 10);
1077 return( 0); // orig address
1078 }
1079
1080 char * _eLMGetPowerMgrVars( void )
1081 {
1082 static char * powerMgrVars = NULL;
1083
1084 if( powerMgrVars == NULL) {
1085 powerMgrVars = (char *) IOMalloc( 0x3c0);
1086 if( powerMgrVars)
1087 bzero( powerMgrVars, 0x3c0);
1088 }
1089 return( powerMgrVars);
1090 }
1091
1092 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1093
1094 OSStatus _eNoErr( void )
1095 {
1096 return( noErr);
1097 }
1098
1099 OSStatus _eFail( void )
1100 {
1101 return( -40);
1102 }
1103
1104 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1105
1106 // fix this!
1107
1108 #define heathrowID ((volatile UInt32 *)0xf3000034)
1109 #define heathrowTermEna (1 << 3)
1110 #define heathrowTermDir (1 << 0)
1111
1112 #define heathrowFeatureControl ((volatile UInt32 *)0xf3000038)
1113 #define heathrowMBRES (1 << 24)
1114
1115 #define heathrowBrightnessControl ((volatile UInt8 *)0xf3000032)
1116 #define defaultBrightness 144
1117 #define heathrowContrastControl ((volatile UInt8 *)0xf3000033)
1118 #define defaultContrast 183
1119
1120 #define gossamerSystemReg1 ((volatile UInt16 *)0xff000004)
1121 #define gossamerAllInOne (1 << 4)
1122
1123 void _eATISetMBRES( UInt32 state )
1124 {
1125 UInt32 value;
1126
1127 value = *heathrowFeatureControl;
1128
1129 if( state == 0)
1130 value &= ~heathrowMBRES;
1131 else if( state == 1)
1132 value |= heathrowMBRES;
1133
1134 *heathrowFeatureControl = value;
1135 eieio();
1136 }
1137
1138 void _eATISetMonitorTermination( Boolean enable )
1139 {
1140
1141 UInt32 value;
1142
1143 value = *heathrowID;
1144
1145 value |= heathrowTermEna;
1146 if( enable)
1147 value |= heathrowTermDir;
1148 else
1149 value &= ~heathrowTermDir;
1150
1151 *heathrowID = value;
1152 eieio();
1153 }
1154
1155 Boolean _eATIIsAllInOne( void )
1156 {
1157 Boolean rtn;
1158 static bool didBrightness;
1159
1160 rtn = (0 == ((*gossamerSystemReg1) & gossamerAllInOne));
1161 if( rtn && !didBrightness) {
1162 *heathrowBrightnessControl = defaultBrightness;
1163 eieio();
1164 *heathrowContrastControl = defaultContrast;
1165 eieio();
1166 didBrightness = true;
1167 }
1168 return( rtn);
1169 }
1170
1171 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1172
1173 static void IONDRVInterruptAction( OSObject * target, void * refCon,
1174 IOService * provider, int index )
1175 {
1176 IONDRVInterruptSet * set;
1177 IONDRVInterruptSource * source;
1178 SInt32 result;
1179
1180 set = (IONDRVInterruptSet *) target;
1181 index++;
1182
1183 do {
1184
1185 assert( (UInt32) index <= set->count);
1186 if( (UInt32) index > set->count)
1187 break;
1188
1189 source = set->sources + index;
1190 result = CallTVector( set, (void *) index, source->refCon, 0, 0, 0,
1191 source->handler );
1192
1193 switch( result ) {
1194
1195 case kIONDRVIsrIsNotComplete:
1196 index++;
1197 case kIONDRVIsrIsComplete:
1198 break;
1199
1200 case kIONDRVMemberNumberParent:
1201 assert( false );
1202 break;
1203
1204 default:
1205 index = result;
1206 set = set->child;
1207 break;
1208 }
1209
1210 } while( result != kIONDRVIsrIsComplete );
1211 }
1212
1213 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1214
1215 static SInt32 IONDRVStdInterruptHandler( IONDRVInterruptSetMember setMember,
1216 void *refCon, UInt32 theIntCount )
1217 {
1218 // assert( false );
1219
1220 return( kIONDRVIsrIsComplete );
1221 }
1222
1223 static bool IONDRVStdInterruptDisabler( IONDRVInterruptSetMember setMember,
1224 void *refCon )
1225 {
1226 IONDRVInterruptSet * set;
1227 IONDRVInterruptSource * source;
1228 bool was;
1229
1230 set = (IONDRVInterruptSet *) setMember.setID;
1231 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1232 assert( setMember.member <= set->count );
1233 source = set->sources + setMember.member;
1234
1235 was = source->enabled;
1236 source->enabled = false;
1237
1238 assert( set->provider );
1239 set->provider->disableInterrupt( setMember.member - 1 );
1240
1241 return( was );
1242 }
1243
1244 static void IONDRVStdInterruptEnabler( IONDRVInterruptSetMember setMember,
1245 void *refCon )
1246 {
1247 IONDRVInterruptSet * set;
1248 IONDRVInterruptSource * source;
1249
1250 set = (IONDRVInterruptSet *) setMember.setID;
1251 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1252 assert( setMember.member <= set->count );
1253 source = set->sources + setMember.member;
1254
1255 source->enabled = true;
1256
1257 assert( set->provider );
1258
1259 if( !source->registered) {
1260 source->registered = true;
1261 set->provider->registerInterrupt( setMember.member - 1, set,
1262 &IONDRVInterruptAction, (void *) 0x53 );
1263 }
1264
1265 set->provider->enableInterrupt( setMember.member - 1 );
1266 }
1267
1268 static IOTVector tvIONDRVStdInterruptHandler = { IONDRVStdInterruptHandler, 0 };
1269 static IOTVector tvIONDRVStdInterruptEnabler = { IONDRVStdInterruptEnabler, 0 };
1270 static IOTVector tvIONDRVStdInterruptDisabler = { IONDRVStdInterruptDisabler, 0 };
1271
1272
1273 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1274
1275 OSStatus
1276 _eGetInterruptFunctions( void * setID,
1277 UInt32 member,
1278 void ** refCon,
1279 IOTVector ** handler,
1280 IOTVector ** enabler,
1281 IOTVector ** disabler )
1282 {
1283 IONDRVInterruptSet * set;
1284 IONDRVInterruptSource * source;
1285 OSStatus err = noErr;
1286
1287 set = (IONDRVInterruptSet *) setID;
1288 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1289 assert( member <= set->count );
1290 source = set->sources + member;
1291
1292 if( refCon)
1293 *refCon = source->refCon;
1294 if( handler)
1295 *handler = source->handler;
1296 if( enabler)
1297 *enabler = source->enabler;
1298 if( disabler)
1299 *disabler = source->disabler;
1300
1301 return( err);
1302 }
1303
1304 IOReturn
1305 IONDRVInstallInterruptFunctions(void * setID,
1306 UInt32 member,
1307 void * refCon,
1308 IOTVector * handler,
1309 IOTVector * enabler,
1310 IOTVector * disabler )
1311 {
1312 IONDRVInterruptSet * set;
1313 IONDRVInterruptSource * source;
1314 OSStatus err = noErr;
1315
1316 set = (IONDRVInterruptSet *) setID;
1317 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1318 if( member > set->count )
1319 return( paramErr );
1320 source = set->sources + member;
1321
1322 source->refCon = refCon;
1323 if( handler)
1324 source->handler = handler;
1325 if( enabler)
1326 source->enabler = enabler;
1327 if( disabler)
1328 source->disabler = disabler;
1329
1330 return( err);
1331 }
1332
1333 OSStatus
1334 _eInstallInterruptFunctions(void * setID,
1335 UInt32 member,
1336 void * refCon,
1337 IOTVector * handler,
1338 IOTVector * enabler,
1339 IOTVector * disabler )
1340 {
1341 return( IONDRVInstallInterruptFunctions( setID, member, refCon,
1342 handler, enabler, disabler ));
1343 }
1344
1345 OSStatus
1346 _eCreateInterruptSet( void * parentSet,
1347 UInt32 parentMember,
1348 UInt32 setSize,
1349 void ** setID,
1350 IOOptionBits options )
1351 {
1352 IONDRVInterruptSet * set;
1353 IONDRVInterruptSet * newSet;
1354 IONDRVInterruptSource * source;
1355 OSStatus err = noErr;
1356
1357 set = (IONDRVInterruptSet *) parentSet;
1358 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1359 assert( parentMember <= set->count );
1360 source = set->sources + parentMember;
1361
1362 newSet = IONDRVInterruptSet::with( 0, options, setSize );
1363 assert( newSet );
1364
1365 if( newSet) for( UInt32 i = 1; i <= setSize; i++ ) {
1366
1367 source = newSet->sources + i;
1368 source->handler = &tvIONDRVStdInterruptHandler;
1369 source->enabler = &tvIONDRVStdInterruptEnabler;
1370 source->disabler = &tvIONDRVStdInterruptDisabler;
1371 }
1372
1373 set->child = newSet;
1374 *setID = newSet;
1375
1376 return( err );
1377 }
1378
1379 OSStatus
1380 _eDeleteInterruptSet( void * setID )
1381 {
1382 IONDRVInterruptSet * set;
1383 OSStatus err = noErr;
1384
1385 set = (IONDRVInterruptSet *) setID;
1386 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1387
1388 set->release();
1389
1390 return( err );
1391 }
1392
1393 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1394
1395 #define MAKEFUNC(s,e) { s, e, 0 }
1396
1397 static FunctionEntry PCILibFuncs[] =
1398 {
1399 MAKEFUNC( "ExpMgrConfigReadLong", _eExpMgrConfigReadLong),
1400 MAKEFUNC( "ExpMgrConfigReadWord", _eExpMgrConfigReadWord),
1401 MAKEFUNC( "ExpMgrConfigReadByte", _eExpMgrConfigReadByte),
1402 MAKEFUNC( "ExpMgrConfigWriteLong", _eExpMgrConfigWriteLong),
1403 MAKEFUNC( "ExpMgrConfigWriteWord", _eExpMgrConfigWriteWord),
1404 MAKEFUNC( "ExpMgrConfigWriteByte", _eExpMgrConfigWriteByte),
1405
1406 MAKEFUNC( "ExpMgrIOReadLong", _eExpMgrIOReadLong),
1407 MAKEFUNC( "ExpMgrIOReadWord", _eExpMgrIOReadWord),
1408 MAKEFUNC( "ExpMgrIOReadByte", _eExpMgrIOReadByte),
1409 MAKEFUNC( "ExpMgrIOWriteLong", _eExpMgrIOWriteLong),
1410 MAKEFUNC( "ExpMgrIOWriteWord", _eExpMgrIOWriteWord),
1411 MAKEFUNC( "ExpMgrIOWriteByte", _eExpMgrIOWriteByte),
1412
1413 MAKEFUNC( "EndianSwap16Bit", _eEndianSwap16Bit),
1414 MAKEFUNC( "EndianSwap32Bit", _eEndianSwap32Bit)
1415 };
1416
1417 static FunctionEntry VideoServicesLibFuncs[] =
1418 {
1419 MAKEFUNC( "VSLPrepareCursorForHardwareCursor",
1420 IONDRVFramebuffer::VSLPrepareCursorForHardwareCursor),
1421 MAKEFUNC( "VSLNewInterruptService", IONDRVFramebuffer::VSLNewInterruptService),
1422 MAKEFUNC( "VSLDisposeInterruptService", IONDRVFramebuffer::VSLDisposeInterruptService),
1423 MAKEFUNC( "VSLDoInterruptService", IONDRVFramebuffer::VSLDoInterruptService),
1424 MAKEFUNC( "VSLSetDisplayConfiguration", _eVSLSetDisplayConfiguration)
1425 };
1426
1427 static FunctionEntry NameRegistryLibFuncs[] =
1428 {
1429 MAKEFUNC( "RegistryEntryIDCopy", _eRegistryEntryIDCopy),
1430 MAKEFUNC( "RegistryEntryIDInit", _eRegistryEntryIDInit),
1431 MAKEFUNC( "RegistryEntryIDDispose", _eNoErr),
1432 MAKEFUNC( "RegistryEntryIDCompare", _eRegistryEntryIDCompare),
1433 MAKEFUNC( "RegistryPropertyGetSize", _eRegistryPropertyGetSize),
1434 MAKEFUNC( "RegistryPropertyGet", _eRegistryPropertyGet),
1435 MAKEFUNC( "RegistryPropertyGetMod", _eRegistryPropertyGetMod),
1436 MAKEFUNC( "RegistryPropertySetMod", _eRegistryPropertySetMod),
1437
1438 MAKEFUNC( "RegistryPropertyIterateCreate", _eRegistryPropertyIterateCreate),
1439 MAKEFUNC( "RegistryPropertyIterateDispose", _eRegistryPropertyIterateDispose),
1440 MAKEFUNC( "RegistryPropertyIterate", _eRegistryPropertyIterate),
1441
1442 MAKEFUNC( "RegistryEntryIterateCreate", _eRegistryEntryIterateCreate),
1443 MAKEFUNC( "RegistryEntryIterateDispose", _eRegistryEntryIterateDispose),
1444 MAKEFUNC( "RegistryEntryIterate", _eRegistryEntryIterate),
1445 MAKEFUNC( "RegistryCStrEntryToName", _eRegistryCStrEntryToName),
1446 MAKEFUNC( "RegistryCStrEntryLookup", _eRegistryCStrEntryLookup),
1447
1448 MAKEFUNC( "RegistryCStrEntryCreate", _eRegistryCStrEntryCreate),
1449 MAKEFUNC( "RegistryEntryDelete", _eNoErr),
1450
1451 MAKEFUNC( "RegistryPropertyCreate", _eRegistryPropertyCreate),
1452 MAKEFUNC( "RegistryPropertyDelete", _eRegistryPropertyDelete),
1453 MAKEFUNC( "RegistryPropertySet", _eRegistryPropertySet)
1454 };
1455
1456
1457 static FunctionEntry DriverServicesLibFuncs[] =
1458 {
1459 MAKEFUNC( "SynchronizeIO", _eSynchronizeIO),
1460 MAKEFUNC( "SetProcessorCacheMode", _eSetProcessorCacheMode),
1461 MAKEFUNC( "BlockCopy", bcopy),
1462 MAKEFUNC( "BlockMove", bcopy),
1463 MAKEFUNC( "BlockMoveData", bcopy),
1464 MAKEFUNC( "CStrCopy", strcpy),
1465 MAKEFUNC( "CStrCmp", strcmp),
1466 MAKEFUNC( "CStrLen", strlen),
1467 MAKEFUNC( "CStrCat", strcat),
1468 MAKEFUNC( "CStrNCopy", strncpy),
1469 MAKEFUNC( "CStrNCmp", strncmp),
1470 MAKEFUNC( "CStrNCat", strncat),
1471 MAKEFUNC( "PStrCopy", _ePStrCopy),
1472
1473 MAKEFUNC( "PoolAllocateResident", _ePoolAllocateResident),
1474 MAKEFUNC( "MemAllocatePhysicallyContiguous", _ePoolAllocateResident),
1475 MAKEFUNC( "PoolDeallocate", _ePoolDeallocate),
1476
1477 MAKEFUNC( "UpTime", _eUpTime),
1478 MAKEFUNC( "AbsoluteDeltaToDuration", _eAbsoluteDeltaToDuration),
1479 MAKEFUNC( "AddAbsoluteToAbsolute", _eAddAbsoluteToAbsolute),
1480 MAKEFUNC( "SubAbsoluteFromAbsolute", _eSubAbsoluteFromAbsolute),
1481 MAKEFUNC( "AddDurationToAbsolute", _eAddDurationToAbsolute),
1482 MAKEFUNC( "NanosecondsToAbsolute", _eNanosecondsToAbsolute),
1483 MAKEFUNC( "AbsoluteToNanoseconds", _eAbsoluteToNanoseconds),
1484 MAKEFUNC( "DurationToAbsolute", _eDurationToAbsolute),
1485 MAKEFUNC( "DelayForHardware", _eDelayForHardware),
1486 MAKEFUNC( "DelayFor", _eDelayFor),
1487
1488 MAKEFUNC( "CurrentExecutionLevel", _eCurrentExecutionLevel),
1489 MAKEFUNC( "IOCommandIsComplete", _eIOCommandIsComplete),
1490
1491 MAKEFUNC( "SysDebugStr", _eNoErr),
1492 MAKEFUNC( "SysDebug", _eNoErr),
1493
1494 MAKEFUNC( "CompareAndSwap", OSCompareAndSwap),
1495
1496 MAKEFUNC( "CreateInterruptSet", _eCreateInterruptSet),
1497 MAKEFUNC( "DeleteInterruptSet", _eDeleteInterruptSet),
1498 MAKEFUNC( "GetInterruptFunctions", _eGetInterruptFunctions),
1499 MAKEFUNC( "InstallInterruptFunctions", _eInstallInterruptFunctions)
1500
1501 };
1502
1503 static FunctionEntry ATIUtilsFuncs[] =
1504 {
1505 // Gossamer onboard ATI
1506 MAKEFUNC( "ATISetMBRES", _eATISetMBRES),
1507 MAKEFUNC( "ATISetMonitorTermination", _eATISetMonitorTermination),
1508 MAKEFUNC( "ATIIsAllInOne", _eATIIsAllInOne)
1509 };
1510
1511 // These are all out of spec
1512
1513 static FunctionEntry InterfaceLibFuncs[] =
1514 {
1515 // Apple control : XPRam and EgretDispatch
1516 MAKEFUNC( "CallUniversalProc", _eFail),
1517 MAKEFUNC( "CallOSTrapUniversalProc", _eCallOSTrapUniversalProc),
1518
1519 // Apple chips65550
1520 // MAKEFUNC( "NewRoutineDescriptor", _eCallOSTrapUniversalProc),
1521 // MAKEFUNC( "DisposeRoutineDescriptor", _eNoErr),
1522 // MAKEFUNC( "InsTime", _eInsTime),
1523 // MAKEFUNC( "PrimeTime", _ePrimeTime),
1524
1525 // Radius PrecisionColor 16
1526 MAKEFUNC( "CountADBs", _eNoErr),
1527 MAKEFUNC( "GetIndADB", _eGetIndADB),
1528 MAKEFUNC( "GetKeys", _eGetKeys)
1529 };
1530
1531 static FunctionEntry PrivateInterfaceLibFuncs[] =
1532 {
1533 // Apple chips65550
1534 MAKEFUNC( "LMGetPowerMgrVars", _eLMGetPowerMgrVars )
1535 };
1536
1537 #define NUMLIBRARIES 7
1538 const ItemCount IONumNDRVLibraries = NUMLIBRARIES;
1539 LibraryEntry IONDRVLibraries[ NUMLIBRARIES ] =
1540 {
1541 { "PCILib", sizeof(PCILibFuncs) / sizeof(FunctionEntry), PCILibFuncs },
1542 { "VideoServicesLib", sizeof(VideoServicesLibFuncs) / sizeof(FunctionEntry), VideoServicesLibFuncs },
1543 { "NameRegistryLib", sizeof(NameRegistryLibFuncs) / sizeof(FunctionEntry), NameRegistryLibFuncs },
1544 { "DriverServicesLib", sizeof(DriverServicesLibFuncs) / sizeof(FunctionEntry), DriverServicesLibFuncs },
1545
1546 // G3
1547 { "ATIUtils", sizeof(ATIUtilsFuncs) / sizeof(FunctionEntry), ATIUtilsFuncs },
1548
1549 // out of spec stuff
1550 { "InterfaceLib", sizeof(InterfaceLibFuncs) / sizeof(FunctionEntry), InterfaceLibFuncs },
1551 { "PrivateInterfaceLib", sizeof(PrivateInterfaceLibFuncs) / sizeof(FunctionEntry), PrivateInterfaceLibFuncs }
1552 };
1553
1554 } /* extern "C" */
1555
1556 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1557
1558 #define super OSObject
1559
1560 OSDefineMetaClassAndStructors(IONDRVInterruptSet, OSObject)
1561
1562 IONDRVInterruptSet * IONDRVInterruptSet::with(IOService * provider,
1563 IOOptionBits options, SInt32 count )
1564 {
1565 IONDRVInterruptSet * set;
1566
1567 set = new IONDRVInterruptSet;
1568 if( set && !set->init()) {
1569 set->release();
1570 set = 0;
1571 }
1572
1573 if( set) {
1574
1575 set->provider = provider;
1576 set->options = options;
1577 set->count = count;
1578
1579 count++;
1580 set->sources = IONew( IONDRVInterruptSource, count );
1581 assert( set->sources );
1582 bzero( set->sources, count * sizeof( IONDRVInterruptSource));
1583 }
1584
1585 return( set );
1586 }
1587
1588 void IONDRVInterruptSet::free()
1589 {
1590 if( sources)
1591 IODelete( sources, IONDRVInterruptSource, count + 1 );
1592
1593 super::free();
1594 }
1595
1596 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1597
1598 #if NDRVLIBTEST
1599
1600 static void IONDRVLibrariesTest( IOService * provider )
1601 {
1602 UInt64 nano;
1603 UnsignedWide nano2;
1604 AbsoluteTime abs1, abs2;
1605
1606 nano = 1000ULL;
1607 abs1 = _eNanosecondsToAbsolute(UInt64ToUnsignedWide(&nano));
1608 IOLog("_eNanosecondsToAbsolute %08lx:%08lx\n", abs1.hi, abs1.lo);
1609 nano2 = _eAbsoluteToNanoseconds(abs1);
1610 IOLog("_eAbsoluteToNanoseconds %08lx:%08lx\n", nano2.hi, nano2.lo);
1611 AbsoluteTime_to_scalar(&abs2) = 0;
1612 IOLog("_eAbsoluteDeltaToDuration %ld\n", _eAbsoluteDeltaToDuration(abs1,abs2));
1613
1614 nano = 0x13161b000ULL;
1615 abs1 = _eNanosecondsToAbsolute(UInt64ToUnsignedWide(&nano));
1616 IOLog("_eNanosecondsToAbsolute %08lx:%08lx\n", abs1.hi, abs1.lo);
1617 nano2 = _eAbsoluteToNanoseconds(abs1);
1618 IOLog("_eAbsoluteToNanoseconds %08lx:%08lx\n", nano2.hi, nano2.lo);
1619 AbsoluteTime_to_scalar(&abs2) = 0;
1620 IOLog("_eAbsoluteDeltaToDuration %ld\n", _eAbsoluteDeltaToDuration(abs1,abs2));
1621
1622 nano = 0x6acfc00000000ULL;
1623 abs1 = _eNanosecondsToAbsolute(UInt64ToUnsignedWide(&nano));
1624 IOLog("_eNanosecondsToAbsolute %08lx:%08lx\n", abs1.hi, abs1.lo);
1625 nano2 = _eAbsoluteToNanoseconds(abs1);
1626 IOLog("_eAbsoluteToNanoseconds %08lx:%08lx\n", nano2.hi, nano2.lo);
1627 AbsoluteTime_to_scalar(&abs2) = 0;
1628 IOLog("_eAbsoluteDeltaToDuration %ld\n", _eAbsoluteDeltaToDuration(abs1,abs2));
1629
1630 abs1 = _eUpTime();
1631 IODelay(10);
1632 abs2 = _eUpTime();
1633 IOLog("10us duration %ld\n", _eAbsoluteDeltaToDuration(abs2,abs1));
1634
1635 abs1 = _eUpTime();
1636 for( int i =0; i < 50000; i++)
1637 _eDelayFor(1);
1638 abs2 = _eUpTime();
1639 IOLog("50000 DelayFor(1) %ld\n", _eAbsoluteDeltaToDuration(abs2,abs1));
1640
1641 abs1 = _eUpTime();
1642 _eDelayFor(50);
1643 abs2 = _eUpTime();
1644 IOLog("DelayFor(50) %ld\n", _eAbsoluteDeltaToDuration(abs2,abs1));
1645
1646 abs1 = _eDurationToAbsolute( -10);
1647 IOLog("_eDurationToAbsolute(-10) %08lx:%08lx\n", abs1.hi, abs1.lo);
1648 abs1 = _eDurationToAbsolute( 10);
1649 IOLog("_eDurationToAbsolute(10) %08lx:%08lx\n", abs1.hi, abs1.lo);
1650
1651 }
1652 #endif
1653
1654 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1655
1656 IOReturn IONDRVLibrariesInitialize( IOService * provider )
1657 {
1658 IODTPlatformExpert * platform;
1659 const OSSymbol * sym;
1660 OSData * data;
1661 OSArray * intSpec;
1662 unsigned int len, i;
1663
1664 #if NDRVLIBTEST
1665 IONDRVLibrariesTest( provider );
1666 #endif
1667
1668 // copy nvram property
1669
1670 if( (platform = OSDynamicCast( IODTPlatformExpert,
1671 IOService::getPlatform()))) {
1672
1673 // IOService::waitForService( IOService::resourceMatching( "IONVRAM" ));
1674
1675 if( kIOReturnSuccess == platform->readNVRAMProperty( provider,
1676 &sym, &data )) {
1677
1678 IONDRVSetNVRAMPropertyName( provider, sym );
1679 provider->setProperty( sym, data);
1680 data->release();
1681 sym->release();
1682 }
1683 }
1684
1685 // create interrupt properties, if none present
1686
1687 if( (intSpec = (OSArray *)provider->getProperty( gIOInterruptSpecifiersKey))
1688 && (0 == provider->getProperty( gIODTAAPLInterruptsKey ))) {
1689 // make AAPL,interrupts property if not present (NW)
1690 for( i = 0, len = 0; i < intSpec->getCount(); i++ ) {
1691 data = (OSData *) intSpec->getObject(i);
1692 assert( data );
1693 len += data->getLength();
1694 }
1695 if( len)
1696 data = OSData::withCapacity( len );
1697 if( data) {
1698 for( i = 0; i < intSpec->getCount(); i++ )
1699 data->appendBytes( (OSData *) intSpec->getObject(i));
1700 provider->setProperty( gIODTAAPLInterruptsKey, data );
1701 data->release();
1702 }
1703 }
1704
1705 // make NDRV interrupts
1706
1707 data = OSData::withCapacity( kIONDRVISTPropertyMemberCount
1708 * sizeof( IONDRVInterruptSetMember));
1709
1710 IONDRVInterruptSetMember setMember;
1711 IONDRVInterruptSet * set;
1712 IONDRVInterruptSource * source;
1713
1714 set = IONDRVInterruptSet::with( provider, 0,
1715 kIONDRVISTPropertyMemberCount );
1716
1717 if( set) for( i = 1; i <= kIONDRVISTPropertyMemberCount; i++ ) {
1718
1719 source = set->sources + i;
1720 source->handler = &tvIONDRVStdInterruptHandler;
1721 source->enabler = &tvIONDRVStdInterruptEnabler;
1722 source->disabler = &tvIONDRVStdInterruptDisabler;
1723
1724 setMember.setID = (void *) set;
1725 setMember.member = i;
1726 data->appendBytes( &setMember, sizeof( setMember));
1727
1728 } else
1729 data = 0;
1730
1731 if( data) {
1732 provider->setProperty( kIONDRVISTPropertyName, data );
1733 data->release();
1734 data = 0;
1735 }
1736
1737 // map memory
1738
1739 IOItemCount numMaps = provider->getDeviceMemoryCount();
1740 IOVirtualAddress virtAddress;
1741
1742 for( i = 0; i < numMaps; i++) {
1743 IODeviceMemory * mem;
1744 IOMemoryMap * map;
1745 bool consoleDevice;
1746
1747 consoleDevice = (0 != provider->getProperty("AAPL,boot-display"));
1748
1749 mem = provider->getDeviceMemoryWithIndex( i );
1750 if( 0 == mem)
1751 continue;
1752
1753 // set up a 1-1 mapping for the BAT map of the console device
1754 // remove this soon
1755 if( consoleDevice && (0 == mem->map( kIOMapReference)))
1756 mem->setMapping( kernel_task, mem->getPhysicalAddress() );
1757
1758 map = mem->map();
1759 if( 0 == map) {
1760 // IOLog("%s: map[%ld] failed\n", provider->getName(), i);
1761 continue;
1762 }
1763
1764 virtAddress = map->getVirtualAddress();
1765 if( !data)
1766 data = OSData::withCapacity( numMaps * sizeof( IOVirtualAddress));
1767 if( !data)
1768 continue;
1769 data->appendBytes( &virtAddress, sizeof( IOVirtualAddress));
1770 kprintf("ndrv base = %lx\n", virtAddress);
1771 }
1772
1773 // NDRV aperture vectors
1774 if( data) {
1775 provider->setProperty( "AAPL,address", data );
1776 data->release();
1777 }
1778
1779 return( kIOReturnSuccess );
1780 }
1781