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@
27 #include "AppleUltra66ATA.h"
30 #define super IOATAStandardDriver
32 extern pmap_t kernel_pmap
;
34 OSDefineMetaClassAndStructors( AppleUltra66ATA
, IOATAStandardDriver
)
36 static inline int rnddiv( int x
, int y
)
41 return ( (x
/ y
) + (( x
% y
) ? 1 : 0) );
49 bool AppleUltra66ATA::configure( IOService
*forProvider
, ATAControllerInfo
*controllerInfo
)
51 provider
= forProvider
;
53 if ( identifyController() == false )
58 ioMapATA
= provider
->mapDeviceMemoryWithIndex(0);
59 if ( ioMapATA
== NULL
) return false;
60 ioBaseATA
= (volatile UInt32
*)ioMapATA
->getVirtualAddress();
62 ioMapDMA
= provider
->mapDeviceMemoryWithIndex(1);
63 if ( ioMapDMA
== NULL
) return false;
64 ioBaseDMA
= (volatile IODBDMAChannelRegisters
*)ioMapDMA
->getVirtualAddress();
66 dmaDescriptors
= (IODBDMADescriptor
*)kalloc(page_size
);
67 if ( dmaDescriptors
== 0 )
72 dmaDescriptorsPhys
= (UInt32
) pmap_extract(kernel_pmap
, (vm_offset_t
) dmaDescriptors
);
74 if ( (UInt32
)dmaDescriptors
& (page_size
- 1) )
76 IOLog("AppleUltra66ATA::%s() - DMA Descriptor memory not page aligned!!", __FUNCTION__
);
80 bzero( dmaDescriptors
, page_size
);
82 numDescriptors
= page_size
/sizeof(IODBDMADescriptor
);
84 dmaMemoryCursor
= IOBigMemoryCursor::withSpecification( 64*1024-2, 0xffffffff );
85 if ( dmaMemoryCursor
== NULL
)
90 bitBucketAddr
= IOMalloc(32);
91 if ( bitBucketAddr
== 0 )
95 bitBucketAddrPhys
= (UInt32
) pmap_extract(kernel_pmap
, (vm_offset_t
) (((UInt32
)bitBucketAddr
+ 0xf) & ~0x0f));
97 interruptEventSource
= IOInterruptEventSource::interruptEventSource( (OSObject
*) this,
98 (IOInterruptEventAction
) &AppleUltra66ATA::interruptOccurred
,
99 (IOService
*) provider
,
102 if ( interruptEventSource
== NULL
)
107 disableControllerInterrupts();
109 getWorkLoop()->addEventSource( interruptEventSource
);
111 controllerInfo
->maxDevicesSupported
= 2;
112 controllerInfo
->devicePrivateDataSize
= 0;
113 controllerInfo
->commandPrivateDataSize
= 0;
114 controllerInfo
->disableCancelCommands
= false;
124 bool AppleUltra66ATA::identifyController()
126 OSData
*compatibleEntry
, *modelEntry
;
130 controllerType
= kControllerTypeDBDMAVersion1
;
132 compatibleEntry
= OSDynamicCast( OSData
, provider
->getProperty( "compatible" ) );
133 if ( compatibleEntry
== 0 ) break;
135 if ( compatibleEntry
->isEqualTo( "keylargo-ata", sizeof("keylargo-ata")-1 ) == true )
137 controllerType
= kControllerTypeDBDMAVersion2
;
139 modelEntry
= OSDynamicCast( OSData
, provider
->getProperty("model") );
140 if ( modelEntry
== 0 ) break;
142 if ( modelEntry
->isEqualTo( "ata-4", sizeof("ata-4")-1 ) == true )
144 controllerType
= kControllerTypeUltra66DBDMA
;
157 bool AppleUltra66ATA::calculateTiming( UInt32 deviceNum
, ATATiming
*pTiming
)
161 switch ( controllerType
)
163 case kControllerTypeDBDMAVersion1
:
164 case kControllerTypeDBDMAVersion2
:
165 switch ( pTiming
->timingProtocol
)
168 rc
= calculatePIOTiming( deviceNum
, pTiming
);
172 rc
= calculateDMATiming( deviceNum
, pTiming
);
180 case kControllerTypeUltra66DBDMA
:
181 switch ( pTiming
->timingProtocol
)
184 rc
= calculateUltra66PIOTiming( deviceNum
, pTiming
);
188 rc
= calculateUltra66DMATiming( deviceNum
, pTiming
);
191 case kATATimingUltraDMA66
:
192 rc
= calculateUltra66UDMATiming( deviceNum
, pTiming
);
212 bool AppleUltra66ATA::calculatePIOTiming( UInt32 unitNum
, ATATiming
*pTiming
)
221 * Calc PIO access time >= minDataAccess in SYSCLK increments
223 accessTicks
= rnddiv(pTiming
->minDataAccess
, kATASysClkNS
);
225 * Hardware limits access times to >= 120 ns
227 accessTicks
-= kATAPioAccessBase
;
228 if (accessTicks
< kATAPioAccessMin
)
230 accessTicks
= kATAPioAccessMin
;
232 accessTime
= (accessTicks
+ kATAPioAccessBase
) * kATASysClkNS
;
235 * Calc recovery time in SYSCLK increments based on time remaining in cycle
237 recTime
= pTiming
->minDataCycle
- accessTime
;
238 recTicks
= rnddiv( recTime
, kATASysClkNS
);
240 * Hardware limits recovery time to >= 150ns
242 recTicks
-= kATAPioRecoveryBase
;
243 if ( recTicks
< kATAPioRecoveryMin
)
245 recTicks
= kATAPioRecoveryMin
;
248 cycleTime
= (recTicks
+ kATAPioRecoveryBase
+ accessTicks
+ kATAPioAccessBase
) * kATASysClkNS
;
250 ideTimingWord
[unitNum
] &= ~0x7ff;
251 ideTimingWord
[unitNum
] |= accessTicks
| (recTicks
<< 5);
254 IOLog("AppleUltra66ATA::%s() Unit %1d PIO Requested Timings: Access: %3dns Cycle: %3dns \n\r",
255 __FUNCTION__
, (int)unitNum
, (int)pTiming
->minDataAccess
, (int)pTiming
->minDataCycle
);
256 IOLog("AppleUltra66ATA::%s() PIO Actual Timings: Access: %3dns Cycle: %3dns\n\r",
257 __FUNCTION__
, accessTime
, cycleTime
);
268 bool AppleUltra66ATA::calculateDMATiming( UInt32 unitNum
, ATATiming
*pTiming
)
279 * Calc DMA access time >= minDataAccess in SYSCLK increments
283 * OHare II erata - Cant handle write cycle times below 150ns
285 cycleTimeOrig
= pTiming
->minDataCycle
;
289 if ( cycleTimeOrig
< 150 ) pTiming
->minDataCycle
= 150;
293 accessTicks
= rnddiv(pTiming
->minDataAccess
, kATASysClkNS
);
295 accessTicks
-= kATADmaAccessBase
;
296 if ( accessTicks
< kATADmaAccessMin
)
298 accessTicks
= kATADmaAccessMin
;
300 accessTime
= (accessTicks
+ kATADmaAccessBase
) * kATASysClkNS
;
303 * Calc recovery time in SYSCLK increments based on time remaining in cycle
305 recTime
= pTiming
->minDataCycle
- accessTime
;
306 recTicks
= rnddiv( recTime
, kATASysClkNS
);
308 recTicks
-= kATADmaRecoveryBase
;
309 if ( recTicks
< kATADmaRecoveryMin
)
311 recTicks
= kATADmaRecoveryMin
;
313 cycleTime
= (recTicks
+ kATADmaRecoveryBase
+ accessTicks
+ kATADmaAccessBase
) * kATASysClkNS
;
316 * If our calculated access time is at least SYSCLK/2 > than what the disk requires,
317 * see if selecting the 1/2 Clock option will help. This adds SYSCLK/2 to
318 * the access time and subtracts SYSCLK/2 from the recovery time.
320 * By setting the H-bit and subtracting one from the current access tick count,
321 * we are reducing the current access time by SYSCLK/2 and the current recovery
322 * time by SYSCLK/2. Now, check if the new cycle time still meets the disk's requirements.
324 if ( controllerType
== kControllerTypeDBDMAVersion1
)
326 if ( (accessTicks
> kATADmaAccessMin
) && ((UInt32
)(accessTime
- kATASysClkNS
/2) >= pTiming
->minDataAccess
) )
328 if ( (UInt32
)(cycleTime
- kATASysClkNS
) >= pTiming
->minDataCycle
)
332 accessTime
-= kATASysClkNS
/2;
333 cycleTime
-= kATASysClkNS
;
338 ideTimingWord
[unitNum
] &= ~0xffff800;
339 ideTimingWord
[unitNum
] |= (accessTicks
| (recTicks
<< 5) | (halfTick
<< 10)) << 11;
342 IOLog("AppleUltra66ATA::%s() Unit %1d DMA Requested Timings: Access: %3dns Cycle: %3dns \n\r",
343 __FUNCTION__
, (int)unitNum
, (int)pTiming
->minDataAccess
, (int)cycleTimeOrig
);
344 IOLog("AppleUltra66ATA::%s() DMA Actual Timings: Access: %3dns Cycle: %3dns\n\r",
345 __FUNCTION__
, accessTime
, cycleTime
);
346 IOLog("AppleUltra66ATA::%s() Ide DMA Timings = %08lx\n\r", __FUNCTION__
, ideTimingWord
[unitNum
] );
357 bool AppleUltra66ATA::calculateUltra66PIOTiming( UInt32 unitNum
, ATATiming
*pTiming
)
366 * Calc PIO access time >= pioAccessTime in SYSCLK increments
368 accessTicks
= rnddiv(pTiming
->minDataAccess
* 1000, kATAUltra66ClockPS
);
369 accessTime
= accessTicks
* kATAUltra66ClockPS
;
372 * Calc recovery time in SYSCLK increments based on time remaining in cycle
374 recTime
= pTiming
->minDataCycle
* 1000 - accessTime
;
375 recTicks
= rnddiv( recTime
, kATAUltra66ClockPS
);
377 cycleTime
= (recTicks
+ accessTicks
) * kATAUltra66ClockPS
;
379 ideTimingWord
[unitNum
] &= ~0xe00003ff;
380 ideTimingWord
[unitNum
] |= accessTicks
| (recTicks
<< 5);
383 IOLog("AppleUltra66ATA::%s() Unit %1d PIO Requested Timings: Access: %3dns Cycle: %3dns \n\r",
384 __FUNCTION__
, (int)unitNum
, (int)pTiming
->minDataAccess
, (int)pTiming
->minDataCycle
);
385 IOLog("AppleUltra66ATA::%s() PIO Actual Timings: Access: %3dns Cycle: %3dns\n\r",
386 __FUNCTION__
, accessTime
/ 1000, cycleTime
/ 1000 );
387 IOLog("AppleUltra66ATA::%s() Ide PIO Timings = %08lx\n\r", __FUNCTION__
, ideTimingWord
[unitNum
] );
398 bool AppleUltra66ATA::calculateUltra66DMATiming( UInt32 unitNum
, ATATiming
*pTiming
)
407 * Calc DMA access time >= dmaAccessTime in SYSCLK increments
409 accessTicks
= rnddiv(pTiming
->minDataAccess
* 1000, kATAUltra66ClockPS
);
410 accessTime
= accessTicks
* kATAUltra66ClockPS
;
413 * Calc recovery time in SYSCLK increments based on time remaining in cycle
415 recTime
= pTiming
->minDataCycle
* 1000 - accessTime
;
416 recTicks
= rnddiv( recTime
, kATAUltra66ClockPS
);
418 cycleTime
= (recTicks
+ accessTicks
) * kATAUltra66ClockPS
;
420 ideTimingWord
[unitNum
] &= ~0x001ffc00;
421 ideTimingWord
[unitNum
] |= (accessTicks
| (recTicks
<< 5)) << 10;
424 IOLog("AppleUltra66ATA::%s() Unit %1d DMA Requested Timings: Access: %3dns Cycle: %3dns \n\r",
425 __FUNCTION__
, (int)unitNum
, (int)pTiming
->minDataAccess
, (int)pTiming
->minDataCycle
);
426 IOLog("AppleUltra66ATA::%s() DMA Actual Timings: Access: %3dns Cycle: %3dns\n\r",
427 __FUNCTION__
, accessTime
/ 1000, cycleTime
/ 1000 );
428 IOLog("AppleUltra66ATA::%s() Ide DMA Timings = %08lx\n\r", __FUNCTION__
, ideTimingWord
[unitNum
] );
439 bool AppleUltra66ATA::calculateUltra66UDMATiming( UInt32 unitNum
, ATATiming
*pTiming
)
447 * Ready to Pause delay in PCI_66_CLOCK / 2 increments
449 rdyToPauseTicks
= rnddiv(pTiming
->minDataAccess
* 1000, kATAUltra66ClockPS
);
450 rdyToPauseTime
= rdyToPauseTicks
* kATAUltra66ClockPS
;
453 * Calculate cycle time in PCI_66_CLOCK / 2 increments
455 cycleTicks
= rnddiv(pTiming
->minDataCycle
* 1000, kATAUltra66ClockPS
);
456 cycleTime
= cycleTicks
* kATAUltra66ClockPS
;
458 ideTimingWord
[unitNum
] &= ~0x1ff00000;
459 ideTimingWord
[unitNum
] |= ((rdyToPauseTicks
<< 5) | (cycleTicks
<< 1) | 1) << 20;
462 IOLog("AppleUltra66ATA::%s() Unit %1d UDMA66 Requested Timings: ReadyToPause: %3dns Cycle: %3dns \n\r",
463 __FUNCTION__
, (int)unitNum
, (int)pTiming
->minDataAccess
, (int)pTiming
->minDataCycle
);
464 IOLog("AppleUltra66ATA::%s() UDMA66 Actual Timings: ReadyToPause: %3dns Cycle: %3dns\n\r",
465 __FUNCTION__
, rdyToPauseTime
/ 1000, cycleTime
/ 1000 );
466 IOLog("AppleUltra66ATA::%s() Ide DMA Timings = %08lx\n\r", __FUNCTION__
, ideTimingWord
[unitNum
] );
477 void AppleUltra66ATA::newDeviceSelected( IOATAStandardDevice
*newDevice
)
479 OSWriteSwapInt32( ioBaseATA
, 0x200, ideTimingWord
[newDevice
->getUnit()] );
488 bool AppleUltra66ATA::selectTiming( UInt32 unitNum
, ATATimingProtocol timingProtocol
)
490 if ( controllerType
== kControllerTypeUltra66DBDMA
)
492 switch ( timingProtocol
)
494 case kATATimingUltraDMA66
:
495 ideTimingWord
[unitNum
] |= 0x00100000;
498 ideTimingWord
[unitNum
] &= ~0x00100000;
511 bool AppleUltra66ATA::programDma( IOATAStandardCommand
*cmd
)
513 IOMemoryDescriptor
*memoryDesc
;
514 IODBDMADescriptor
*dmaDesc
;
517 IOPhysicalSegment physSeg
;
521 IODBDMAReset( ioBaseDMA
);
523 cmd
->getPointers( &memoryDesc
, &dmaReqLength
, &isWrite
);
525 if ( dmaReqLength
== 0 )
532 dmaCmd
= (isWrite
== true) ? kdbdmaOutputMore
: kdbdmaInputMore
;
533 dmaDesc
= dmaDescriptors
;
535 for ( i
= 0; i
< numDescriptors
; i
++, dmaDesc
++ )
537 if ( dmaMemoryCursor
->getPhysicalSegments( memoryDesc
, offset
, &physSeg
, 1 ) != 1 )
542 IOMakeDBDMADescriptor( dmaDesc
,
550 offset
+= physSeg
.length
;
553 if ( i
== numDescriptors
)
559 * Note: ATAPI always transfers even byte-counts. Send the extra byte to/from the bit-bucket
560 * if the requested transfer length is odd.
562 if ( dmaReqLength
& 1 )
565 IOMakeDBDMADescriptor( dmaDesc
++,
576 if ( i
== numDescriptors
)
582 IOMakeDBDMADescriptor( dmaDesc
,
591 IOSetDBDMACommandPtr( ioBaseDMA
, dmaDescriptorsPhys
);
602 bool AppleUltra66ATA::startDma( IOATAStandardCommand
* )
604 if ( dmaReqLength
!= 0 )
606 IODBDMAContinue( ioBaseDMA
);
616 bool AppleUltra66ATA::stopDma( IOATAStandardCommand
*, UInt32
*transferCount
)
620 UInt32 byteCount
= 0;
624 if ( dmaReqLength
== 0 )
629 IODBDMAStop( ioBaseDMA
);
631 for ( i
=0; i
< numDescriptors
; i
++ )
633 ccResult
= IOGetCCResult( &dmaDescriptors
[i
] );
635 if ( (ccResult
& (kdbdmaStatusActive
| kdbdmaStatusDead
)) == 0 )
639 byteCount
+= (IOGetCCOperation( &dmaDescriptors
[i
] ) & kdbdmaReqCountMask
) - (ccResult
& kdbdmaResCountMask
);
642 *transferCount
= byteCount
;
651 bool AppleUltra66ATA::resetDma()
653 IODBDMAReset( ioBaseDMA
);
661 bool AppleUltra66ATA::checkDmaActive()
663 return ((IOGetDBDMAChannelStatus( ioBaseDMA
) & kdbdmaActive
) != 0);
671 void AppleUltra66ATA::disableControllerInterrupts()
673 interruptEventSource
->disable();
680 void AppleUltra66ATA::enableControllerInterrupts()
682 interruptEventSource
->enable();
689 void AppleUltra66ATA::free()
691 if ( interruptEventSource
!= 0 )
693 interruptEventSource
->disable();
694 interruptEventSource
->release();
707 if ( bitBucketAddr
!= 0 )
709 IOFree( bitBucketAddr
, 32 );
712 if ( dmaDescriptors
!= 0 )
714 kfree( (vm_offset_t
)dmaDescriptors
, page_size
);
722 void AppleUltra66ATA::writeATAReg( UInt32 regIndex
, UInt32 regValue
)
724 regIndex
+= (regIndex
>= kATARegDeviceControl
) ? (kATACS3RegBase
- kATARegDeviceControl
+ 6) : 0;
728 *((volatile UInt8
*)ioBaseATA
+ (regIndex
<<4)) = regValue
;
732 *(volatile UInt16
*)ioBaseATA
= regValue
;
737 UInt32
AppleUltra66ATA::readATAReg( UInt32 regIndex
)
739 regIndex
+= (regIndex
>= kATARegAltStatus
) ? (kATACS3RegBase
- kATARegAltStatus
+ 6) : 0;
743 return *((volatile UInt8
*)ioBaseATA
+ (regIndex
<<4));
747 return *(volatile UInt16
*)ioBaseATA
;