📄 plio.c
字号:
/*
* ======== plio.c ========
*/
#include <std.h>
#include <fxn.h>
#include <hwi.h>
#include <pip.h>
#include <sys.h>
#include <lio.h>
#include <plio.h>
#include <string.h> /* for memset() */
static Void rxCallback(Arg arg, Uns nmaus);
static Void txCallback(Arg arg, Uns nmaus);
static Void transfer (PLIO_Handle plio, Uns numFrames);
#pragma CODE_SECTION(PLIO_new, ".text:init");
#pragma CODE_SECTION(PLIO_rxPrime, ".text:PLIO_rx");
#pragma CODE_SECTION(PLIO_rxStart, ".text:PLIO_rx");
#pragma CODE_SECTION(PLIO_txPrime, ".text:PLIO_tx");
#pragma CODE_SECTION(PLIO_txStart, ".text:PLIO_tx");
#pragma CODE_SECTION(txCallback, ".text:PLIO_tx");
#pragma CODE_SECTION(rxCallback, ".text:PLIO_rx");
/*
* These macros are used to work-around a problem with 'notifyWriter'
* calls from PLIO_txStart() ...
*/
#ifdef _55_
/* PIP_Obj structure is defined differently for 55x */
#define getNotifyWriterFxn(pip) ((pip)->writerSock.notifyFxn.fxn)
#define setNotifyWriterFxn(pip, notify) \
((pip)->writerSock.notifyFxn.fxn = (notify))
#else
#define getNotifyWriterFxn(pip) ((pip)->notifyWriter.fxn)
#define setNotifyWriterFxn(pip, notify) ((pip)->notifyWriter.fxn = (notify))
#endif
/*
* ======== PLIO_ATTRS ========
*/
PLIO_Attrs PLIO_ATTRS = {
NULL, // name
0 // arg to LIO_open
};
/*
* ======== PLIO_new ========
*/
Void PLIO_new(
PLIO_Handle plio,
PIP_Handle pip,
LIO_Mode mode,
LIO_Fxns *fxns,
PLIO_Attrs *attrs
)
{
LIO_Tcallback cb;
plio->pip = pip;
plio->fxns = fxns;
plio->submitCount = 0;
plio->submitLimit = PIP_getWriterNumFrames(pip);
if (attrs == NULL) {
attrs = &PLIO_ATTRS;
}
if (mode == LIO_INPUT) {
cb = rxCallback;
plio->curdesc = PIP_getWriterCurdesc(pip);
}
else {
cb = txCallback;
plio->curdesc = PIP_getReaderCurdesc(pip);
}
/* open the channel */
plio->controller = fxns->open(attrs->name, mode, attrs->openArgs,
cb, (Arg)plio);
if (plio->controller == NULL) {
SYS_abort("PLIO_new: controller open failed");
}
}
/*
* ======== transfer ========
* plio->submitCount
* The count of frames submitted to the LIO controller is stored
* in plio->submitCount. Transfer() looks ahead in the pipe using
* the pipe descriptor. The number of frames taken from the pipe
* in this way is kept in plio->submitCount. Therefore the number of
* frames available in the pipe is the number of frames indicated by
* PIP_getReaderNumFrames() or PIP_getWriterNumFrames()
* less the value of plio->submitCount.
*
* plio->submitLimit
* The capacity of the LIO controller is stored in plio->submitLimit.
* At initialization plio->submitLimit is set to a large number.
* When the LIO submit returns an error, plio->submitLimit is set to
* the value of plio->submitCount. Thereafter, plio->submitLimit
* represents the maximum frames the controller can accept.
*/
static Void transfer (PLIO_Handle plio, Uns numFrames)
{
PIP_Curdesc *curdesc;
if (numFrames > plio->submitCount) { // check for available frames
curdesc = plio->curdesc; // pipe descriptor
plio->curdesc = curdesc->next; // next pipe descriptor
plio->submitCount++; // increment counter
if ( 0 > // submit returns negative # for error
plio->fxns->submit ( // submit function
plio->controller, // channel object
curdesc->addr, // frame address
curdesc->size * sizeof(Int) // require count in MAUs,
) // PIP element is a word
)
{ // frame not accepted
plio->submitCount--; // decrement counter
plio->curdesc = curdesc; // previous descriptor
plio->submitLimit = plio->submitCount; // record max frames
}
}
}
/*
* ======== rxCallback ========
*/
static Void rxCallback (Arg arg, Uns nmaus)
{
PLIO_Handle plio = (PLIO_Handle)(arg);
PIP_Handle pip = plio->pip;
/*
* Must update the pipe before calling submit again.
* We have used the pointer to the next frame,
* but PIP_alloc has not been called yet.
*/
PIP_alloc(pip);
/* set size and return completed frame - PIP needs size in words! */
PIP_setWriterSize(pip, nmaus / sizeof(Int));
PIP_put(pip);
/* decrement count of submitted frames */
plio->submitCount--;
/* start next transfer */
transfer(plio, PIP_getWriterNumFrames(plio->pip));
}
/*
* ======== txCallback ========
*/
static Void txCallback (Arg arg, Uns nmaus)
{
PLIO_Handle plio = (PLIO_Handle)(arg);
PIP_Handle pip = plio->pip;
/*
* Must update the pipe before calling submit again.
* We have used the pointer to the next frame,
* but PIP_get has not been called yet.
*/
PIP_get(pip);
/* return completed frame */
PIP_free(pip);
/* decrement count of submitted frames */
plio->submitCount--;
/* start next transfer */
transfer(plio, PIP_getReaderNumFrames(plio->pip));
}
/*
* ======== PLIO_rxPrime ========
* submit one frame if receive not busy
*/
Void PLIO_rxPrime (PLIO_Handle plio)
{
Uns imask;
imask = HWI_disable();
if (plio->submitCount < plio->submitLimit) {
transfer(plio, PIP_getWriterNumFrames(plio->pip));
}
HWI_restore(imask);
}
/*
* ======== PLIO_rxStart ========
* submit frames to receiver
*
* CONSTRAINTS:
* - PLIO_rxStart() may only be called in main() before interrupts
* are enabled
*/
Void PLIO_rxStart (PLIO_Handle plio, Uns frameCount)
{
for ( ; frameCount > 0; frameCount--) {
transfer(plio, PIP_getWriterNumFrames(plio->pip));
}
}
/*
* ======== PLIO_txPrime ========
* submit one frame if transmit not busy
*/
Void PLIO_txPrime (PLIO_Handle plio)
{
if (plio->submitCount < plio->submitLimit) {
transfer(plio, PIP_getReaderNumFrames(plio->pip));
}
}
/*
* ======== PLIO_txStart ========
* submit initialized frames to transmitter
*
* CONSTRAINTS:
* - PLIO_txStart() may only be called in main() before interrupts
* are enabled
*/
Void PLIO_txStart (PLIO_Handle plio, Uns frameCount, Uns initialValue)
{
PIP_Handle pip = plio->pip;
char *buf;
Fxn notifySave;
/*
* Work-around notifyWriter problem at startup.
* Without this work-around, the PIP_alloc() calls below cause
* notifyWriter to be called and the application to have incorrect
* view of the PIP state (application thinks an empty output frame
* is available when no frame is actually available).
*/
notifySave = getNotifyWriterFxn(pip);
setNotifyWriterFxn(pip, (Fxn)FXN_F_nop);
for ( ; frameCount > 0; frameCount--) {
if (PIP_getWriterNumFrames(pip) <= 0) break;
PIP_alloc(pip);
buf = PIP_getWriterAddr(pip);
memset(buf, initialValue, PIP_getWriterSize(pip) * sizeof(Int));
PIP_put(pip);
}
/* restore notifyWriter function to its' configured state */
setNotifyWriterFxn(pip, notifySave);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -