]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOPCIBus/IOPCIDevice.cpp
0212aa67e10c8fd89e5ac1d565facc34093b29ab
[apple/xnu.git] / iokit / Families / IOPCIBus / IOPCIDevice.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 <IOKit/pci/IOPCIBridge.h>
32 #include <IOKit/pci/IOPCIDevice.h>
33 #include <IOKit/pci/IOAGPDevice.h>
34 #include <IOKit/IOPlatformExpert.h>
35
36 #include <IOKit/IOLib.h>
37 #include <IOKit/assert.h>
38
39 #include <libkern/c++/OSContainers.h>
40
41 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
42
43 #define super IOService
44
45 OSDefineMetaClassAndStructors(IOPCIDevice, IOService)
46 OSMetaClassDefineReservedUnused(IOPCIDevice, 0);
47 OSMetaClassDefineReservedUnused(IOPCIDevice, 1);
48 OSMetaClassDefineReservedUnused(IOPCIDevice, 2);
49 OSMetaClassDefineReservedUnused(IOPCIDevice, 3);
50 OSMetaClassDefineReservedUnused(IOPCIDevice, 4);
51 OSMetaClassDefineReservedUnused(IOPCIDevice, 5);
52 OSMetaClassDefineReservedUnused(IOPCIDevice, 6);
53 OSMetaClassDefineReservedUnused(IOPCIDevice, 7);
54 OSMetaClassDefineReservedUnused(IOPCIDevice, 8);
55 OSMetaClassDefineReservedUnused(IOPCIDevice, 9);
56 OSMetaClassDefineReservedUnused(IOPCIDevice, 10);
57 OSMetaClassDefineReservedUnused(IOPCIDevice, 11);
58 OSMetaClassDefineReservedUnused(IOPCIDevice, 12);
59 OSMetaClassDefineReservedUnused(IOPCIDevice, 13);
60 OSMetaClassDefineReservedUnused(IOPCIDevice, 14);
61 OSMetaClassDefineReservedUnused(IOPCIDevice, 15);
62
63 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
64
65 // stub driver has two power states, off and on
66
67 enum { kIOPCIDevicePowerStateCount = 2 };
68
69 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
70 // attach
71 //
72 // We clamp power on. The effect is
73 // to prevent system sleep. If a driver is loaded which can
74 // power manage the device, it will become our child and we
75 // will remove the clamp. This prevents the system
76 // from sleeping when there are non-power-managed
77 // PCI cards installed.
78 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
79
80 bool IOPCIDevice::attach( IOService * provider )
81 {
82 static const IOPMPowerState powerStates[ kIOPCIDevicePowerStateCount ] = {
83 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
84 { 1, IOPMPowerOn, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }
85 };
86
87 // initialize superclass variables
88 PMinit();
89 // register as controlling driver
90 registerPowerDriver( this, (IOPMPowerState *) powerStates,
91 kIOPCIDevicePowerStateCount );
92 // join the tree
93 provider->joinPMtree( this);
94
95 // clamp power on if this is a slot device
96 slotNameProperty = provider->getProperty ("AAPL,slot-name");
97 if (slotNameProperty != NULL)
98 changePowerStateToPriv (1);
99
100 return super::attach(provider);
101 }
102
103
104 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
105 // maxCapabilityForDomainState
106 //
107 // If the power domain is supplying power, the device
108 // can be on. If there is no power it can only be off.
109 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
110
111 unsigned long IOPCIDevice::maxCapabilityForDomainState(
112 IOPMPowerFlags domainState )
113 {
114 if( domainState & IOPMPowerOn )
115 return( kIOPCIDevicePowerStateCount - 1);
116 else
117 return( 0);
118 }
119
120
121 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
122 // initialPowerStateForDomainState
123 //
124 // This is our first information about the power domain state.
125 // If power is on in the new state, the device is on.
126 // If domain power is off, the device is also off.
127 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
128 unsigned long IOPCIDevice::initialPowerStateForDomainState(
129 IOPMPowerFlags domainState )
130 {
131 if( domainState & IOPMPowerOn)
132 return( kIOPCIDevicePowerStateCount - 1);
133 else
134 return( 0);
135 }
136
137 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
138 // powerStateForDomainState
139 //
140 // The power domain may be changing state.
141 // If power is on in the new state, the device will be on.
142 // If domain power is off, the device will be off.
143 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
144
145 unsigned long IOPCIDevice::powerStateForDomainState(
146 IOPMPowerFlags domainState )
147 {
148 if( domainState & IOPMPowerOn)
149 return( pm_vars->myCurrentState);
150 else
151 return( 0);
152 }
153
154 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
155 // setPowerState
156 //
157 // Saves and restores PCI config space if power is going down or up.
158 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
159
160 IOReturn IOPCIDevice::setPowerState( unsigned long powerState,
161 IOService * whatDevice )
162 {
163 parent->setDevicePowerState( this, powerState );
164
165 return( IOPMAckImplied);
166 }
167
168 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
169 // addPowerChild
170 //
171 //
172 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
173
174 IOReturn IOPCIDevice::addPowerChild ( IOService * theChild )
175 {
176 IOReturn result = IOPMNoErr;
177
178 result = super::addPowerChild (theChild);
179
180 if ((slotNameProperty != NULL) && (result == IOPMNoErr))
181 changePowerStateToPriv(0);
182
183 return result;
184 }
185
186 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
187 // joinPMtree
188 //
189 // A policy-maker for our PCI device calls here when initializing,
190 // to be attached into the power management hierarchy.
191 // We attach this driver as our child so we can save and restore its config
192 // space across power cycles.
193 //
194 // This overrides the default function of the IOService joinPMtree.
195 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
196
197 void IOPCIDevice::joinPMtree( IOService * driver )
198 {
199 // hook it into the tree
200 pm_vars->thePlatform->PMRegisterDevice( this, driver);
201 }
202
203 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
204
205 bool IOPCIDevice::matchPropertyTable( OSDictionary * table, SInt32 * score )
206 {
207 return( parent->matchNubWithPropertyTable( this, table, score ));
208 }
209
210 bool IOPCIDevice::compareName( OSString * name, OSString ** matched = 0 ) const
211 {
212 return( parent->compareNubName( this, name, matched ));
213 }
214
215 IOReturn IOPCIDevice::getResources( void )
216 {
217 return( parent->getNubResources( this ));
218 }
219
220 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
221
222 UInt32 IOPCIDevice::configRead32( IOPCIAddressSpace _space,
223 UInt8 offset )
224 {
225 return( parent->configRead32( _space, offset ));
226 }
227
228 void IOPCIDevice::configWrite32( IOPCIAddressSpace _space,
229 UInt8 offset, UInt32 data )
230 {
231 parent->configWrite32( _space, offset, data );
232 }
233
234 UInt16 IOPCIDevice::configRead16( IOPCIAddressSpace _space,
235 UInt8 offset )
236 {
237 return( parent->configRead16( _space, offset ));
238 }
239
240 void IOPCIDevice::configWrite16( IOPCIAddressSpace _space,
241 UInt8 offset, UInt16 data )
242 {
243 parent->configWrite16( _space, offset, data );
244 }
245
246 UInt8 IOPCIDevice::configRead8( IOPCIAddressSpace _space,
247 UInt8 offset )
248 {
249 return( parent->configRead8( _space, offset ));
250 }
251
252 void IOPCIDevice::configWrite8( IOPCIAddressSpace _space,
253 UInt8 offset, UInt8 data )
254 {
255 parent->configWrite8( _space, offset, data );
256 }
257
258 UInt32 IOPCIDevice::configRead32( UInt8 offset )
259 {
260 return( parent->configRead32( space, offset ));
261 }
262
263 void IOPCIDevice::configWrite32( UInt8 offset, UInt32 data )
264 {
265 parent->configWrite32( space, offset, data );
266 }
267
268 UInt16 IOPCIDevice::configRead16( UInt8 offset )
269 {
270 return( parent->configRead16( space, offset ));
271 }
272
273 void IOPCIDevice::configWrite16( UInt8 offset, UInt16 data )
274 {
275 parent->configWrite16( space, offset, data );
276 }
277
278 UInt8 IOPCIDevice::configRead8( UInt8 offset )
279 {
280 return( parent->configRead8( space, offset ));
281 }
282
283 void IOPCIDevice::configWrite8( UInt8 offset, UInt8 data )
284 {
285 parent->configWrite8( space, offset, data );
286 }
287
288 IOReturn IOPCIDevice::saveDeviceState( IOOptionBits options = 0 )
289 {
290 return( parent->saveDeviceState( this, options ) );
291 }
292
293 IOReturn IOPCIDevice::restoreDeviceState( IOOptionBits options = 0 )
294 {
295 return( parent->restoreDeviceState( this, options ) );
296 }
297
298 UInt32 IOPCIDevice::findPCICapability( UInt8 capabilityID, UInt8 * offset = 0 )
299 {
300 return( parent->findPCICapability( space, capabilityID, offset ));
301 }
302
303 UInt32 IOPCIDevice::setConfigBits( UInt8 reg, UInt32 mask, UInt32 value )
304 {
305 UInt32 was;
306 UInt32 bits;
307
308 bits = configRead32( reg );
309 was = (bits & mask);
310 bits &= ~mask;
311 bits |= (value & mask);
312 configWrite32( reg, bits );
313
314 return( was );
315 }
316
317 bool IOPCIDevice::setBusMasterEnable( bool enable )
318 {
319 return( 0 != setConfigBits( kIOPCIConfigCommand, kIOPCICommandBusMaster,
320 enable ? kIOPCICommandBusMaster : 0));
321 }
322
323 bool IOPCIDevice::setMemoryEnable( bool enable )
324 {
325 return( 0 != setConfigBits( kIOPCIConfigCommand, kIOPCICommandMemorySpace,
326 enable ? kIOPCICommandMemorySpace : 0));
327 }
328
329 bool IOPCIDevice::setIOEnable( bool enable, bool /* exclusive = false */ )
330 {
331 // exclusive is TODO.
332 return( 0 != setConfigBits( kIOPCIConfigCommand, kIOPCICommandIOSpace,
333 enable ? kIOPCICommandIOSpace : 0));
334 }
335
336 UInt8 IOPCIDevice::getBusNumber( void )
337 {
338 return( space.s.busNum );
339 }
340
341 UInt8 IOPCIDevice::getDeviceNumber( void )
342 {
343 return( space.s.deviceNum );
344 }
345
346 UInt8 IOPCIDevice::getFunctionNumber( void )
347 {
348 return( space.s.functionNum );
349 }
350
351 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
352
353 IODeviceMemory * IOPCIDevice::getDeviceMemoryWithRegister( UInt8 reg )
354 {
355 OSArray * array;
356 IODeviceMemory * range;
357 unsigned int i = 0;
358
359 array = (OSArray *) getProperty( gIODeviceMemoryKey);
360 if( 0 == array)
361 return( 0);
362
363 while( (range = (IODeviceMemory *) array->getObject( i++ ))) {
364 if( reg == (range->getTag() & 0xff))
365 break;
366 }
367
368 return( range);
369 }
370
371 IOMemoryMap * IOPCIDevice:: mapDeviceMemoryWithRegister( UInt8 reg,
372 IOOptionBits options = 0 )
373 {
374 IODeviceMemory * range;
375 IOMemoryMap * map;
376
377 range = getDeviceMemoryWithRegister( reg );
378 if( range)
379 map = range->map( options );
380 else
381 map = 0;
382
383 return( map );
384 }
385
386 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
387
388 IODeviceMemory * IOPCIDevice::ioDeviceMemory( void )
389 {
390 return( parent->ioDeviceMemory() );
391 }
392
393 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
394
395 IOService * IOPCIDevice::matchLocation( IOService * /* client */ )
396 {
397 return( this );
398 }
399
400 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
401
402 #undef super
403 #define super IOPCIDevice
404
405 OSDefineMetaClassAndStructors(IOAGPDevice, IOPCIDevice)
406 OSMetaClassDefineReservedUnused(IOAGPDevice, 0);
407 OSMetaClassDefineReservedUnused(IOAGPDevice, 1);
408 OSMetaClassDefineReservedUnused(IOAGPDevice, 2);
409 OSMetaClassDefineReservedUnused(IOAGPDevice, 3);
410 OSMetaClassDefineReservedUnused(IOAGPDevice, 4);
411 OSMetaClassDefineReservedUnused(IOAGPDevice, 5);
412 OSMetaClassDefineReservedUnused(IOAGPDevice, 6);
413 OSMetaClassDefineReservedUnused(IOAGPDevice, 7);
414 OSMetaClassDefineReservedUnused(IOAGPDevice, 8);
415 OSMetaClassDefineReservedUnused(IOAGPDevice, 9);
416 OSMetaClassDefineReservedUnused(IOAGPDevice, 10);
417 OSMetaClassDefineReservedUnused(IOAGPDevice, 11);
418 OSMetaClassDefineReservedUnused(IOAGPDevice, 12);
419 OSMetaClassDefineReservedUnused(IOAGPDevice, 13);
420 OSMetaClassDefineReservedUnused(IOAGPDevice, 14);
421 OSMetaClassDefineReservedUnused(IOAGPDevice, 15);
422 OSMetaClassDefineReservedUnused(IOAGPDevice, 16);
423
424 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
425
426 IOReturn IOAGPDevice::createAGPSpace( IOOptionBits options,
427 IOPhysicalAddress * address,
428 IOPhysicalLength * length )
429 {
430 return( parent->createAGPSpace( this, options, address, length ));
431 }
432
433 IOReturn IOAGPDevice::destroyAGPSpace( void )
434 {
435 return( parent->destroyAGPSpace( this ));
436 }
437
438 IORangeAllocator * IOAGPDevice::getAGPRangeAllocator( void )
439 {
440 return( parent->getAGPRangeAllocator( this ));
441 }
442
443 IOOptionBits IOAGPDevice::getAGPStatus( IOOptionBits options = 0 )
444 {
445 return( parent->getAGPStatus( this, options ));
446 }
447
448 IOReturn IOAGPDevice::resetAGP( IOOptionBits options = 0 )
449 {
450 return( parent->resetAGPDevice( this, options ));
451 }
452
453 IOReturn IOAGPDevice::getAGPSpace( IOPhysicalAddress * address,
454 IOPhysicalLength * length )
455 {
456 return( parent->getAGPSpace( this, address, length ));
457 }
458
459 IOReturn IOAGPDevice::commitAGPMemory( IOMemoryDescriptor * memory,
460 IOByteCount agpOffset,
461 IOOptionBits options = 0 )
462 {
463 return( parent->commitAGPMemory( this, memory, agpOffset, options ));
464 }
465
466 IOReturn IOAGPDevice::releaseAGPMemory( IOMemoryDescriptor * memory,
467 IOByteCount agpOffset,
468 IOOptionBits options = 0 )
469 {
470 return( parent->releaseAGPMemory( this, memory, agpOffset, options ));
471 }
472
473