2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
27 * 23 Nov 98 sdouglas created from objc version.
31 #include <IOKit/system.h>
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 #include <IOKit/IOCatalogue.h>
43 #include <libkern/c++/OSContainers.h>
46 #include <machine/machine_routines.h>
50 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
52 #define super IOService
54 OSDefineMetaClassAndAbstractStructors( IOPCIBridge
, IOService
)
55 OSMetaClassDefineReservedUnused(IOPCIBridge
, 0);
56 OSMetaClassDefineReservedUnused(IOPCIBridge
, 1);
57 OSMetaClassDefineReservedUnused(IOPCIBridge
, 2);
58 OSMetaClassDefineReservedUnused(IOPCIBridge
, 3);
59 OSMetaClassDefineReservedUnused(IOPCIBridge
, 4);
60 OSMetaClassDefineReservedUnused(IOPCIBridge
, 5);
61 OSMetaClassDefineReservedUnused(IOPCIBridge
, 6);
62 OSMetaClassDefineReservedUnused(IOPCIBridge
, 7);
63 OSMetaClassDefineReservedUnused(IOPCIBridge
, 8);
64 OSMetaClassDefineReservedUnused(IOPCIBridge
, 9);
65 OSMetaClassDefineReservedUnused(IOPCIBridge
, 10);
66 OSMetaClassDefineReservedUnused(IOPCIBridge
, 11);
67 OSMetaClassDefineReservedUnused(IOPCIBridge
, 12);
68 OSMetaClassDefineReservedUnused(IOPCIBridge
, 13);
69 OSMetaClassDefineReservedUnused(IOPCIBridge
, 14);
70 OSMetaClassDefineReservedUnused(IOPCIBridge
, 15);
71 OSMetaClassDefineReservedUnused(IOPCIBridge
, 16);
72 OSMetaClassDefineReservedUnused(IOPCIBridge
, 17);
73 OSMetaClassDefineReservedUnused(IOPCIBridge
, 18);
74 OSMetaClassDefineReservedUnused(IOPCIBridge
, 19);
75 OSMetaClassDefineReservedUnused(IOPCIBridge
, 20);
76 OSMetaClassDefineReservedUnused(IOPCIBridge
, 21);
77 OSMetaClassDefineReservedUnused(IOPCIBridge
, 22);
78 OSMetaClassDefineReservedUnused(IOPCIBridge
, 23);
79 OSMetaClassDefineReservedUnused(IOPCIBridge
, 24);
80 OSMetaClassDefineReservedUnused(IOPCIBridge
, 25);
81 OSMetaClassDefineReservedUnused(IOPCIBridge
, 26);
82 OSMetaClassDefineReservedUnused(IOPCIBridge
, 27);
83 OSMetaClassDefineReservedUnused(IOPCIBridge
, 28);
84 OSMetaClassDefineReservedUnused(IOPCIBridge
, 29);
85 OSMetaClassDefineReservedUnused(IOPCIBridge
, 30);
86 OSMetaClassDefineReservedUnused(IOPCIBridge
, 31);
88 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
90 // 1 log, 2 disable DT
94 static void setupIntelPIC(IOPCIDevice
* nub
);
97 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
98 // stub driver has two power states, off and on
100 enum { kIOPCIBridgePowerStateCount
= 2 };
102 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
104 bool IOPCIBridge::start( IOService
* provider
)
106 static const IOPMPowerState powerStates
[ kIOPCIBridgePowerStateCount
] = {
107 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
108 { 1, IOPMPowerOn
, IOPMPowerOn
, IOPMPowerOn
, 0, 0, 0, 0, 0, 0, 0, 0 }
111 if( !super::start( provider
))
114 // empty ranges to start
115 bridgeMemoryRanges
= IORangeAllocator::withRange( 0, 1, 8,
116 IORangeAllocator::kLocking
);
117 assert( bridgeMemoryRanges
);
118 setProperty( "Bridge Memory Ranges", bridgeMemoryRanges
);
120 bridgeIORanges
= IORangeAllocator::withRange( 0, 1, 8,
121 IORangeAllocator::kLocking
);
122 assert( bridgeIORanges
);
123 setProperty( "Bridge IO Ranges", bridgeIORanges
);
125 if( !configure( provider
))
128 // initialize superclass variables
130 // register as controlling driver
131 registerPowerDriver( this, (IOPMPowerState
*) powerStates
,
132 kIOPCIBridgePowerStateCount
);
134 provider
->joinPMtree( this);
136 temporaryPowerClampOn();
138 probeBus( provider
, firstBusNum() );
143 IOReturn
IOPCIBridge::setDevicePowerState( IOPCIDevice
* device
,
144 unsigned long powerState
)
147 return( restoreDeviceState( device
));
149 return( saveDeviceState( device
));
152 enum { kSavedConfigSize
= 64 };
153 enum { kSavedConfigs
= 16 };
155 IOReturn
IOPCIBridge::saveDeviceState( IOPCIDevice
* device
,
156 IOOptionBits options
= 0 )
160 if( !device
->savedConfig
)
161 device
->savedConfig
= IONew( UInt32
, kSavedConfigSize
);
162 if( !device
->savedConfig
)
163 return( kIOReturnNotReady
);
165 for( i
= 1; i
< kSavedConfigs
; i
++)
166 device
->savedConfig
[i
] = device
->configRead32( i
* 4 );
168 return( kIOReturnSuccess
);
171 IOReturn
IOPCIBridge::restoreDeviceState( IOPCIDevice
* device
,
172 IOOptionBits options
= 0 )
176 if( !device
->savedConfig
)
177 return( kIOReturnNotReady
);
179 for( i
= 2; i
< kSavedConfigs
; i
++)
180 device
->configWrite32( i
* 4, device
->savedConfig
[ i
]);
182 device
->configWrite32( kIOPCIConfigCommand
, device
->savedConfig
[1]);
184 IODelete( device
->savedConfig
, UInt32
, kSavedConfigSize
);
185 device
->savedConfig
= 0;
187 return( kIOReturnSuccess
);
191 bool IOPCIBridge::configure( IOService
* provider
)
196 static SInt32
PCICompare( UInt32
/* cellCount */, UInt32 cleft
[], UInt32 cright
[] )
198 IOPCIPhysicalAddress
* left
= (IOPCIPhysicalAddress
*) cleft
;
199 IOPCIPhysicalAddress
* right
= (IOPCIPhysicalAddress
*) cright
;
200 static const UInt8 spacesEq
[] = { 0, 1, 2, 2 };
202 if( spacesEq
[ left
->physHi
.s
.space
] != spacesEq
[ right
->physHi
.s
.space
])
205 return( left
->physLo
- right
->physLo
);
208 void IOPCIBridge::nvLocation( IORegistryEntry
* entry
,
209 UInt8
* busNum
, UInt8
* deviceNum
, UInt8
* functionNum
)
213 nub
= OSDynamicCast( IOPCIDevice
, entry
);
216 *busNum
= nub
->space
.s
.busNum
;
217 *deviceNum
= nub
->space
.s
.deviceNum
;
218 *functionNum
= nub
->space
.s
.functionNum
;
221 void IOPCIBridge::spaceFromProperties( OSDictionary
* propTable
,
222 IOPCIAddressSpace
* space
)
225 IOPCIAddressSpace
* inSpace
;
229 if( (regProp
= (OSData
*) propTable
->getObject("reg"))) {
231 inSpace
= (IOPCIAddressSpace
*) regProp
->getBytesNoCopy();
232 space
->s
.busNum
= inSpace
->s
.busNum
;
233 space
->s
.deviceNum
= inSpace
->s
.deviceNum
;
234 space
->s
.functionNum
= inSpace
->s
.functionNum
;
238 IORegistryEntry
* IOPCIBridge::findMatching( OSIterator
* kids
,
239 IOPCIAddressSpace space
)
241 IORegistryEntry
* found
= 0;
242 IOPCIAddressSpace regSpace
;
247 && (found
= (IORegistryEntry
*) kids
->getNextObject())) {
249 spaceFromProperties( found
->getPropertyTable(), ®Space
);
250 if( space
.bits
!= regSpace
.bits
)
257 OSDictionary
* IOPCIBridge::constructProperties( IOPCIAddressSpace space
)
259 OSDictionary
* propTable
;
262 UInt16 vendor
, device
;
265 const OSSymbol
* nameProp
;
270 struct IOPCIGenericNames
{
275 static const IOPCIGenericNames genericNames
[] = {
276 { "display", 0xffffff, 0x000100 },
277 { "scsi", 0xffff00, 0x010000 },
278 { "ethernet", 0xffff00, 0x020000 },
279 { "display", 0xff0000, 0x030000 },
280 { "pci-bridge", 0xffff00, 0x060400 },
283 const IOPCIGenericNames
* nextName
;
285 compatBuf
= (char *) IOMalloc( 256 );
287 propTable
= OSDictionary::withCapacity( 8 );
289 if( compatBuf
&& propTable
) {
291 prop
= OSData::withBytes( &space
, sizeof( space
) );
293 propTable
->setObject("reg", prop
);
297 value
= configRead32( space
, kIOPCIConfigVendorID
);
299 device
= value
>> 16;
301 prop
= OSData::withBytes( &vendor
, 2 );
303 propTable
->setObject("vendor-id", prop
);
307 prop
= OSData::withBytes( &device
, 2 );
309 propTable
->setObject("device-id", prop
);
313 value
= configRead32( space
, kIOPCIConfigRevisionID
);
315 prop
= OSData::withBytes( &byte
, 1 );
317 propTable
->setObject("revision-id", prop
);
324 for( nextName
= genericNames
;
325 (0 == name
) && nextName
->name
;
327 if( (value
& nextName
->mask
) == nextName
->classCode
)
328 name
= nextName
->name
;
331 // start compatible list
332 nextCompat
= compatBuf
;
333 sprintf( nextCompat
, "pci%x,%x", vendor
, device
);
334 nameStr
= nextCompat
;
336 value
= configRead32( space
, kIOPCIConfigSubSystemVendorID
);
339 device
= value
>> 16;
341 prop
= OSData::withBytes( &vendor
, 2 );
343 propTable
->setObject("subsystem-vendor-id", prop
);
346 prop
= OSData::withBytes( &device
, 2 );
348 propTable
->setObject("subsystem-id", prop
);
352 nextCompat
+= strlen( nextCompat
) + 1;
353 sprintf( nextCompat
, "pci%x,%x", vendor
, device
);
354 nameStr
= nextCompat
;
357 nextCompat
+= strlen( nextCompat
) + 1;
358 prop
= OSData::withBytes( compatBuf
, nextCompat
- compatBuf
);
360 propTable
->setObject( "compatible", prop
);
367 nameProp
= OSSymbol::withCString( name
);
369 propTable
->setObject( gIONameKey
, (OSSymbol
*) nameProp
);
375 IOFree( compatBuf
, 256 );
380 IOPCIDevice
* IOPCIBridge::createNub( OSDictionary
* from
)
382 return( new IOPCIDevice
);
385 bool IOPCIBridge::initializeNub( IOPCIDevice
* nub
,
386 OSDictionary
* from
)
388 spaceFromProperties( from
, &nub
->space
);
390 if( ioDeviceMemory())
391 nub
->ioMap
= ioDeviceMemory()->map();
396 bool IOPCIBridge::publishNub( IOPCIDevice
* nub
, UInt32
/* index */ )
402 UInt32
*regData
, expRomReg
;
403 IOMemoryMap
* memoryMap
;
404 IOVirtualAddress virtAddr
;
407 if( nub
->space
.s
.functionNum
)
408 sprintf( location
, "%X,%X", nub
->space
.s
.deviceNum
,
409 nub
->space
.s
.functionNum
);
411 sprintf( location
, "%X", nub
->space
.s
.deviceNum
);
412 nub
->setLocation( location
);
413 IODTFindSlotName( nub
, nub
->space
.s
.deviceNum
);
415 // Look for a "driver-reg,AAPL,MacOSX,PowerPC" property.
416 if( (data
= (OSData
*)nub
->getProperty( "driver-reg,AAPL,MacOSX,PowerPC"))) {
417 if( data
->getLength() == (2 * sizeof(UInt32
))) {
418 regData
= (UInt32
*)data
->getBytesNoCopy();
420 getNubResources(nub
);
421 memoryMap
= nub
->mapDeviceMemoryWithRegister(kIOPCIConfigExpansionROMBase
);
422 if( memoryMap
!= 0) {
423 virtAddr
= memoryMap
->getVirtualAddress();
424 virtAddr
+= regData
[0];
426 nub
->setMemoryEnable(true);
428 expRomReg
= nub
->configRead32(kIOPCIConfigExpansionROMBase
);
429 nub
->configWrite32(kIOPCIConfigExpansionROMBase
, expRomReg
| 1);
431 driverData
= OSData::withBytesNoCopy((void *)virtAddr
, regData
[1]);
432 if ( driverData
!= 0) {
433 gIOCatalogue
->addExtensionsFromArchive(driverData
);
435 driverData
->release();
438 nub
->configWrite32(kIOPCIConfigExpansionROMBase
, expRomReg
);
440 nub
->setMemoryEnable(false);
442 memoryMap
->release();
447 ok
= nub
->attach( this );
449 nub
->registerService();
456 void IOPCIBridge::publishNubs( OSIterator
* kids
, UInt32 index
)
458 IORegistryEntry
* found
;
460 OSDictionary
* propTable
;
464 while( (found
= (IORegistryEntry
*) kids
->getNextObject())) {
466 propTable
= found
->getPropertyTable();
467 nub
= createNub( propTable
);
470 if( !initializeNub( nub
, propTable
))
472 if( !nub
->init( found
, gIODTPlane
))
475 publishNub( nub
, index
++ );
478 IOLog("%08lx = 0:%08lx 4:%08lx ", nub
->space
.bits
,
479 nub
->configRead32(kIOPCIConfigVendorID
),
480 nub
->configRead32(kIOPCIConfigCommand
) );
486 UInt8
IOPCIBridge::firstBusNum( void )
491 UInt8
IOPCIBridge::lastBusNum( void )
496 void IOPCIBridge::probeBus( IOService
* provider
, UInt8 busNum
)
498 IORegistryEntry
* regEntry
;
499 OSDictionary
* propTable
;
500 IOPCIDevice
* nub
= 0;
501 IOPCIAddressSpace space
;
503 UInt8 scanDevice
, scanFunction
, lastFunction
;
504 OSIterator
* kidsIter
;
507 IODTSetResolving( provider
, PCICompare
, nvLocation
);
512 kidsIter
= provider
->getChildIterator( gIODTPlane
);
515 space
.s
.busNum
= busNum
;
517 for( scanDevice
= 0; scanDevice
<= 31; scanDevice
++ ) {
520 for( scanFunction
= 0; scanFunction
<= lastFunction
; scanFunction
++ ) {
522 space
.s
.deviceNum
= scanDevice
;
523 space
.s
.functionNum
= scanFunction
;
525 if( (regEntry
= findMatching( kidsIter
, space
))) {
529 /* probe - should guard exceptions */
531 // DEC bridge really needs safe probe
534 vendor
= configRead32( space
, kIOPCIConfigVendorID
);
535 vendor
&= 0x0000ffff;
536 if( (0 == vendor
) || (0xffff == vendor
))
539 // look in function 0 for multi function flag
540 if( (0 == scanFunction
)
541 && (0x00800000 & configRead32( space
,
542 kIOPCIConfigCacheLineSize
)))
545 propTable
= constructProperties( space
);
547 && (nub
= createNub( propTable
))
548 && (initializeNub( nub
, propTable
))
549 && nub
->init( propTable
)) {
553 publishNub( nub
, index
++);
560 publishNubs( kidsIter
, index
);
565 bool IOPCIBridge::addBridgeMemoryRange( IOPhysicalAddress start
,
566 IOPhysicalLength length
, bool host
)
568 IORangeAllocator
* platformRanges
;
573 platformRanges
= getPlatform()->getPhysicalRangeAllocator();
574 assert( platformRanges
);
576 // out of the platform
577 ok
= platformRanges
->allocateRange( start
, length
);
579 kprintf("%s: didn't get host range (%08lx:%08lx)\n", getName(),
583 // and into the bridge
584 bridgeMemoryRanges
->deallocate( start
, length
);
589 bool IOPCIBridge::addBridgeIORange( IOByteCount start
, IOByteCount length
)
594 bridgeIORanges
->deallocate( start
, length
);
599 bool IOPCIBridge::constructRange( IOPCIAddressSpace
* flags
,
600 IOPhysicalAddress phys
,
601 IOPhysicalLength len
,
604 IODeviceMemory
* range
;
605 IODeviceMemory
* ioMemory
;
606 IORangeAllocator
* bridgeRanges
;
612 if( kIOPCIIOSpace
== flags
->s
.space
) {
614 bridgeRanges
= bridgeIORanges
;
615 if( (ioMemory
= ioDeviceMemory())) {
617 phys
&= 0x00ffffff; // seems bogus
618 range
= IODeviceMemory::withSubRange( ioMemory
, phys
, len
);
621 range
= IODeviceMemory::withRange(
622 phys
+ ioMemory
->getPhysicalAddress(), len
);
628 bridgeRanges
= bridgeMemoryRanges
;
629 range
= IODeviceMemory::withRange( phys
, len
);
636 // Do nothing for Intel -- I/O ports are not accessed through
637 // memory on this platform, but through I/O port instructions
640 ok
= bridgeRanges
->allocateRange( phys
, len
);
642 IOLog("%s: bad range %d(%08lx:%08lx)\n", getName(), flags
->s
.space
,
646 range
->setTag( flags
->bits
);
647 ok
= array
->setObject( range
);
657 IOReturn
IOPCIBridge::getDTNubAddressing( IOPCIDevice
* regEntry
)
660 IORegistryEntry
* parentEntry
;
661 OSData
* addressProperty
;
662 IOPhysicalAddress phys
;
663 IOPhysicalLength len
;
668 addressProperty
= (OSData
*) regEntry
->getProperty( "assigned-addresses" );
669 if( 0 == addressProperty
)
670 return( kIOReturnSuccess
);
672 parentEntry
= regEntry
->getParentEntry( gIODTPlane
);
673 if( 0 == parentEntry
)
674 return( kIOReturnBadArgument
);
676 array
= OSArray::withCapacity( 1 );
678 return( kIOReturnNoMemory
);
680 reg
= (UInt32
*) addressProperty
->getBytesNoCopy();
681 num
= addressProperty
->getLength() / (4 * cells
);
683 for( i
= 0; i
< num
; i
++) {
685 if( IODTResolveAddressCell( parentEntry
, reg
, &phys
, &len
))
687 constructRange( (IOPCIAddressSpace
*) reg
, phys
, len
, array
);
692 if( array
->getCount())
693 regEntry
->setProperty( gIODeviceMemoryKey
, array
);
697 return( kIOReturnSuccess
);
700 IOReturn
IOPCIBridge::getNubAddressing( IOPCIDevice
* nub
)
703 IOPhysicalAddress phys
;
704 IOPhysicalLength len
;
706 IOPCIAddressSpace reg
;
711 value
= nub
->configRead32( kIOPCIConfigVendorID
);
712 if( 0x0003106b == value
) // control doesn't play well
713 return( kIOReturnSuccess
);
715 // only header type 0
716 value
= nub
->configRead32( kIOPCIConfigCacheLineSize
);
717 if( value
& 0x007f0000)
718 return( kIOReturnSuccess
);
720 array
= OSArray::withCapacity( 1 );
722 return( kIOReturnNoMemory
);
724 for( regNum
= 0x10; regNum
< 0x28; regNum
+= 4) {
727 s
= ml_set_interrupts_enabled(FALSE
);
728 memEna
= nub
->setMemoryEnable( false );
729 ioEna
= nub
->setIOEnable( false );
731 save
= nub
->configRead32( regNum
);
733 nub
->configWrite32( regNum
, 0xffffffff );
734 value
= nub
->configRead32( regNum
);
736 nub
->configWrite32( regNum
, save
);
737 nub
->setMemoryEnable( memEna
);
738 nub
->setIOEnable( ioEna
);
739 ml_set_interrupts_enabled( s
);
746 reg
.s
.registerNum
= regNum
;
749 reg
.s
.space
= kIOPCIIOSpace
;
752 reg
.s
.prefetch
= (0 != (value
& 8));
755 case 2: /* below 1Mb */
758 case 0: /* 32-bit mem */
759 case 6: /* reserved */
760 reg
.s
.space
= kIOPCI32BitMemorySpace
;
763 case 4: /* 64-bit mem */
764 reg
.s
.space
= kIOPCI64BitMemorySpace
;
771 phys
= IOPhysical32( 0, save
& value
);
772 len
= IOPhysical32( 0, -value
);
775 IOLog("Space %08lx : %08lx, %08lx\n", reg
.bits
, phys
, len
);
777 constructRange( ®
, phys
, len
, array
);
780 if( array
->getCount())
781 nub
->setProperty( gIODeviceMemoryKey
, array
);
785 return( kIOReturnSuccess
);
788 bool IOPCIBridge::isDTNub( IOPCIDevice
* nub
)
790 return( 0 != nub
->getParentEntry( gIODTPlane
));
793 IOReturn
IOPCIBridge::getNubResources( IOService
* service
)
795 IOPCIDevice
* nub
= (IOPCIDevice
*) service
;
798 if( service
->getDeviceMemory())
799 return( kIOReturnSuccess
);
802 err
= getDTNubAddressing( nub
);
804 err
= getNubAddressing( nub
);
809 bool IOPCIBridge::matchKeys( IOPCIDevice
* nub
, const char * keys
,
810 UInt32 defaultMask
, UInt8 regNum
)
813 UInt32 mask
, value
, reg
;
817 value
= strtoul( keys
, (char **) &next
, 16);
821 while( (*next
) == ' ')
825 mask
= strtoul( next
+ 1, (char **) &next
, 16);
829 reg
= nub
->configRead32( regNum
);
830 found
= ((value
& mask
) == (reg
& mask
));
839 bool IOPCIBridge::pciMatchNub( IOPCIDevice
* nub
,
840 OSDictionary
* table
,
849 struct IOPCIMatchingKeys
{
850 const char * propName
;
854 IOPCIMatchingKeys
* look
;
855 static IOPCIMatchingKeys matching
[] = {
857 { 0x00 + 1, 0x2c }, 0xffffffff },
858 { kIOPCIPrimaryMatchKey
,
859 { 0x00 }, 0xffffffff },
860 { kIOPCISecondaryMatchKey
,
861 { 0x2c }, 0xffffffff },
862 { kIOPCIClassMatchKey
,
863 { 0x08 }, 0xffffff00 }};
865 for( look
= matching
;
866 (match
&& (look
< (&matching
[4])));
869 prop
= (OSString
*) table
->getObject( look
->propName
);
871 keys
= prop
->getCStringNoCopy();
874 ((false == match
) && (i
< 4));
877 regNum
= look
->regs
[ i
];
878 match
= matchKeys( nub
, keys
,
879 look
->defaultMask
, regNum
& 0xfc );
880 if( 0 == (1 & regNum
))
889 bool IOPCIBridge::matchNubWithPropertyTable( IOService
* nub
,
890 OSDictionary
* table
,
895 matches
= pciMatchNub( (IOPCIDevice
*) nub
, table
, score
);
900 bool IOPCIBridge::compareNubName( const IOService
* nub
,
901 OSString
* name
, OSString
** matched
) const
903 return( IODTCompareNubName( nub
, name
, matched
));
906 UInt32
IOPCIBridge::findPCICapability( IOPCIAddressSpace space
,
907 UInt8 capabilityID
, UInt8
* found
)
915 if( 0 == ((kIOPCIStatusCapabilities
<< 16)
916 & (configRead32( space
, kIOPCIConfigCommand
))))
919 offset
= configRead32( space
, kIOPCIConfigCapabilitiesPtr
);
921 data
= configRead32( space
, offset
);
922 if( capabilityID
== (data
& 0xff)) {
927 offset
= (data
>> 8) & 0xfc;
933 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
935 IOReturn
IOPCIBridge::createAGPSpace( IOAGPDevice
* master
,
936 IOOptionBits options
,
937 IOPhysicalAddress
* address
,
938 IOPhysicalLength
* length
)
940 return( kIOReturnUnsupported
);
943 IOReturn
IOPCIBridge::destroyAGPSpace( IOAGPDevice
* master
)
945 return( kIOReturnUnsupported
);
948 IORangeAllocator
* IOPCIBridge::getAGPRangeAllocator( IOAGPDevice
* master
)
953 IOOptionBits
IOPCIBridge::getAGPStatus( IOAGPDevice
* master
,
954 IOOptionBits options
= 0 )
959 IOReturn
IOPCIBridge::commitAGPMemory( IOAGPDevice
* master
,
960 IOMemoryDescriptor
* memory
,
961 IOByteCount agpOffset
,
962 IOOptionBits options
)
964 return( kIOReturnUnsupported
);
967 IOReturn
IOPCIBridge::releaseAGPMemory( IOAGPDevice
* master
,
968 IOMemoryDescriptor
* memory
,
969 IOByteCount agpOffset
,
970 IOOptionBits options
)
972 return( kIOReturnUnsupported
);
975 IOReturn
IOPCIBridge::resetAGPDevice( IOAGPDevice
* master
,
976 IOOptionBits options
= 0 )
978 return( kIOReturnUnsupported
);
981 IOReturn
IOPCIBridge::getAGPSpace( IOAGPDevice
* master
,
982 IOPhysicalAddress
* address
,
983 IOPhysicalLength
* length
)
985 return( kIOReturnUnsupported
);
988 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
991 #define super IOPCIBridge
993 OSDefineMetaClassAndStructors(IOPCI2PCIBridge
, IOPCIBridge
)
994 OSMetaClassDefineReservedUnused(IOPCI2PCIBridge
, 0);
995 OSMetaClassDefineReservedUnused(IOPCI2PCIBridge
, 1);
996 OSMetaClassDefineReservedUnused(IOPCI2PCIBridge
, 2);
997 OSMetaClassDefineReservedUnused(IOPCI2PCIBridge
, 3);
998 OSMetaClassDefineReservedUnused(IOPCI2PCIBridge
, 4);
999 OSMetaClassDefineReservedUnused(IOPCI2PCIBridge
, 5);
1000 OSMetaClassDefineReservedUnused(IOPCI2PCIBridge
, 6);
1001 OSMetaClassDefineReservedUnused(IOPCI2PCIBridge
, 7);
1002 OSMetaClassDefineReservedUnused(IOPCI2PCIBridge
, 8);
1004 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1006 IOService
* IOPCI2PCIBridge::probe( IOService
* provider
,
1010 if( 0 == (bridgeDevice
= OSDynamicCast( IOPCIDevice
, provider
)))
1019 kPCI2PCIBusNumbers
= 0x18,
1020 kPCI2PCIIORange
= 0x1c,
1021 kPCI2PCIMemoryRange
= 0x20,
1022 kPCI2PCIPrefetchMemoryRange
= 0x24,
1023 kPCI2PCIUpperIORange
= 0x30
1026 bool IOPCI2PCIBridge::configure( IOService
* provider
)
1032 end
= bridgeDevice
->configRead32( kPCI2PCIMemoryRange
);
1034 start
= (end
& 0xfff0) << 16;
1036 ok
= addBridgeMemoryRange( start
, end
- start
+ 1, false );
1039 end
= bridgeDevice
->configRead32( kPCI2PCIPrefetchMemoryRange
);
1041 start
= (end
& 0xfff0) << 16;
1043 ok
= addBridgeMemoryRange( start
, end
- start
+ 1, false );
1046 end
= bridgeDevice
->configRead32( kPCI2PCIIORange
);
1048 start
= (end
& 0xf0) << 8;
1049 end
= (end
& 0xffff) | 0xfff;
1050 ok
= addBridgeIORange( start
, end
- start
+ 1 );
1055 return( super::configure( provider
));
1058 void IOPCI2PCIBridge::saveBridgeState( void )
1062 for (cnt
= 0; cnt
< kIOPCIBridgeRegs
; cnt
++) {
1063 bridgeState
[cnt
] = bridgeDevice
->configRead32(cnt
* 4);
1067 void IOPCI2PCIBridge::restoreBridgeState( void )
1071 for (cnt
= 0; cnt
< kIOPCIBridgeRegs
; cnt
++) {
1072 bridgeDevice
->configWrite32(cnt
* 4, bridgeState
[cnt
]);
1076 UInt8
IOPCI2PCIBridge::firstBusNum( void )
1080 value
= bridgeDevice
->configRead32( kPCI2PCIBusNumbers
);
1082 return( (value
>> 8) & 0xff );
1085 UInt8
IOPCI2PCIBridge::lastBusNum( void )
1089 value
= bridgeDevice
->configRead32( kPCI2PCIBusNumbers
);
1091 return( (value
>> 16) & 0xff );
1094 IOPCIAddressSpace
IOPCI2PCIBridge::getBridgeSpace( void )
1096 return( bridgeDevice
->space
);
1099 UInt32
IOPCI2PCIBridge::configRead32( IOPCIAddressSpace space
,
1102 return( bridgeDevice
->configRead32( space
, offset
));
1105 void IOPCI2PCIBridge::configWrite32( IOPCIAddressSpace space
,
1106 UInt8 offset
, UInt32 data
)
1108 bridgeDevice
->configWrite32( space
, offset
, data
);
1111 UInt16
IOPCI2PCIBridge::configRead16( IOPCIAddressSpace space
,
1114 return( bridgeDevice
->configRead16( space
, offset
));
1117 void IOPCI2PCIBridge::configWrite16( IOPCIAddressSpace space
,
1118 UInt8 offset
, UInt16 data
)
1120 bridgeDevice
->configWrite16( space
, offset
, data
);
1123 UInt8
IOPCI2PCIBridge::configRead8( IOPCIAddressSpace space
,
1126 return( bridgeDevice
->configRead8( space
, offset
));
1129 void IOPCI2PCIBridge::configWrite8( IOPCIAddressSpace space
,
1130 UInt8 offset
, UInt8 data
)
1132 bridgeDevice
->configWrite8( space
, offset
, data
);
1135 IODeviceMemory
* IOPCI2PCIBridge::ioDeviceMemory( void )
1137 return( bridgeDevice
->ioDeviceMemory());
1140 bool IOPCI2PCIBridge::publishNub( IOPCIDevice
* nub
, UInt32 index
)
1143 nub
->setProperty( "IOChildIndex" , index
, 32 );
1145 return( super::publishNub( nub
, index
) );
1150 static void setupIntelPIC(IOPCIDevice
*nub
)
1152 OSDictionary
*propTable
;
1153 OSArray
*controller
;
1157 extern OSSymbol
*gIntelPICName
;
1159 propTable
= nub
->getPropertyTable();
1160 if (!propTable
) return;
1163 // Create the interrupt specifer array.
1164 specifier
= OSArray::withCapacity(1);
1167 irq
= nub
->configRead32(kIOPCIConfigInterruptLine
) & 0xf;
1168 tmpData
= OSData::withBytes(&irq
, sizeof(irq
));
1170 specifier
->setObject(tmpData
);
1174 controller
= OSArray::withCapacity(1);
1176 controller
->setObject(gIntelPICName
);
1178 // Put the two arrays into the property table.
1179 propTable
->setObject(gIOInterruptControllersKey
, controller
);
1180 controller
->release();
1182 propTable
->setObject(gIOInterruptSpecifiersKey
, specifier
);
1183 specifier
->release();