Annotation of XNU/iokit/Families/IOPCIBus/IOPCIBridge.cpp, revision 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.