|
|
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: * 23 Nov 98 sdouglas created from objc version.
27: * 05 Nov 99 sdouglas added UniNorth AGP based on UniNorthAGPDriver.c
* by Fernando Urbina, Kent Miller.
28: *
29: */
30:
31: #include <IOKit/system.h>
32: #include <ppc/proc_reg.h>
33:
34: #include <libkern/c++/OSContainers.h>
35: #include <libkern/OSByteOrder.h>
36:
37: #include <IOKit/IODeviceMemory.h>
38: #include <IOKit/IORangeAllocator.h>
39: #include <IOKit/IODeviceTreeSupport.h>
40: #include <IOKit/IOPlatformExpert.h>
41: #include <IOKit/IOLib.h>
42: #include <IOKit/assert.h>
43:
44: #include "AppleMacRiscPCI.h"
45:
46: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47:
48: #define super IOPCIBridge
49:
50: OSDefineMetaClassAndStructors(AppleMacRiscPCI, IOPCIBridge)
51:
52: OSDefineMetaClassAndStructors(AppleMacRiscVCI, AppleMacRiscPCI)
53:
54: OSDefineMetaClassAndStructors(AppleMacRiscAGP, AppleMacRiscPCI)
55:
56: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
57:
58: bool AppleMacRiscPCI::start( IOService * provider )
59: {
60: IOPCIPhysicalAddress ioAddrCell;
61: IOPhysicalAddress ioPhys;
62: IOPhysicalAddress ioPhysLen;
63: OSArray * array;
64: IODeviceMemory::InitElement rangeList[ 3 ];
65: IORegistryEntry * bridge;
66: OSData * busProp;
67:
68: if( !IODTMatchNubWithKeys(provider, "('pci', 'vci')"))
69: return( false);
70:
71: if( IODTMatchNubWithKeys(provider, "'uni-north'"))
72: configDataOffsetMask = 0x7;
73: else
74: configDataOffsetMask = 0x3;
75:
76: if( 0 == (lock = IOSimpleLockAlloc()))
77: return( false );
78:
79: ioAddrCell.physHi.bits = 0;
80: ioAddrCell.physHi.s.space = kIOPCIIOSpace;
81: ioAddrCell.physMid = 0;
82: ioAddrCell.physLo = 0;
83: ioAddrCell.lengthHi = 0;
84: ioAddrCell.lengthLo = 0x10000;
85:
86: bridge = provider;
87:
88: if( ! IODTResolveAddressCell( bridge, (UInt32 *) &ioAddrCell,
89: &ioPhys, &ioPhysLen) ) {
90:
91: IOLog("%s: couldn't find my base\n", getName());
92: return( false);
93: }
94:
95: /* define more explicit ranges */
96:
97: rangeList[0].start = ioPhys;
98: rangeList[0].length = ioPhysLen;
99: rangeList[1].start = ioPhys + 0x00800000;
100: rangeList[1].length = 4;
101: rangeList[2].start = ioPhys + 0x00c00000;
102: rangeList[2].length = 4;
103:
104: IORangeAllocator * platformRanges;
105: platformRanges = IOService::getPlatform()->getPhysicalRangeAllocator();
106: assert( platformRanges );
107: platformRanges->allocateRange( ioPhys, 0x01000000 );
108:
109: array = IODeviceMemory::arrayFromList( rangeList, 3 );
110: if( !array)
111: return( false);
112:
113: provider->setDeviceMemory( array );
114: array->release();
115: ioMemory = (IODeviceMemory *) array->getObject( 0 );
116:
117: /* map registers */
118:
119: if( (configAddrMap = provider->mapDeviceMemoryWithIndex( 1 )))
120: configAddr = (volatile UInt32 *) configAddrMap->getVirtualAddress();
121: if( (configDataMap = provider->mapDeviceMemoryWithIndex( 2 )))
122: configData = (volatile UInt32 *) configDataMap->getVirtualAddress();
123:
124: if( !configAddr || !configData)
125: return( false);
126:
127: busProp = (OSData *) bridge->getProperty("bus-range");
128: if( busProp)
129: primaryBus = *((UInt32 *) busProp->getBytesNoCopy());
130:
131: return( super::start( provider));
132: }
133:
134: bool AppleMacRiscPCI::configure( IOService * provider )
135: {
136: UInt32 addressSelects;
137: UInt32 index;
138: bool ok;
139:
140: addressSelects = configRead32( getBridgeSpace(), kMacRISCAddressSelect );
141:
142: coarseAddressMask = addressSelects >> 16;
143: fineAddressMask = addressSelects & 0xffff;
144:
145: for( index = 0; index < 15; index++ ) {
146: if( coarseAddressMask & (1 << index)) {
147: ok = addBridgeMemoryRange( index << 28, 0x10000000, true );
148: }
149: }
150:
151: // if( coarseAddressMask & (1 << 15)) // F segment
152: for( index = 0; index < 15; index++ ) {
153: if( fineAddressMask & (1 << index)) {
154: ok = addBridgeMemoryRange( (0xf0 | index) << 24,
155: 0x01000000, true );
156: }
157: }
158:
159: ok = addBridgeIORange( 0, 0x10000 );
160:
161: return( super::configure( provider));
162: }
163:
164: void AppleMacRiscPCI::free()
165: {
166: if( configAddrMap)
167: configAddrMap->release();
168: if( configDataMap)
169: configDataMap->release();
170: if( lock)
171: IOSimpleLockFree( lock);
172:
173: super::free();
174: }
175:
176: IODeviceMemory * AppleMacRiscPCI::ioDeviceMemory( void )
177: {
178: return( ioMemory);
179: }
180:
181: IODeviceMemory * AppleMacRiscVCI::ioDeviceMemory( void )
182: {
183: return( 0 );
184: }
185:
186: bool AppleMacRiscVCI::configure( IOService * provider )
187: {
188: addBridgeMemoryRange( 0x90000000, 0x10000000, true );
189:
190: return( AppleMacRiscPCI::configure( provider));
191: }
192:
193: UInt8 AppleMacRiscPCI::firstBusNum( void )
194: {
195: return( primaryBus );
196: }
197:
198: UInt8 AppleMacRiscPCI::lastBusNum( void )
199: {
200: return( firstBusNum() );
201: }
202:
203: IOPCIAddressSpace AppleMacRiscPCI::getBridgeSpace( void )
204: {
205: IOPCIAddressSpace space;
206:
207: space.bits = 0;
208: space.s.busNum = primaryBus;
209: space.s.deviceNum = kBridgeSelfDevice;
210:
211: return( space );
212: }
213:
214: inline bool AppleMacRiscPCI::setConfigSpace( IOPCIAddressSpace space,
215: UInt8 offset )
216: {
217: UInt32 addrCycle;
218:
219: if( space.s.busNum == primaryBus) {
220:
221: if( space.s.deviceNum < kBridgeSelfDevice)
222: return( false);
223:
224: // primary config cycle
225: addrCycle = ( (1 << space.s.deviceNum)
226: | (space.s.functionNum << 8)
227: | offset );
228:
229: } else {
230: // pass thru config cycle
231: addrCycle = ( (space.bits)
232: | offset
233: | 1 );
234: }
235:
236: do {
237: OSWriteSwapInt32( configAddr, 0, addrCycle);
238: eieio();
239: } while( addrCycle != OSReadSwapInt32( configAddr, 0 ));
240: eieio();
241:
242: return( true );
243: }
244:
245:
246: UInt32 AppleMacRiscPCI::configRead32( IOPCIAddressSpace space,
247: UInt8 offset )
248: {
249: UInt32 data;
250: IOInterruptState ints;
251:
252: ints = IOSimpleLockLockDisableInterrupt( lock );
253:
254: if( setConfigSpace( space, offset )) {
255:
256: data = OSReadSwapInt32( configData, offset & configDataOffsetMask );
257: eieio();
258:
259: } else
260: data = 0xffffffff;
261:
262: IOSimpleLockUnlockEnableInterrupt( lock, ints );
263:
264: return( data );
265: }
266:
267: void AppleMacRiscPCI::configWrite32( IOPCIAddressSpace space,
268: UInt8 offset, UInt32 data )
269: {
270: IOInterruptState ints;
271:
272: ints = IOSimpleLockLockDisableInterrupt( lock );
273:
274: if( setConfigSpace( space, offset )) {
275:
276: OSWriteSwapInt32( configData, offset & configDataOffsetMask, data );
277: eieio();
278: /* read to sync (?) */
279: (void) OSReadSwapInt32( configData, offset & configDataOffsetMask );
280: eieio();
281: sync();
282: isync();
283: }
284:
285: IOSimpleLockUnlockEnableInterrupt( lock, ints );
286: }
287:
288: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
289:
290: #undef super
291: #define super AppleMacRiscPCI
292:
293: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
294:
295: bool AppleMacRiscAGP::configure( IOService * provider )
296: {
297: if( !findPCICapability( getBridgeSpace(), kIOPCIAGPCapability))
298: return( false );
299:
300: return( super::configure( provider));
301: }
302:
303: IOPCIDevice * AppleMacRiscAGP::createNub( OSDictionary * from )
304: {
305: IOPCIDevice * nub;
306: IOPCIAddressSpace space;
307: bool isAGP;
308:
309: spaceFromProperties( from, &space);
310:
311: isAGP = ( (space.s.deviceNum != getBridgeSpace().s.deviceNum)
312: && findPCICapability( space, kIOPCIAGPCapability));
313:
314: if( isAGP)
315: nub = new IOAGPDevice;
316: else
317: nub = super::createNub( from );
318:
319: return( nub );
320: }
321:
322: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
323:
324: IOReturn AppleMacRiscAGP::createAGPSpace( IOPCIAddressSpace master,
325: IOOptionBits options,
326: IOPhysicalAddress * address,
327: IOPhysicalLength * length )
328: {
329: IOReturn err;
330: IORangeAllocator * platformRanges;
331: IOPCIAddressSpace target = getBridgeSpace();
332: IOPhysicalLength agpLength;
333: IOPhysicalAddress gartPhys;
334:
335: enum { agpSpacePerPage = 4 * 1024 * 1024 };
336: enum { agpBytesPerGartByte = 1024 };
337: enum { alignLen = 4 * 1024 * 1024 - 1 };
338:
339: destroyAGPSpace( master );
340:
341: agpLength = *length;
342: if( !agpLength)
343: agpLength = 32 * 1024 * 1024;
344:
345: agpLength = (agpLength + alignLen) & ~alignLen;
346:
347: err = kIOReturnVMError;
348: do {
349:
350: gartLength = agpLength / agpBytesPerGartByte;
351: gartArray = (volatile UInt32 *) IOMallocContiguous(
352: gartLength, 4096, &gartPhys );
353: if( !gartArray)
354: continue;
355: //IOMapPages( kernel_map, gartArray, gartPhys, gartLength, kIOMapInhibitCache );
356: bzero( (void *) gartArray, gartLength);
357:
358: platformRanges = getPlatform()->getPhysicalRangeAllocator();
359:
360: for( agpBaseIndex = 0xf; agpBaseIndex > 0; agpBaseIndex--) {
361: systemBase = agpBaseIndex * 0x10000000;
362: if( platformRanges->allocateRange( systemBase, agpLength )) {
363: systemLength = agpLength;
364: break;
365: }
366: }
367: if( !systemLength)
368: continue;
369:
370: agpRange = IORangeAllocator::withRange( agpLength, 4096 );
371: if( !agpRange)
372: continue;
373:
374: *address = systemBase;
375: *length = systemLength;
376: #if 0
377: coarseAddressMask |= (1 << agpBaseIndex);
378: configWrite32( target, kMacRISCAddressSelect,
379: (coarseAddressMask << 16) | fineAddressMask );
380: #endif
381: configWrite32( target, kUniNAGP_BASE, agpBaseIndex << 28 );
382:
383: assert( 0 == (gartPhys & 0xfff));
384: configWrite32( target, kUniNGART_BASE,
385: gartPhys | (agpLength / agpSpacePerPage));
386:
387: err = kIOReturnSuccess;
388:
389: } while( false );
390:
391: if( kIOReturnSuccess == err)
392: setAGPEnable( master, true, 1 );
393: else
394: destroyAGPSpace( master );
395:
396: return( err );
397: }
398:
399: IOReturn AppleMacRiscAGP::destroyAGPSpace( IOPCIAddressSpace master )
400: {
401: IORangeAllocator * platformRanges;
402:
403: setAGPEnable( master, false, 0 );
404:
405: if( gartArray) {
406: IOFreeContiguous( (void *) gartArray, gartLength);
407: gartArray = 0;
408: }
409: if( agpRange) {
410: agpRange->release();
411: agpRange = 0;
412: }
413: if( systemLength) {
414: platformRanges = getPlatform()->getPhysicalRangeAllocator();
415: platformRanges->deallocate( systemBase, systemLength);
416: systemLength = 0;
417: }
418:
419: return( kIOReturnSuccess );
420: }
421:
422: IORangeAllocator * AppleMacRiscAGP::getAGPRangeAllocator(
423: IOPCIAddressSpace master )
424: {
425: // if( agpRange) agpRange->retain();
426: return( agpRange );
427: }
428:
429: IOOptionBits AppleMacRiscAGP::getAGPStatus( IOPCIAddressSpace master,
430: IOOptionBits options = 0 )
431: {
432: return( configRead32( getBridgeSpace(), kUniNINTERNAL_STATUS ) );
433: }
434:
435: IOReturn AppleMacRiscAGP::commitAGPMemory( IOPCIAddressSpace master,
436: IOMemoryDescriptor * memory,
437: IOByteCount agpOffset,
438: IOOptionBits options = 0 )
439: {
440: IOPCIAddressSpace target = getBridgeSpace();
441: IOReturn err = kIOReturnSuccess;
442: UInt32 offset = 0;
443: IOPhysicalAddress physAddr;
444: IOByteCount len;
445:
446: // ok = agpRange->allocate( memory->getLength(), &agpOffset );
447:
448: assert( agpOffset < systemLength );
449: agpOffset /= (page_size / 4);
450: while( (physAddr = memory->getPhysicalSegment( offset, &len ))) {
451:
452: offset += len;
453: len = (len + 0xfff) & ~0xfff;
454: while( len > 0) {
455: OSWriteLittleInt32( gartArray, agpOffset,
456: ((physAddr & ~0xfff) | 1));
457: agpOffset += 4;
458: physAddr += page_size;
459: len -= page_size;
460: }
461: }
462: flush_dcache( (vm_offset_t) gartArray, gartLength, false);
463: sync();
464: isync();
465: #if 1
466: configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV );
467: configWrite32( target, kUniNGART_CTRL, kGART_EN );
468: configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_2xRESET);
469: configWrite32( target, kUniNGART_CTRL, kGART_EN );
470: #endif
471:
472: return( err );
473: }
474:
475: IOReturn AppleMacRiscAGP::releaseAGPMemory( IOPCIAddressSpace master,
476: IOMemoryDescriptor * memory,
477: IOByteCount agpOffset )
478: {
479: IOPCIAddressSpace target = getBridgeSpace();
480: IOReturn err = kIOReturnSuccess;
481: IOByteCount length;
482:
483: if( !memory)
484: return( kIOReturnBadArgument );
485:
486: length = memory->getLength();
487:
488: if( (agpOffset + length) >= systemLength)
489: return( kIOReturnBadArgument );
490:
491: // agpRange->deallocate( agpOffset, length );
492:
493: length = (length + 0xfff) & ~0xfff;
494: agpOffset /= page_size;
495: while( length > 0) {
496: gartArray[ agpOffset++ ] = 0;
497: length -= page_size;
498: }
499: flush_dcache( (vm_offset_t) gartArray, gartLength, false);
500: sync();
501: isync();
502:
503: configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV );
504: configWrite32( target, kUniNGART_CTRL, kGART_EN );
505: configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_2xRESET);
506: configWrite32( target, kUniNGART_CTRL, kGART_EN );
507:
508: return( err );
509: }
510:
511: IOReturn AppleMacRiscAGP::setAGPEnable( IOPCIAddressSpace master,
512: bool enable, IOOptionBits options )
513: {
514: IOReturn err = kIOReturnSuccess;
515: IOPCIAddressSpace target = getBridgeSpace();
516: UInt32 command;
517: UInt32 targetStatus, masterStatus;
518:
519: if( enable) {
520:
521: targetStatus = configRead32( target, kIOPCIConfigAGPTargetStatus );
522: masterStatus = configRead32( master, kIOPCIConfigAGPMasterStatus );
523:
524: command = kIOAGPSideBandAddresssing
525: | kIOAGP4xDataRate | kIOAGP2xDataRate | kIOAGP1xDataRate;
526: command &= targetStatus;
527: command &= masterStatus;
528:
529: if( command & kIOAGP4xDataRate)
530: command &= ~(kIOAGP2xDataRate | kIOAGP1xDataRate);
531: else if( command & kIOAGP2xDataRate)
532: command &= ~(kIOAGP1xDataRate);
533:
534: command |= kIOAGPEnable;
535:
536: if( targetStatus > masterStatus)
537: targetStatus = masterStatus;
538: command |= (targetStatus & kIOAGPRequestQueueMask);
539:
540: #if 1
541: configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV );
542: configWrite32( target, kUniNGART_CTRL, kGART_EN );
543: configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_2xRESET);
544: configWrite32( target, kUniNGART_CTRL, kGART_EN );
545: #endif
546: do {
547: configWrite32( target, kIOPCIConfigAGPTargetCommand, command );
548: } while( (command & kIOAGPEnable) !=
549: (kIOAGPEnable & configRead32( target, kIOPCIConfigAGPTargetCommand)));
550:
551: do {
552: configWrite32( master, kIOPCIConfigAGPMasterCommand, command );
553: } while( (command & kIOAGPEnable) !=
554: (kIOAGPEnable & configRead32( master, kIOPCIConfigAGPMasterCommand)));
555:
556: configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV );
557: configWrite32( target, kUniNGART_CTRL, kGART_EN );
558: configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_2xRESET);
559: configWrite32( target, kUniNGART_CTRL, kGART_EN );
560:
561: } else {
562:
563: configWrite32( master, kIOPCIConfigAGPMasterCommand, 0 );
564: configWrite32( target, kIOPCIConfigAGPTargetCommand, 0 );
565: configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV );
566: configWrite32( target, kUniNGART_CTRL, 0 );
567: configWrite32( target, kUniNGART_CTRL, kGART_2xRESET);
568: configWrite32( target, kUniNGART_CTRL, 0 );
569: }
570:
571: return( err );
572: }
573:
574: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.