|
|
1.1 root 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: *
27: * 23 Nov 98 sdouglas created from objc version.
28: *
29: */
30:
31: #include <IOKit/system.h>
32:
33: #include <IOKit/pci/IOPCIBridge.h>
34: #include <IOKit/pci/IOPCIDevice.h>
35: #include <IOKit/pci/IOAGPDevice.h>
36: #include <IOKit/IODeviceTreeSupport.h>
37: #include <IOKit/IORangeAllocator.h>
38: #include <IOKit/IOPlatformExpert.h>
39: #include <IOKit/IOLib.h>
40: #include <IOKit/assert.h>
41:
42: #include <libkern/c++/OSContainers.h>
43:
44: extern "C" {
45: #include <machine/machine_routines.h>
46: };
47:
48:
49: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
50:
51: #define super IOService
52:
53: OSDefineMetaClass( IOPCIBridge, IOService )
54: OSDefineAbstractStructors( IOPCIBridge, IOService )
55:
56: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
57:
58: // 1 log, 2 disable DT
59: int gIOPCIDebug = 0;
60:
61: #ifdef __I386__
62: static void setupIntelPIC(IOPCIDevice *nub);
63: #endif
64:
65: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
66:
67: bool IOPCIBridge::start( IOService * provider )
68: {
69: if( !super::start( provider))
70: return( false);
71:
72: // empty ranges to start
73: bridgeMemoryRanges = IORangeAllocator::withRange( 0, 1, 8,
74: IORangeAllocator::kLocking );
75: assert( bridgeMemoryRanges );
76: setProperty( "Bridge Memory Ranges", bridgeMemoryRanges );
77:
78: bridgeIORanges = IORangeAllocator::withRange( 0, 1, 8,
79: IORangeAllocator::kLocking );
80: assert( bridgeIORanges );
81: setProperty( "Bridge IO Ranges", bridgeIORanges );
82:
83: if( !configure( provider))
84: return( false);
85:
86: probeBus( provider, firstBusNum() );
87:
88: return( true );
89: }
90:
91: bool IOPCIBridge::configure( IOService * provider )
92: {
93: return( true );
94: }
95:
96: static SInt32 PCICompare( UInt32 /* cellCount */, UInt32 cleft[], UInt32 cright[] )
97: {
98: IOPCIPhysicalAddress * left = (IOPCIPhysicalAddress *) cleft;
99: IOPCIPhysicalAddress * right = (IOPCIPhysicalAddress *) cright;
100: static const UInt8 spacesEq[] = { 0, 1, 2, 2 };
101:
102: if( spacesEq[ left->physHi.s.space ] != spacesEq[ right->physHi.s.space ])
103: return( -1);
104:
105: return( left->physLo - right->physLo );
106: }
107:
108: void IOPCIBridge::nvLocation( IORegistryEntry * entry,
109: UInt8 * busNum, UInt8 * deviceNum, UInt8 * functionNum )
110: {
111: IOPCIDevice * nub;
112:
113: nub = OSDynamicCast( IOPCIDevice, entry );
114: assert( nub );
115:
116: *busNum = nub->space.s.busNum;
117: *deviceNum = nub->space.s.deviceNum;
118: *functionNum = nub->space.s.functionNum;
119: }
120:
121: void IOPCIBridge::spaceFromProperties( OSDictionary * propTable,
122: IOPCIAddressSpace * space )
123: {
124: OSData * regProp;
125: IOPCIAddressSpace * inSpace;
126:
127: space->bits = 0;
128:
129: if( (regProp = (OSData *) propTable->getObject("reg"))) {
130:
131: inSpace = (IOPCIAddressSpace *) regProp->getBytesNoCopy();
132: space->s.busNum = inSpace->s.busNum;
133: space->s.deviceNum = inSpace->s.deviceNum;
134: space->s.functionNum = inSpace->s.functionNum;
135: }
136: }
137:
138: IORegistryEntry * IOPCIBridge::findMatching( OSIterator * kids,
139: IOPCIAddressSpace space )
140: {
141: IORegistryEntry * found = 0;
142: IOPCIAddressSpace regSpace;
143:
144: if( kids) {
145: kids->reset();
146: while( (0 == found)
147: && (found = (IORegistryEntry *) kids->getNextObject())) {
148:
149: spaceFromProperties( found->getPropertyTable(), ®Space);
150: if( space.bits != regSpace.bits)
151: found = 0;
152: }
153: }
154: return( found );
155: }
156:
157: OSDictionary * IOPCIBridge::constructProperties( IOPCIAddressSpace space )
158: {
159: OSDictionary * propTable;
160: UInt32 value;
161: UInt8 byte;
162: UInt16 vendor, device;
163: OSData * prop;
164: const char * name;
165: const OSSymbol * nameProp;
166: char * nameStr;
167: char * compatBuf;
168: char * nextCompat;
169:
170: struct IOPCIGenericNames {
171: const char * name;
172: UInt32 mask;
173: UInt32 classCode;
174: };
175: static const IOPCIGenericNames genericNames[] = {
176: { "display", 0xffffff, 0x000100 },
177: { "scsi", 0xffff00, 0x010000 },
178: { "ethernet", 0xffff00, 0x020000 },
179: { "display", 0xff0000, 0x030000 },
180: { "pci-bridge", 0xffff00, 0x060400 },
181: { 0, 0, 0 }
182: };
183: const IOPCIGenericNames * nextName;
184:
185: compatBuf = (char *) IOMalloc( 256 );
186:
187: propTable = OSDictionary::withCapacity( 8 );
188:
189: if( compatBuf && propTable) {
190:
191: prop = OSData::withBytes( &space, sizeof( space) );
192: if( prop) {
193: propTable->setObject("reg", prop );
194: prop->release();
195: }
196:
197: value = configRead32( space, kIOPCIConfigVendorID );
198: vendor = value;
199: device = value >> 16;
200:
201: prop = OSData::withBytes( &vendor, 2 );
202: if( prop) {
203: propTable->setObject("vendor-id", prop );
204: prop->release();
205: }
206:
207: prop = OSData::withBytes( &device, 2 );
208: if( prop) {
209: propTable->setObject("device-id", prop );
210: prop->release();
211: }
212:
213: value = configRead32( space, kIOPCIConfigRevisionID );
214: byte = value & 0xff;
215: prop = OSData::withBytes( &byte, 1 );
216: if( prop) {
217: propTable->setObject("revision-id", prop );
218: prop->release();
219: }
220:
221: // make generic name
222: value >>= 8;
223: name = 0;
224: for( nextName = genericNames;
225: (0 == name) && nextName->name;
226: nextName++ ) {
227: if( (value & nextName->mask) == nextName->classCode)
228: name = nextName->name;
229: }
230:
231: // start compatible list
232: nextCompat = compatBuf;
233: sprintf( nextCompat, "pci%x,%x", vendor, device);
234: nameStr = nextCompat;
235:
236: value = configRead32( space, kIOPCIConfigSubSystemVendorID );
237: if( value) {
238: vendor = value;
239: device = value >> 16;
240:
241: prop = OSData::withBytes( &vendor, 2 );
242: if( prop) {
243: propTable->setObject("subsystem-vendor-id", prop );
244: prop->release();
245: }
246: prop = OSData::withBytes( &device, 2 );
247: if( prop) {
248: propTable->setObject("subsystem-id", prop );
249: prop->release();
250: }
251:
252: nextCompat += strlen( nextCompat ) + 1;
253: sprintf( nextCompat, "pci%x,%x", vendor, device);
254: nameStr = nextCompat;
255: }
256:
257: nextCompat += strlen( nextCompat ) + 1;
258: prop = OSData::withBytes( compatBuf, nextCompat - compatBuf);
259: if( prop) {
260: propTable->setObject( "compatible", prop );
261: prop->release();
262: }
263:
264: if( 0 == name)
265: name = nameStr;
266:
267: nameProp = OSSymbol::withCString( name );
268: if( nameProp) {
269: propTable->setObject( gIONameKey, (OSSymbol *) nameProp);
270: nameProp->release();
271: }
272: }
273:
274: if( compatBuf)
275: IOFree( compatBuf, 256 );
276:
277: return( propTable );
278: }
279:
280: IOPCIDevice * IOPCIBridge::createNub( OSDictionary * from )
281: {
282: return( new IOPCIDevice );
283: }
284:
285: bool IOPCIBridge::initializeNub( IOPCIDevice * nub,
286: OSDictionary * from )
287: {
288: spaceFromProperties( from, &nub->space);
289: nub->parent = this;
290: if( ioDeviceMemory())
291: nub->ioMap = ioDeviceMemory()->map();
292:
293: return( true );
294: }
295:
296: bool IOPCIBridge::publishNub( IOPCIDevice * nub, UInt32 /* index */ )
297: {
298: char location[ 24 ];
299: bool ok;
300:
301: if( nub) {
302: if( nub->space.s.functionNum)
303: sprintf( location, "%X,%X", nub->space.s.deviceNum,
304: nub->space.s.functionNum );
305: else
306: sprintf( location, "%X", nub->space.s.deviceNum );
307: nub->setLocation( location );
308: IODTFindSlotName( nub, nub->space.s.deviceNum );
309:
310: ok = nub->attach( this );
311: if( ok)
312: nub->registerService();
313: } else
314: ok = false;
315:
316: return( ok );
317: }
318:
319: void IOPCIBridge::publishNubs( OSIterator * kids, UInt32 index )
320: {
321: IORegistryEntry * found;
322: IOPCIDevice * nub;
323: OSDictionary * propTable;
324:
325: if( kids) {
326: kids->reset();
327: while( (found = (IORegistryEntry *) kids->getNextObject())) {
328:
329: propTable = found->getPropertyTable();
330: nub = createNub( propTable );
331: if( !nub)
332: continue;
333: if( !initializeNub( nub, propTable))
334: continue;
335: if( !nub->init( found, gIODTPlane))
336: continue;
337:
338: publishNub( nub, index++ );
339:
340: if( 1 & gIOPCIDebug)
341: IOLog("%08lx = 0:%08lx 4:%08lx ", nub->space.bits,
342: nub->configRead32(kIOPCIConfigVendorID),
343: nub->configRead32(kIOPCIConfigCommand) );
344:
345: }
346: }
347: }
348:
349: UInt8 IOPCIBridge::firstBusNum( void )
350: {
351: return( 0 );
352: }
353:
354: UInt8 IOPCIBridge::lastBusNum( void )
355: {
356: return( 255 );
357: }
358:
359: void IOPCIBridge::probeBus( IOService * provider, UInt8 busNum )
360: {
361: IORegistryEntry * regEntry;
362: OSDictionary * propTable;
363: IOPCIDevice * nub = 0;
364: IOPCIAddressSpace space;
365: UInt32 vendor;
366: UInt8 scanDevice, scanFunction, lastFunction;
367: OSIterator * kidsIter;
368: UInt32 index = 0;
369:
370: IODTSetResolving( provider, PCICompare, nvLocation );
371:
372: if( 2 & gIOPCIDebug)
373: kidsIter = 0;
374: else
375: kidsIter = provider->getChildIterator( gIODTPlane );
376:
377: space.bits = 0;
378: space.s.busNum = busNum;
379:
380: for( scanDevice = 0; scanDevice <= 31; scanDevice++ ) {
381:
382: lastFunction = 0;
383: for( scanFunction = 0; scanFunction <= lastFunction; scanFunction++ ) {
384:
385: space.s.deviceNum = scanDevice;
386: space.s.functionNum = scanFunction;
387:
388: if( (regEntry = findMatching( kidsIter, space ))) {
389:
390:
391: } else {
392: /* probe - should guard exceptions */
393: #ifdef __ppc__
394: // DEC bridge really needs safe probe
395: continue;
396: #endif
397: vendor = configRead32( space, kIOPCIConfigVendorID );
398: vendor &= 0x0000ffff;
399: if( (0 == vendor) || (0xffff == vendor))
400: continue;
401:
402: // look in function 0 for multi function flag
403: if( (0 == scanFunction)
404: && (0x00800000 & configRead32( space,
405: kIOPCIConfigCacheLineSize )))
406: lastFunction = 7;
407:
408: propTable = constructProperties( space );
409: if( propTable
410: && (nub = createNub( propTable))
411: && (initializeNub( nub, propTable))
412: && nub->init( propTable )) {
413: #ifdef __I386__
414: setupIntelPIC(nub);
415: #endif
416: publishNub( nub, index++);
417: }
418: }
419: }
420: }
421:
422: if( kidsIter) {
423: publishNubs( kidsIter, index );
424: kidsIter->release();
425: }
426: }
427:
428: bool IOPCIBridge::addBridgeMemoryRange( IOPhysicalAddress start,
429: IOPhysicalLength length, bool host )
430: {
431: IORangeAllocator * platformRanges;
432: bool ok = true;
433:
434: if( host ) {
435:
436: platformRanges = getPlatform()->getPhysicalRangeAllocator();
437: assert( platformRanges );
438:
439: // out of the platform
440: ok = platformRanges->allocateRange( start, length );
441: if( !ok)
442: kprintf("%s: didn't get host range (%08lx:%08lx)\n", getName(),
443: start, length);
444: }
445:
446: // and into the bridge
447: bridgeMemoryRanges->deallocate( start, length );
448:
449: return( ok );
450: }
451:
452: bool IOPCIBridge::addBridgeIORange( IOByteCount start, IOByteCount length )
453: {
454: bool ok = true;
455:
456: // into the bridge
457: bridgeIORanges->deallocate( start, length );
458:
459: return( ok );
460: }
461:
462: bool IOPCIBridge::constructRange( IOPCIAddressSpace * flags,
463: IOPhysicalAddress phys,
464: IOPhysicalLength len,
465: OSArray * array )
466: {
467: IODeviceMemory * range;
468: IODeviceMemory * ioMemory;
469: IORangeAllocator * bridgeRanges;
470: bool ok;
471:
472: if( !array)
473: return( false );
474:
475: if( kIOPCIIOSpace == flags->s.space) {
476:
477: bridgeRanges = bridgeIORanges;
478: if( (ioMemory = ioDeviceMemory())) {
479:
480: phys &= 0x00ffffff; // seems bogus
481: range = IODeviceMemory::withSubRange( ioMemory, phys, len );
482: if( range == 0)
483: /* didn't fit */
484: range = IODeviceMemory::withRange(
485: phys + ioMemory->getPhysicalAddress(), len );
486:
487: } else
488: range = 0;
489:
490: } else {
491: bridgeRanges = bridgeMemoryRanges;
492: range = IODeviceMemory::withRange( phys, len );
493: }
494:
495:
496: if( range) {
497:
498: #ifdef i386
499: // Do nothing for Intel -- I/O ports are not accessed through
500: // memory on this platform, but through I/O port instructions
501: #else
502:
503: ok = bridgeRanges->allocateRange( phys, len );
504: if( !ok)
505: IOLog("%s: bad range %d(%08lx:%08lx)\n", getName(), flags->s.space,
506: phys, len);
507: #endif
508:
509: range->setTag( flags->bits );
510: ok = array->setObject( range );
511: range->release();
512:
513: } else
514: ok = false;
515:
516: return( ok );
517: }
518:
519:
520: IOReturn IOPCIBridge::getDTNubAddressing( IOPCIDevice * regEntry )
521: {
522: OSArray * array;
523: IORegistryEntry * parentEntry;
524: OSData * addressProperty;
525: IOPhysicalAddress phys;
526: IOPhysicalLength len;
527: UInt32 cells = 5;
528: int i, num;
529: UInt32 * reg;
530:
531: addressProperty = (OSData *) regEntry->getProperty( "assigned-addresses" );
532: if( 0 == addressProperty)
533: return( kIOReturnSuccess );
534:
535: parentEntry = regEntry->getParentEntry( gIODTPlane );
536: if( 0 == parentEntry)
537: return( kIOReturnBadArgument );
538:
539: array = OSArray::withCapacity( 1 );
540: if( 0 == array)
541: return( kIOReturnNoMemory );
542:
543: reg = (UInt32 *) addressProperty->getBytesNoCopy();
544: num = addressProperty->getLength() / (4 * cells);
545:
546: for( i = 0; i < num; i++) {
547:
548: if( IODTResolveAddressCell( parentEntry, reg, &phys, &len ))
549:
550: constructRange( (IOPCIAddressSpace *) reg, phys, len, array );
551:
552: reg += cells;
553: }
554:
555: if( array->getCount())
556: regEntry->setProperty( gIODeviceMemoryKey, array);
557:
558: array->release();
559:
560: return( kIOReturnSuccess);
561: }
562:
563: IOReturn IOPCIBridge::getNubAddressing( IOPCIDevice * nub )
564: {
565: OSArray * array;
566: IOPhysicalAddress phys;
567: IOPhysicalLength len;
568: UInt32 save, value;
569: IOPCIAddressSpace reg;
570: UInt8 regNum;
571: bool memEna, ioEna;
572: boolean_t s;
573:
574: value = nub->configRead32( kIOPCIConfigVendorID );
575: if( 0x0003106b == value ) // control doesn't play well
576: return( kIOReturnSuccess );
577:
578: // only header type 0
579: value = nub->configRead32( kIOPCIConfigCacheLineSize );
580: if( value & 0x007f0000)
581: return( kIOReturnSuccess );
582:
583: array = OSArray::withCapacity( 1 );
584: if( 0 == array)
585: return( kIOReturnNoMemory );
586:
587: for( regNum = 0x10; regNum < 0x28; regNum += 4) {
588:
589: // begin scary
590: s = ml_set_interrupts_enabled(FALSE);
591: memEna = nub->setMemoryEnable( false );
592: ioEna = nub->setIOEnable( false );
593:
594: save = nub->configRead32( regNum );
595:
596: nub->configWrite32( regNum, 0xffffffff );
597: value = nub->configRead32( regNum );
598:
599: nub->configWrite32( regNum, save );
600: nub->setMemoryEnable( memEna );
601: nub->setIOEnable( ioEna );
602: ml_set_interrupts_enabled( s );
603: // end scary
604:
605: if( 0 == value)
606: continue;
607:
608: reg = nub->space;
609: reg.s.registerNum = regNum;
610:
611: if( value & 1) {
612: reg.s.space = kIOPCIIOSpace;
613:
614: } else {
615: reg.s.prefetch = (0 != (value & 8));
616:
617: switch( value & 6) {
618: case 2: /* below 1Mb */
619: reg.s.t = 1;
620: /* fall thru */
621: case 0: /* 32-bit mem */
622: case 6: /* reserved */
623: reg.s.space = kIOPCI32BitMemorySpace;
624: break;
625:
626: case 4: /* 64-bit mem */
627: reg.s.space = kIOPCI64BitMemorySpace;
628: regNum += 4;
629: break;
630: }
631: }
632:
633: value &= 0xfffffff0;
634: phys = IOPhysical32( 0, save & value );
635: len = IOPhysical32( 0, -value );
636:
637: if( 1 & gIOPCIDebug)
638: IOLog("Space %08lx : %08lx, %08lx\n", reg.bits, phys, len);
639:
640: constructRange( ®, phys, len, array );
641: }
642:
643: if( array->getCount())
644: nub->setProperty( gIODeviceMemoryKey, array);
645:
646: array->release();
647:
648: return( kIOReturnSuccess);
649: }
650:
651: bool IOPCIBridge::isDTNub( IOPCIDevice * nub )
652: {
653: return( 0 != nub->getParentEntry( gIODTPlane ));
654: }
655:
656: IOReturn IOPCIBridge::getNubResources( IOService * service )
657: {
658: IOPCIDevice * nub = (IOPCIDevice *) service;
659: IOReturn err;
660:
661: if( service->getDeviceMemory())
662: return( kIOReturnSuccess );
663:
664: if( isDTNub( nub))
665: err = getDTNubAddressing( nub );
666: else
667: err = getNubAddressing( nub );
668:
669: return( err);
670: }
671:
672: bool IOPCIBridge::matchKeys( IOPCIDevice * nub, const char * keys,
673: UInt32 defaultMask, UInt8 regNum )
674: {
675: const char * next;
676: UInt32 mask, value, reg;
677: bool found = false;
678:
679: do {
680: value = strtoul( keys, (char **) &next, 16);
681: if( next == keys)
682: break;
683:
684: while( (*next) == ' ')
685: next++;
686:
687: if( (*next) == '&')
688: mask = strtoul( next + 1, (char **) &next, 16);
689: else
690: mask = defaultMask;
691:
692: reg = nub->configRead32( regNum );
693: found = (value == (reg & mask));
694: keys = next;
695:
696: } while( !found);
697:
698: return( found );
699: }
700:
701:
702: bool IOPCIBridge::pciMatchNub( IOPCIDevice * nub,
703: OSDictionary * table )
704: {
705: OSString * prop;
706: const char * keys;
707: bool match = true;
708: UInt8 regNum;
709: int i;
710:
711: struct IOPCIMatchingKeys {
712: const char * propName;
713: UInt8 regs[ 4 ];
714: UInt32 defaultMask;
715: };
716: IOPCIMatchingKeys * look;
717: static IOPCIMatchingKeys matching[] = {
718: { kIOPCIMatchKey,
719: { 0x00 + 1, 0x2c }, 0xffffffff },
720: { kIOPCIPrimaryMatchKey,
721: { 0x00 }, 0xffffffff },
722: { kIOPCISecondaryMatchKey,
723: { 0x2c }, 0xffffffff },
724: { kIOPCIClassMatchKey,
725: { 0x08 }, 0xffffff00 }};
726:
727: for( look = matching;
728: (match && (look < (&matching[4])));
729: look++ ) {
730:
731: prop = (OSString *) table->getObject( look->propName );
732: if( prop) {
733: keys = prop->getCStringNoCopy();
734: match = false;
735: for( i = 0;
736: ((false == match) && (i < 4));
737: i++ ) {
738:
739: regNum = look->regs[ i ];
740: match = matchKeys( nub, keys,
741: look->defaultMask, regNum & 0xfc );
742: if( 0 == (1 & regNum))
743: break;
744: }
745: }
746: }
747:
748: return( match );
749: }
750:
751: bool IOPCIBridge::matchNubWithPropertyTable( IOService * nub,
752: OSDictionary * table )
753: {
754: bool matches;
755:
756: matches = pciMatchNub( (IOPCIDevice *) nub, table);
757:
758: return( matches );
759: }
760:
761: bool IOPCIBridge::compareNubName( const IOService * nub,
762: OSString * name, OSString ** matched ) const
763: {
764: return( IODTCompareNubName( nub, name, matched ));
765: }
766:
767: UInt32 IOPCIBridge::findPCICapability( IOPCIAddressSpace space,
768: UInt8 capabilityID )
769: {
770: UInt32 data = 0;
771:
772: if( 0 == ((kIOPCIStatusCapabilities << 16)
773: & (configRead32( space, kIOPCIConfigCommand))))
774: return( 0 );
775:
776: data = configRead32( space, kIOPCIConfigCapabilitiesPtr );
777: while( data) {
778: data = configRead32( space, data );
779: if( capabilityID == (data & 0xff))
780: break;
781: data = (data >> 8) & 0xfc;
782: }
783:
784: return( data );
785: }
786:
787: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
788:
789: IOReturn IOPCIBridge::createAGPSpace( IOPCIAddressSpace master,
790: IOOptionBits options,
791: IOPhysicalAddress * address,
792: IOPhysicalLength * length )
793: {
794: return( kIOReturnUnsupported );
795: }
796:
797: IOReturn IOPCIBridge::destroyAGPSpace( IOPCIAddressSpace master )
798: {
799: return( kIOReturnUnsupported );
800: }
801:
802: IORangeAllocator * IOPCIBridge::getAGPRangeAllocator( IOPCIAddressSpace master )
803: {
804: return( 0 );
805: }
806:
807: IOOptionBits IOPCIBridge::getAGPStatus( IOPCIAddressSpace master,
808: IOOptionBits options = 0 )
809: {
810: return( 0 );
811: }
812:
813: IOReturn IOPCIBridge::commitAGPMemory( IOPCIAddressSpace master,
814: IOMemoryDescriptor * memory,
815: IOByteCount agpOffset,
816: IOOptionBits options = 0 )
817: {
818: return( kIOReturnUnsupported );
819: }
820:
821: IOReturn IOPCIBridge::releaseAGPMemory( IOPCIAddressSpace master,
822: IOMemoryDescriptor * memory,
823: IOByteCount agpOffset )
824: {
825: return( kIOReturnUnsupported );
826: }
827:
828: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
829:
830: #undef super
831: #define super IOPCIBridge
832:
833: OSDefineMetaClassAndStructors(IOPCI2PCIBridge, IOPCIBridge)
834:
835: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
836:
837: IOService * IOPCI2PCIBridge::probe( IOService * provider,
838: SInt32 * score )
839: {
840:
841: if( 0 == (bridgeDevice = OSDynamicCast( IOPCIDevice, provider)))
842: return( 0 );
843:
844: *score -= 100;
845:
846: return( this );
847: }
848:
849: enum {
850: kPCI2PCIBusNumbers = 0x18,
851: kPCI2PCIIORange = 0x1c,
852: kPCI2PCIMemoryRange = 0x20,
853: kPCI2PCIPrefetchMemoryRange = 0x24,
854: kPCI2PCIUpperIORange = 0x30
855: };
856:
857: bool IOPCI2PCIBridge::configure( IOService * provider )
858: {
859: UInt32 end;
860: UInt32 start;
861: bool ok;
862:
863: end = bridgeDevice->configRead32( kPCI2PCIMemoryRange );
864: if( end ) {
865: start = (end & 0xfff0) << 16;
866: end |= 0x000fffff;
867: ok = addBridgeMemoryRange( start, end - start + 1, false );
868: }
869:
870: end = bridgeDevice->configRead32( kPCI2PCIPrefetchMemoryRange );
871: if( end) {
872: start = (end & 0xfff0) << 16;
873: end |= 0x000fffff;
874: ok = addBridgeMemoryRange( start, end - start + 1, false );
875: }
876:
877: end = bridgeDevice->configRead32( kPCI2PCIIORange );
878: if( end) {
879: start = (end & 0xf0) << 8;
880: end = (end & 0xffff) | 0xfff;
881: ok = addBridgeIORange( start, end - start + 1 );
882: }
883:
884: return( super::configure( provider ));
885: }
886:
887: UInt8 IOPCI2PCIBridge::firstBusNum( void )
888: {
889: UInt32 value;
890:
891: value = bridgeDevice->configRead32( kPCI2PCIBusNumbers );
892:
893: return( (value >> 8) & 0xff );
894: }
895:
896: UInt8 IOPCI2PCIBridge::lastBusNum( void )
897: {
898: UInt32 value;
899:
900: value = bridgeDevice->configRead32( kPCI2PCIBusNumbers );
901:
902: return( (value >> 16) & 0xff );
903: }
904:
905: IOPCIAddressSpace IOPCI2PCIBridge::getBridgeSpace( void )
906: {
907: return( bridgeDevice->space );
908: }
909:
910: UInt32 IOPCI2PCIBridge::configRead32( IOPCIAddressSpace space,
911: UInt8 offset )
912: {
913: return( bridgeDevice->configRead32( space, offset ));
914: }
915:
916: void IOPCI2PCIBridge::configWrite32( IOPCIAddressSpace space,
917: UInt8 offset, UInt32 data )
918: {
919: bridgeDevice->configWrite32( space, offset, data );
920: }
921:
922: IODeviceMemory * IOPCI2PCIBridge::ioDeviceMemory( void )
923: {
924: return( bridgeDevice->ioDeviceMemory());
925: }
926:
927: bool IOPCI2PCIBridge::publishNub( IOPCIDevice * nub, UInt32 index )
928: {
929: if( nub)
930: nub->setProperty( "IOChildIndex" , index, 32 );
931:
932: return( super::publishNub( nub, index ) );
933: }
934:
935: #ifdef __I386__
936:
937: static void setupIntelPIC(IOPCIDevice *nub)
938: {
939: OSDictionary *propTable;
940: OSArray *controller;
941: OSArray *specifier;
942: OSData *tmpData;
943: long irq;
944: extern OSSymbol *gIntelPICName;
945:
946: propTable = nub->getPropertyTable();
947: if (!propTable) return;
948:
949: do {
950: // Create the interrupt specifer array.
951: specifier = OSArray::withCapacity(1);
952: if ( !specifier )
953: break;
954: irq = nub->configRead32(kIOPCIConfigInterruptLine) & 0xf;
955: tmpData = OSData::withBytes(&irq, sizeof(irq));
956: if ( tmpData ) {
957: specifier->setObject(tmpData);
958: tmpData->release();
959: }
960:
961: controller = OSArray::withCapacity(1);
962: if ( controller ) {
963: controller->setObject(gIntelPICName);
964:
965: // Put the two arrays into the property table.
966: propTable->setObject(gIOInterruptControllersKey, controller);
967: controller->release();
968: }
969: propTable->setObject(gIOInterruptSpecifiersKey, specifier);
970: specifier->release();
971: } while( false );
972: }
973:
974: #endif
975:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.