|
|
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) 1998 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * HISTORY ! 26: * ! 27: * 23 Nov 98 sdouglas created from objc version. ! 28: * ! 29: */ ! 30: ! 31: #include <IOKit/system.h> ! 32: ! 33: #include <IOKit/pci/IOPCIBridge.h> ! 34: #include <IOKit/pci/IOPCIDevice.h> ! 35: #include <IOKit/pci/IOAGPDevice.h> ! 36: #include <IOKit/IODeviceTreeSupport.h> ! 37: #include <IOKit/IORangeAllocator.h> ! 38: #include <IOKit/IOPlatformExpert.h> ! 39: #include <IOKit/IOLib.h> ! 40: #include <IOKit/assert.h> ! 41: ! 42: #include <libkern/c++/OSContainers.h> ! 43: ! 44: extern "C" { ! 45: #include <machine/machine_routines.h> ! 46: }; ! 47: ! 48: ! 49: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 50: ! 51: #define super IOService ! 52: ! 53: OSDefineMetaClass( IOPCIBridge, IOService ) ! 54: OSDefineAbstractStructors( IOPCIBridge, IOService ) ! 55: ! 56: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 57: ! 58: // 1 log, 2 disable DT ! 59: int gIOPCIDebug = 0; ! 60: ! 61: #ifdef __I386__ ! 62: static void setupIntelPIC(IOPCIDevice *nub); ! 63: #endif ! 64: ! 65: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 66: ! 67: bool IOPCIBridge::start( IOService * provider ) ! 68: { ! 69: if( !super::start( provider)) ! 70: return( false); ! 71: ! 72: // empty ranges to start ! 73: bridgeMemoryRanges = IORangeAllocator::withRange( 0, 1, 8, ! 74: IORangeAllocator::kLocking ); ! 75: assert( bridgeMemoryRanges ); ! 76: setProperty( "Bridge Memory Ranges", bridgeMemoryRanges ); ! 77: ! 78: bridgeIORanges = IORangeAllocator::withRange( 0, 1, 8, ! 79: IORangeAllocator::kLocking ); ! 80: assert( bridgeIORanges ); ! 81: setProperty( "Bridge IO Ranges", bridgeIORanges ); ! 82: ! 83: if( !configure( provider)) ! 84: return( false); ! 85: ! 86: probeBus( provider, firstBusNum() ); ! 87: ! 88: return( true ); ! 89: } ! 90: ! 91: bool IOPCIBridge::configure( IOService * provider ) ! 92: { ! 93: return( true ); ! 94: } ! 95: ! 96: static SInt32 PCICompare( UInt32 /* cellCount */, UInt32 cleft[], UInt32 cright[] ) ! 97: { ! 98: IOPCIPhysicalAddress * left = (IOPCIPhysicalAddress *) cleft; ! 99: IOPCIPhysicalAddress * right = (IOPCIPhysicalAddress *) cright; ! 100: static const UInt8 spacesEq[] = { 0, 1, 2, 2 }; ! 101: ! 102: if( spacesEq[ left->physHi.s.space ] != spacesEq[ right->physHi.s.space ]) ! 103: return( -1); ! 104: ! 105: return( left->physLo - right->physLo ); ! 106: } ! 107: ! 108: void IOPCIBridge::nvLocation( IORegistryEntry * entry, ! 109: UInt8 * busNum, UInt8 * deviceNum, UInt8 * functionNum ) ! 110: { ! 111: IOPCIDevice * nub; ! 112: ! 113: nub = OSDynamicCast( IOPCIDevice, entry ); ! 114: assert( nub ); ! 115: ! 116: *busNum = nub->space.s.busNum; ! 117: *deviceNum = nub->space.s.deviceNum; ! 118: *functionNum = nub->space.s.functionNum; ! 119: } ! 120: ! 121: void IOPCIBridge::spaceFromProperties( OSDictionary * propTable, ! 122: IOPCIAddressSpace * space ) ! 123: { ! 124: OSData * regProp; ! 125: IOPCIAddressSpace * inSpace; ! 126: ! 127: space->bits = 0; ! 128: ! 129: if( (regProp = (OSData *) propTable->getObject("reg"))) { ! 130: ! 131: inSpace = (IOPCIAddressSpace *) regProp->getBytesNoCopy(); ! 132: space->s.busNum = inSpace->s.busNum; ! 133: space->s.deviceNum = inSpace->s.deviceNum; ! 134: space->s.functionNum = inSpace->s.functionNum; ! 135: } ! 136: } ! 137: ! 138: IORegistryEntry * IOPCIBridge::findMatching( OSIterator * kids, ! 139: IOPCIAddressSpace space ) ! 140: { ! 141: IORegistryEntry * found = 0; ! 142: IOPCIAddressSpace regSpace; ! 143: ! 144: if( kids) { ! 145: kids->reset(); ! 146: while( (0 == found) ! 147: && (found = (IORegistryEntry *) kids->getNextObject())) { ! 148: ! 149: spaceFromProperties( found->getPropertyTable(), ®Space); ! 150: if( space.bits != regSpace.bits) ! 151: found = 0; ! 152: } ! 153: } ! 154: return( found ); ! 155: } ! 156: ! 157: OSDictionary * IOPCIBridge::constructProperties( IOPCIAddressSpace space ) ! 158: { ! 159: OSDictionary * propTable; ! 160: UInt32 value; ! 161: UInt8 byte; ! 162: UInt16 vendor, device; ! 163: OSData * prop; ! 164: const char * name; ! 165: const OSSymbol * nameProp; ! 166: char * nameStr; ! 167: char * compatBuf; ! 168: char * nextCompat; ! 169: ! 170: struct IOPCIGenericNames { ! 171: const char * name; ! 172: UInt32 mask; ! 173: UInt32 classCode; ! 174: }; ! 175: static const IOPCIGenericNames genericNames[] = { ! 176: { "display", 0xffffff, 0x000100 }, ! 177: { "scsi", 0xffff00, 0x010000 }, ! 178: { "ethernet", 0xffff00, 0x020000 }, ! 179: { "display", 0xff0000, 0x030000 }, ! 180: { "pci-bridge", 0xffff00, 0x060400 }, ! 181: { 0, 0, 0 } ! 182: }; ! 183: const IOPCIGenericNames * nextName; ! 184: ! 185: compatBuf = (char *) IOMalloc( 256 ); ! 186: ! 187: propTable = OSDictionary::withCapacity( 8 ); ! 188: ! 189: if( compatBuf && propTable) { ! 190: ! 191: prop = OSData::withBytes( &space, sizeof( space) ); ! 192: if( prop) { ! 193: propTable->setObject("reg", prop ); ! 194: prop->release(); ! 195: } ! 196: ! 197: value = configRead32( space, kIOPCIConfigVendorID ); ! 198: vendor = value; ! 199: device = value >> 16; ! 200: ! 201: prop = OSData::withBytes( &vendor, 2 ); ! 202: if( prop) { ! 203: propTable->setObject("vendor-id", prop ); ! 204: prop->release(); ! 205: } ! 206: ! 207: prop = OSData::withBytes( &device, 2 ); ! 208: if( prop) { ! 209: propTable->setObject("device-id", prop ); ! 210: prop->release(); ! 211: } ! 212: ! 213: value = configRead32( space, kIOPCIConfigRevisionID ); ! 214: byte = value & 0xff; ! 215: prop = OSData::withBytes( &byte, 1 ); ! 216: if( prop) { ! 217: propTable->setObject("revision-id", prop ); ! 218: prop->release(); ! 219: } ! 220: ! 221: // make generic name ! 222: value >>= 8; ! 223: name = 0; ! 224: for( nextName = genericNames; ! 225: (0 == name) && nextName->name; ! 226: nextName++ ) { ! 227: if( (value & nextName->mask) == nextName->classCode) ! 228: name = nextName->name; ! 229: } ! 230: ! 231: // start compatible list ! 232: nextCompat = compatBuf; ! 233: sprintf( nextCompat, "pci%x,%x", vendor, device); ! 234: nameStr = nextCompat; ! 235: ! 236: value = configRead32( space, kIOPCIConfigSubSystemVendorID ); ! 237: if( value) { ! 238: vendor = value; ! 239: device = value >> 16; ! 240: ! 241: prop = OSData::withBytes( &vendor, 2 ); ! 242: if( prop) { ! 243: propTable->setObject("subsystem-vendor-id", prop ); ! 244: prop->release(); ! 245: } ! 246: prop = OSData::withBytes( &device, 2 ); ! 247: if( prop) { ! 248: propTable->setObject("subsystem-id", prop ); ! 249: prop->release(); ! 250: } ! 251: ! 252: nextCompat += strlen( nextCompat ) + 1; ! 253: sprintf( nextCompat, "pci%x,%x", vendor, device); ! 254: nameStr = nextCompat; ! 255: } ! 256: ! 257: nextCompat += strlen( nextCompat ) + 1; ! 258: prop = OSData::withBytes( compatBuf, nextCompat - compatBuf); ! 259: if( prop) { ! 260: propTable->setObject( "compatible", prop ); ! 261: prop->release(); ! 262: } ! 263: ! 264: if( 0 == name) ! 265: name = nameStr; ! 266: ! 267: nameProp = OSSymbol::withCString( name ); ! 268: if( nameProp) { ! 269: propTable->setObject( gIONameKey, (OSSymbol *) nameProp); ! 270: nameProp->release(); ! 271: } ! 272: } ! 273: ! 274: if( compatBuf) ! 275: IOFree( compatBuf, 256 ); ! 276: ! 277: return( propTable ); ! 278: } ! 279: ! 280: IOPCIDevice * IOPCIBridge::createNub( OSDictionary * from ) ! 281: { ! 282: return( new IOPCIDevice ); ! 283: } ! 284: ! 285: bool IOPCIBridge::initializeNub( IOPCIDevice * nub, ! 286: OSDictionary * from ) ! 287: { ! 288: spaceFromProperties( from, &nub->space); ! 289: nub->parent = this; ! 290: if( ioDeviceMemory()) ! 291: nub->ioMap = ioDeviceMemory()->map(); ! 292: ! 293: return( true ); ! 294: } ! 295: ! 296: bool IOPCIBridge::publishNub( IOPCIDevice * nub, UInt32 /* index */ ) ! 297: { ! 298: char location[ 24 ]; ! 299: bool ok; ! 300: ! 301: if( nub) { ! 302: if( nub->space.s.functionNum) ! 303: sprintf( location, "%X,%X", nub->space.s.deviceNum, ! 304: nub->space.s.functionNum ); ! 305: else ! 306: sprintf( location, "%X", nub->space.s.deviceNum ); ! 307: nub->setLocation( location ); ! 308: IODTFindSlotName( nub, nub->space.s.deviceNum ); ! 309: ! 310: ok = nub->attach( this ); ! 311: if( ok) ! 312: nub->registerService(); ! 313: } else ! 314: ok = false; ! 315: ! 316: return( ok ); ! 317: } ! 318: ! 319: void IOPCIBridge::publishNubs( OSIterator * kids, UInt32 index ) ! 320: { ! 321: IORegistryEntry * found; ! 322: IOPCIDevice * nub; ! 323: OSDictionary * propTable; ! 324: ! 325: if( kids) { ! 326: kids->reset(); ! 327: while( (found = (IORegistryEntry *) kids->getNextObject())) { ! 328: ! 329: propTable = found->getPropertyTable(); ! 330: nub = createNub( propTable ); ! 331: if( !nub) ! 332: continue; ! 333: if( !initializeNub( nub, propTable)) ! 334: continue; ! 335: if( !nub->init( found, gIODTPlane)) ! 336: continue; ! 337: ! 338: publishNub( nub, index++ ); ! 339: ! 340: if( 1 & gIOPCIDebug) ! 341: IOLog("%08lx = 0:%08lx 4:%08lx ", nub->space.bits, ! 342: nub->configRead32(kIOPCIConfigVendorID), ! 343: nub->configRead32(kIOPCIConfigCommand) ); ! 344: ! 345: } ! 346: } ! 347: } ! 348: ! 349: UInt8 IOPCIBridge::firstBusNum( void ) ! 350: { ! 351: return( 0 ); ! 352: } ! 353: ! 354: UInt8 IOPCIBridge::lastBusNum( void ) ! 355: { ! 356: return( 255 ); ! 357: } ! 358: ! 359: void IOPCIBridge::probeBus( IOService * provider, UInt8 busNum ) ! 360: { ! 361: IORegistryEntry * regEntry; ! 362: OSDictionary * propTable; ! 363: IOPCIDevice * nub = 0; ! 364: IOPCIAddressSpace space; ! 365: UInt32 vendor; ! 366: UInt8 scanDevice, scanFunction, lastFunction; ! 367: OSIterator * kidsIter; ! 368: UInt32 index = 0; ! 369: ! 370: IODTSetResolving( provider, PCICompare, nvLocation ); ! 371: ! 372: if( 2 & gIOPCIDebug) ! 373: kidsIter = 0; ! 374: else ! 375: kidsIter = provider->getChildIterator( gIODTPlane ); ! 376: ! 377: space.bits = 0; ! 378: space.s.busNum = busNum; ! 379: ! 380: for( scanDevice = 0; scanDevice <= 31; scanDevice++ ) { ! 381: ! 382: lastFunction = 0; ! 383: for( scanFunction = 0; scanFunction <= lastFunction; scanFunction++ ) { ! 384: ! 385: space.s.deviceNum = scanDevice; ! 386: space.s.functionNum = scanFunction; ! 387: ! 388: if( (regEntry = findMatching( kidsIter, space ))) { ! 389: ! 390: ! 391: } else { ! 392: /* probe - should guard exceptions */ ! 393: #ifdef __ppc__ ! 394: // DEC bridge really needs safe probe ! 395: continue; ! 396: #endif ! 397: vendor = configRead32( space, kIOPCIConfigVendorID ); ! 398: vendor &= 0x0000ffff; ! 399: if( (0 == vendor) || (0xffff == vendor)) ! 400: continue; ! 401: ! 402: // look in function 0 for multi function flag ! 403: if( (0 == scanFunction) ! 404: && (0x00800000 & configRead32( space, ! 405: kIOPCIConfigCacheLineSize ))) ! 406: lastFunction = 7; ! 407: ! 408: propTable = constructProperties( space ); ! 409: if( propTable ! 410: && (nub = createNub( propTable)) ! 411: && (initializeNub( nub, propTable)) ! 412: && nub->init( propTable )) { ! 413: #ifdef __I386__ ! 414: setupIntelPIC(nub); ! 415: #endif ! 416: publishNub( nub, index++); ! 417: } ! 418: } ! 419: } ! 420: } ! 421: ! 422: if( kidsIter) { ! 423: publishNubs( kidsIter, index ); ! 424: kidsIter->release(); ! 425: } ! 426: } ! 427: ! 428: bool IOPCIBridge::addBridgeMemoryRange( IOPhysicalAddress start, ! 429: IOPhysicalLength length, bool host ) ! 430: { ! 431: IORangeAllocator * platformRanges; ! 432: bool ok = true; ! 433: ! 434: if( host ) { ! 435: ! 436: platformRanges = getPlatform()->getPhysicalRangeAllocator(); ! 437: assert( platformRanges ); ! 438: ! 439: // out of the platform ! 440: ok = platformRanges->allocateRange( start, length ); ! 441: if( !ok) ! 442: kprintf("%s: didn't get host range (%08lx:%08lx)\n", getName(), ! 443: start, length); ! 444: } ! 445: ! 446: // and into the bridge ! 447: bridgeMemoryRanges->deallocate( start, length ); ! 448: ! 449: return( ok ); ! 450: } ! 451: ! 452: bool IOPCIBridge::addBridgeIORange( IOByteCount start, IOByteCount length ) ! 453: { ! 454: bool ok = true; ! 455: ! 456: // into the bridge ! 457: bridgeIORanges->deallocate( start, length ); ! 458: ! 459: return( ok ); ! 460: } ! 461: ! 462: bool IOPCIBridge::constructRange( IOPCIAddressSpace * flags, ! 463: IOPhysicalAddress phys, ! 464: IOPhysicalLength len, ! 465: OSArray * array ) ! 466: { ! 467: IODeviceMemory * range; ! 468: IODeviceMemory * ioMemory; ! 469: IORangeAllocator * bridgeRanges; ! 470: bool ok; ! 471: ! 472: if( !array) ! 473: return( false ); ! 474: ! 475: if( kIOPCIIOSpace == flags->s.space) { ! 476: ! 477: bridgeRanges = bridgeIORanges; ! 478: if( (ioMemory = ioDeviceMemory())) { ! 479: ! 480: phys &= 0x00ffffff; // seems bogus ! 481: range = IODeviceMemory::withSubRange( ioMemory, phys, len ); ! 482: if( range == 0) ! 483: /* didn't fit */ ! 484: range = IODeviceMemory::withRange( ! 485: phys + ioMemory->getPhysicalAddress(), len ); ! 486: ! 487: } else ! 488: range = 0; ! 489: ! 490: } else { ! 491: bridgeRanges = bridgeMemoryRanges; ! 492: range = IODeviceMemory::withRange( phys, len ); ! 493: } ! 494: ! 495: ! 496: if( range) { ! 497: ! 498: #ifdef i386 ! 499: // Do nothing for Intel -- I/O ports are not accessed through ! 500: // memory on this platform, but through I/O port instructions ! 501: #else ! 502: ! 503: ok = bridgeRanges->allocateRange( phys, len ); ! 504: if( !ok) ! 505: IOLog("%s: bad range %d(%08lx:%08lx)\n", getName(), flags->s.space, ! 506: phys, len); ! 507: #endif ! 508: ! 509: range->setTag( flags->bits ); ! 510: ok = array->setObject( range ); ! 511: range->release(); ! 512: ! 513: } else ! 514: ok = false; ! 515: ! 516: return( ok ); ! 517: } ! 518: ! 519: ! 520: IOReturn IOPCIBridge::getDTNubAddressing( IOPCIDevice * regEntry ) ! 521: { ! 522: OSArray * array; ! 523: IORegistryEntry * parentEntry; ! 524: OSData * addressProperty; ! 525: IOPhysicalAddress phys; ! 526: IOPhysicalLength len; ! 527: UInt32 cells = 5; ! 528: int i, num; ! 529: UInt32 * reg; ! 530: ! 531: addressProperty = (OSData *) regEntry->getProperty( "assigned-addresses" ); ! 532: if( 0 == addressProperty) ! 533: return( kIOReturnSuccess ); ! 534: ! 535: parentEntry = regEntry->getParentEntry( gIODTPlane ); ! 536: if( 0 == parentEntry) ! 537: return( kIOReturnBadArgument ); ! 538: ! 539: array = OSArray::withCapacity( 1 ); ! 540: if( 0 == array) ! 541: return( kIOReturnNoMemory ); ! 542: ! 543: reg = (UInt32 *) addressProperty->getBytesNoCopy(); ! 544: num = addressProperty->getLength() / (4 * cells); ! 545: ! 546: for( i = 0; i < num; i++) { ! 547: ! 548: if( IODTResolveAddressCell( parentEntry, reg, &phys, &len )) ! 549: ! 550: constructRange( (IOPCIAddressSpace *) reg, phys, len, array ); ! 551: ! 552: reg += cells; ! 553: } ! 554: ! 555: if( array->getCount()) ! 556: regEntry->setProperty( gIODeviceMemoryKey, array); ! 557: ! 558: array->release(); ! 559: ! 560: return( kIOReturnSuccess); ! 561: } ! 562: ! 563: IOReturn IOPCIBridge::getNubAddressing( IOPCIDevice * nub ) ! 564: { ! 565: OSArray * array; ! 566: IOPhysicalAddress phys; ! 567: IOPhysicalLength len; ! 568: UInt32 save, value; ! 569: IOPCIAddressSpace reg; ! 570: UInt8 regNum; ! 571: bool memEna, ioEna; ! 572: boolean_t s; ! 573: ! 574: value = nub->configRead32( kIOPCIConfigVendorID ); ! 575: if( 0x0003106b == value ) // control doesn't play well ! 576: return( kIOReturnSuccess ); ! 577: ! 578: // only header type 0 ! 579: value = nub->configRead32( kIOPCIConfigCacheLineSize ); ! 580: if( value & 0x007f0000) ! 581: return( kIOReturnSuccess ); ! 582: ! 583: array = OSArray::withCapacity( 1 ); ! 584: if( 0 == array) ! 585: return( kIOReturnNoMemory ); ! 586: ! 587: for( regNum = 0x10; regNum < 0x28; regNum += 4) { ! 588: ! 589: // begin scary ! 590: s = ml_set_interrupts_enabled(FALSE); ! 591: memEna = nub->setMemoryEnable( false ); ! 592: ioEna = nub->setIOEnable( false ); ! 593: ! 594: save = nub->configRead32( regNum ); ! 595: ! 596: nub->configWrite32( regNum, 0xffffffff ); ! 597: value = nub->configRead32( regNum ); ! 598: ! 599: nub->configWrite32( regNum, save ); ! 600: nub->setMemoryEnable( memEna ); ! 601: nub->setIOEnable( ioEna ); ! 602: ml_set_interrupts_enabled( s ); ! 603: // end scary ! 604: ! 605: if( 0 == value) ! 606: continue; ! 607: ! 608: reg = nub->space; ! 609: reg.s.registerNum = regNum; ! 610: ! 611: if( value & 1) { ! 612: reg.s.space = kIOPCIIOSpace; ! 613: ! 614: } else { ! 615: reg.s.prefetch = (0 != (value & 8)); ! 616: ! 617: switch( value & 6) { ! 618: case 2: /* below 1Mb */ ! 619: reg.s.t = 1; ! 620: /* fall thru */ ! 621: case 0: /* 32-bit mem */ ! 622: case 6: /* reserved */ ! 623: reg.s.space = kIOPCI32BitMemorySpace; ! 624: break; ! 625: ! 626: case 4: /* 64-bit mem */ ! 627: reg.s.space = kIOPCI64BitMemorySpace; ! 628: regNum += 4; ! 629: break; ! 630: } ! 631: } ! 632: ! 633: value &= 0xfffffff0; ! 634: phys = IOPhysical32( 0, save & value ); ! 635: len = IOPhysical32( 0, -value ); ! 636: ! 637: if( 1 & gIOPCIDebug) ! 638: IOLog("Space %08lx : %08lx, %08lx\n", reg.bits, phys, len); ! 639: ! 640: constructRange( ®, phys, len, array ); ! 641: } ! 642: ! 643: if( array->getCount()) ! 644: nub->setProperty( gIODeviceMemoryKey, array); ! 645: ! 646: array->release(); ! 647: ! 648: return( kIOReturnSuccess); ! 649: } ! 650: ! 651: bool IOPCIBridge::isDTNub( IOPCIDevice * nub ) ! 652: { ! 653: return( 0 != nub->getParentEntry( gIODTPlane )); ! 654: } ! 655: ! 656: IOReturn IOPCIBridge::getNubResources( IOService * service ) ! 657: { ! 658: IOPCIDevice * nub = (IOPCIDevice *) service; ! 659: IOReturn err; ! 660: ! 661: if( service->getDeviceMemory()) ! 662: return( kIOReturnSuccess ); ! 663: ! 664: if( isDTNub( nub)) ! 665: err = getDTNubAddressing( nub ); ! 666: else ! 667: err = getNubAddressing( nub ); ! 668: ! 669: return( err); ! 670: } ! 671: ! 672: bool IOPCIBridge::matchKeys( IOPCIDevice * nub, const char * keys, ! 673: UInt32 defaultMask, UInt8 regNum ) ! 674: { ! 675: const char * next; ! 676: UInt32 mask, value, reg; ! 677: bool found = false; ! 678: ! 679: do { ! 680: value = strtoul( keys, (char **) &next, 16); ! 681: if( next == keys) ! 682: break; ! 683: ! 684: while( (*next) == ' ') ! 685: next++; ! 686: ! 687: if( (*next) == '&') ! 688: mask = strtoul( next + 1, (char **) &next, 16); ! 689: else ! 690: mask = defaultMask; ! 691: ! 692: reg = nub->configRead32( regNum ); ! 693: found = (value == (reg & mask)); ! 694: keys = next; ! 695: ! 696: } while( !found); ! 697: ! 698: return( found ); ! 699: } ! 700: ! 701: ! 702: bool IOPCIBridge::pciMatchNub( IOPCIDevice * nub, ! 703: OSDictionary * table ) ! 704: { ! 705: OSString * prop; ! 706: const char * keys; ! 707: bool match = true; ! 708: UInt8 regNum; ! 709: int i; ! 710: ! 711: struct IOPCIMatchingKeys { ! 712: const char * propName; ! 713: UInt8 regs[ 4 ]; ! 714: UInt32 defaultMask; ! 715: }; ! 716: IOPCIMatchingKeys * look; ! 717: static IOPCIMatchingKeys matching[] = { ! 718: { kIOPCIMatchKey, ! 719: { 0x00 + 1, 0x2c }, 0xffffffff }, ! 720: { kIOPCIPrimaryMatchKey, ! 721: { 0x00 }, 0xffffffff }, ! 722: { kIOPCISecondaryMatchKey, ! 723: { 0x2c }, 0xffffffff }, ! 724: { kIOPCIClassMatchKey, ! 725: { 0x08 }, 0xffffff00 }}; ! 726: ! 727: for( look = matching; ! 728: (match && (look < (&matching[4]))); ! 729: look++ ) { ! 730: ! 731: prop = (OSString *) table->getObject( look->propName ); ! 732: if( prop) { ! 733: keys = prop->getCStringNoCopy(); ! 734: match = false; ! 735: for( i = 0; ! 736: ((false == match) && (i < 4)); ! 737: i++ ) { ! 738: ! 739: regNum = look->regs[ i ]; ! 740: match = matchKeys( nub, keys, ! 741: look->defaultMask, regNum & 0xfc ); ! 742: if( 0 == (1 & regNum)) ! 743: break; ! 744: } ! 745: } ! 746: } ! 747: ! 748: return( match ); ! 749: } ! 750: ! 751: bool IOPCIBridge::matchNubWithPropertyTable( IOService * nub, ! 752: OSDictionary * table ) ! 753: { ! 754: bool matches; ! 755: ! 756: matches = pciMatchNub( (IOPCIDevice *) nub, table); ! 757: ! 758: return( matches ); ! 759: } ! 760: ! 761: bool IOPCIBridge::compareNubName( const IOService * nub, ! 762: OSString * name, OSString ** matched ) const ! 763: { ! 764: return( IODTCompareNubName( nub, name, matched )); ! 765: } ! 766: ! 767: UInt32 IOPCIBridge::findPCICapability( IOPCIAddressSpace space, ! 768: UInt8 capabilityID ) ! 769: { ! 770: UInt32 data = 0; ! 771: ! 772: if( 0 == ((kIOPCIStatusCapabilities << 16) ! 773: & (configRead32( space, kIOPCIConfigCommand)))) ! 774: return( 0 ); ! 775: ! 776: data = configRead32( space, kIOPCIConfigCapabilitiesPtr ); ! 777: while( data) { ! 778: data = configRead32( space, data ); ! 779: if( capabilityID == (data & 0xff)) ! 780: break; ! 781: data = (data >> 8) & 0xfc; ! 782: } ! 783: ! 784: return( data ); ! 785: } ! 786: ! 787: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 788: ! 789: IOReturn IOPCIBridge::createAGPSpace( IOPCIAddressSpace master, ! 790: IOOptionBits options, ! 791: IOPhysicalAddress * address, ! 792: IOPhysicalLength * length ) ! 793: { ! 794: return( kIOReturnUnsupported ); ! 795: } ! 796: ! 797: IOReturn IOPCIBridge::destroyAGPSpace( IOPCIAddressSpace master ) ! 798: { ! 799: return( kIOReturnUnsupported ); ! 800: } ! 801: ! 802: IORangeAllocator * IOPCIBridge::getAGPRangeAllocator( IOPCIAddressSpace master ) ! 803: { ! 804: return( 0 ); ! 805: } ! 806: ! 807: IOOptionBits IOPCIBridge::getAGPStatus( IOPCIAddressSpace master, ! 808: IOOptionBits options = 0 ) ! 809: { ! 810: return( 0 ); ! 811: } ! 812: ! 813: IOReturn IOPCIBridge::commitAGPMemory( IOPCIAddressSpace master, ! 814: IOMemoryDescriptor * memory, ! 815: IOByteCount agpOffset, ! 816: IOOptionBits options = 0 ) ! 817: { ! 818: return( kIOReturnUnsupported ); ! 819: } ! 820: ! 821: IOReturn IOPCIBridge::releaseAGPMemory( IOPCIAddressSpace master, ! 822: IOMemoryDescriptor * memory, ! 823: IOByteCount agpOffset ) ! 824: { ! 825: return( kIOReturnUnsupported ); ! 826: } ! 827: ! 828: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 829: ! 830: #undef super ! 831: #define super IOPCIBridge ! 832: ! 833: OSDefineMetaClassAndStructors(IOPCI2PCIBridge, IOPCIBridge) ! 834: ! 835: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 836: ! 837: IOService * IOPCI2PCIBridge::probe( IOService * provider, ! 838: SInt32 * score ) ! 839: { ! 840: ! 841: if( 0 == (bridgeDevice = OSDynamicCast( IOPCIDevice, provider))) ! 842: return( 0 ); ! 843: ! 844: *score -= 100; ! 845: ! 846: return( this ); ! 847: } ! 848: ! 849: enum { ! 850: kPCI2PCIBusNumbers = 0x18, ! 851: kPCI2PCIIORange = 0x1c, ! 852: kPCI2PCIMemoryRange = 0x20, ! 853: kPCI2PCIPrefetchMemoryRange = 0x24, ! 854: kPCI2PCIUpperIORange = 0x30 ! 855: }; ! 856: ! 857: bool IOPCI2PCIBridge::configure( IOService * provider ) ! 858: { ! 859: UInt32 end; ! 860: UInt32 start; ! 861: bool ok; ! 862: ! 863: end = bridgeDevice->configRead32( kPCI2PCIMemoryRange ); ! 864: if( end ) { ! 865: start = (end & 0xfff0) << 16; ! 866: end |= 0x000fffff; ! 867: ok = addBridgeMemoryRange( start, end - start + 1, false ); ! 868: } ! 869: ! 870: end = bridgeDevice->configRead32( kPCI2PCIPrefetchMemoryRange ); ! 871: if( end) { ! 872: start = (end & 0xfff0) << 16; ! 873: end |= 0x000fffff; ! 874: ok = addBridgeMemoryRange( start, end - start + 1, false ); ! 875: } ! 876: ! 877: end = bridgeDevice->configRead32( kPCI2PCIIORange ); ! 878: if( end) { ! 879: start = (end & 0xf0) << 8; ! 880: end = (end & 0xffff) | 0xfff; ! 881: ok = addBridgeIORange( start, end - start + 1 ); ! 882: } ! 883: ! 884: return( super::configure( provider )); ! 885: } ! 886: ! 887: UInt8 IOPCI2PCIBridge::firstBusNum( void ) ! 888: { ! 889: UInt32 value; ! 890: ! 891: value = bridgeDevice->configRead32( kPCI2PCIBusNumbers ); ! 892: ! 893: return( (value >> 8) & 0xff ); ! 894: } ! 895: ! 896: UInt8 IOPCI2PCIBridge::lastBusNum( void ) ! 897: { ! 898: UInt32 value; ! 899: ! 900: value = bridgeDevice->configRead32( kPCI2PCIBusNumbers ); ! 901: ! 902: return( (value >> 16) & 0xff ); ! 903: } ! 904: ! 905: IOPCIAddressSpace IOPCI2PCIBridge::getBridgeSpace( void ) ! 906: { ! 907: return( bridgeDevice->space ); ! 908: } ! 909: ! 910: UInt32 IOPCI2PCIBridge::configRead32( IOPCIAddressSpace space, ! 911: UInt8 offset ) ! 912: { ! 913: return( bridgeDevice->configRead32( space, offset )); ! 914: } ! 915: ! 916: void IOPCI2PCIBridge::configWrite32( IOPCIAddressSpace space, ! 917: UInt8 offset, UInt32 data ) ! 918: { ! 919: bridgeDevice->configWrite32( space, offset, data ); ! 920: } ! 921: ! 922: IODeviceMemory * IOPCI2PCIBridge::ioDeviceMemory( void ) ! 923: { ! 924: return( bridgeDevice->ioDeviceMemory()); ! 925: } ! 926: ! 927: bool IOPCI2PCIBridge::publishNub( IOPCIDevice * nub, UInt32 index ) ! 928: { ! 929: if( nub) ! 930: nub->setProperty( "IOChildIndex" , index, 32 ); ! 931: ! 932: return( super::publishNub( nub, index ) ); ! 933: } ! 934: ! 935: #ifdef __I386__ ! 936: ! 937: static void setupIntelPIC(IOPCIDevice *nub) ! 938: { ! 939: OSDictionary *propTable; ! 940: OSArray *controller; ! 941: OSArray *specifier; ! 942: OSData *tmpData; ! 943: long irq; ! 944: extern OSSymbol *gIntelPICName; ! 945: ! 946: propTable = nub->getPropertyTable(); ! 947: if (!propTable) return; ! 948: ! 949: do { ! 950: // Create the interrupt specifer array. ! 951: specifier = OSArray::withCapacity(1); ! 952: if ( !specifier ) ! 953: break; ! 954: irq = nub->configRead32(kIOPCIConfigInterruptLine) & 0xf; ! 955: tmpData = OSData::withBytes(&irq, sizeof(irq)); ! 956: if ( tmpData ) { ! 957: specifier->setObject(tmpData); ! 958: tmpData->release(); ! 959: } ! 960: ! 961: controller = OSArray::withCapacity(1); ! 962: if ( controller ) { ! 963: controller->setObject(gIntelPICName); ! 964: ! 965: // Put the two arrays into the property table. ! 966: propTable->setObject(gIOInterruptControllersKey, controller); ! 967: controller->release(); ! 968: } ! 969: propTable->setObject(gIOInterruptSpecifiersKey, specifier); ! 970: specifier->release(); ! 971: } while( false ); ! 972: } ! 973: ! 974: #endif ! 975:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.