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>
36 #include <architecture/i386/kernBootStruct.h>
37 #include <architecture/i386/pio.h>
39 #include "AppleI386PCI.h"
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
45 #define super IOPCIBridge
47 OSDefineMetaClassAndStructors(AppleI386PCI
, IOPCIBridge
)
49 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
51 bool AppleI386PCI::start( IOService
* provider
)
54 PCI_bus_info_t
* info
;
56 if( 0 == (lock
= IOSimpleLockAlloc()))
59 prop
= (OSData
*) provider
->getProperty("pci-bus-info");
63 info
= (PCI_bus_info_t
*) prop
->getBytesNoCopy();
65 maxBusNum
= info
->maxBusNum
;
67 majorVersion
= info
->majorVersion
;
68 minorVersion
= info
->minorVersion
;
69 BIOS16Present
= info
->BIOSPresent
;
70 BIOS32Present
= false;
71 BIOS32Entry
= 0x00000000;
72 configMethod1
= info
->u_bus
.s
.configMethod1
;
73 configMethod2
= info
->u_bus
.s
.configMethod2
;
74 specialCycle1
= info
->u_bus
.s
.specialCycle1
;
75 specialCycle2
= info
->u_bus
.s
.specialCycle2
;
78 if ((BIOS16Present) & !(configMethod1 | configMethod2)) {
79 // This is a PCI system, but neither method is supported
80 // Lets try them both just in case (ala NEC ExpressII P60)
81 if (!(configMethod1 = [self test_M1]))
82 configMethod2 = [self test_M2];
86 #define IFYES(b, s) ((b) ? s : "")
87 IOLog("PCI Ver=%x.%02x BusCount=%d Features=[ %s%s%s%s%s%s]\n",
88 majorVersion
, minorVersion
, maxBusNum
+1,
89 IFYES(BIOS16Present
, "BIOS16 "), IFYES(BIOS32Present
, "BIOS32 "),
90 IFYES(configMethod1
, "CM1 "), IFYES(configMethod2
, "CM2 "),
91 IFYES(specialCycle1
, "SC1 "), IFYES(specialCycle2
, "SC2 ") );
95 else if (configMethod2
)
100 ioMemory
= IODeviceMemory::withRange( 0, 65536 );
103 ioMemory
->setMapping( kernel_task
, 0 ); /* mapped to zero in IO space */
105 return( super::start( provider
));
108 bool AppleI386PCI::configure( IOService
* provider
)
112 ok
= addBridgeMemoryRange( 0x80000000, 0x7f000000, true );
113 ok
= addBridgeIORange( 0, 0x10000 );
115 return( super::configure( provider
));
118 void AppleI386PCI::free()
123 IOSimpleLockFree( lock
);
128 IODeviceMemory
* AppleI386PCI::ioDeviceMemory( void )
134 UInt8
AppleI386PCI::firstBusNum( void )
139 UInt8
AppleI386PCI::lastBusNum( void )
141 return( firstBusNum() );
144 IOPCIAddressSpace
AppleI386PCI::getBridgeSpace( void )
146 IOPCIAddressSpace space
;
153 /* defines for Configuration Method #1 (PCI 2.0 Spec, sec 3.6.4.1.1) */
154 #define PCI_CONFIG_ADDRESS 0x0cf8
155 #define PCI_CONFIG_DATA 0x0cfc
157 /* defines for Configuration Method #2 (PCI 2.0 Spec, sec 3.6.4.1.3) */
158 #define PCI_CSE_REGISTER 0x0cf8
159 #define PCI_BUS_FORWARD 0x0cfa
161 #define PCI_DEFAULT_DATA 0xffffffff
167 unsigned long address
, data
;
169 for (address
= 0x80000000; address
< 0x80010000; address
+= 0x800) {
170 outl (PCI_CONFIG_ADDRESS
, address
);
171 if (inl (PCI_CONFIG_ADDRESS
) != address
) {
174 data
= inl(PCI_CONFIG_DATA
);
175 if ((data
!= PCI_DEFAULT_DATA
) && (data
!= 0x00)) {
176 outl (PCI_CONFIG_ADDRESS
, 0);
181 outl (PCI_CONFIG_ADDRESS
, 0);
187 unsigned long address
, data
;
189 /* Enable configuration space at I/O ports Cxxx. */
191 outb (PCI_CSE_REGISTER
, 0xF0);
192 if (inb (PCI_CSE_REGISTER
) != 0xF0) {
196 outb (PCI_BUS_FORWARD
, 0x00);
197 if (inb (PCI_BUS_FORWARD
) != 0x00) {
200 /* Search all devices on the bus. */
201 for (address
= 0xc000; address
<= 0xcfff; address
+= 0x100) {
203 if ((data
!= PCI_DEFAULT_DATA
) && (data
!= 0x00)) {
204 outb (PCI_CSE_REGISTER
, 0);
209 outb (PCI_CSE_REGISTER
, 0);
214 UInt32
AppleI386PCI::configRead32Method1( IOPCIAddressSpace space
,
217 IOPCIAddressSpace addrCycle
;
218 UInt32 data
= PCI_DEFAULT_DATA
;
221 addrCycle
.s
.reloc
= 1;
222 addrCycle
.s
.registerNum
= offset
;
224 outl( PCI_CONFIG_ADDRESS
, addrCycle
.bits
);
225 if (inl( PCI_CONFIG_ADDRESS
) == addrCycle
.bits
)
226 data
= inl( PCI_CONFIG_DATA
);
228 outl( PCI_CONFIG_ADDRESS
, 0);
234 void AppleI386PCI::configWrite32Method1( IOPCIAddressSpace space
,
235 UInt8 offset
, UInt32 data
)
237 IOPCIAddressSpace addrCycle
;
240 addrCycle
.s
.reloc
= 1;
241 addrCycle
.s
.registerNum
= offset
;
243 outl( PCI_CONFIG_ADDRESS
, addrCycle
.bits
);
244 if (inl( PCI_CONFIG_ADDRESS
) == addrCycle
.bits
)
245 outl(PCI_CONFIG_DATA
, data
);
247 outl( PCI_CONFIG_ADDRESS
, 0);
250 UInt16
AppleI386PCI::configRead16Method1( IOPCIAddressSpace space
,
253 IOPCIAddressSpace addrCycle
;
254 UInt16 data
= 0xffff;
257 addrCycle
.s
.reloc
= 1;
258 addrCycle
.s
.registerNum
= offset
;
260 outl( PCI_CONFIG_ADDRESS
, addrCycle
.bits
);
261 if (inl( PCI_CONFIG_ADDRESS
) == addrCycle
.bits
)
262 data
= inw( PCI_CONFIG_DATA
);
264 outl( PCI_CONFIG_ADDRESS
, 0);
270 void AppleI386PCI::configWrite16Method1( IOPCIAddressSpace space
,
271 UInt8 offset
, UInt16 data
)
273 IOPCIAddressSpace addrCycle
;
276 addrCycle
.s
.reloc
= 1;
277 addrCycle
.s
.registerNum
= offset
;
279 outl( PCI_CONFIG_ADDRESS
, addrCycle
.bits
);
280 if (inl( PCI_CONFIG_ADDRESS
) == addrCycle
.bits
)
281 outw(PCI_CONFIG_DATA
, data
);
283 outl( PCI_CONFIG_ADDRESS
, 0);
286 UInt8
AppleI386PCI::configRead8Method1( IOPCIAddressSpace space
,
289 IOPCIAddressSpace addrCycle
;
293 addrCycle
.s
.reloc
= 1;
294 addrCycle
.s
.registerNum
= offset
;
296 outl( PCI_CONFIG_ADDRESS
, addrCycle
.bits
);
297 if (inl( PCI_CONFIG_ADDRESS
) == addrCycle
.bits
)
298 data
= inb( PCI_CONFIG_DATA
);
300 outl( PCI_CONFIG_ADDRESS
, 0);
306 void AppleI386PCI::configWrite8Method1( IOPCIAddressSpace space
,
307 UInt8 offset
, UInt8 data
)
309 IOPCIAddressSpace addrCycle
;
312 addrCycle
.s
.reloc
= 1;
313 addrCycle
.s
.registerNum
= offset
;
315 outl( PCI_CONFIG_ADDRESS
, addrCycle
.bits
);
316 if (inl( PCI_CONFIG_ADDRESS
) == addrCycle
.bits
)
317 outb(PCI_CONFIG_DATA
, data
);
319 outl( PCI_CONFIG_ADDRESS
, 0);
322 UInt32
AppleI386PCI::configRead32Method2( IOPCIAddressSpace space
,
325 UInt32 data
= PCI_DEFAULT_DATA
;
328 if( space
.s
.deviceNum
> 15)
331 cse
= 0xf0 | (space
.s
.functionNum
<< 1);
332 outb( PCI_CSE_REGISTER
, cse
);
333 if (inb( PCI_CSE_REGISTER
) == cse
) {
334 outb( PCI_BUS_FORWARD
, space
.s
.busNum
);
335 if (inb( PCI_BUS_FORWARD
) == space
.s
.busNum
) {
338 | (space
.s
.deviceNum
<< 8));
340 outb( PCI_BUS_FORWARD
, 0x00);
342 outb( PCI_CSE_REGISTER
, 0x00);
348 void AppleI386PCI::configWrite32Method2( IOPCIAddressSpace space
,
349 UInt8 offset
, UInt32 data
)
353 if( space
.s
.deviceNum
> 15)
356 cse
= 0xf0 | (space
.s
.functionNum
<< 1);
357 outb( PCI_CSE_REGISTER
, cse
);
358 if (inb( PCI_CSE_REGISTER
) == cse
) {
359 outb( PCI_BUS_FORWARD
, space
.s
.busNum
);
360 if (inb( PCI_BUS_FORWARD
) == space
.s
.busNum
) {
363 | (space
.s
.deviceNum
<< 8), data
);
365 outb( PCI_BUS_FORWARD
, 0x00);
367 outb( PCI_CSE_REGISTER
, 0x00);
370 UInt16
AppleI386PCI::configRead16Method2( IOPCIAddressSpace space
,
373 UInt16 data
= 0xffff;
376 if( space
.s
.deviceNum
> 15)
379 cse
= 0xf0 | (space
.s
.functionNum
<< 1);
380 outb( PCI_CSE_REGISTER
, cse
);
381 if (inb( PCI_CSE_REGISTER
) == cse
) {
382 outb( PCI_BUS_FORWARD
, space
.s
.busNum
);
383 if (inb( PCI_BUS_FORWARD
) == space
.s
.busNum
) {
386 | (space
.s
.deviceNum
<< 8));
388 outb( PCI_BUS_FORWARD
, 0x00);
390 outb( PCI_CSE_REGISTER
, 0x00);
396 void AppleI386PCI::configWrite16Method2( IOPCIAddressSpace space
,
397 UInt8 offset
, UInt16 data
)
401 if( space
.s
.deviceNum
> 15)
404 cse
= 0xf0 | (space
.s
.functionNum
<< 1);
405 outb( PCI_CSE_REGISTER
, cse
);
406 if (inb( PCI_CSE_REGISTER
) == cse
) {
407 outb( PCI_BUS_FORWARD
, space
.s
.busNum
);
408 if (inb( PCI_BUS_FORWARD
) == space
.s
.busNum
) {
411 | (space
.s
.deviceNum
<< 8), data
);
413 outb( PCI_BUS_FORWARD
, 0x00);
415 outb( PCI_CSE_REGISTER
, 0x00);
419 UInt8
AppleI386PCI::configRead8Method2( IOPCIAddressSpace space
,
422 UInt16 data
= 0xffff;
425 if( space
.s
.deviceNum
> 15)
428 cse
= 0xf0 | (space
.s
.functionNum
<< 1);
429 outb( PCI_CSE_REGISTER
, cse
);
430 if (inb( PCI_CSE_REGISTER
) == cse
) {
431 outb( PCI_BUS_FORWARD
, space
.s
.busNum
);
432 if (inb( PCI_BUS_FORWARD
) == space
.s
.busNum
) {
435 | (space
.s
.deviceNum
<< 8));
437 outb( PCI_BUS_FORWARD
, 0x00);
439 outb( PCI_CSE_REGISTER
, 0x00);
445 void AppleI386PCI::configWrite8Method2( IOPCIAddressSpace space
,
446 UInt8 offset
, UInt8 data
)
450 if( space
.s
.deviceNum
> 15)
453 cse
= 0xf0 | (space
.s
.functionNum
<< 1);
454 outb( PCI_CSE_REGISTER
, cse
);
455 if (inb( PCI_CSE_REGISTER
) == cse
) {
456 outb( PCI_BUS_FORWARD
, space
.s
.busNum
);
457 if (inb( PCI_BUS_FORWARD
) == space
.s
.busNum
) {
460 | (space
.s
.deviceNum
<< 8), data
);
462 outb( PCI_BUS_FORWARD
, 0x00);
464 outb( PCI_CSE_REGISTER
, 0x00);
468 UInt32
AppleI386PCI::configRead32( IOPCIAddressSpace space
,
471 IOInterruptState ints
;
474 ints
= IOSimpleLockLockDisableInterrupt( lock
);
477 retval
= configRead32Method1( space
, offset
);
479 retval
= configRead32Method2( space
, offset
);
481 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
485 void AppleI386PCI::configWrite32( IOPCIAddressSpace space
,
486 UInt8 offset
, UInt32 data
)
488 IOInterruptState ints
;
490 ints
= IOSimpleLockLockDisableInterrupt( lock
);
493 configWrite32Method1( space
, offset
, data
);
495 configWrite32Method2( space
, offset
, data
);
497 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
500 UInt16
AppleI386PCI::configRead16( IOPCIAddressSpace space
,
503 IOInterruptState ints
;
506 ints
= IOSimpleLockLockDisableInterrupt( lock
);
509 retval
= configRead16Method1( space
, offset
);
511 retval
= configRead16Method2( space
, offset
);
513 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
517 void AppleI386PCI::configWrite16( IOPCIAddressSpace space
,
518 UInt8 offset
, UInt16 data
)
520 IOInterruptState ints
;
522 ints
= IOSimpleLockLockDisableInterrupt( lock
);
525 configWrite16Method1( space
, offset
, data
);
527 configWrite16Method2( space
, offset
, data
);
529 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
532 UInt8
AppleI386PCI::configRead8( IOPCIAddressSpace space
,
535 IOInterruptState ints
;
538 ints
= IOSimpleLockLockDisableInterrupt( lock
);
541 retval
= configRead8Method1( space
, offset
);
543 retval
= configRead8Method2( space
, offset
);
545 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);
549 void AppleI386PCI::configWrite8( IOPCIAddressSpace space
,
550 UInt8 offset
, UInt8 data
)
552 IOInterruptState ints
;
554 ints
= IOSimpleLockLockDisableInterrupt( lock
);
557 configWrite8Method1( space
, offset
, data
);
559 configWrite8Method2( space
, offset
, data
);
561 IOSimpleLockUnlockEnableInterrupt( lock
, ints
);