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 Apple Computer, Inc. All rights reserved.
26 * 23 Nov 98 sdouglas created from objc version.
29 #include <IOKit/system.h>
31 #include <libkern/c++/OSContainers.h>
32 #include <IOKit/IODeviceMemory.h>
33 #include <IOKit/IODeviceTreeSupport.h>
34 #include <IOKit/IOLib.h>
35 #include <libkern/OSByteOrder.h>
37 #include "AppleGracklePCI.h"
39 #include <IOKit/assert.h>
41 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43 #define super IOPCIBridge
45 OSDefineMetaClassAndStructors(AppleGracklePCI
, IOPCIBridge
)
47 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49 bool AppleGracklePCI::start( IOService
* provider
)
51 IOPCIPhysicalAddress ioAddrCell
;
52 IOPhysicalAddress ioPhys
;
53 IOPhysicalAddress ioPhysLen
;
55 IODeviceMemory::InitElement rangeList
[ 3 ];
56 IORegistryEntry
* bridge
;
58 IOPCIAddressSpace grackleSpace
;
61 if( 0 == (lock
= IOSimpleLockAlloc()))
64 ioAddrCell
.physHi
.bits
= 0;
65 ioAddrCell
.physHi
.s
.space
= kIOPCIIOSpace
;
66 ioAddrCell
.physMid
= 0;
67 ioAddrCell
.physLo
= 0;
68 ioAddrCell
.lengthHi
= 0;
69 ioAddrCell
.lengthLo
= 0x10000;
73 if( ! IODTResolveAddressCell( bridge
, (UInt32
*) &ioAddrCell
,
74 &ioPhys
, &ioPhysLen
) ) {
76 IOLog("%s: couldn't find my base\n", getName());
80 /* define more explicit ranges */
82 rangeList
[0].start
= ioPhys
;
83 rangeList
[0].length
= ioPhysLen
;
84 rangeList
[1].start
= ioPhys
+ 0x00c00000;
85 rangeList
[1].length
= 4;
86 rangeList
[2].start
= ioPhys
+ 0x00e00000;
87 rangeList
[2].length
= 4;
89 array
= IODeviceMemory::arrayFromList( rangeList
, 3 );
93 provider
->setDeviceMemory( array
);
95 ioMemory
= (IODeviceMemory
*) array
->getObject( 0 );
97 if( (configAddrMap
= provider
->mapDeviceMemoryWithIndex( 1 )))
98 configAddr
= (volatile UInt32
*) configAddrMap
->getVirtualAddress();
99 if( (configDataMap
= provider
->mapDeviceMemoryWithIndex( 2 )))
100 configData
= (volatile UInt8
*) configDataMap
->getVirtualAddress();
102 if( !configAddr
|| !configData
)
105 busProp
= (OSData
*) bridge
->getProperty("bus-range");
107 primaryBus
= *((UInt32
*) busProp
->getBytesNoCopy());
109 // Check to see if there is a set loop snoop property.
110 if( provider
->getProperty("set-loop-snoop")) {
111 // Turn on the Loop Snoop bit in PICR1.
112 // See: MPC106 User's Manual p. 3-55.
113 grackleSpace
.bits
= 0x80000000;
114 picr1
= configRead32(grackleSpace
, 0xA8);
116 configWrite32(grackleSpace
, 0xA8, picr1
);
119 // register iteself so we can find it:
122 // Publish the AccessMPC106PerformanceRegister platform function.
123 publishResource("AccessMPC106PerformanceRegister", this);
125 return( super::start( provider
));
128 bool AppleGracklePCI::configure( IOService
* provider
)
132 ok
= addBridgeMemoryRange( 0x80000000, 0x7f000000, true );
133 ok
= addBridgeIORange( 0, 0x10000 );
135 return( super::configure( provider
));
138 void AppleGracklePCI::free()
141 configAddrMap
->release();
143 configDataMap
->release();
145 IOSimpleLockFree( lock
);
150 IODeviceMemory
* AppleGracklePCI::ioDeviceMemory( void )
155 UInt8
AppleGracklePCI::firstBusNum( void )
157 return( primaryBus
);
160 UInt8
AppleGracklePCI::lastBusNum( void )
162 return( firstBusNum() );
165 IOPCIAddressSpace
AppleGracklePCI::getBridgeSpace( void )
167 IOPCIAddressSpace space
;
170 space
.s
.deviceNum
= kBridgeSelfDevice
;
175 inline void AppleGracklePCI::setConfigSpace( IOPCIAddressSpace space
,
178 IOPCIAddressSpace addrCycle
;
181 addrCycle
.s
.reloc
= 1;
182 addrCycle
.s
.registerNum
= offset
& 0xfc;
184 OSWriteSwapInt32( configAddr
, 0, addrCycle
.bits
);
186 OSReadSwapInt32( configAddr
, 0 );
191 UInt32
AppleGracklePCI::configRead32( IOPCIAddressSpace space
,
195 IOInterruptState ints
;
197 ints
= IOSimpleLockLockDisableInterrupt( lock
);
199 setConfigSpace( space
, offset
);
201 data
= OSReadSwapInt32( configData
, 0 );
204 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
208 void AppleGracklePCI::configWrite32( IOPCIAddressSpace space
,
209 UInt8 offset
, UInt32 data
)
211 IOInterruptState ints
;
213 ints
= IOSimpleLockLockDisableInterrupt( lock
);
215 setConfigSpace( space
, offset
);
217 OSWriteSwapInt32( configData
, 0, data
);
220 (void) OSReadSwapInt32( configData
, 0 );
223 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
226 UInt16
AppleGracklePCI::configRead16( IOPCIAddressSpace space
,
230 IOInterruptState ints
;
232 ints
= IOSimpleLockLockDisableInterrupt( lock
);
234 setConfigSpace( space
, offset
);
236 offset
= (offset
& 2);
238 data
= OSReadSwapInt16( configData
, offset
);
241 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
245 void AppleGracklePCI::configWrite16( IOPCIAddressSpace space
,
246 UInt8 offset
, UInt16 data
)
248 IOInterruptState ints
;
250 ints
= IOSimpleLockLockDisableInterrupt( lock
);
252 setConfigSpace( space
, offset
);
254 offset
= (offset
& 2);
256 OSWriteSwapInt16( configData
, offset
, data
);
259 (void) OSReadSwapInt16( configData
, offset
);
262 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
265 UInt8
AppleGracklePCI::configRead8( IOPCIAddressSpace space
,
269 IOInterruptState ints
;
271 ints
= IOSimpleLockLockDisableInterrupt( lock
);
273 setConfigSpace( space
, offset
);
275 offset
= (offset
& 3);
277 data
= configData
[ offset
];
280 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
284 void AppleGracklePCI::configWrite8( IOPCIAddressSpace space
,
285 UInt8 offset
, UInt8 data
)
287 IOInterruptState ints
;
289 ints
= IOSimpleLockLockDisableInterrupt( lock
);
291 setConfigSpace( space
, offset
);
293 offset
= (offset
& 3);
295 configData
[ offset
] = data
;
298 data
= configData
[ offset
];
301 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
304 IOReturn
AppleGracklePCI::callPlatformFunction(const OSSymbol
*functionName
,
305 bool waitForFunction
,
306 void *param1
, void *param2
,
307 void *param3
, void *param4
)
309 if (functionName
->isEqualTo("AccessMPC106PerformanceRegister")) {
310 return accessMPC106PerformanceRegister((bool)param1
, (long)param2
,
311 (unsigned long *)param3
);
314 return super::callPlatformFunction(functionName
, waitForFunction
,
315 param1
, param2
, param3
, param4
);
320 kMCMonitorModeControl
= 0,
322 kMCPerformanceMonitor0
,
323 kMCPerformanceMonitor1
,
324 kMCPerformanceMonitor2
,
325 kMCPerformanceMonitor3
328 IOReturn
AppleGracklePCI::accessMPC106PerformanceRegister(bool write
,
332 IOPCIAddressSpace grackleSpace
;
333 unsigned long offset
;
336 case kMCMonitorModeControl
: offset
= kMPC106MMCR0
; break;
337 case kMCCommand
: offset
= kMPC106CMDR0
; break;
338 case kMCPerformanceMonitor0
: offset
= kMPC106PMC0
; break;
339 case kMCPerformanceMonitor1
: offset
= kMPC106PMC1
; break;
340 case kMCPerformanceMonitor2
: offset
= kMPC106PMC2
; break;
341 case kMCPerformanceMonitor3
: offset
= kMPC106PMC3
; break;
342 default : return kIOReturnBadArgument
;
345 if (data
== 0) return kIOReturnBadArgument
;
347 grackleSpace
.bits
= 0x80000000;
350 configWrite32(grackleSpace
, offset
, *data
);
352 *data
= configRead32(grackleSpace
, offset
);
355 return kIOReturnSuccess
;