#include <libkern/OSByteOrder.h>
#include <libkern/OSAtomic.h>
#include <IOKit/assert.h>
#include <IOKit/IOCommandGate.h>
#include <IOKit/IOTypes.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/pci/IOPCIDevice.h>
#include <IOKit/ata/IOATATypes.h>
#include <IOKit/ata/IOATAController.h>
#include <IOKit/ata/IOATACommand.h>
#include <IOKit/ata/IOATADevice.h>
#include <IOKit/ata/IOATABusInfo.h>
#include <IOKit/ata/IOATADevConfig.h>
#include "AppleKauaiATA.h"
#include <IOKit/ata/ATADeviceNub.h>
#ifdef DLOG
#undef DLOG
#endif
#ifdef ATA_DEBUG
#define DLOG(fmt, args...) IOLog(fmt, ## args)
#else
#define DLOG(fmt, args...)
#endif
#define ATARecordEventMACRO(type,param,bus,data) (void) (type); (void) (param); (void) (bus); (void) (data)
#define kCompatibleString "kauai-ata"
#define kCompatibleString2 "K2-UATA"
#define kCompatibleString3 "shasta-ata"
#define kModelPropertyKey "model"
#define kCableTypeKey "cable-type"
#define kModel6String "ata-6"
#define k80ConductorString "80-conductor"
#define kATASupportedPIOModes 0x001F // modes 4, 3, 2, 1, and 0
#define kATASupportedMultiDMAModes 0x0007 // modes 2, 1, and 0
#define kATASupportedUltraDMAModes 0x003f // modes 5, 4, 3, 2, 1, and 0
#define kATASupportedUltraDMA133Modes 0x007f // modes 6, 5, 4, 3, 2, 1, and 0
#define kAppleKauaiPIOCycleEntries 11
#define kAppleKauaiMultiDMACycleEntries 9
#define kAppleKauaiUltraDMACycleEntries 6
#define kAppleKauaiUltraDMA133CycleEntries 7
#define kATAMaxPIOMode 4
#define kATAMaxMultiDMAMode 2
#define kATAMaxUltraDMA133Mode 6
#define kATAXferDMADesc 33
#define kATAMaxDMADesc kATAXferDMADesc + 2
#define kMaxATAXfer 512 * 256
#define kRX_bufferSize 512 * 256
#pragma mark -IOService Overrides -
#define super MacIOATA
OSDefineMetaClassAndStructors( AppleKauaiATA, MacIOATA )
bool
AppleKauaiATA::init(OSDictionary* properties)
{
DLOG("AppleKauaiATA init start\n");
if (super::init(properties) == false)
{
DLOG("AppleKauaiATA: super::init() failed\n");
return false;
}
_needsResync = false;
dmaBuffer = 0;
clientBuffer = 0;
bufferRX = false;
rxFeatureOn = false;
ultra133 = false;
DLOG("AppleKauaiATA init done\n");
return true;
}
IOService*
AppleKauaiATA::probe(IOService* provider, SInt32* score)
{
OSData *compatibleEntry;
DLOG("AppleKauaiATA starting probe\n");
compatibleEntry = OSDynamicCast( OSData, provider->getProperty( "compatible" ) );
if ( compatibleEntry == 0 )
{
DLOG("AppleKauaiATA failed getting compatible property\n");
return 0;
}
if ( compatibleEntry->isEqualTo( kCompatibleString, sizeof(kCompatibleString)-1 ) == false )
{
if( compatibleEntry->isEqualTo( kCompatibleString2, sizeof(kCompatibleString2)-1 ) == false)
{
if( compatibleEntry->isEqualTo( kCompatibleString3, sizeof(kCompatibleString3)-1 ) == false)
{
DLOG("AppleKauaiATA compatible property doesn't match\n");
return 0;
}
ultra133 = true;
rxFeatureOn = true;
IOLog("AppleKauaiATA shasta-ata features enabled\n");
}
rxFeatureOn = true;
DLOG("AppleKauaiATA rx buffer feature enabled\n");
}
OSData *registryEntry;
registryEntry = OSDynamicCast( OSData, provider->getProperty( kModelPropertyKey ) );
if( registryEntry == 0)
{
DLOG("AppleKauaiATA unknown model property.\n");
return 0;
}
busTimings[0].pioMWRegValue = busTimings[1].pioMWRegValue = 0x08000A92 | 0x00618000;
busTimings[0].ultraRegValue = busTimings[1].ultraRegValue = 0x00002921;
if( ultra133 )
{ busTimings[0].pioMWRegValue = busTimings[1].pioMWRegValue = 0x0a820c97; busTimings[0].ultraRegValue = busTimings[1].ultraRegValue = 0x00033031; }
busTimings[0].ataPIOSpeedMode = busTimings[1].ataPIOSpeedMode = 0x01 ; busTimings[0].ataPIOCycleTime = busTimings[1].ataPIOCycleTime = 600 ; busTimings[0].ataMultiDMASpeed = busTimings[1].ataMultiDMASpeed = 0x01; busTimings[0].ataMultiCycleTime = busTimings[1].ataMultiCycleTime = 480; busTimings[0].ataUltraDMASpeedMode = busTimings[1].ataUltraDMASpeedMode = 0x20;
return this;
}
bool
AppleKauaiATA::start(IOService *provider)
{
DLOG("AppleKauaiATA::start() begin\n");
if( ! OSDynamicCast(IOPCIDevice, provider ) )
{
DLOG("AppleKauaiATA provider not IOPCIDevice!\n");
return false;
}
if( ! provider->open(this) )
{
DLOG("AppleKauai provider did not open\n");
return false;
}
if( rxFeatureOn )
{
dmaBuffer = IOBufferMemoryDescriptor::withOptions( kIOMemoryDirectionMask,
kRX_bufferSize,
4096);
if( ! dmaBuffer )
{
DLOG( "kauai ata failed to create dmaBuffer\n");
return false;
}
((IOPCIDevice *)provider)->configWrite8( (UInt8) 0xC, (UInt8) 0x08);
((IOPCIDevice *)provider)->configWrite8( (UInt8) 0x4, (UInt8) (((IOPCIDevice *)provider)->configRead8(0x4) | 0x10));
DLOG( "kauai ata created rx buffer\n");
}
((IOPCIDevice *)provider)->setMemoryEnable(true);
((IOPCIDevice *)provider)->setBusMasterEnable( true );
ATADeviceNub* newNub=0L;
if (!super::start( provider))
{
DLOG("AppleKauaiATA: super::start() failed\n");
provider->close(this);
return false;
}
DLOG("AppleKauaiATA::start() done\n");
for( UInt32 i = 0; i < 2; i++)
{
if( _devInfo[i].type != kUnknownATADeviceType )
{
DLOG("AppleKauaiATA creating nub\n");
newNub = ATADeviceNub::ataDeviceNub( (IOATAController*)this, (ataUnitID) i, _devInfo[i].type );
if( newNub )
{
DLOG("AppleKauaiATA attach nub\n");
newNub->attach(this);
_nub[i] = (IOATADevice*) newNub;
DLOG("AppleKauaiATA register nub\n");
if( rxFeatureOn )
{
OSNumber* rx_alignLimit ;
rx_alignLimit = OSNumber::withNumber( (kRX_bufferSize), 32);
newNub->setProperty( kIOMaximumByteCountReadKey, rx_alignLimit);
rx_alignLimit->release();
}
newNub->registerService();
newNub = 0L;
}
}
}
return true;
}
void
AppleKauaiATA::free()
{
super::free();
}
IOWorkLoop*
AppleKauaiATA::getWorkLoop() const
{
DLOG("AppleKauaiATA::getWorkLoop\n");
IOWorkLoop* wl = _workLoop;
if (!wl)
{
wl = IOWorkLoop::workLoop();
if (!wl)
return 0;
}
return wl;
}
bool
AppleKauaiATA::configureTFPointers(void)
{
DLOG("AppleKauaiATA config TF Pointers \n");
DLOG("AppleKauaiATA configureTFPointers begin\n");
_baseAddressMap = _provider->mapDeviceMemoryWithIndex(0);
if( !_baseAddressMap )
{
DLOG("AppleKauaiATA no base map\n");
return false;
}
volatile UInt8* baseAddress = (volatile UInt8*)_baseAddressMap->getVirtualAddress();
if( !baseAddress )
{
DLOG("AppleKauaiATA no base address\n");
return false;
}
_kauaiATAFCR = (volatile UInt32*) baseAddress;
DLOG("MacIOATA baseAdress = %lx\n", baseAddress);
_dmaControlReg = (volatile IODBDMAChannelRegisters*) (baseAddress + 0x1000);
baseAddress += 0x2000;
_tfDataReg = (volatile UInt16*) (baseAddress + 0x00);
_tfFeatureReg = baseAddress + 0x10;
_tfSCountReg = baseAddress + 0x20;
_tfSectorNReg = baseAddress + 0x30;
_tfCylLoReg = baseAddress + 0x40;
_tfCylHiReg = baseAddress + 0x50;
_tfSDHReg = baseAddress + 0x60;
_tfStatusCmdReg = baseAddress + 0x70;
_tfAltSDevCReg = baseAddress + 0x160;
_timingConfigReg = (volatile UInt32*) (baseAddress + 0x200);
_ultraTimingControl = (volatile UInt32*) (baseAddress + 0x210);
_autoPollingControl = (volatile UInt32*) (baseAddress + 0x220);
_interruptPendingReg = (volatile UInt32*) (baseAddress + 0x300);
DLOG("MacIOATA configureTFPointers end\n");
DLOG("AppleKauaiATA enable FCR \n");
OSWriteSwapInt32(_kauaiATAFCR, 0, 0x00000007 );
DLOG("AppleKauaiATA setting default timing \n");
selectIOTiming( (ataUnitID) 0 );
DLOG("AppleKauaiATA configTFPointers done\n");
return true;
}
IOReturn
AppleKauaiATA::provideBusInfo( IOATABusInfo* infoOut)
{
if( infoOut == 0)
{
DLOG("AppleKauaiATA nil pointer in provideBusInfo\n");
return -1;
}
infoOut->zeroData();
infoOut->setSocketType( kInternalATASocket );
infoOut->setPIOModes( kATASupportedPIOModes);
infoOut->setDMAModes( kATASupportedMultiDMAModes );
infoOut->setUltraModes( kATASupportedUltraDMAModes );
if( ultra133 )
{
infoOut->setUltraModes( kATASupportedUltraDMA133Modes );
}
infoOut->setExtendedLBA( true ); infoOut->setMaxBlocksExtended( 0x0800 ); if( rxFeatureOn)
infoOut->setMaxBlocksExtended( 0x0100 );
UInt8 units = 0;
if( _devInfo[0].type != kUnknownATADeviceType )
units++;
if( _devInfo[1].type != kUnknownATADeviceType )
units++;
infoOut->setUnits( units);
return kATANoErr;
}
IOReturn
AppleKauaiATA::getConfig( IOATADevConfig* configRequest, UInt32 unitNumber)
{
if( configRequest == 0
|| unitNumber > 1 )
{
DLOG("AppleKauaiATA bad param in getConfig\n");
return -1;
}
configRequest->setPIOMode( busTimings[unitNumber].ataPIOSpeedMode);
configRequest->setDMAMode(busTimings[unitNumber].ataMultiDMASpeed);
configRequest->setPIOCycleTime(busTimings[unitNumber].ataPIOCycleTime );
configRequest->setDMACycleTime(busTimings[unitNumber].ataMultiCycleTime);
configRequest->setPacketConfig( _devInfo[unitNumber].packetSend );
configRequest->setUltraMode(busTimings[unitNumber].ataUltraDMASpeedMode);
return kATANoErr;
}
IOReturn
AppleKauaiATA::selectConfig( IOATADevConfig* configRequest, UInt32 unitNumber)
{
if( configRequest == 0
|| unitNumber > 1 )
{
DLOG("AppleKauaiATA bad param in setConfig\n");
return -1;
}
if( ( configRequest->getPIOMode() & kATASupportedPIOModes ) == 0x00 )
{
DLOG("AppleKauaiATA setConfig PIO mode not supported\n");
return kATAModeNotSupported;
}
UInt8 ultraSupported = kATASupportedUltraDMAModes;
if( ultra133 )
{
ultraSupported = kATASupportedUltraDMA133Modes;
}
if( configRequest->getUltraMode() & ~ultraSupported )
{
DLOG("AppleKauaiATA setConfig no ultra\n");
return kATAModeNotSupported;
}
if( configRequest->getDMAMode() & ~kATASupportedMultiDMAModes )
{
DLOG("AppleKauaiATA setConfig DMA mode not supported\n");
return kATAModeNotSupported;
}
if( configRequest->getDMAMode() > 0x0000
&& configRequest->getUltraMode() > 0x0000 )
{
DLOG("AppleKauaiATA err, only one DMA class allowed in config select\n");
return kATAModeNotSupported;
}
_devInfo[unitNumber].packetSend = configRequest->getPacketConfig();
DLOG("AppleKauaiATA setConfig packetConfig = %ld\n", _devInfo[unitNumber].packetSend );
return selectIOTimerValue(configRequest, unitNumber);
}
IOReturn
AppleKauaiATA::selectIOTimerValue( IOATADevConfig* configRequest, UInt32 unitNumber)
{
static const UInt16 MinPIOCycle[kATAMaxPIOMode + 1] =
{
600, 383, 240, 180, 120 };
static const UInt16 MinMultiDMACycle[kATAMaxMultiDMAMode + 1] =
{
480, 150, 120 };
UInt32 PIOCycleValue100[kAppleKauaiPIOCycleEntries] =
{
0x08000FFF, 0x08000A92, 0x0800060F, 0x08000492, 0x0800048F, 0x080003CF, 0x080003CC, 0x0800038B, 0x0800030C, 0x05000249, 0x04000148 };
UInt32 PIOCycleValue133[kAppleKauaiPIOCycleEntries] =
{
0x08000FFF, 0x0A000C97, 0x07000712, 0x040003CD, 0x040003CD, 0x040003CD, 0x040003CD, 0x040003CD, 0x040003CD, 0x0400028B, 0x0400010A };
static const UInt16 PIOCycleTime[ kAppleKauaiPIOCycleEntries ]=
{
930, 600, 383, 360, 330, 300, 270, 240, 239, 180, 120, };
static const UInt32 MultiDMACycleValue100[kAppleKauaiMultiDMACycleEntries] =
{
0x00FFF000, 0x00618000, 0x00492000, 0x0038E000, 0x0030C000, 0x002CB000, 0x00249000, 0x00209000, 0x00148000 };
static const UInt32 MultiDMACycleValue133[kAppleKauaiMultiDMACycleEntries] =
{
0x00FFF000, 0x00820800, 0x00820800, 0x00820800, 0x00820800, 0x00820800, 0x00820800, 0x0028B000, 0x001CA000 };
static const UInt16 MultiDMACycleTime[kAppleKauaiMultiDMACycleEntries] =
{
1260, 480, 360, 270, 240, 210, 180, 150, 120 };
static const UInt32 UltraDMACycleValue100[kAppleKauaiUltraDMACycleEntries ] =
{
0x000070C1, 0x00005D81, 0x00004A61, 0x00003A51, 0x00002A31, 0x00002921 };
static const UInt32 UltraDMACycleValue133[kAppleKauaiUltraDMA133CycleEntries] =
{
0x00035901, 0x000348b1, 0x00033881, 0x00033861, 0x00033841, 0x00033031, 0x00033021 };
static const UInt16 UltraDMACycleTime100[kAppleKauaiUltraDMACycleEntries] =
{
120, 90, 60, 45, 30, 20
};
static const UInt16 UltraDMACycleTime133[kAppleKauaiUltraDMA133CycleEntries] =
{
120, 90, 60, 45, 30, 20, 15 };
UInt32 pioConfigBits = PIOCycleValue100[0];
if( ultra133 )
{
pioConfigBits = PIOCycleValue133[0];
}
UInt32 pioModeNumber = bitSigToNumeric( configRequest->getPIOMode());
if( pioModeNumber > kATAMaxPIOMode )
{
DLOG("AppleKauaiATA pio mode out of range\n");
return kATAModeNotSupported;
}
UInt32 pioCycleTime = configRequest->getPIOCycleTime();
if( pioCycleTime < MinPIOCycle[ pioModeNumber ] )
{
pioCycleTime = MinPIOCycle[ pioModeNumber ];
}
for( int i = kAppleKauaiPIOCycleEntries - 1; i >= 0; i--)
{
if( pioCycleTime <= PIOCycleTime[ i ] )
{
pioConfigBits = PIOCycleValue100[i];
if( ultra133 )
{
pioConfigBits = PIOCycleValue133[i];
}
break;
}
}
UInt32 mwdmaConfigBits = MultiDMACycleValue100[0];
if( ultra133 )
{
mwdmaConfigBits = MultiDMACycleValue133[0];
}
UInt32 dmaModeNumber = 0;
UInt32 dmaCycleTime = 0;
if( configRequest->getDMAMode() )
{
dmaModeNumber = bitSigToNumeric( configRequest->getDMAMode() );
if( dmaModeNumber > kATAMaxMultiDMAMode )
{
dmaModeNumber = 0;
}
dmaCycleTime = configRequest->getDMACycleTime();
if( dmaCycleTime < MinMultiDMACycle[ dmaModeNumber ] )
{
dmaCycleTime = MinMultiDMACycle[ dmaModeNumber ];
}
for( int i = kAppleKauaiMultiDMACycleEntries - 1; i >= 0; i--)
{
if( dmaCycleTime <= MultiDMACycleTime[ i ] )
{
mwdmaConfigBits = MultiDMACycleValue100[i];
if( ultra133 )
{
mwdmaConfigBits = MultiDMACycleValue133[i];
}
break;
}
}
}
UInt32 ultraModeNumber = 0;
UInt32 ultraConfigBits = 0;
if( configRequest->getUltraMode() )
{
ultraModeNumber = bitSigToNumeric( configRequest->getUltraMode() );
if( ultra133 )
{
if( ultraModeNumber > 6)
ultraModeNumber = 6;
ultraConfigBits = UltraDMACycleValue133[ ultraModeNumber ];
} else {
if( ultraModeNumber > 5 )
ultraModeNumber = 5;
ultraConfigBits = UltraDMACycleValue100[ ultraModeNumber ];
}
}
busTimings[unitNumber].pioMWRegValue = mwdmaConfigBits | pioConfigBits;
busTimings[unitNumber].ultraRegValue = ultraConfigBits;
busTimings[unitNumber].ataPIOSpeedMode = configRequest->getPIOMode();
busTimings[unitNumber].ataPIOCycleTime = pioCycleTime;
busTimings[unitNumber].ataMultiDMASpeed = configRequest->getDMAMode();
busTimings[unitNumber].ataMultiCycleTime = dmaCycleTime;
busTimings[unitNumber].ataUltraDMASpeedMode = configRequest->getUltraMode();
DLOG("AppleKauaiATA PIO mode %x at %ld ns selected for device: %x\n", (int)pioModeNumber, pioCycleTime, (int)unitNumber);
DLOG("AppleKauaiATA DMA mode %x at %ld ns selected for device: %x\n", (int)dmaModeNumber, dmaCycleTime, (int)unitNumber);
DLOG("AppleKauaiATA Ultra mode %x at %ld ns selected for device: %x\n", (int)ultraModeNumber, UltraDMACycleTime[ultraModeNumber], (int)unitNumber);
DLOG("AppleKauai pio/mw cycle value = %x for unit: %x\n", busTimings[unitNumber].pioMWRegValue, unitNumber);
DLOG("AppleKauai ultra cycle value = %x for unit: %x\n", busTimings[unitNumber].ultraRegValue, unitNumber);
return getConfig( configRequest, unitNumber);
}
void
AppleKauaiATA::selectIOTiming( ataUnitID unit )
{
OSWriteSwapInt32( _kauaiATAFCR, 0, 0x7);
OSWriteSwapInt32(_timingConfigReg, 0, busTimings[unit].pioMWRegValue );
OSWriteSwapInt32( _ultraTimingControl, 0, busTimings[unit].ultraRegValue);
}
IOReturn
AppleKauaiATA::handleDeviceInterrupt(void)
{
if( !_currentCommand )
{
volatile UInt8 status = *_tfStatusCmdReg;
OSSynchronizeIO();
status++; return 0;
}
UInt32 intStatus = OSReadLittleInt32( (void*) _interruptPendingReg, 0x00);
OSSynchronizeIO();
if( !(intStatus & 0x40000000)
&& !_needsResync )
{
volatile UInt8 status = *_tfStatusCmdReg;
OSSynchronizeIO();
status++;
return 0;
}
return super::handleDeviceInterrupt();
}
IOReturn
AppleKauaiATA::selectDevice( ataUnitID unit )
{
_devIntSrc->disable();
IOReturn result = super::selectDevice( unit);
_devIntSrc->enable();
return result;
}
IOReturn
AppleKauaiATA::synchronousIO(void)
{
_devIntSrc->disable();
IOReturn result = super::synchronousIO();
UInt32 intStatus = OSReadLittleInt32( (void*) _interruptPendingReg, 0x00);
OSSynchronizeIO();
while( (intStatus & 0x40000000) )
{
volatile UInt8 status = *_tfStatusCmdReg;
OSSynchronizeIO();
status++;
intStatus = OSReadLittleInt32( (void*) _interruptPendingReg, 0x00);
OSSynchronizeIO();
}
_devIntSrc->enable();
return result;
}
IOReturn
AppleKauaiATA::handleBusReset(void)
{
bool isATAPIReset = ((_currentCommand->getFlags() & mATAFlagProtocolATAPI) != 0);
bool doATAPI[2];
IOReturn err = kATANoErr;
UInt8 index;
UInt8 statCheck;
DLOG("AppleKauaiATA bus reset start.\n");
doATAPI[0] = doATAPI[1] = false;
if(isATAPIReset)
{
doATAPI[_currentCommand->getUnit()] = true; }
for(index=0;index<2;index++)
{
if( doATAPI[index] && _devInfo[index].type == kATAPIDeviceType)
{
OSSynchronizeIO();
*_tfSDHReg = mATASectorSize + (index << 4);
OSSynchronizeIO();
statCheck = *_tfAltSDevCReg;
err = softResetBus(true);
}
}
if(isATAPIReset)
{
executeEventCallouts( kATAPIResetEvent, _currentCommand->getUnit() );
}
if(!isATAPIReset)
{
err = softResetBus();
executeEventCallouts( kATAResetEvent, kATAInvalidDeviceID );
}
_currentCommand->state = IOATAController::kATAComplete;
DLOG("AppleKauaiATA bus reset done.\n");
completeIO( err );
return err;
}
IOATAController::transState
AppleKauaiATA::determineATAPIState(void)
{
IOATAController::transState drivePhase = super::determineATAPIState();
if( _currentCommand->state > drivePhase
|| _currentCommand->state == kATAStarted )
{
return (IOATAController::transState) _currentCommand->state;
}
return drivePhase;
}
void
AppleKauaiATA::processDMAInterrupt(void)
{
_needsResync = _resyncInterrupts;
super::processDMAInterrupt();
_needsResync = false;
}
bool
AppleKauaiATA::allocDMAChannel(void)
{
if( !_dmaControlReg )
{
DLOG("AppleKauaiATA no DMA address\n");
return false;
}
_descriptors = (IODBDMADescriptor*)IOMallocContiguous( sizeof(IODBDMADescriptor) * kATAMaxDMADesc,
0x10,
&_descriptorsPhysical );
if( ! _descriptors )
{
DLOG("AppleKauaiATA alloc descriptors failed\n");
return false;
}
_DMACursor = IODBDMAMemoryCursor::withSpecification(0xFFFE,
kMaxATAXfer
);
if( ! _DMACursor )
{
DLOG("AppleKauaiATA alloc DMACursor failed\n");
return false;
}
initATADMAChains(_descriptors);
return true;
}
IOReturn
AppleKauaiATA::handleExecIO( void )
{
if( ! rxFeatureOn)
goto preflightDone;
DLOG("AppleKauaiATA checking flags %X\n", _currentCommand->getFlags() );
if( _currentCommand->getFlags() & (mATAFlagUseDMA)
&& _currentCommand->getFlags() & (mATAFlagIORead) )
{
DLOG("AppleKauaiATA checking alignment\n");
if(_currentCommand->getOpcode() == kATAPIFnExecIO)
{
DLOG("AppleKauaiATA ATAPI length check\n");
UInt32 remainder = _currentCommand->getByteCount() % 16;
if( remainder )
{
DLOG("AppleKauaiATA convert ATAPI to PIO remainder = %d\n", remainder);
_currentCommand->setFlags( _currentCommand->getFlags() & (~mATAFlagUseDMA) );
_currentCommand->getTaskFilePtr()->ataTFFeatures = 0x00;
goto preflightDone;
}
if( _currentCommand->getByteCount() > kRX_bufferSize )
{
DLOG("AppleKauaiATA count exceeds buffer size!!! %d\n", _currentCommand->getByteCount());
goto preflightDone;
}
DLOG("AppleKauaiATA double buffering dma\n");
clientBuffer = _currentCommand->getBuffer();
bufferRX = true;
_currentCommand->setBuffer(dmaBuffer);
dmaBuffer->prepare(kIODirectionIn);
}
}
preflightDone:
return super::handleExecIO();
}
void
AppleKauaiATA::completeIO( IOReturn commandResult )
{
if( bufferRX )
{
DLOG("AppleKauaiATA complete double buffer\n");
bufferRX = false;
dmaBuffer->complete(kIODirectionIn);
clientBuffer->writeBytes(0, dmaBuffer->getBytesNoCopy(), _currentCommand->getActualTransfer() );
_currentCommand->setBuffer( clientBuffer );
clientBuffer = 0;
}
super::completeIO( commandResult );
}