IOFWDCLTranslator.cpp [plain text]
#include <IOKit/firewire/IOFWDCLTranslator.h>
static void DCLReceivePacketStart(
DCLCommandPtr *ppCurrentDCLCommand,
UInt32 packetHeader,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferPacketPtr pDCLTransferPacket;
UInt8 * transferBuffer;
UInt8 * packetBuffer;
SInt32 transferSize, packetSize;
pDCLTransferPacket = (DCLTransferPacketPtr) *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(
DCLCommandPtr *ppCurrentDCLCommand,
UInt32 packetHeader,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferPacketPtr pDCLTransferPacket;
UInt8 * transferBuffer;
UInt8 * packetBuffer;
UInt32 transferSize, packetSize;
pDCLTransferPacket = (DCLTransferPacketPtr) *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(
DCLCommandPtr *ppCurrentDCLCommand,
UInt32 packetHeader,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferBufferPtr pDCLTransferBuffer;
UInt8 * buffer;
UInt32 bufferOffset, bufferSize;
UInt32 bufferSizeLeft;
UInt8 * packetBuffer;
UInt32 packetSize;
UInt32 transferSize;
pDCLTransferBuffer = (DCLTransferBufferPtr) *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(
DCLCommandPtr *ppCurrentDCLCommand,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferPacketPtr pDCLTransferPacket;
UInt8 * transferBuffer;
UInt8 * packetBuffer;
UInt32 transferSize, packetSize;
pDCLTransferPacket = (DCLTransferPacketPtr) *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(
DCLCommandPtr *ppCurrentDCLCommand,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferBufferPtr pDCLTransferBuffer;
UInt8 * buffer;
UInt32 bufferOffset, bufferSize;
UInt32 bufferSizeLeft;
UInt8 * packetBuffer;
UInt32 packetSize;
UInt32 transferPacketSize;
UInt32 transferSize;
pDCLTransferBuffer = (DCLTransferBufferPtr) *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(
DCLCommandPtr *ppCurrentDCLCommand,
UInt32 packetHeader,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLCommandPtr pCurrentDCLCommand;
DCLCallProcPtr pDCLCallProc;
DCLJumpPtr 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 = (DCLCallProcPtr) pCurrentDCLCommand;
if (pDCLCallProc->proc != NULL)
(*(pDCLCallProc->proc)) ((DCLCommandPtr) pDCLCallProc);
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
case kDCLJumpOp :
pDCLJump = (DCLJumpPtr) pCurrentDCLCommand;
pCurrentDCLCommand = (DCLCommandPtr) pDCLJump->pJumpDCLLabel;
*pGetNextPacket = false;
break;
default :
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
}
*ppCurrentDCLCommand = pCurrentDCLCommand;
}
static void RunTalkingDCLEngine(
UInt32 * packetHeader,
DCLCommandPtr *ppCurrentDCLCommand,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLCommandPtr pCurrentDCLCommand;
DCLCallProcPtr pDCLCallProc;
DCLJumpPtr pDCLJump;
DCLSetTagSyncBitsPtr pDCLSetTagSyncBits;
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 = (DCLCallProcPtr) pCurrentDCLCommand;
if (pDCLCallProc->proc != NULL)
(*(pDCLCallProc->proc)) ((DCLCommandPtr) pDCLCallProc);
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
case kDCLJumpOp :
pDCLJump = (DCLJumpPtr) pCurrentDCLCommand;
pCurrentDCLCommand = (DCLCommandPtr) pDCLJump->pJumpDCLLabel;
*pGetNextPacket = false;
break;
case kDCLLabelOp :
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
case kDCLSetTagSyncBitsOp :
pDCLSetTagSyncBits = (DCLSetTagSyncBitsPtr) pCurrentDCLCommand;
*packetHeader &= ~(kFWIsochTag | kFWIsochSy);
*packetHeader |= (pDCLSetTagSyncBits->tagBits << kFWIsochTagPhase);
*packetHeader |= (pDCLSetTagSyncBits->syncBits << kFWIsochSyPhase);
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
default :
pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand;
*pGetNextPacket = false;
break;
}
*ppCurrentDCLCommand = pCurrentDCLCommand;
}
OSDefineMetaClass( IODCLTranslator, IODCLProgram )
OSDefineAbstractStructors(IODCLTranslator, IODCLProgram)
bool IODCLTranslator::init(DCLCommandPtr toInterpret)
{
if(!IODCLProgram::init())
return false;
fToInterpret = toInterpret;
return true;
}
IOReturn IODCLTranslator::notify(UInt32 notificationType,
DCLCommandPtr *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();
}
void IODCLTranslator::ListeningDCLPingPongProc(DCLCommandPtr pDCLCommand)
{
IODCLTranslator * me;
DCLCommandPtr pCurrentDCLCommand;
DCLTransferPacketPtr pDCLTransferPacket;
UInt8 * packetBuffer;
UInt32 packetHeader;
UInt32 packetSize;
UInt32 packetNum;
bool getNextPacket;
me = (IODCLTranslator *)((DCLCallProcPtr)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 = (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(DCLCommandPtr pDCLCommand)
{
IODCLTranslator * me;
DCLCommandPtr pCurrentDCLCommand;
DCLTransferPacketPtr pDCLTransferPacket;
UInt8 * packetBuffer;
UInt32 packetHeader;
UInt32 packetSize;
UInt32 packetNum;
bool getNextPacket;
me = (IODCLTranslator *)((DCLCallProcPtr)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) |
(me->fPacketHeader & ~(kFWIsochDataLength));
*((UInt32 *) packetBuffer) = packetHeader;
packetSize += 4; pDCLTransferPacket->size = packetSize;
me->fHWProgram->notify(kFWDCLModifyNotification,
(DCLCommandPtr *) 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;
DCLTransferPacketPtr pDCLTransferPacket = &fTransfers[0];
DCLCallProcPtr pDCLPingPongProc = &fCalls[0];
UInt8 *pingPongBuffer = fBuffer;
if(!fHWProgram)
return kIOReturnInternalError;
fPacketHeader = chan << kFWIsochChanNumPhase;
fStartLabel.pNextDCLCommand = (DCLCommandPtr)pDCLTransferPacket;
fStartLabel.opcode = kDCLLabelOp;
for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) {
for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) {
pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr)(pDCLTransferPacket+1);
pDCLTransferPacket->opcode = kDCLSendPacketWithHeaderStartOp | kFWDCLOpDynamicFlag;
pDCLTransferPacket->buffer = pingPongBuffer;
pDCLTransferPacket->size = kMaxIsochPacketSize;
pingPongBuffer += kMaxIsochPacketSize;
pDCLTransferPacket++;
}
(pDCLTransferPacket-1)->pNextDCLCommand = (DCLCommandPtr)pDCLPingPongProc;
pDCLPingPongProc->pNextDCLCommand = (DCLCommandPtr) pDCLTransferPacket;
pDCLPingPongProc->opcode = kDCLCallProcOp;
pDCLPingPongProc->proc = TalkingDCLPingPongProc;
pDCLPingPongProc->procData = (UInt32) this;
pDCLPingPongProc++;
}
(pDCLPingPongProc-1)->pNextDCLCommand = (DCLCommandPtr)&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((DCLCommandPtr)&fCalls[i]);
}
return fHWProgram->start();
}
OSDefineMetaClassAndStructors(IODCLTranslateListen, IODCLTranslator)
IOReturn IODCLTranslateListen::compile(IOFWSpeed speed, UInt32 chan)
{
int pingPongNum;
int packetNum;
DCLTransferPacketPtr pDCLTransferPacket = &fTransfers[0];
DCLCallProcPtr pDCLPingPongProc = &fCalls[0];
UInt8 *pingPongBuffer = fBuffer;
if(!fHWProgram)
return kIOReturnInternalError;
fPacketHeader = chan << kFWIsochChanNumPhase;
fStartLabel.pNextDCLCommand = (DCLCommandPtr)pDCLTransferPacket;
fStartLabel.opcode = kDCLLabelOp;
for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) {
for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) {
pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr)(pDCLTransferPacket+1);
pDCLTransferPacket->opcode = kDCLReceivePacketStartOp | kFWDCLOpDynamicFlag;
pDCLTransferPacket->buffer = pingPongBuffer;
pDCLTransferPacket->size = kMaxIsochPacketSize;
pingPongBuffer += kMaxIsochPacketSize;
pDCLTransferPacket++;
}
(pDCLTransferPacket-1)->pNextDCLCommand = (DCLCommandPtr)pDCLPingPongProc;
pDCLPingPongProc->pNextDCLCommand = (DCLCommandPtr) pDCLTransferPacket;
pDCLPingPongProc->opcode = kDCLCallProcOp;
pDCLPingPongProc->proc = ListeningDCLPingPongProc;
pDCLPingPongProc->procData = (UInt32) this;
pDCLPingPongProc++;
}
(pDCLPingPongProc-1)->pNextDCLCommand = (DCLCommandPtr)&fJumpToStart;
fJumpToStart.pNextDCLCommand = NULL;
fJumpToStart.opcode = kDCLJumpOp | kFWDCLOpDynamicFlag;
fJumpToStart.pJumpDCLLabel = &fStartLabel;
return fHWProgram->compile(speed, chan);
}
IOReturn IODCLTranslateListen::start()
{
fPingCount = 0;
return fHWProgram->start();
}