]> git.saurik.com Git - apple/xnu.git/blob - iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Drivers / pci / drvApplePCI / AppleGracklePCI.cpp
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 }