]>
Commit | Line | Data |
---|---|---|
1c79356b A |
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 | * 23 Nov 98 sdouglas created from objc version. | |
27 | */ | |
28 | ||
29 | #include <IOKit/system.h> | |
30 | ||
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> | |
36 | ||
37 | #include "AppleGracklePCI.h" | |
38 | ||
39 | #include <IOKit/assert.h> | |
40 | ||
41 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
42 | ||
43 | #define super IOPCIBridge | |
44 | ||
45 | OSDefineMetaClassAndStructors(AppleGracklePCI, IOPCIBridge) | |
46 | ||
47 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
48 | ||
49 | bool AppleGracklePCI::start( IOService * provider ) | |
50 | { | |
51 | IOPCIPhysicalAddress ioAddrCell; | |
52 | IOPhysicalAddress ioPhys; | |
53 | IOPhysicalAddress ioPhysLen; | |
54 | OSArray * array; | |
55 | IODeviceMemory::InitElement rangeList[ 3 ]; | |
56 | IORegistryEntry * bridge; | |
57 | OSData * busProp; | |
58 | IOPCIAddressSpace grackleSpace; | |
59 | UInt32 picr1; | |
60 | ||
61 | if( 0 == (lock = IOSimpleLockAlloc())) | |
62 | return( false ); | |
63 | ||
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; | |
70 | ||
71 | bridge = provider; | |
72 | ||
73 | if( ! IODTResolveAddressCell( bridge, (UInt32 *) &ioAddrCell, | |
74 | &ioPhys, &ioPhysLen) ) { | |
75 | ||
76 | IOLog("%s: couldn't find my base\n", getName()); | |
77 | return( false); | |
78 | } | |
79 | ||
80 | /* define more explicit ranges */ | |
81 | ||
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; | |
88 | ||
89 | array = IODeviceMemory::arrayFromList( rangeList, 3 ); | |
90 | if( !array) | |
91 | return( false); | |
92 | ||
93 | provider->setDeviceMemory( array ); | |
94 | array->release(); | |
95 | ioMemory = (IODeviceMemory *) array->getObject( 0 ); | |
96 | ||
97 | if( (configAddrMap = provider->mapDeviceMemoryWithIndex( 1 ))) | |
98 | configAddr = (volatile UInt32 *) configAddrMap->getVirtualAddress(); | |
99 | if( (configDataMap = provider->mapDeviceMemoryWithIndex( 2 ))) | |
100 | configData = (volatile UInt8 *) configDataMap->getVirtualAddress(); | |
101 | ||
102 | if( !configAddr || !configData) | |
103 | return( false); | |
104 | ||
105 | busProp = (OSData *) bridge->getProperty("bus-range"); | |
106 | if( busProp) | |
107 | primaryBus = *((UInt32 *) busProp->getBytesNoCopy()); | |
108 | ||
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); | |
115 | picr1 |= (1 << 4); | |
116 | configWrite32(grackleSpace, 0xA8, picr1); | |
117 | } | |
118 | ||
119 | // register iteself so we can find it: | |
120 | registerService(); | |
121 | ||
122 | // Publish the AccessMPC106PerformanceRegister platform function. | |
123 | publishResource("AccessMPC106PerformanceRegister", this); | |
124 | ||
125 | return( super::start( provider)); | |
126 | } | |
127 | ||
128 | bool AppleGracklePCI::configure( IOService * provider ) | |
129 | { | |
130 | bool ok; | |
131 | ||
132 | ok = addBridgeMemoryRange( 0x80000000, 0x7f000000, true ); | |
133 | ok = addBridgeIORange( 0, 0x10000 ); | |
134 | ||
135 | return( super::configure( provider )); | |
136 | } | |
137 | ||
138 | void AppleGracklePCI::free() | |
139 | { | |
140 | if( configAddrMap) | |
141 | configAddrMap->release(); | |
142 | if( configDataMap) | |
143 | configDataMap->release(); | |
144 | if( lock) | |
145 | IOSimpleLockFree( lock); | |
146 | ||
147 | super::free(); | |
148 | } | |
149 | ||
150 | IODeviceMemory * AppleGracklePCI::ioDeviceMemory( void ) | |
151 | { | |
152 | return( ioMemory); | |
153 | } | |
154 | ||
155 | UInt8 AppleGracklePCI::firstBusNum( void ) | |
156 | { | |
157 | return( primaryBus ); | |
158 | } | |
159 | ||
160 | UInt8 AppleGracklePCI::lastBusNum( void ) | |
161 | { | |
162 | return( firstBusNum() ); | |
163 | } | |
164 | ||
165 | IOPCIAddressSpace AppleGracklePCI::getBridgeSpace( void ) | |
166 | { | |
167 | IOPCIAddressSpace space; | |
168 | ||
169 | space.bits = 0; | |
170 | space.s.deviceNum = kBridgeSelfDevice; | |
171 | ||
172 | return( space ); | |
173 | } | |
174 | ||
175 | inline void AppleGracklePCI::setConfigSpace( IOPCIAddressSpace space, | |
176 | UInt8 offset ) | |
177 | { | |
178 | IOPCIAddressSpace addrCycle; | |
179 | ||
180 | addrCycle = space; | |
181 | addrCycle.s.reloc = 1; | |
182 | addrCycle.s.registerNum = offset & 0xfc; | |
183 | ||
184 | OSWriteSwapInt32( configAddr, 0, addrCycle.bits); | |
185 | eieio(); | |
186 | OSReadSwapInt32( configAddr, 0 ); | |
187 | eieio(); | |
188 | } | |
189 | ||
190 | ||
191 | UInt32 AppleGracklePCI::configRead32( IOPCIAddressSpace space, | |
192 | UInt8 offset ) | |
193 | { | |
194 | UInt32 data; | |
195 | IOInterruptState ints; | |
196 | ||
197 | ints = IOSimpleLockLockDisableInterrupt( lock ); | |
198 | ||
199 | setConfigSpace( space, offset ); | |
200 | ||
201 | data = OSReadSwapInt32( configData, 0 ); | |
202 | eieio(); | |
203 | ||
204 | IOSimpleLockUnlockEnableInterrupt( lock, ints ); | |
205 | return( data ); | |
206 | } | |
207 | ||
208 | void AppleGracklePCI::configWrite32( IOPCIAddressSpace space, | |
209 | UInt8 offset, UInt32 data ) | |
210 | { | |
211 | IOInterruptState ints; | |
212 | ||
213 | ints = IOSimpleLockLockDisableInterrupt( lock ); | |
214 | ||
215 | setConfigSpace( space, offset ); | |
216 | ||
217 | OSWriteSwapInt32( configData, 0, data ); | |
218 | eieio(); | |
219 | /* read to sync */ | |
220 | (void) OSReadSwapInt32( configData, 0 ); | |
221 | eieio(); | |
222 | ||
223 | IOSimpleLockUnlockEnableInterrupt( lock, ints ); | |
224 | } | |
225 | ||
226 | UInt16 AppleGracklePCI::configRead16( IOPCIAddressSpace space, | |
227 | UInt8 offset ) | |
228 | { | |
229 | UInt16 data; | |
230 | IOInterruptState ints; | |
231 | ||
232 | ints = IOSimpleLockLockDisableInterrupt( lock ); | |
233 | ||
234 | setConfigSpace( space, offset ); | |
235 | ||
236 | offset = (offset & 2); | |
237 | ||
238 | data = OSReadSwapInt16( configData, offset ); | |
239 | eieio(); | |
240 | ||
241 | IOSimpleLockUnlockEnableInterrupt( lock, ints ); | |
242 | return( data ); | |
243 | } | |
244 | ||
245 | void AppleGracklePCI::configWrite16( IOPCIAddressSpace space, | |
246 | UInt8 offset, UInt16 data ) | |
247 | { | |
248 | IOInterruptState ints; | |
249 | ||
250 | ints = IOSimpleLockLockDisableInterrupt( lock ); | |
251 | ||
252 | setConfigSpace( space, offset ); | |
253 | ||
254 | offset = (offset & 2); | |
255 | ||
256 | OSWriteSwapInt16( configData, offset, data ); | |
257 | eieio(); | |
258 | /* read to sync */ | |
259 | (void) OSReadSwapInt16( configData, offset ); | |
260 | eieio(); | |
261 | ||
262 | IOSimpleLockUnlockEnableInterrupt( lock, ints ); | |
263 | } | |
264 | ||
265 | UInt8 AppleGracklePCI::configRead8( IOPCIAddressSpace space, | |
266 | UInt8 offset ) | |
267 | { | |
268 | UInt8 data; | |
269 | IOInterruptState ints; | |
270 | ||
271 | ints = IOSimpleLockLockDisableInterrupt( lock ); | |
272 | ||
273 | setConfigSpace( space, offset ); | |
274 | ||
275 | offset = (offset & 3); | |
276 | ||
277 | data = configData[ offset ]; | |
278 | eieio(); | |
279 | ||
280 | IOSimpleLockUnlockEnableInterrupt( lock, ints ); | |
281 | return( data ); | |
282 | } | |
283 | ||
284 | void AppleGracklePCI::configWrite8( IOPCIAddressSpace space, | |
285 | UInt8 offset, UInt8 data ) | |
286 | { | |
287 | IOInterruptState ints; | |
288 | ||
289 | ints = IOSimpleLockLockDisableInterrupt( lock ); | |
290 | ||
291 | setConfigSpace( space, offset ); | |
292 | ||
293 | offset = (offset & 3); | |
294 | ||
295 | configData[ offset ] = data; | |
296 | eieio(); | |
297 | /* read to sync */ | |
298 | data = configData[ offset ]; | |
299 | eieio(); | |
300 | ||
301 | IOSimpleLockUnlockEnableInterrupt( lock, ints ); | |
302 | } | |
303 | ||
304 | IOReturn AppleGracklePCI::callPlatformFunction(const OSSymbol *functionName, | |
305 | bool waitForFunction, | |
306 | void *param1, void *param2, | |
307 | void *param3, void *param4) | |
308 | { | |
309 | if (functionName->isEqualTo("AccessMPC106PerformanceRegister")) { | |
310 | return accessMPC106PerformanceRegister((bool)param1, (long)param2, | |
311 | (unsigned long *)param3); | |
312 | } | |
313 | ||
314 | return super::callPlatformFunction(functionName, waitForFunction, | |
315 | param1, param2, param3, param4); | |
316 | } | |
317 | ||
318 | ||
319 | enum { | |
320 | kMCMonitorModeControl = 0, | |
321 | kMCCommand, | |
322 | kMCPerformanceMonitor0, | |
323 | kMCPerformanceMonitor1, | |
324 | kMCPerformanceMonitor2, | |
325 | kMCPerformanceMonitor3 | |
326 | }; | |
327 | ||
328 | IOReturn AppleGracklePCI::accessMPC106PerformanceRegister(bool write, | |
329 | long regNumber, | |
330 | unsigned long *data) | |
331 | { | |
332 | IOPCIAddressSpace grackleSpace; | |
333 | unsigned long offset; | |
334 | ||
335 | switch (regNumber) { | |
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; | |
343 | } | |
344 | ||
345 | if (data == 0) return kIOReturnBadArgument; | |
346 | ||
347 | grackleSpace.bits = 0x80000000; | |
348 | ||
349 | if (write) { | |
350 | configWrite32(grackleSpace, offset, *data); | |
351 | } else { | |
352 | *data = configRead32(grackleSpace, offset); | |
353 | } | |
354 | ||
355 | return kIOReturnSuccess; | |
356 | } |