Source to iokit/Families/IOFireWire/IOFWDCLTranslator.cpp
/*
* Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* The contents of this file constitute Original Code as defined in and
* are subject to the Apple Public Source License Version 1.1 (the
* "License"). You may not use this file except in compliance with the
* License. Please obtain a copy of the License at
* http://www.apple.com/publicsource and read it before using this file.
*
* This Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* HISTORY
*
*/
#include <IOKit/firewire/IOFWDCLTranslator.h>
////////////////////////////////////////////////////////////////////////////////
//
// FWDCLReceivePacketStart
//
// This routine runs a DCL receive packet start command.
//
static void DCLReceivePacketStart(
DCLCommandPtr *ppCurrentDCLCommand,
UInt32 packetHeader,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferPacketPtr pDCLTransferPacket;
UInt8 * transferBuffer;
UInt8 * packetBuffer;
SInt32 transferSize, packetSize;
// Recast DCL command.
pDCLTransferPacket = (DCLTransferPacketPtr) *ppCurrentDCLCommand;
// Get some parameters.
transferBuffer = (UInt8 *)pDCLTransferPacket->buffer;
transferSize = pDCLTransferPacket->size - sizeof (UInt32);
packetSize = *pPacketSize;
if (transferSize > packetSize)
transferSize = packetSize;
packetBuffer = *pPacketBuffer;
// Transfer the packet data.
*((UInt32 *) transferBuffer) = packetHeader;
transferBuffer += sizeof (UInt32);
if (transferSize > 0) {
bcopy (packetBuffer, transferBuffer, transferSize);
packetSize -= transferSize;
packetBuffer += transferSize;
}
// Check if we need another packet.
*pGetNextPacket = true;
if (pDCLTransferPacket->pNextDCLCommand != NULL)
{
if ((pDCLTransferPacket->pNextDCLCommand->opcode & ~kFWDCLOpFlagMask) ==
kDCLReceivePacketOp)
{
*pGetNextPacket = false;
}
}
// Update parameters.
*ppCurrentDCLCommand = pDCLTransferPacket->pNextDCLCommand;
*pPacketBuffer = packetBuffer;
*pPacketSize = packetSize;
}
////////////////////////////////////////////////////////////////////////////////
//
// DCLReceivePacket
//
// This routine runs a DCL receive packet command.
//
static void DCLReceivePacket(
DCLCommandPtr *ppCurrentDCLCommand,
UInt32 packetHeader,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferPacketPtr pDCLTransferPacket;
UInt8 * transferBuffer;
UInt8 * packetBuffer;
UInt32 transferSize, packetSize;
// Recast DCL command.
pDCLTransferPacket = (DCLTransferPacketPtr) *ppCurrentDCLCommand;
// Get some parameters.
transferBuffer = (UInt8 *)pDCLTransferPacket->buffer;
transferSize = pDCLTransferPacket->size;
packetSize = *pPacketSize;
if (transferSize > packetSize)
transferSize = packetSize;
packetBuffer = *pPacketBuffer;
// Transfer the packet data.
if (transferSize > 0)
{
bcopy (packetBuffer, transferBuffer, transferSize);
packetSize -= transferSize;
packetBuffer += transferSize;
}
// Check if we need another packet.
*pGetNextPacket = true;
if (pDCLTransferPacket->pNextDCLCommand != NULL)
{
if ((pDCLTransferPacket->pNextDCLCommand->opcode & ~kFWDCLOpFlagMask) ==
kDCLReceivePacketOp)
{
*pGetNextPacket = false;
}
}
// Update parameters.
*ppCurrentDCLCommand = pDCLTransferPacket->pNextDCLCommand;
*pPacketBuffer = packetBuffer;
*pPacketSize = packetSize;
}
////////////////////////////////////////////////////////////////////////////////
//
// FWDCLReceiveBuffer
//
// This routine runs a DCL receive buffer command.
//zzz should we include packet header?
//zzz should we clip off end of packet when buffer is filled?
//
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;
// Recast current DCL command.
pDCLTransferBuffer = (DCLTransferBufferPtr) *ppCurrentDCLCommand;
// Get some parameters.
buffer = (UInt8 *)pDCLTransferBuffer->buffer;
bufferOffset = pDCLTransferBuffer->bufferOffset;
bufferSize = pDCLTransferBuffer->size;
packetBuffer = *pPacketBuffer;
packetSize = *pPacketSize;
// Compute size of transfer.
bufferSizeLeft = bufferSize - bufferOffset;
if (bufferSizeLeft > packetSize)
transferSize = packetSize;
else
transferSize = bufferSizeLeft;
// Transfer the packet data.
if (transferSize > 0)
{
bcopy (packetBuffer, buffer + bufferOffset, transferSize);
packetBuffer += transferSize;
packetSize -= transferSize;
bufferOffset += transferSize;
}
// Check if we're done with this DCL or need another packet.
if (bufferOffset == bufferSize)
{
*ppCurrentDCLCommand = pDCLTransferBuffer->pNextDCLCommand;
*pGetNextPacket = false;
}
else
{
*pGetNextPacket = true;
}
// Update parameters.
pDCLTransferBuffer->bufferOffset = bufferOffset;
*pPacketBuffer = packetBuffer;
*pPacketSize = packetSize;
}
////////////////////////////////////////////////////////////////////////////////
//
// DCLSendPacket
//
// This routine runs a DCL send packet command.
//
static void DCLSendPacket(
DCLCommandPtr *ppCurrentDCLCommand,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLTransferPacketPtr pDCLTransferPacket;
UInt8 * transferBuffer;
UInt8 * packetBuffer;
UInt32 transferSize, packetSize;
// Recast DCL command.
pDCLTransferPacket = (DCLTransferPacketPtr) *ppCurrentDCLCommand;
// Get some parameters.
transferBuffer = (UInt8 *)pDCLTransferPacket->buffer;
transferSize = pDCLTransferPacket->size;
packetSize = *pPacketSize;
packetBuffer = *pPacketBuffer + packetSize;
// Transfer the packet data.
bcopy (transferBuffer, packetBuffer, transferSize);
packetSize += transferSize;
// Check if we need another packet.
*pGetNextPacket = true;
if (pDCLTransferPacket->pNextDCLCommand != NULL)
{
if ((pDCLTransferPacket->pNextDCLCommand->opcode & ~kFWDCLOpFlagMask) ==
kDCLSendPacketOp)
{
*pGetNextPacket = false;
}
}
// Update parameters.
*ppCurrentDCLCommand = pDCLTransferPacket->pNextDCLCommand;
*pPacketSize = packetSize;
}
////////////////////////////////////////////////////////////////////////////////
//
// DCLSendBuffer
//
// This routine runs a DCL send buffer command.
//zzz should we clip off end of packet when buffer is emptied?
//
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;
// Recast current DCL command.
pDCLTransferBuffer = (DCLTransferBufferPtr) *ppCurrentDCLCommand;
// Get some parameters.
buffer = (UInt8 *)pDCLTransferBuffer->buffer;
bufferOffset = pDCLTransferBuffer->bufferOffset;
bufferSize = pDCLTransferBuffer->size;
packetSize = *pPacketSize;
packetBuffer = *pPacketBuffer + packetSize;
transferPacketSize = pDCLTransferBuffer->packetSize;
// Compute size of transfer.
bufferSizeLeft = bufferSize - bufferOffset;
if (bufferSizeLeft > transferPacketSize)
transferSize = transferPacketSize;
else
transferSize = bufferSizeLeft;
// Transfer the packet data.
if (transferSize > 0)
{
bcopy (buffer + bufferOffset, packetBuffer, transferSize);
packetSize += transferSize;
bufferOffset += transferSize;
}
// Check if we're done with this DCL or need another packet.
//zzz is this the best way to do this?
//zzz what if the next transfer command is a transfer packet command?
if (bufferOffset == bufferSize)
{
*ppCurrentDCLCommand = pDCLTransferBuffer->pNextDCLCommand;
*pGetNextPacket = false;
}
else
{
*pGetNextPacket = true;
}
// Update parameters.
pDCLTransferBuffer->bufferOffset = bufferOffset;
*pPacketSize = packetSize;
}
////////////////////////////////////////////////////////////////////////////////
//
// FWRunTranslatedDCLEngine
//
// This routine runs the current DCL command using the given packet. It will
// update the current DCL command, packet buffer pointer, packet size, and will
// set get next packet to true if it needs another packet.
//zzz maybe a vector table would be nice
//zzz implement rest of DCL commands.
//
static void RunListeningDCLEngine(
DCLCommandPtr *ppCurrentDCLCommand,
UInt32 packetHeader,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLCommandPtr pCurrentDCLCommand;
DCLCallProcPtr pDCLCallProc;
DCLJumpPtr pDCLJump;
// Run the current DCL command.
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;
// Call the handler if there is one.
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;
}
// Update current DCL command.
*ppCurrentDCLCommand = pCurrentDCLCommand;
}
////////////////////////////////////////////////////////////////////////////////
//
// FWRunTranslatedTalkingDCLEngine
//
// This routine runs the current DCL command using the given packet. It will
// update the current DCL command, packet buffer pointer, packet size, and will
// set get next packet to true if it needs another packet.
//zzz maybe a vector table would be nice
//
static void RunTalkingDCLEngine(
UInt32 * packetHeader,
DCLCommandPtr *ppCurrentDCLCommand,
UInt8 * *pPacketBuffer,
UInt32 *pPacketSize,
bool *pGetNextPacket)
{
DCLCommandPtr pCurrentDCLCommand;
DCLCallProcPtr pDCLCallProc;
DCLJumpPtr pDCLJump;
DCLSetTagSyncBitsPtr pDCLSetTagSyncBits;
// Run the current DCL command.
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;
// Call the handler if there is one.
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;
}
// Update current DCL command.
*ppCurrentDCLCommand = pCurrentDCLCommand;
}
OSDefineMetaClass( IODCLTranslator, IODCLProgram )
OSDefineAbstractStructors(IODCLTranslator, IODCLProgram)
bool IODCLTranslator::init(DCLCommandPtr toInterpret)
{
if(!IODCLProgram::init())
return false;
// Allocate buffers etc. for programs
fToInterpret = toInterpret;
return true;
}
IOReturn IODCLTranslator::notify(UInt32 notificationType,
DCLCommandPtr *dclCommandList, UInt32 numDCLCommands)
{
return kIOReturnSuccess; // Nothing to do, we're interpreting anyway
}
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];
// Run all packets through DCL program.
for (packetNum = 0;
((packetNum < kNumPacketsPerPingPong) && (pCurrentDCLCommand != NULL));
packetNum++) {
// Compute packet size.
packetBuffer = (UInt8 *)pDCLTransferPacket->buffer;
packetHeader = *((UInt32 *) packetBuffer);
packetBuffer += sizeof (UInt32);
packetSize = (packetHeader & kFWIsochDataLength) >> kFWIsochDataLengthPhase;
// Run this packet through DCL program.
getNextPacket = false;
while ((!getNextPacket) && (pCurrentDCLCommand != NULL)) {
RunListeningDCLEngine (
&pCurrentDCLCommand,
packetHeader,
&packetBuffer,
&packetSize,
&getNextPacket);
}
// Update for next packet.
pDCLTransferPacket++;
}
// Update DCL translation data.
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];
// Run all packets through DCL program.
for (packetNum = 0;
((packetNum < kNumPacketsPerPingPong) && (pCurrentDCLCommand != NULL));
packetNum++) {
// Compute packet size.
packetBuffer = (UInt8 *)pDCLTransferPacket->buffer;
packetSize = sizeof (UInt32);
// Run this packet through DCL program.
getNextPacket = false;
while ((!getNextPacket) && (pCurrentDCLCommand != NULL)) {
RunTalkingDCLEngine (&(me->fPacketHeader),
&pCurrentDCLCommand,
&packetBuffer,
&packetSize,
&getNextPacket);
}
// Update packet header.
packetSize -= 4;//zzz not the best way
packetHeader =
(packetSize << kFWIsochDataLengthPhase) |
(me->fPacketHeader & ~(kFWIsochDataLength));
*((UInt32 *) packetBuffer) = packetHeader;
// Update send packet DCL.
packetSize += 4;//zzz really, not the best way
// Change the transfer packet command.
pDCLTransferPacket->size = packetSize;
// Send notification to DCL compiler.
me->fHWProgram->notify(kFWDCLModifyNotification,
(DCLCommandPtr *) pDCLTransferPacket, 1);
// Update for next packet.
pDCLTransferPacket++;
}
// Update DCL translation data.
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;
// Create label for start of loop.
fStartLabel.pNextDCLCommand = (DCLCommandPtr)pDCLTransferPacket;
fStartLabel.opcode = kDCLLabelOp;
// Create kNumPingPongs ping pong buffer lists of kNumPacketsPerPingPong
// packets each.
for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) {
// Create transfer DCL for each packet.
for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) {
// Receive one packet up to kMaxIsochPacketSize bytes.
pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr)(pDCLTransferPacket+1);
pDCLTransferPacket->opcode = kDCLSendPacketWithHeaderStartOp | kFWDCLOpDynamicFlag;
pDCLTransferPacket->buffer = pingPongBuffer;
pDCLTransferPacket->size = kMaxIsochPacketSize;
pingPongBuffer += kMaxIsochPacketSize;
pDCLTransferPacket++;
}
// Correct next opcode for last transfer op.
(pDCLTransferPacket-1)->pNextDCLCommand = (DCLCommandPtr)pDCLPingPongProc;
// Call the ping pong proc.
pDCLPingPongProc->pNextDCLCommand = (DCLCommandPtr) pDCLTransferPacket;
pDCLPingPongProc->opcode = kDCLCallProcOp;
pDCLPingPongProc->proc = TalkingDCLPingPongProc;
pDCLPingPongProc->procData = (UInt32) this;
pDCLPingPongProc++;
}
// Correct next opcode for last call op.
(pDCLPingPongProc-1)->pNextDCLCommand = (DCLCommandPtr)&fJumpToStart;
// Loop to start of ping pong.
fJumpToStart.pNextDCLCommand = NULL;
fJumpToStart.opcode = kDCLJumpOp | kFWDCLOpDynamicFlag;
fJumpToStart.pJumpDCLLabel = &fStartLabel;
return fHWProgram->compile(speed, chan);
}
IOReturn IODCLTranslateTalk::start()
{
int i;
fPingCount = 0;
// Prime all buffers
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;
// Create label for start of loop.
fStartLabel.pNextDCLCommand = (DCLCommandPtr)pDCLTransferPacket;
fStartLabel.opcode = kDCLLabelOp;
// Create kNumPingPongs ping pong buffer lists of kNumPacketsPerPingPong
// packets each.
for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) {
// Create transfer DCL for each packet.
for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) {
// Receive one packet up to kMaxIsochPacketSize bytes.
pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr)(pDCLTransferPacket+1);
pDCLTransferPacket->opcode = kDCLReceivePacketStartOp | kFWDCLOpDynamicFlag;
pDCLTransferPacket->buffer = pingPongBuffer;
pDCLTransferPacket->size = kMaxIsochPacketSize;
pingPongBuffer += kMaxIsochPacketSize;
pDCLTransferPacket++;
}
// Correct next opcode for last transfer op.
(pDCLTransferPacket-1)->pNextDCLCommand = (DCLCommandPtr)pDCLPingPongProc;
// Call the ping pong proc.
pDCLPingPongProc->pNextDCLCommand = (DCLCommandPtr) pDCLTransferPacket;
pDCLPingPongProc->opcode = kDCLCallProcOp;
pDCLPingPongProc->proc = ListeningDCLPingPongProc;
pDCLPingPongProc->procData = (UInt32) this;
pDCLPingPongProc++;
}
// Correct next opcode for last call op.
(pDCLPingPongProc-1)->pNextDCLCommand = (DCLCommandPtr)&fJumpToStart;
// Loop to start of ping pong.
fJumpToStart.pNextDCLCommand = NULL;
fJumpToStart.opcode = kDCLJumpOp | kFWDCLOpDynamicFlag;
fJumpToStart.pJumpDCLLabel = &fStartLabel;
return fHWProgram->compile(speed, chan);
}
IOReturn IODCLTranslateListen::start()
{
fPingCount = 0;
return fHWProgram->start();
}