]> git.saurik.com Git - apple/xnu.git/blame - iokit/Drivers/pci/drvApplePCI/AppleI386PCI.cpp
xnu-124.13.tar.gz
[apple/xnu.git] / iokit / Drivers / pci / drvApplePCI / AppleI386PCI.cpp
CommitLineData
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
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
47OSDefineMetaClassAndStructors(AppleI386PCI, IOPCIBridge)
48
49/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
50
51bool 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
108bool 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
118void AppleI386PCI::free()
119{
120 if( ioMemory)
121 ioMemory->release();
122 if( lock)
123 IOSimpleLockFree( lock);
124
125 super::free();
126}
127
128IODeviceMemory * AppleI386PCI::ioDeviceMemory( void )
129{
130 return( ioMemory);
131}
132
133
134UInt8 AppleI386PCI::firstBusNum( void )
135{
136 return( 0 );
137}
138
139UInt8 AppleI386PCI::lastBusNum( void )
140{
141 return( firstBusNum() );
142}
143
144IOPCIAddressSpace 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
214UInt32 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
234void 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
250UInt16 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
270void 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
286UInt8 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
306void 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
322UInt32 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
348void 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
370UInt16 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
396void 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
419UInt8 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
445void 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
468UInt32 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
485void 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
500UInt16 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
517void 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
532UInt8 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
549void 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