IOFWDCLTranslator.cpp [plain text]
#include <IOKit/firewire/IOFWDCLTranslator.h>
static void DCLReceivePacketStart(
DCLCommand** ppCurrentDCLCommand,
UInt32 packetHeader,
UInt8** pPacketBuffer,
UInt32* pPacketSize,
bool* pGetNextPacket)
{
DCLTransferPacket* pDCLTransferPacket;
UInt8 * transferBuffer;
UInt8 * packetBuffer;
SInt32 transferSize, packetSize;
pDCLTransferPacket = (DCLTransferPacket*) *ppCurrentDCLCommand;
transferBuffer = (UInt8 *)pDCLTransferPacket->buffer;
transferSize = pDCLTransferPacket->size - sizeof (UInt32);
packetSize = *pPacketSize;
if (transferSize > packetSize)
transferSize = packetSize;
packetBuffer = *pPacketBuffer;
*((UInt32 *) transferBuffer) = packetHeader;
transferBuffer += sizeof (UInt32);
if (transferSize > 0) {
bcopy (packetBuffer, transferBuffer, transferSize);
packetSize -= transferSize;
packetBuffer += transferSize;
}
*pGetNextPacket = true;
if (pDCLTransferPacket->pNextDCLCommand != NULL)
{
if ((pDCLTransferPacket->pNextDCLCommand->opcode & ~kFWDCLOpFlagMask) ==
kDCLReceivePacketOp)
{
*pGetNextPacket = false;
}
}
*ppCurrentDCLCommand = pDCLTransferPacket->pNextDCLCommand;
*pPacketBuffer = packetBuffer;
*pPacketSize = packetSize;
}
static void DCLReceivePacket(
DCLCommand** ppCurrentDCLCommand,
UInt32 packetHeader,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferPacket* pDCLTransferPacket;
UInt8 * transferBuffer;
UInt8 * packetBuffer;
UInt32 transferSize, packetSize;
pDCLTransferPacket = (DCLTransferPacket*) *ppCurrentDCLCommand;
transferBuffer = (UInt8 *)pDCLTransferPacket->buffer;
transferSize = pDCLTransferPacket->size;
packetSize = *pPacketSize;
if (transferSize > packetSize)
transferSize = packetSize;
packetBuffer = *pPacketBuffer;
if (transferSize > 0)
{
bcopy (packetBuffer, transferBuffer, transferSize);
packetSize -= transferSize;
packetBuffer += transferSize;
}
*pGetNextPacket = true;
if (pDCLTransferPacket->pNextDCLCommand != NULL)
{
if ((pDCLTransferPacket->pNextDCLCommand->opcode & ~kFWDCLOpFlagMask) ==
kDCLReceivePacketOp)
{
*pGetNextPacket = false;
}
}
*ppCurrentDCLCommand = pDCLTransferPacket->pNextDCLCommand;
*pPacketBuffer = packetBuffer;
*pPacketSize = packetSize;
}
static void DCLReceiveBuffer( DCLCommand** ppCurrentDCLCommand, UInt32 packetHeader,
UInt8** pPacketBuffer, UInt32* pPacketSize, bool* pGetNextPacket )
{
DCLTransferBuffer* pDCLTransferBuffer;
UInt8 * buffer;
UInt32 bufferOffset, bufferSize;
UInt32 bufferSizeLeft;
UInt8 * packetBuffer;
UInt32 packetSize;
UInt32 transferSize;
pDCLTransferBuffer = (DCLTransferBuffer*) *ppCurrentDCLCommand;
buffer = (UInt8 *)pDCLTransferBuffer->buffer;
bufferOffset = pDCLTransferBuffer->bufferOffset;
bufferSize = pDCLTransferBuffer->size;
packetBuffer = *pPacketBuffer;
packetSize = *pPacketSize;
bufferSizeLeft = bufferSize - bufferOffset;
if (bufferSizeLeft > packetSize)
transferSize = packetSize;
else
transferSize = bufferSizeLeft;
if (transferSize > 0)
{
bcopy (packetBuffer, buffer + bufferOffset, transferSize);
packetBuffer += transferSize;
packetSize -= transferSize;
bufferOffset += transferSize;
}
if (bufferOffset == bufferSize)
{
*ppCurrentDCLCommand = pDCLTransferBuffer->pNextDCLCommand;
*pGetNextPacket = false;
}
else
{
*pGetNextPacket = true;
}
pDCLTransferBuffer->bufferOffset = bufferOffset;
*pPacketBuffer = packetBuffer;
*pPacketSize = packetSize;
}
static void DCLSendPacket(
DCLCommand** ppCurrentDCLCommand,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferPacket* pDCLTransferPacket;
UInt8 * transferBuffer;
UInt8 * packetBuffer;
UInt32 transferSize, packetSize;
pDCLTransferPacket = (DCLTransferPacket*) *ppCurrentDCLCommand;
transferBuffer = (UInt8 *)pDCLTransferPacket->buffer;
transferSize = pDCLTransferPacket->size;
packetSize = *pPacketSize;
packetBuffer = *pPacketBuffer + packetSize;
bcopy (transferBuffer, packetBuffer, transferSize);
packetSize += transferSize;
*pGetNextPacket = true;
if (pDCLTransferPacket->pNextDCLCommand != NULL)
{
if ((pDCLTransferPacket->pNextDCLCommand->opcode & ~kFWDCLOpFlagMask) ==
kDCLSendPacketOp)
{
*pGetNextPacket = false;
}
}
*ppCurrentDCLCommand = pDCLTransferPacket->pNextDCLCommand;
*pPacketSize = packetSize;
}
static void DCLSendBuffer( DCLCommand** ppCurrentDCLCommand, UInt8** pPacketBuffer, UInt32* pPacketSize, bool* pGetNextPacket)
{
DCLTransferBuffer* pDCLTransferBuffer;
UInt8 * buffer;
UInt32 bufferOffset, bufferSize;
UInt32 bufferSizeLeft;
UInt8 * packetBuffer;
UInt32 packetSize;
UInt32 transferPacketSize;
UInt32 transferSize;
pDCLTransferBuffer = (DCLTransferBuffer*) *ppCurrentDCLCommand;
buffer = (UInt8 *)pDCLTransferBuffer->buffer;
bufferOffset = pDCLTransferBuffer->bufferOffset;
bufferSize = pDCLTransferBuffer->size;
packetSize = *pPacketSize;
packetBuffer = *pPacketBuffer + packetSize;
transferPacketSize = pDCLTransferBuffer->packetSize;
bufferSizeLeft = bufferSize - bufferOffset;
if (bufferSizeLeft > transferPacketSize)
transferSize = transferPacketSize;
else
transferSize = bufferSizeLeft;
if (transferSize > 0)
{
bcopy (buffer + bufferOffset, packetBuffer, transferSize);
packetSize += transferSize;
bufferOffset += transferSize;
}
if (bufferOffset == bufferSize)
{
*ppCurrentDCLCommand = pDCLTransferBuffer->pNextDCLCommand;
*pGetNextPacket = false;
}
else
{
*pGetNextPacket = true;
}
pDCLTransferBuffer->bufferOffset = bufferOffset;
*pPacketSize = packetSize;
}
static void RunListeningDCLEngine( DCLCommand** ppCurrentDCLCommand, UInt32 packetHeader, UInt8** pPacketBuffer,
UInt32* pPacketSize, bool* pGetNextPacket)
{
DCLCommand* pCurrentDCLCommand;
DCLCallProc* pDCLCallProc;
DCLJump* pDCLJump;
pCurrentDCLCommand = *ppCurrentDCLCommand;
switch (pCurrentDCLCommand->opcode & ~kFWDCLOpFlagMask)
{
case kDCLReceivePacketStartOp :
DCLReceivePacketStart (
&pCurrentDCLCommand,
packetHeader,
pPacketBuffer,
pPacketSize,
pGetNextPacket);
break;
case kDCLReceivePacketOp :
DCLReceivePacket (
&pCurrentDCLCommand,
packetHeader,
pPacketBuffer,
pPacketSize,
pGetNextPacket);
break;
case kDCLReceiveBufferOp :
DCLReceiveBuffer (
&pCurrentDCLCommand,
packetHeader,
pPacketBuffer,
pPacketSize,
pGetNextPacket);
break;
case kDCLCallProcOp :
pDCLCallProc = (DCLCallProc*) pCurrentDCLCommand;
if (pDCLCallProc->proc != NULL)
(*(pDCLCallProc->proc)) ((DCLCommand*) pDCLCallProc);
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
case kDCLJumpOp :
pDCLJump = (DCLJump*) pCurrentDCLCommand;
pCurrentDCLCommand = (DCLCommand*) pDCLJump->pJumpDCLLabel;
*pGetNextPacket = false;
break;
default :
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
}
*ppCurrentDCLCommand = pCurrentDCLCommand;
}
static void RunTalkingDCLEngine( UInt32* packetHeader, DCLCommand** ppCurrentDCLCommand,
UInt8** pPacketBuffer, UInt32* pPacketSize, bool* pGetNextPacket)
{
DCLCommand* pCurrentDCLCommand;
DCLCallProc* pDCLCallProc;
DCLJump* pDCLJump;
DCLSetTagSyncBits* pDCLSetTagSyncBits;
UInt32 host_header;
pCurrentDCLCommand = *ppCurrentDCLCommand;
switch (pCurrentDCLCommand->opcode & ~kFWDCLOpFlagMask)
{
case kDCLSendPacketStartOp :
case kDCLSendPacketOp :
DCLSendPacket (
&pCurrentDCLCommand,
pPacketBuffer,
pPacketSize,
pGetNextPacket);
break;
case kDCLSendBufferOp :
DCLSendBuffer (
&pCurrentDCLCommand,
pPacketBuffer,
pPacketSize,
pGetNextPacket);
break;
case kDCLCallProcOp :
pDCLCallProc = (DCLCallProc*) pCurrentDCLCommand;
if (pDCLCallProc->proc != NULL)
(*(pDCLCallProc->proc)) ((DCLCommand*) pDCLCallProc);
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
case kDCLJumpOp :
pDCLJump = (DCLJump*) pCurrentDCLCommand;
pCurrentDCLCommand = (DCLCommand*) pDCLJump->pJumpDCLLabel;
*pGetNextPacket = false;
break;
case kDCLLabelOp :
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
case kDCLSetTagSyncBitsOp :
pDCLSetTagSyncBits = (DCLSetTagSyncBits*) pCurrentDCLCommand;
host_header = OSSwapBigToHostInt32( *packetHeader );
host_header &= ~(kFWIsochTag | kFWIsochSy);
host_header |= (pDCLSetTagSyncBits->tagBits << kFWIsochTagPhase);
host_header |= (pDCLSetTagSyncBits->syncBits << kFWIsochSyPhase);
*packetHeader = OSSwapHostToBigInt32( host_header );
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
default :
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
}
*ppCurrentDCLCommand = pCurrentDCLCommand;
}
OSDefineMetaClass( IODCLTranslator, IODCLProgram )
OSDefineAbstractStructors(IODCLTranslator, IODCLProgram)
bool IODCLTranslator::init(DCLCommand* toInterpret)
{
if(!IODCLProgram::init())
return false;
fToInterpret = toInterpret;
return true;
}
IOReturn
IODCLTranslator :: notify (
IOFWDCLNotificationType notificationType,
DCLCommand ** dclCommandList,
UInt32 numDCLCommands )
{
return kIOReturnSuccess; }
IOReturn IODCLTranslator::allocateHW(IOFWSpeed speed, UInt32 chan)
{
if(!fHWProgram)
return kIOReturnInternalError;
return fHWProgram->allocateHW(speed, chan);
}
IOReturn IODCLTranslator::releaseHW()
{
if(!fHWProgram)
return kIOReturnInternalError;
return fHWProgram->releaseHW();
}
void IODCLTranslator::stop()
{
fHWProgram->stop();
}
DCLCommand*
IODCLTranslator::getTranslatorOpcodes()
{
return (DCLCommand*)&fStartLabel;
}
void
IODCLTranslator::setHWProgram(IODCLProgram *program)
{
fHWProgram = program;
}
void
IODCLTranslator::ListeningDCLPingPongProc(DCLCommand* pDCLCommand)
{
IODCLTranslator * me;
DCLCommand* pCurrentDCLCommand;
DCLTransferPacket* pDCLTransferPacket;
UInt8 * packetBuffer;
UInt32 packetHeader;
UInt32 packetSize;
UInt32 packetNum;
bool getNextPacket;
me = (IODCLTranslator *)((DCLCallProc*)pDCLCommand)->procData;
pCurrentDCLCommand = me->fCurrentDCLCommand;
pDCLTransferPacket = &me->fTransfers[me->fPingCount * kNumPacketsPerPingPong];
for (packetNum = 0;
((packetNum < kNumPacketsPerPingPong) && (pCurrentDCLCommand != NULL));
packetNum++) {
packetBuffer = (UInt8 *)pDCLTransferPacket->buffer;
packetHeader = *((UInt32 *) packetBuffer);
packetBuffer += sizeof (UInt32);
packetSize = (OSSwapBigToHostInt32(packetHeader) & kFWIsochDataLength) >> kFWIsochDataLengthPhase;
getNextPacket = false;
while ((!getNextPacket) && (pCurrentDCLCommand != NULL)) {
RunListeningDCLEngine (
&pCurrentDCLCommand,
packetHeader,
&packetBuffer,
&packetSize,
&getNextPacket);
}
pDCLTransferPacket++;
}
me->fCurrentDCLCommand = pCurrentDCLCommand;
me->fPingCount++;
if(me->fPingCount > kNumPingPongs)
me->fPingCount = 0;
}
void IODCLTranslator::TalkingDCLPingPongProc(DCLCommand* pDCLCommand)
{
IODCLTranslator * me;
DCLCommand* pCurrentDCLCommand;
DCLTransferPacket* pDCLTransferPacket;
UInt8 * packetBuffer;
UInt32 packetHeader;
UInt32 packetSize;
UInt32 packetNum;
bool getNextPacket;
me = (IODCLTranslator *)((DCLCallProc*)pDCLCommand)->procData;
pCurrentDCLCommand = me->fCurrentDCLCommand;
pDCLTransferPacket = &me->fTransfers[me->fPingCount * kNumPacketsPerPingPong];
for (packetNum = 0;
((packetNum < kNumPacketsPerPingPong) && (pCurrentDCLCommand != NULL));
packetNum++) {
packetBuffer = (UInt8 *)pDCLTransferPacket->buffer;
packetSize = sizeof (UInt32);
getNextPacket = false;
while ((!getNextPacket) && (pCurrentDCLCommand != NULL)) {
RunTalkingDCLEngine (&(me->fPacketHeader),
&pCurrentDCLCommand,
&packetBuffer,
&packetSize,
&getNextPacket);
}
packetSize -= 4; packetHeader =
(packetSize << kFWIsochDataLengthPhase) |
(OSSwapBigToHostInt32(me->fPacketHeader) & ~(kFWIsochDataLength));
*((UInt32 *) packetBuffer) = OSSwapHostToBigInt32(packetHeader);
packetSize += 4; pDCLTransferPacket->size = packetSize;
me->fHWProgram->notify(kFWDCLModifyNotification,
(DCLCommand**) pDCLTransferPacket, 1);
pDCLTransferPacket++;
}
me->fCurrentDCLCommand = pCurrentDCLCommand;
me->fPingCount++;
if(me->fPingCount > kNumPingPongs)
me->fPingCount = 0;
}
OSDefineMetaClassAndStructors(IODCLTranslateTalk, IODCLTranslator)
IOReturn IODCLTranslateTalk::compile(IOFWSpeed speed, UInt32 chan)
{
int pingPongNum;
int packetNum;
DCLTransferPacket* pDCLTransferPacket = &fTransfers[0];
DCLCallProc* pDCLPingPongProc = &fCalls[0];
UInt8 *pingPongBuffer = fBuffer;
if(!fHWProgram)
return kIOReturnInternalError;
fPacketHeader = OSSwapHostToBigInt32( chan << kFWIsochChanNumPhase );
fStartLabel.pNextDCLCommand = (DCLCommand*)pDCLTransferPacket;
fStartLabel.opcode = kDCLLabelOp;
for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) {
for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) {
pDCLTransferPacket->pNextDCLCommand = (DCLCommand*)(pDCLTransferPacket+1);
pDCLTransferPacket->opcode = kDCLSendPacketWithHeaderStartOp | kFWDCLOpDynamicFlag;
pDCLTransferPacket->buffer = pingPongBuffer;
pDCLTransferPacket->size = kMaxIsochPacketSize;
pingPongBuffer += kMaxIsochPacketSize;
pDCLTransferPacket++;
}
(pDCLTransferPacket-1)->pNextDCLCommand = (DCLCommand*)pDCLPingPongProc;
pDCLPingPongProc->pNextDCLCommand = (DCLCommand*) pDCLTransferPacket;
pDCLPingPongProc->opcode = kDCLCallProcOp;
pDCLPingPongProc->proc = TalkingDCLPingPongProc;
pDCLPingPongProc->procData = (UInt32) this;
pDCLPingPongProc++;
}
(pDCLPingPongProc-1)->pNextDCLCommand = (DCLCommand*)&fJumpToStart;
fJumpToStart.pNextDCLCommand = NULL;
fJumpToStart.opcode = kDCLJumpOp | kFWDCLOpDynamicFlag;
fJumpToStart.pJumpDCLLabel = &fStartLabel;
return fHWProgram->compile(speed, chan);
}
IOReturn IODCLTranslateTalk::start()
{
int i;
fPingCount = 0;
for(i=0; i<kNumPingPongs; i++) {
TalkingDCLPingPongProc((DCLCommand*)&fCalls[i]);
}
return fHWProgram->start();
}
OSDefineMetaClassAndStructors(IODCLTranslateListen, IODCLTranslator)
IOReturn IODCLTranslateListen::compile(IOFWSpeed speed, UInt32 chan)
{
int pingPongNum;
int packetNum;
DCLTransferPacket* pDCLTransferPacket = &fTransfers[0];
DCLCallProc* pDCLPingPongProc = &fCalls[0];
UInt8 *pingPongBuffer = fBuffer;
if(!fHWProgram)
return kIOReturnInternalError;
fPacketHeader = OSSwapHostToBigInt32( chan << kFWIsochChanNumPhase );
fStartLabel.pNextDCLCommand = (DCLCommand*)pDCLTransferPacket;
fStartLabel.opcode = kDCLLabelOp;
for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) {
for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) {
pDCLTransferPacket->pNextDCLCommand = (DCLCommand*)(pDCLTransferPacket+1);
pDCLTransferPacket->opcode = kDCLReceivePacketStartOp | kFWDCLOpDynamicFlag;
pDCLTransferPacket->buffer = pingPongBuffer;
pDCLTransferPacket->size = kMaxIsochPacketSize;
pingPongBuffer += kMaxIsochPacketSize;
pDCLTransferPacket++;
}
(pDCLTransferPacket-1)->pNextDCLCommand = (DCLCommand*)pDCLPingPongProc;
pDCLPingPongProc->pNextDCLCommand = (DCLCommand*) pDCLTransferPacket;
pDCLPingPongProc->opcode = kDCLCallProcOp;
pDCLPingPongProc->proc = ListeningDCLPingPongProc;
pDCLPingPongProc->procData = (UInt32) this;
pDCLPingPongProc++;
}
(pDCLPingPongProc-1)->pNextDCLCommand = (DCLCommand*)&fJumpToStart;
fJumpToStart.pNextDCLCommand = NULL;
fJumpToStart.opcode = kDCLJumpOp | kFWDCLOpDynamicFlag;
fJumpToStart.pJumpDCLLabel = &fStartLabel;
return fHWProgram->compile(speed, chan);
}
IOReturn IODCLTranslateListen::start()
{
fPingCount = 0;
return fHWProgram->start();
}