]> git.saurik.com Git - apple/xnu.git/blob - iokit/Drivers/pci/drvApplePCI/AppleI386PCI.cpp
40423ac11b60821d89e5f171b9ac7873bd01628a
[apple/xnu.git] / iokit / Drivers / pci / drvApplePCI / AppleI386PCI.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
36 #include <architecture/i386/kernBootStruct.h>
37 #include <architecture/i386/pio.h>
38
39 #include "AppleI386PCI.h"
40
41 #include <assert.h>
42
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
44
45 #define super IOPCIBridge
46
47 OSDefineMetaClassAndStructors(AppleI386PCI, IOPCIBridge)
48
49 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
50
51 bool AppleI386PCI::start( IOService * provider )
52 {
53 OSData * prop;
54 PCI_bus_info_t * info;
55
56 if( 0 == (lock = IOSimpleLockAlloc()))
57 return( false );
58
59 prop = (OSData *) provider->getProperty("pci-bus-info");
60 if( 0 == prop)
61 return( false);
62
63 info = (PCI_bus_info_t *) prop->getBytesNoCopy();
64
65 maxBusNum = info->maxBusNum;
66 maxDevNum = 0;
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;
76
77 /*
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];
83 }
84 */
85
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 ") );
92
93 if (configMethod1)
94 maxDevNum = 31;
95 else if (configMethod2)
96 maxDevNum = 15;
97 else
98 return( false );
99
100 ioMemory = IODeviceMemory::withRange( 0, 65536 );
101 if( !ioMemory)
102 return( false);
103 ioMemory->setMapping( kernel_task, 0 ); /* mapped to zero in IO space */
104
105 return( super::start( provider));
106 }
107
108 bool AppleI386PCI::configure( IOService * provider )
109 {
110 bool ok;
111
112 ok = addBridgeMemoryRange( 0x80000000, 0x7f000000, true );
113 ok = addBridgeIORange( 0, 0x10000 );
114
115 return( super::configure( provider ));
116 }
117
118 void AppleI386PCI::free()
119 {
120 if( ioMemory)
121 ioMemory->release();
122 if( lock)
123 IOSimpleLockFree( lock);
124
125 super::free();
126 }
127
128 IODeviceMemory * AppleI386PCI::ioDeviceMemory( void )
129 {
130 return( ioMemory);
131 }
132
133
134 UInt8 AppleI386PCI::firstBusNum( void )
135 {
136 return( 0 );
137 }
138
139 UInt8 AppleI386PCI::lastBusNum( void )
140 {
141 return( firstBusNum() );
142 }
143
144 IOPCIAddressSpace AppleI386PCI::getBridgeSpace( void )
145 {
146 IOPCIAddressSpace space;
147
148 space.bits = 0;
149
150 return( space );
151 }
152
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
156
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
160
161 #define PCI_DEFAULT_DATA 0xffffffff
162
163 #if 0
164
165 - (BOOL) test_M1
166 {
167 unsigned long address, data;
168
169 for (address = 0x80000000; address < 0x80010000; address += 0x800) {
170 outl (PCI_CONFIG_ADDRESS, address);
171 if (inl (PCI_CONFIG_ADDRESS) != address) {
172 return NO;
173 }
174 data = inl(PCI_CONFIG_DATA);
175 if ((data != PCI_DEFAULT_DATA) && (data != 0x00)) {
176 outl (PCI_CONFIG_ADDRESS, 0);
177 return YES;
178 }
179 }
180
181 outl (PCI_CONFIG_ADDRESS, 0);
182 return NO;
183 }
184
185 - (BOOL) test_M2
186 {
187 unsigned long address, data;
188
189 /* Enable configuration space at I/O ports Cxxx. */
190
191 outb (PCI_CSE_REGISTER, 0xF0);
192 if (inb (PCI_CSE_REGISTER) != 0xF0) {
193 return NO;
194 }
195
196 outb (PCI_BUS_FORWARD, 0x00);
197 if (inb (PCI_BUS_FORWARD) != 0x00) {
198 return NO;
199 }
200 /* Search all devices on the bus. */
201 for (address = 0xc000; address <= 0xcfff; address += 0x100) {
202 data = inl(address);
203 if ((data != PCI_DEFAULT_DATA) && (data != 0x00)) {
204 outb (PCI_CSE_REGISTER, 0);
205 return YES;
206 }
207 }
208
209 outb (PCI_CSE_REGISTER, 0);
210 return NO;
211 }
212 #endif
213
214 UInt32 AppleI386PCI::configRead32Method1( IOPCIAddressSpace space,
215 UInt8 offset )
216 {
217 IOPCIAddressSpace addrCycle;
218 UInt32 data = PCI_DEFAULT_DATA;
219
220 addrCycle = space;
221 addrCycle.s.reloc = 1;
222 addrCycle.s.registerNum = offset;
223
224 outl( PCI_CONFIG_ADDRESS, addrCycle.bits);
225 if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits)
226 data = inl( PCI_CONFIG_DATA);
227
228 outl( PCI_CONFIG_ADDRESS, 0);
229
230 return( data );
231 }
232
233
234 void AppleI386PCI::configWrite32Method1( IOPCIAddressSpace space,
235 UInt8 offset, UInt32 data )
236 {
237 IOPCIAddressSpace addrCycle;
238
239 addrCycle = space;
240 addrCycle.s.reloc = 1;
241 addrCycle.s.registerNum = offset;
242
243 outl( PCI_CONFIG_ADDRESS, addrCycle.bits);
244 if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits)
245 outl(PCI_CONFIG_DATA, data);
246
247 outl( PCI_CONFIG_ADDRESS, 0);
248 }
249
250 UInt16 AppleI386PCI::configRead16Method1( IOPCIAddressSpace space,
251 UInt8 offset )
252 {
253 IOPCIAddressSpace addrCycle;
254 UInt16 data = 0xffff;
255
256 addrCycle = space;
257 addrCycle.s.reloc = 1;
258 addrCycle.s.registerNum = offset;
259
260 outl( PCI_CONFIG_ADDRESS, addrCycle.bits);
261 if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits)
262 data = inw( PCI_CONFIG_DATA);
263
264 outl( PCI_CONFIG_ADDRESS, 0);
265
266 return( data );
267 }
268
269
270 void AppleI386PCI::configWrite16Method1( IOPCIAddressSpace space,
271 UInt8 offset, UInt16 data )
272 {
273 IOPCIAddressSpace addrCycle;
274
275 addrCycle = space;
276 addrCycle.s.reloc = 1;
277 addrCycle.s.registerNum = offset;
278
279 outl( PCI_CONFIG_ADDRESS, addrCycle.bits);
280 if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits)
281 outw(PCI_CONFIG_DATA, data);
282
283 outl( PCI_CONFIG_ADDRESS, 0);
284 }
285
286 UInt8 AppleI386PCI::configRead8Method1( IOPCIAddressSpace space,
287 UInt8 offset )
288 {
289 IOPCIAddressSpace addrCycle;
290 UInt8 data = 0xff;
291
292 addrCycle = space;
293 addrCycle.s.reloc = 1;
294 addrCycle.s.registerNum = offset;
295
296 outl( PCI_CONFIG_ADDRESS, addrCycle.bits);
297 if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits)
298 data = inb( PCI_CONFIG_DATA);
299
300 outl( PCI_CONFIG_ADDRESS, 0);
301
302 return( data );
303 }
304
305
306 void AppleI386PCI::configWrite8Method1( IOPCIAddressSpace space,
307 UInt8 offset, UInt8 data )
308 {
309 IOPCIAddressSpace addrCycle;
310
311 addrCycle = space;
312 addrCycle.s.reloc = 1;
313 addrCycle.s.registerNum = offset;
314
315 outl( PCI_CONFIG_ADDRESS, addrCycle.bits);
316 if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits)
317 outb(PCI_CONFIG_DATA, data);
318
319 outl( PCI_CONFIG_ADDRESS, 0);
320 }
321
322 UInt32 AppleI386PCI::configRead32Method2( IOPCIAddressSpace space,
323 UInt8 offset )
324 {
325 UInt32 data = PCI_DEFAULT_DATA;
326 UInt8 cse;
327
328 if( space.s.deviceNum > 15)
329 return( data);
330
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) {
336 data = inl( 0xc000
337 | (offset & 0xfc)
338 | (space.s.deviceNum << 8));
339 }
340 outb( PCI_BUS_FORWARD, 0x00);
341 }
342 outb( PCI_CSE_REGISTER, 0x00);
343
344 return( data );
345 }
346
347
348 void AppleI386PCI::configWrite32Method2( IOPCIAddressSpace space,
349 UInt8 offset, UInt32 data )
350 {
351 UInt8 cse;
352
353 if( space.s.deviceNum > 15)
354 return;
355
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) {
361 outl( 0xc000
362 | (offset & 0xfc)
363 | (space.s.deviceNum << 8), data);
364 }
365 outb( PCI_BUS_FORWARD, 0x00);
366 }
367 outb( PCI_CSE_REGISTER, 0x00);
368 }
369
370 UInt16 AppleI386PCI::configRead16Method2( IOPCIAddressSpace space,
371 UInt8 offset )
372 {
373 UInt16 data = 0xffff;
374 UInt8 cse;
375
376 if( space.s.deviceNum > 15)
377 return( data);
378
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) {
384 data = inw( 0xc000
385 | (offset & 0xfe)
386 | (space.s.deviceNum << 8));
387 }
388 outb( PCI_BUS_FORWARD, 0x00);
389 }
390 outb( PCI_CSE_REGISTER, 0x00);
391
392 return( data );
393 }
394
395
396 void AppleI386PCI::configWrite16Method2( IOPCIAddressSpace space,
397 UInt8 offset, UInt16 data )
398 {
399 UInt8 cse;
400
401 if( space.s.deviceNum > 15)
402 return;
403
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) {
409 outw( 0xc000
410 | (offset & 0xfe)
411 | (space.s.deviceNum << 8), data);
412 }
413 outb( PCI_BUS_FORWARD, 0x00);
414 }
415 outb( PCI_CSE_REGISTER, 0x00);
416 }
417
418
419 UInt8 AppleI386PCI::configRead8Method2( IOPCIAddressSpace space,
420 UInt8 offset )
421 {
422 UInt16 data = 0xffff;
423 UInt8 cse;
424
425 if( space.s.deviceNum > 15)
426 return( data);
427
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) {
433 data = inb( 0xc000
434 | (offset)
435 | (space.s.deviceNum << 8));
436 }
437 outb( PCI_BUS_FORWARD, 0x00);
438 }
439 outb( PCI_CSE_REGISTER, 0x00);
440
441 return( data );
442 }
443
444
445 void AppleI386PCI::configWrite8Method2( IOPCIAddressSpace space,
446 UInt8 offset, UInt8 data )
447 {
448 UInt8 cse;
449
450 if( space.s.deviceNum > 15)
451 return;
452
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) {
458 outb( 0xc000
459 | (offset)
460 | (space.s.deviceNum << 8), data);
461 }
462 outb( PCI_BUS_FORWARD, 0x00);
463 }
464 outb( PCI_CSE_REGISTER, 0x00);
465 }
466
467
468 UInt32 AppleI386PCI::configRead32( IOPCIAddressSpace space,
469 UInt8 offset )
470 {
471 IOInterruptState ints;
472 UInt32 retval;
473
474 ints = IOSimpleLockLockDisableInterrupt( lock );
475
476 if( configMethod1)
477 retval = configRead32Method1( space, offset );
478 else
479 retval = configRead32Method2( space, offset );
480
481 IOSimpleLockUnlockEnableInterrupt( lock, ints );
482 return(retval);
483 }
484
485 void AppleI386PCI::configWrite32( IOPCIAddressSpace space,
486 UInt8 offset, UInt32 data )
487 {
488 IOInterruptState ints;
489
490 ints = IOSimpleLockLockDisableInterrupt( lock );
491
492 if( configMethod1)
493 configWrite32Method1( space, offset, data );
494 else
495 configWrite32Method2( space, offset, data );
496
497 IOSimpleLockUnlockEnableInterrupt( lock, ints );
498 }
499
500 UInt16 AppleI386PCI::configRead16( IOPCIAddressSpace space,
501 UInt8 offset )
502 {
503 IOInterruptState ints;
504 UInt16 retval;
505
506 ints = IOSimpleLockLockDisableInterrupt( lock );
507
508 if( configMethod1)
509 retval = configRead16Method1( space, offset );
510 else
511 retval = configRead16Method2( space, offset );
512
513 IOSimpleLockUnlockEnableInterrupt( lock, ints );
514 return(retval);
515 }
516
517 void AppleI386PCI::configWrite16( IOPCIAddressSpace space,
518 UInt8 offset, UInt16 data )
519 {
520 IOInterruptState ints;
521
522 ints = IOSimpleLockLockDisableInterrupt( lock );
523
524 if( configMethod1)
525 configWrite16Method1( space, offset, data );
526 else
527 configWrite16Method2( space, offset, data );
528
529 IOSimpleLockUnlockEnableInterrupt( lock, ints );
530 }
531
532 UInt8 AppleI386PCI::configRead8( IOPCIAddressSpace space,
533 UInt8 offset )
534 {
535 IOInterruptState ints;
536 UInt8 retval;
537
538 ints = IOSimpleLockLockDisableInterrupt( lock );
539
540 if( configMethod1)
541 retval = configRead8Method1( space, offset );
542 else
543 retval = configRead8Method2( space, offset );
544
545 IOSimpleLockUnlockEnableInterrupt( lock, ints );
546 return(retval);
547 }
548
549 void AppleI386PCI::configWrite8( IOPCIAddressSpace space,
550 UInt8 offset, UInt8 data )
551 {
552 IOInterruptState ints;
553
554 ints = IOSimpleLockLockDisableInterrupt( lock );
555
556 if( configMethod1)
557 configWrite8Method1( space, offset, data );
558 else
559 configWrite8Method2( space, offset, data );
560
561 IOSimpleLockUnlockEnableInterrupt( lock, ints );
562 }
563