]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IONDRVSupport/IONDRVLibraries.cpp
565126fefbda3c69de100b3c6a8d24e19b5f0802
[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
660 if( parentEntry) {
661 REG_ENTRY_TO_OBJ( parentEntry, regEntry)
662 } else
663 regEntry = 0;
664
665 buf = IONew( char, 512 );
666 if( !buf)
667 return( nrNotEnoughMemoryErr );
668
669 cvtPath = buf;
670 if( ':' == path[0])
671 path++;
672 else if( 0 == strncmp( path, kDTRoot, strlen( kDTRoot ))) {
673 path += strlen( kDTRoot ) - 1;
674 regEntry = 0;
675 }
676
677 do {
678 c = *(path++);
679 if( ':' == c)
680 c = '/';
681 *(cvtPath++) = c;
682 } while( c != 0 );
683
684 if( regEntry)
685 regEntry = regEntry->childFromPath( buf, gIODTPlane );
686 else
687 regEntry = IORegistryEntry::fromPath( buf, gIODTPlane );
688
689 if( regEntry) {
690 MAKE_REG_ENTRY( newEntry, regEntry);
691 regEntry->release();
692 err = noErr;
693 } else
694 err = nrNotFoundErr;
695
696 IODelete( buf, char, 512 );
697
698 return( err );
699 }
700
701
702 OSStatus
703 _eRegistryCStrEntryCreate( const RegEntryID * parentEntry,
704 char * name,
705 RegEntryID newEntry)
706 {
707 IORegistryEntry * newDev;
708 IORegistryEntry * parent;
709
710 REG_ENTRY_TO_OBJ( parentEntry, parent)
711
712 // NOT published
713
714 newDev = new IORegistryEntry;
715 if( newDev && (false == newDev->init()))
716 newDev = 0;
717
718 if( newDev) {
719 newDev->attachToParent( parent, gIODTPlane );
720 if( ':' == name[0])
721 name++;
722 newDev->setName( name );
723 }
724
725 MAKE_REG_ENTRY( newEntry, newDev);
726
727 if( newDev)
728 return( noErr);
729 else
730 return( nrNotCreatedErr);
731 }
732
733 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
734
735 extern "C" {
736
737 // in NDRVLibrariesAsm.s
738 extern void _eSynchronizeIO( void );
739
740 // platform expert
741 extern vm_offset_t
742 PEResidentAddress( vm_offset_t address, vm_size_t length );
743
744 };
745
746 enum {
747 kProcessorCacheModeDefault = 0,
748 kProcessorCacheModeInhibited = 1,
749 kProcessorCacheModeWriteThrough = 2,
750 kProcessorCacheModeCopyBack = 3
751 };
752
753 OSStatus _eSetProcessorCacheMode( UInt32 /* space */, void * /* addr */,
754 UInt32 /* len */, UInt32 /* mode */ )
755 {
756 #if 0
757 struct phys_entry* pp;
758 vm_offset_t spa;
759 vm_offset_t epa;
760 int wimg;
761
762 // This doesn't change any existing kernel mapping eg. BAT changes etc.
763 // but this is enough to change user level mappings for DPS etc.
764 // Should use a kernel service when one is available.
765
766 spa = kvtophys( (vm_offset_t)addr);
767 if( spa == 0) {
768 spa = PEResidentAddress( (vm_offset_t)addr, len);
769 if( spa == 0)
770 return( kIOReturnVMError);
771 }
772 epa = (len + spa + 0xfff) & 0xfffff000;
773 spa &= 0xfffff000;
774
775 switch( mode) {
776 case kProcessorCacheModeWriteThrough:
777 wimg = PTE_WIMG_WT_CACHED_COHERENT_GUARDED;
778 break;
779 case kProcessorCacheModeCopyBack:
780 wimg = PTE_WIMG_CB_CACHED_COHERENT_GUARDED;
781 break;
782 default:
783 wimg = PTE_WIMG_UNCACHED_COHERENT_GUARDED;
784 break;
785 }
786
787 while( spa < epa) {
788 pp = pmap_find_physentry(spa);
789 if (pp != PHYS_NULL)
790 pp->pte1.bits.wimg = wimg;
791 spa += PAGE_SIZE;
792 }
793 #endif
794 _eSynchronizeIO();
795 return( noErr);
796 }
797
798 char * _ePStrCopy( char *to, const char *from )
799 {
800 UInt32 len;
801 char * copy;
802
803 copy = to;
804 len = *(from++);
805 *(copy++) = len;
806 bcopy( from, copy, len);
807 return( to);
808 }
809
810 LogicalAddress _ePoolAllocateResident(ByteCount byteSize, Boolean clear)
811 {
812 LogicalAddress mem;
813
814 mem = (LogicalAddress) kern_os_malloc( (size_t) byteSize );
815 if( clear && mem)
816 memset( mem, 0, byteSize);
817
818 return( mem);
819 }
820
821 OSStatus _ePoolDeallocate( LogicalAddress address )
822 {
823 kern_os_free( (void *) address );
824 return( noErr);
825 }
826
827 UInt32 _eCurrentExecutionLevel(void)
828 {
829 return(0); // == kTaskLevel, HWInt == 6
830 }
831
832 // don't expect any callers of this
833 OSErr _eIOCommandIsComplete( UInt32 /* commandID */, OSErr result)
834 {
835 LOG("_eIOCommandIsComplete\n");
836 return( result); // !!??!!
837 }
838
839 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
840
841 #include <kern/clock.h>
842
843
844 AbsoluteTime _eUpTime( void )
845 {
846 AbsoluteTime result;
847
848 clock_get_uptime( &result);
849
850 return( result);
851 }
852
853 AbsoluteTime _eAddAbsoluteToAbsolute(AbsoluteTime left, AbsoluteTime right)
854 {
855 AbsoluteTime result = left;
856
857 ADD_ABSOLUTETIME( &left, &right);
858
859 return( result);
860 }
861
862
863 AbsoluteTime _eSubAbsoluteFromAbsolute(AbsoluteTime left, AbsoluteTime right)
864 {
865 AbsoluteTime result = left;
866
867 // !! ATI bug fix here:
868 // They expect the 64-bit result to be signed. The spec says < 0 => 0
869 // To workaround, make sure this routine takes 10 us to execute.
870 IODelay( 10);
871
872 if( CMP_ABSOLUTETIME( &result, &right) < 0) {
873 AbsoluteTime_to_scalar( &result ) = 0;
874 } else {
875 result = left;
876 SUB_ABSOLUTETIME( &result, &right);
877 }
878
879 return( result);
880 }
881
882
883 AbsoluteTime _eDurationToAbsolute( Duration theDuration)
884 {
885 AbsoluteTime result;
886
887 if( theDuration > 0) {
888 clock_interval_to_absolutetime_interval( theDuration, kMillisecondScale,
889 &result );
890
891 } else {
892 clock_interval_to_absolutetime_interval( (-theDuration), kMicrosecondScale,
893 &result );
894 }
895
896 return( result);
897 }
898
899 AbsoluteTime _eAddDurationToAbsolute( Duration duration, AbsoluteTime absolute )
900 {
901 return( _eAddAbsoluteToAbsolute(_eDurationToAbsolute( duration), absolute));
902 }
903
904 #define UnsignedWideToUInt64(x) (*(UInt64 *)(x))
905 #define UInt64ToUnsignedWide(x) (*(UnsignedWide *)(x))
906
907 AbsoluteTime _eNanosecondsToAbsolute ( UnsignedWide theNanoseconds)
908 {
909 AbsoluteTime result;
910 UInt64 nano = UnsignedWideToUInt64(&theNanoseconds);
911
912 nanoseconds_to_absolutetime( nano, &result);
913
914 return( result);
915 }
916
917 UnsignedWide _eAbsoluteToNanoseconds( AbsoluteTime absolute )
918 {
919 UnsignedWide result;
920 UInt64 nano;
921
922 absolutetime_to_nanoseconds( absolute, &nano);
923 result = UInt64ToUnsignedWide( &nano );
924
925 return( result);
926 }
927
928 Duration _eAbsoluteDeltaToDuration( AbsoluteTime left, AbsoluteTime right )
929 {
930 Duration dur;
931 AbsoluteTime result;
932 UInt64 nano;
933
934 if( CMP_ABSOLUTETIME( &left, &right) < 0)
935 return( 0);
936
937 result = left;
938 SUB_ABSOLUTETIME( &result, &right);
939 absolutetime_to_nanoseconds( result, &nano);
940
941 if( nano >= ((1ULL << 31) * 1000ULL)) {
942 // +ve milliseconds
943 if( nano >= ((1ULL << 31) * 1000ULL * 1000ULL))
944 dur = 0x7fffffff;
945 else
946 dur = nano / 1000000ULL;
947 } else {
948 // -ve microseconds
949 dur = -(nano / 1000ULL);
950 }
951
952 return( dur);
953 }
954
955
956 OSStatus _eDelayForHardware( AbsoluteTime time )
957 {
958 AbsoluteTime deadline;
959
960 clock_absolutetime_interval_to_deadline( time, &deadline );
961 clock_delay_until( deadline );
962
963 return( noErr);
964 }
965
966 OSStatus _eDelayFor( Duration theDuration )
967 {
968 #if 1
969
970 // In Marconi, DelayFor uses the old toolbox Delay routine
971 // which is based on the 60 Hz timer. Durations are not
972 // rounded up when converting to ticks. Yes, really.
973 // Some ATI drivers call DelayFor(1) 50000 times starting up.
974 // There is some 64-bit math there so we'd better reproduce
975 // the overhead of that calculation.
976
977 #define DELAY_FOR_TICK_NANO 16666666
978 #define DELAY_FOR_TICK_MILLI 17
979 #define NANO32_MILLI 4295
980
981 UnsignedWide nano;
982 AbsoluteTime abs;
983 unsigned int ms;
984
985 abs = _eDurationToAbsolute( theDuration);
986 nano = _eAbsoluteToNanoseconds( abs);
987
988 ms = (nano.lo / DELAY_FOR_TICK_NANO) * DELAY_FOR_TICK_MILLI;
989 ms += nano.hi * NANO32_MILLI;
990 if( ms)
991 IOSleep( ms);
992
993 #else
994 // Accurate, but incompatible, version
995
996 #define SLEEP_THRESHOLD 5000
997
998 if( theDuration < 0) {
999
1000 // us duration
1001 theDuration -= theDuration;
1002 if( theDuration > SLEEP_THRESHOLD)
1003 IOSleep( (theDuration + 999) / 1000);
1004 else
1005 IODelay( theDuration);
1006
1007 } else {
1008
1009 // ms duration
1010 if( theDuration > (SLEEP_THRESHOLD / 1000))
1011 IOSleep( theDuration ); // ms
1012 else
1013 IODelay( theDuration * 1000); // us
1014 }
1015 #endif
1016
1017 return( noErr);
1018 }
1019
1020 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1021
1022 OSStatus _eCallOSTrapUniversalProc( UInt32 /* theProc */,
1023 UInt32 procInfo, UInt32 trap, UInt8 * pb )
1024 {
1025 OSStatus err = -40;
1026 struct PMgrOpParamBlock {
1027 SInt16 pmCommand;
1028 SInt16 pmLength;
1029 UInt8 * pmSBuffer;
1030 UInt8 * pmRBuffer;
1031 UInt8 pmData[4];
1032 };
1033 #define readExtSwitches 0xDC
1034
1035 if( (procInfo == 0x133822)
1036 && (trap == 0xa085) ) {
1037
1038 PMgrOpParamBlock * pmOp = (PMgrOpParamBlock *) pb;
1039
1040 if( (readExtSwitches == pmOp->pmCommand) && pmOp->pmRBuffer) {
1041 OSNumber * num = OSDynamicCast(OSNumber,
1042 IOService::getPlatform()->getProperty("AppleExtSwitchBootState"));
1043 *pmOp->pmRBuffer = (num->unsigned32BitValue() & 1);
1044 err = noErr;
1045 }
1046
1047 } else if( (procInfo == 0x133822)
1048 && (trap == 0xa092) ) {
1049
1050 UInt8 addr, reg, data;
1051
1052 addr = pb[ 2 ];
1053 reg = pb[ 3 ];
1054 pb = *( (UInt8 **) ((UInt32) pb + 8));
1055 data = pb[ 1 ];
1056 (*PE_write_IIC)( addr, reg, data );
1057 err = noErr;
1058 }
1059 return( err);
1060 }
1061
1062 const UInt32 * _eGetKeys( void )
1063 {
1064 static const UInt32 zeros[] = { 0, 0, 0, 0 };
1065
1066 return( zeros);
1067 }
1068
1069 UInt32 _eGetIndADB( void * adbInfo, UInt32 /* index */)
1070 {
1071 bzero( adbInfo, 10);
1072 return( 0); // orig address
1073 }
1074
1075 char * _eLMGetPowerMgrVars( void )
1076 {
1077 static char * powerMgrVars = NULL;
1078
1079 if( powerMgrVars == NULL) {
1080 powerMgrVars = (char *) IOMalloc( 0x3c0);
1081 if( powerMgrVars)
1082 bzero( powerMgrVars, 0x3c0);
1083 }
1084 return( powerMgrVars);
1085 }
1086
1087 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1088
1089 OSStatus _eNoErr( void )
1090 {
1091 return( noErr);
1092 }
1093
1094 OSStatus _eFail( void )
1095 {
1096 return( -40);
1097 }
1098
1099 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1100
1101 // fix this!
1102
1103 #define heathrowID ((volatile UInt32 *)0xf3000034)
1104 #define heathrowTermEna (1 << 3)
1105 #define heathrowTermDir (1 << 0)
1106
1107 #define heathrowFeatureControl ((volatile UInt32 *)0xf3000038)
1108 #define heathrowMBRES (1 << 24)
1109
1110 #define heathrowBrightnessControl ((volatile UInt8 *)0xf3000032)
1111 #define defaultBrightness 144
1112 #define heathrowContrastControl ((volatile UInt8 *)0xf3000033)
1113 #define defaultContrast 183
1114
1115 #define gossamerSystemReg1 ((volatile UInt16 *)0xff000004)
1116 #define gossamerAllInOne (1 << 4)
1117
1118 void _eATISetMBRES( UInt32 state )
1119 {
1120 UInt32 value;
1121
1122 value = *heathrowFeatureControl;
1123
1124 if( state == 0)
1125 value &= ~heathrowMBRES;
1126 else if( state == 1)
1127 value |= heathrowMBRES;
1128
1129 *heathrowFeatureControl = value;
1130 eieio();
1131 }
1132
1133 void _eATISetMonitorTermination( Boolean enable )
1134 {
1135
1136 UInt32 value;
1137
1138 value = *heathrowID;
1139
1140 value |= heathrowTermEna;
1141 if( enable)
1142 value |= heathrowTermDir;
1143 else
1144 value &= ~heathrowTermDir;
1145
1146 *heathrowID = value;
1147 eieio();
1148 }
1149
1150 Boolean _eATIIsAllInOne( void )
1151 {
1152 Boolean rtn;
1153 static bool didBrightness;
1154
1155 rtn = (0 == ((*gossamerSystemReg1) & gossamerAllInOne));
1156 if( rtn && !didBrightness) {
1157 *heathrowBrightnessControl = defaultBrightness;
1158 eieio();
1159 *heathrowContrastControl = defaultContrast;
1160 eieio();
1161 didBrightness = true;
1162 }
1163 return( rtn);
1164 }
1165
1166 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1167
1168 static void IONDRVInterruptAction( OSObject * target, void * refCon,
1169 IOService * provider, int index )
1170 {
1171 IONDRVInterruptSet * set;
1172 IONDRVInterruptSource * source;
1173 SInt32 result;
1174
1175 set = (IONDRVInterruptSet *) target;
1176 index++;
1177
1178 do {
1179
1180 assert( (UInt32) index <= set->count);
1181 if( (UInt32) index > set->count)
1182 break;
1183
1184 source = set->sources + index;
1185 result = CallTVector( set, (void *) index, source->refCon, 0, 0, 0,
1186 source->handler );
1187
1188 switch( result ) {
1189
1190 case kIONDRVIsrIsNotComplete:
1191 index++;
1192 case kIONDRVIsrIsComplete:
1193 break;
1194
1195 case kIONDRVMemberNumberParent:
1196 assert( false );
1197 break;
1198
1199 default:
1200 index = result;
1201 set = set->child;
1202 break;
1203 }
1204
1205 } while( result != kIONDRVIsrIsComplete );
1206 }
1207
1208 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1209
1210 static SInt32 IONDRVStdInterruptHandler( IONDRVInterruptSetMember setMember,
1211 void *refCon, UInt32 theIntCount )
1212 {
1213 // assert( false );
1214
1215 return( kIONDRVIsrIsComplete );
1216 }
1217
1218 static bool IONDRVStdInterruptDisabler( IONDRVInterruptSetMember setMember,
1219 void *refCon )
1220 {
1221 IONDRVInterruptSet * set;
1222 IONDRVInterruptSource * source;
1223 bool was;
1224
1225 set = (IONDRVInterruptSet *) setMember.setID;
1226 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1227 assert( setMember.member <= set->count );
1228 source = set->sources + setMember.member;
1229
1230 was = source->enabled;
1231 source->enabled = false;
1232
1233 assert( set->provider );
1234 set->provider->disableInterrupt( setMember.member - 1 );
1235
1236 return( was );
1237 }
1238
1239 static void IONDRVStdInterruptEnabler( IONDRVInterruptSetMember setMember,
1240 void *refCon )
1241 {
1242 IONDRVInterruptSet * set;
1243 IONDRVInterruptSource * source;
1244
1245 set = (IONDRVInterruptSet *) setMember.setID;
1246 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1247 assert( setMember.member <= set->count );
1248 source = set->sources + setMember.member;
1249
1250 source->enabled = true;
1251
1252 assert( set->provider );
1253
1254 if( !source->registered) {
1255 source->registered = true;
1256 set->provider->registerInterrupt( setMember.member - 1, set,
1257 &IONDRVInterruptAction, (void *) 0x53 );
1258 }
1259
1260 set->provider->enableInterrupt( setMember.member - 1 );
1261 }
1262
1263 static IOTVector tvIONDRVStdInterruptHandler = { IONDRVStdInterruptHandler, 0 };
1264 static IOTVector tvIONDRVStdInterruptEnabler = { IONDRVStdInterruptEnabler, 0 };
1265 static IOTVector tvIONDRVStdInterruptDisabler = { IONDRVStdInterruptDisabler, 0 };
1266
1267
1268 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1269
1270 OSStatus
1271 _eGetInterruptFunctions( void * setID,
1272 UInt32 member,
1273 void ** refCon,
1274 IOTVector ** handler,
1275 IOTVector ** enabler,
1276 IOTVector ** disabler )
1277 {
1278 IONDRVInterruptSet * set;
1279 IONDRVInterruptSource * source;
1280 OSStatus err = noErr;
1281
1282 set = (IONDRVInterruptSet *) setID;
1283 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1284 assert( member <= set->count );
1285 source = set->sources + member;
1286
1287 if( refCon)
1288 *refCon = source->refCon;
1289 if( handler)
1290 *handler = source->handler;
1291 if( enabler)
1292 *enabler = source->enabler;
1293 if( disabler)
1294 *disabler = source->disabler;
1295
1296 return( err);
1297 }
1298
1299 IOReturn
1300 IONDRVInstallInterruptFunctions(void * setID,
1301 UInt32 member,
1302 void * refCon,
1303 IOTVector * handler,
1304 IOTVector * enabler,
1305 IOTVector * disabler )
1306 {
1307 IONDRVInterruptSet * set;
1308 IONDRVInterruptSource * source;
1309 OSStatus err = noErr;
1310
1311 set = (IONDRVInterruptSet *) setID;
1312 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1313 if( member > set->count )
1314 return( paramErr );
1315 source = set->sources + member;
1316
1317 source->refCon = refCon;
1318 if( handler)
1319 source->handler = handler;
1320 if( enabler)
1321 source->enabler = enabler;
1322 if( disabler)
1323 source->disabler = disabler;
1324
1325 return( err);
1326 }
1327
1328 OSStatus
1329 _eInstallInterruptFunctions(void * setID,
1330 UInt32 member,
1331 void * refCon,
1332 IOTVector * handler,
1333 IOTVector * enabler,
1334 IOTVector * disabler )
1335 {
1336 return( IONDRVInstallInterruptFunctions( setID, member, refCon,
1337 handler, enabler, disabler ));
1338 }
1339
1340 OSStatus
1341 _eCreateInterruptSet( void * parentSet,
1342 UInt32 parentMember,
1343 UInt32 setSize,
1344 void ** setID,
1345 IOOptionBits options )
1346 {
1347 IONDRVInterruptSet * set;
1348 IONDRVInterruptSet * newSet;
1349 IONDRVInterruptSource * source;
1350 OSStatus err = noErr;
1351
1352 set = (IONDRVInterruptSet *) parentSet;
1353 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1354 assert( parentMember <= set->count );
1355 source = set->sources + parentMember;
1356
1357 newSet = IONDRVInterruptSet::with( 0, options, setSize );
1358 assert( newSet );
1359
1360 if( newSet) for( UInt32 i = 1; i <= setSize; i++ ) {
1361
1362 source = newSet->sources + i;
1363 source->handler = &tvIONDRVStdInterruptHandler;
1364 source->enabler = &tvIONDRVStdInterruptEnabler;
1365 source->disabler = &tvIONDRVStdInterruptDisabler;
1366 }
1367
1368 set->child = newSet;
1369 *setID = newSet;
1370
1371 return( err );
1372 }
1373
1374 OSStatus
1375 _eDeleteInterruptSet( void * setID )
1376 {
1377 IONDRVInterruptSet * set;
1378 OSStatus err = noErr;
1379
1380 set = (IONDRVInterruptSet *) setID;
1381 assert( OSDynamicCast( IONDRVInterruptSet, set ));
1382
1383 set->release();
1384
1385 return( err );
1386 }
1387
1388 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1389
1390 #define MAKEFUNC(s,e) { s, e, 0 }
1391
1392 static FunctionEntry PCILibFuncs[] =
1393 {
1394 MAKEFUNC( "ExpMgrConfigReadLong", _eExpMgrConfigReadLong),
1395 MAKEFUNC( "ExpMgrConfigReadWord", _eExpMgrConfigReadWord),
1396 MAKEFUNC( "ExpMgrConfigReadByte", _eExpMgrConfigReadByte),
1397 MAKEFUNC( "ExpMgrConfigWriteLong", _eExpMgrConfigWriteLong),
1398 MAKEFUNC( "ExpMgrConfigWriteWord", _eExpMgrConfigWriteWord),
1399 MAKEFUNC( "ExpMgrConfigWriteByte", _eExpMgrConfigWriteByte),
1400
1401 MAKEFUNC( "ExpMgrIOReadLong", _eExpMgrIOReadLong),
1402 MAKEFUNC( "ExpMgrIOReadWord", _eExpMgrIOReadWord),
1403 MAKEFUNC( "ExpMgrIOReadByte", _eExpMgrIOReadByte),
1404 MAKEFUNC( "ExpMgrIOWriteLong", _eExpMgrIOWriteLong),
1405 MAKEFUNC( "ExpMgrIOWriteWord", _eExpMgrIOWriteWord),
1406 MAKEFUNC( "ExpMgrIOWriteByte", _eExpMgrIOWriteByte),
1407
1408 MAKEFUNC( "EndianSwap16Bit", _eEndianSwap16Bit),
1409 MAKEFUNC( "EndianSwap32Bit", _eEndianSwap32Bit)
1410 };
1411
1412 static FunctionEntry VideoServicesLibFuncs[] =
1413 {
1414 MAKEFUNC( "VSLPrepareCursorForHardwareCursor",
1415 IONDRVFramebuffer::VSLPrepareCursorForHardwareCursor),
1416 MAKEFUNC( "VSLNewInterruptService", IONDRVFramebuffer::VSLNewInterruptService),
1417 MAKEFUNC( "VSLDisposeInterruptService", IONDRVFramebuffer::VSLDisposeInterruptService),
1418 MAKEFUNC( "VSLDoInterruptService", IONDRVFramebuffer::VSLDoInterruptService),
1419 MAKEFUNC( "VSLSetDisplayConfiguration", _eVSLSetDisplayConfiguration)
1420 };
1421
1422 static FunctionEntry NameRegistryLibFuncs[] =
1423 {
1424 MAKEFUNC( "RegistryEntryIDCopy", _eRegistryEntryIDCopy),
1425 MAKEFUNC( "RegistryEntryIDInit", _eRegistryEntryIDInit),
1426 MAKEFUNC( "RegistryEntryIDDispose", _eNoErr),
1427 MAKEFUNC( "RegistryEntryIDCompare", _eRegistryEntryIDCompare),
1428 MAKEFUNC( "RegistryPropertyGetSize", _eRegistryPropertyGetSize),
1429 MAKEFUNC( "RegistryPropertyGet", _eRegistryPropertyGet),
1430 MAKEFUNC( "RegistryPropertyGetMod", _eRegistryPropertyGetMod),
1431 MAKEFUNC( "RegistryPropertySetMod", _eRegistryPropertySetMod),
1432
1433 MAKEFUNC( "RegistryPropertyIterateCreate", _eRegistryPropertyIterateCreate),
1434 MAKEFUNC( "RegistryPropertyIterateDispose", _eRegistryPropertyIterateDispose),
1435 MAKEFUNC( "RegistryPropertyIterate", _eRegistryPropertyIterate),
1436
1437 MAKEFUNC( "RegistryEntryIterateCreate", _eRegistryEntryIterateCreate),
1438 MAKEFUNC( "RegistryEntryIterateDispose", _eRegistryEntryIterateDispose),
1439 MAKEFUNC( "RegistryEntryIterate", _eRegistryEntryIterate),
1440 MAKEFUNC( "RegistryCStrEntryToName", _eRegistryCStrEntryToName),
1441 MAKEFUNC( "RegistryCStrEntryLookup", _eRegistryCStrEntryLookup),
1442
1443 MAKEFUNC( "RegistryCStrEntryCreate", _eRegistryCStrEntryCreate),
1444 MAKEFUNC( "RegistryEntryDelete", _eNoErr),
1445
1446 MAKEFUNC( "RegistryPropertyCreate", _eRegistryPropertyCreate),
1447 MAKEFUNC( "RegistryPropertyDelete", _eRegistryPropertyDelete),
1448 MAKEFUNC( "RegistryPropertySet", _eRegistryPropertySet)
1449 };
1450
1451
1452 static FunctionEntry DriverServicesLibFuncs[] =
1453 {
1454 MAKEFUNC( "SynchronizeIO", _eSynchronizeIO),
1455 MAKEFUNC( "SetProcessorCacheMode", _eSetProcessorCacheMode),
1456 MAKEFUNC( "BlockCopy", bcopy),
1457 MAKEFUNC( "BlockMove", bcopy),
1458 MAKEFUNC( "BlockMoveData", bcopy),
1459 MAKEFUNC( "CStrCopy", strcpy),
1460 MAKEFUNC( "CStrCmp", strcmp),
1461 MAKEFUNC( "CStrLen", strlen),
1462 MAKEFUNC( "CStrCat", strcat),
1463 MAKEFUNC( "CStrNCopy", strncpy),
1464 MAKEFUNC( "CStrNCmp", strncmp),
1465 MAKEFUNC( "CStrNCat", strncat),
1466 MAKEFUNC( "PStrCopy", _ePStrCopy),
1467
1468 MAKEFUNC( "PoolAllocateResident", _ePoolAllocateResident),
1469 MAKEFUNC( "MemAllocatePhysicallyContiguous", _ePoolAllocateResident),
1470 MAKEFUNC( "PoolDeallocate", _ePoolDeallocate),
1471
1472 MAKEFUNC( "UpTime", _eUpTime),
1473 MAKEFUNC( "AbsoluteDeltaToDuration", _eAbsoluteDeltaToDuration),
1474 MAKEFUNC( "AddAbsoluteToAbsolute", _eAddAbsoluteToAbsolute),
1475 MAKEFUNC( "SubAbsoluteFromAbsolute", _eSubAbsoluteFromAbsolute),
1476 MAKEFUNC( "AddDurationToAbsolute", _eAddDurationToAbsolute),
1477 MAKEFUNC( "NanosecondsToAbsolute", _eNanosecondsToAbsolute),
1478 MAKEFUNC( "AbsoluteToNanoseconds", _eAbsoluteToNanoseconds),
1479 MAKEFUNC( "DurationToAbsolute", _eDurationToAbsolute),
1480 MAKEFUNC( "DelayForHardware", _eDelayForHardware),
1481 MAKEFUNC( "DelayFor", _eDelayFor),
1482
1483 MAKEFUNC( "CurrentExecutionLevel", _eCurrentExecutionLevel),
1484 MAKEFUNC( "IOCommandIsComplete", _eIOCommandIsComplete),
1485
1486 MAKEFUNC( "SysDebugStr", _eNoErr),
1487 MAKEFUNC( "SysDebug", _eNoErr),
1488
1489 MAKEFUNC( "CompareAndSwap", OSCompareAndSwap),
1490
1491 MAKEFUNC( "CreateInterruptSet", _eCreateInterruptSet),
1492 MAKEFUNC( "DeleteInterruptSet", _eDeleteInterruptSet),
1493 MAKEFUNC( "GetInterruptFunctions", _eGetInterruptFunctions),
1494 MAKEFUNC( "InstallInterruptFunctions", _eInstallInterruptFunctions)
1495
1496 };
1497
1498 static FunctionEntry ATIUtilsFuncs[] =
1499 {
1500 // Gossamer onboard ATI
1501 MAKEFUNC( "ATISetMBRES", _eATISetMBRES),
1502 MAKEFUNC( "ATISetMonitorTermination", _eATISetMonitorTermination),
1503 MAKEFUNC( "ATIIsAllInOne", _eATIIsAllInOne)
1504 };
1505
1506 // These are all out of spec
1507
1508 static FunctionEntry InterfaceLibFuncs[] =
1509 {
1510 // Apple control : XPRam and EgretDispatch
1511 MAKEFUNC( "CallUniversalProc", _eFail),
1512 MAKEFUNC( "CallOSTrapUniversalProc", _eCallOSTrapUniversalProc),
1513
1514 // Apple chips65550
1515 // MAKEFUNC( "NewRoutineDescriptor", _eCallOSTrapUniversalProc),
1516 // MAKEFUNC( "DisposeRoutineDescriptor", _eNoErr),
1517 // MAKEFUNC( "InsTime", _eInsTime),
1518 // MAKEFUNC( "PrimeTime", _ePrimeTime),
1519
1520 // Radius PrecisionColor 16
1521 MAKEFUNC( "CountADBs", _eNoErr),
1522 MAKEFUNC( "GetIndADB", _eGetIndADB),
1523 MAKEFUNC( "GetKeys", _eGetKeys)
1524 };
1525
1526 static FunctionEntry PrivateInterfaceLibFuncs[] =
1527 {
1528 // Apple chips65550
1529 MAKEFUNC( "LMGetPowerMgrVars", _eLMGetPowerMgrVars )
1530 };
1531
1532 #define NUMLIBRARIES 7
1533 const ItemCount IONumNDRVLibraries = NUMLIBRARIES;
1534 LibraryEntry IONDRVLibraries[ NUMLIBRARIES ] =
1535 {
1536 { "PCILib", sizeof(PCILibFuncs) / sizeof(FunctionEntry), PCILibFuncs },
1537 { "VideoServicesLib", sizeof(VideoServicesLibFuncs) / sizeof(FunctionEntry), VideoServicesLibFuncs },
1538 { "NameRegistryLib", sizeof(NameRegistryLibFuncs) / sizeof(FunctionEntry), NameRegistryLibFuncs },
1539 { "DriverServicesLib", sizeof(DriverServicesLibFuncs) / sizeof(FunctionEntry), DriverServicesLibFuncs },
1540
1541 // G3
1542 { "ATIUtils", sizeof(ATIUtilsFuncs) / sizeof(FunctionEntry), ATIUtilsFuncs },
1543
1544 // out of spec stuff
1545 { "InterfaceLib", sizeof(InterfaceLibFuncs) / sizeof(FunctionEntry), InterfaceLibFuncs },
1546 { "PrivateInterfaceLib", sizeof(PrivateInterfaceLibFuncs) / sizeof(FunctionEntry), PrivateInterfaceLibFuncs }
1547 };
1548
1549 } /* extern "C" */
1550
1551 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1552
1553 #define super OSObject
1554
1555 OSDefineMetaClassAndStructors(IONDRVInterruptSet, OSObject)
1556
1557 IONDRVInterruptSet * IONDRVInterruptSet::with(IOService * provider,
1558 IOOptionBits options, SInt32 count )
1559 {
1560 IONDRVInterruptSet * set;
1561
1562 set = new IONDRVInterruptSet;
1563 if( set && !set->init()) {
1564 set->release();
1565 set = 0;
1566 }
1567
1568 if( set) {
1569
1570 set->provider = provider;
1571 set->options = options;
1572 set->count = count;
1573
1574 count++;
1575 set->sources = IONew( IONDRVInterruptSource, count );
1576 assert( set->sources );
1577 bzero( set->sources, count * sizeof( IONDRVInterruptSource));
1578 }
1579
1580 return( set );
1581 }
1582
1583 void IONDRVInterruptSet::free()
1584 {
1585 if( sources)
1586 IODelete( sources, IONDRVInterruptSource, count + 1 );
1587
1588 super::free();
1589 }
1590
1591 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1592
1593 #if NDRVLIBTEST
1594
1595 static void IONDRVLibrariesTest( IOService * provider )
1596 {
1597 UInt64 nano;
1598 UnsignedWide nano2;
1599 AbsoluteTime abs1, abs2;
1600
1601 nano = 1000ULL;
1602 abs1 = _eNanosecondsToAbsolute(UInt64ToUnsignedWide(&nano));
1603 IOLog("_eNanosecondsToAbsolute %08lx:%08lx\n", abs1.hi, abs1.lo);
1604 nano2 = _eAbsoluteToNanoseconds(abs1);
1605 IOLog("_eAbsoluteToNanoseconds %08lx:%08lx\n", nano2.hi, nano2.lo);
1606 AbsoluteTime_to_scalar(&abs2) = 0;
1607 IOLog("_eAbsoluteDeltaToDuration %ld\n", _eAbsoluteDeltaToDuration(abs1,abs2));
1608
1609 nano = 0x13161b000ULL;
1610 abs1 = _eNanosecondsToAbsolute(UInt64ToUnsignedWide(&nano));
1611 IOLog("_eNanosecondsToAbsolute %08lx:%08lx\n", abs1.hi, abs1.lo);
1612 nano2 = _eAbsoluteToNanoseconds(abs1);
1613 IOLog("_eAbsoluteToNanoseconds %08lx:%08lx\n", nano2.hi, nano2.lo);
1614 AbsoluteTime_to_scalar(&abs2) = 0;
1615 IOLog("_eAbsoluteDeltaToDuration %ld\n", _eAbsoluteDeltaToDuration(abs1,abs2));
1616
1617 nano = 0x6acfc00000000ULL;
1618 abs1 = _eNanosecondsToAbsolute(UInt64ToUnsignedWide(&nano));
1619 IOLog("_eNanosecondsToAbsolute %08lx:%08lx\n", abs1.hi, abs1.lo);
1620 nano2 = _eAbsoluteToNanoseconds(abs1);
1621 IOLog("_eAbsoluteToNanoseconds %08lx:%08lx\n", nano2.hi, nano2.lo);
1622 AbsoluteTime_to_scalar(&abs2) = 0;
1623 IOLog("_eAbsoluteDeltaToDuration %ld\n", _eAbsoluteDeltaToDuration(abs1,abs2));
1624
1625 abs1 = _eUpTime();
1626 IODelay(10);
1627 abs2 = _eUpTime();
1628 IOLog("10us duration %ld\n", _eAbsoluteDeltaToDuration(abs2,abs1));
1629
1630 abs1 = _eUpTime();
1631 for( int i =0; i < 50000; i++)
1632 _eDelayFor(1);
1633 abs2 = _eUpTime();
1634 IOLog("50000 DelayFor(1) %ld\n", _eAbsoluteDeltaToDuration(abs2,abs1));
1635
1636 abs1 = _eUpTime();
1637 _eDelayFor(50);
1638 abs2 = _eUpTime();
1639 IOLog("DelayFor(50) %ld\n", _eAbsoluteDeltaToDuration(abs2,abs1));
1640
1641 abs1 = _eDurationToAbsolute( -10);
1642 IOLog("_eDurationToAbsolute(-10) %08lx:%08lx\n", abs1.hi, abs1.lo);
1643 abs1 = _eDurationToAbsolute( 10);
1644 IOLog("_eDurationToAbsolute(10) %08lx:%08lx\n", abs1.hi, abs1.lo);
1645
1646 }
1647 #endif
1648
1649 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1650
1651 IOReturn IONDRVLibrariesInitialize( IOService * provider )
1652 {
1653 IODTPlatformExpert * platform;
1654 const OSSymbol * sym;
1655 OSData * data;
1656 OSArray * intSpec;
1657 unsigned int len, i;
1658
1659 #if NDRVLIBTEST
1660 IONDRVLibrariesTest( provider );
1661 #endif
1662
1663 // copy nvram property
1664
1665 if( (platform = OSDynamicCast( IODTPlatformExpert,
1666 IOService::getPlatform()))) {
1667
1668 // IOService::waitForService( IOService::resourceMatching( "IONVRAM" ));
1669
1670 if( kIOReturnSuccess == platform->readNVRAMProperty( provider,
1671 &sym, &data )) {
1672
1673 IONDRVSetNVRAMPropertyName( provider, sym );
1674 provider->setProperty( sym, data);
1675 data->release();
1676 sym->release();
1677 }
1678 }
1679
1680 // create interrupt properties, if none present
1681
1682 if( (intSpec = (OSArray *)provider->getProperty( gIOInterruptSpecifiersKey))
1683 && (0 == provider->getProperty( gIODTAAPLInterruptsKey ))) {
1684 // make AAPL,interrupts property if not present (NW)
1685 for( i = 0, len = 0; i < intSpec->getCount(); i++ ) {
1686 data = (OSData *) intSpec->getObject(i);
1687 assert( data );
1688 len += data->getLength();
1689 }
1690 if( len)
1691 data = OSData::withCapacity( len );
1692 if( data) {
1693 for( i = 0; i < intSpec->getCount(); i++ )
1694 data->appendBytes( (OSData *) intSpec->getObject(i));
1695 provider->setProperty( gIODTAAPLInterruptsKey, data );
1696 data->release();
1697 }
1698 }
1699
1700 // make NDRV interrupts
1701
1702 data = OSData::withCapacity( kIONDRVISTPropertyMemberCount
1703 * sizeof( IONDRVInterruptSetMember));
1704
1705 IONDRVInterruptSetMember setMember;
1706 IONDRVInterruptSet * set;
1707 IONDRVInterruptSource * source;
1708
1709 set = IONDRVInterruptSet::with( provider, 0,
1710 kIONDRVISTPropertyMemberCount );
1711
1712 if( set) for( i = 1; i <= kIONDRVISTPropertyMemberCount; i++ ) {
1713
1714 source = set->sources + i;
1715 source->handler = &tvIONDRVStdInterruptHandler;
1716 source->enabler = &tvIONDRVStdInterruptEnabler;
1717 source->disabler = &tvIONDRVStdInterruptDisabler;
1718
1719 setMember.setID = (void *) set;
1720 setMember.member = i;
1721 data->appendBytes( &setMember, sizeof( setMember));
1722
1723 } else
1724 data = 0;
1725
1726 if( data) {
1727 provider->setProperty( kIONDRVISTPropertyName, data );
1728 data->release();
1729 data = 0;
1730 }
1731
1732 // map memory
1733
1734 IOItemCount numMaps = provider->getDeviceMemoryCount();
1735 IOVirtualAddress virtAddress;
1736
1737 for( i = 0; i < numMaps; i++) {
1738 IODeviceMemory * mem;
1739 IOMemoryMap * map;
1740 bool consoleDevice;
1741
1742 consoleDevice = (0 != provider->getProperty("AAPL,boot-display"));
1743
1744 mem = provider->getDeviceMemoryWithIndex( i );
1745 if( 0 == mem)
1746 continue;
1747
1748 // set up a 1-1 mapping for the BAT map of the console device
1749 // remove this soon
1750 if( consoleDevice && (0 == mem->map( kIOMapReference)))
1751 mem->setMapping( kernel_task, mem->getPhysicalAddress() );
1752
1753 map = mem->map();
1754 if( 0 == map) {
1755 // IOLog("%s: map[%ld] failed\n", provider->getName(), i);
1756 continue;
1757 }
1758
1759 virtAddress = map->getVirtualAddress();
1760 if( !data)
1761 data = OSData::withCapacity( numMaps * sizeof( IOVirtualAddress));
1762 if( !data)
1763 continue;
1764 data->appendBytes( &virtAddress, sizeof( IOVirtualAddress));
1765 kprintf("ndrv base = %lx\n", virtAddress);
1766 }
1767
1768 // NDRV aperture vectors
1769 if( data) {
1770 provider->setProperty( "AAPL,address", data );
1771 data->release();
1772 }
1773
1774 return( kIOReturnSuccess );
1775 }
1776