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