Annotation of XNU/iokit/Families/IOPCIBus/IOPCIBridge.cpp, revision 1.1.1.1

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(), &regSpace);
                    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( &reg, 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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.