📄 pio.c
字号:
/*
* Copyright 2003 by Texas Instruments Incorporated.
* All rights reserved. Property of Texas Instruments Incorporated.
* Restricted rights to use, duplicate or disclose this code are
* granted through contract.
*
*/
/* "@(#) DDK 1.10.00.23 07-02-03 (ddk-b12)" */
/*
* ======== pio.c ========
*/
#include <std.h>
#include <dev.h>
#include <fxn.h>
#include <hwi.h>
#include <pip.h>
#include <que.h>
#include <sys.h>
#include <iom.h>
#include <pio.h>
#include <string.h> /* for memset() */
static Void rxCallback(Arg arg, IOM_Packet *packet);
static Void txCallback(Arg arg, IOM_Packet *packet);
static Void transfer (PIO_Handle pio, Uns numFrames);
#pragma CODE_SECTION(PIO_init, ".text:init");
#pragma CODE_SECTION(PIO_new, ".text:init");
#pragma CODE_SECTION(PIO_rxPrime, ".text:PIO_rx");
#pragma CODE_SECTION(PIO_rxStart, ".text:PIO_rx");
#pragma CODE_SECTION(PIO_txPrime, ".text:PIO_tx");
#pragma CODE_SECTION(PIO_txStart, ".text:PIO_tx");
#pragma CODE_SECTION(txCallback, ".text:PIO_tx");
#pragma CODE_SECTION(rxCallback, ".text:PIO_rx");
/*
* These macros are used to work-around a problem with 'notifyWriter'
* calls from PIO_txStart() ...
*/
#ifdef _55_
/* PIP_Obj structure is defined differently for 55x */
#define getNotifyWriterFxn(pip) ((pip)->readerSock.notifyFxn.fxn)
#define setNotifyWriterFxn(pip, notify) \
((pip)->readerSock.notifyFxn.fxn = (notify))
#else
#define getNotifyWriterFxn(pip) ((pip)->notifyWriter.fxn)
#define setNotifyWriterFxn(pip, notify) ((pip)->notifyWriter.fxn = (notify))
#endif
/*
* ======== PIO_ATTRS ========
*/
PIO_Attrs PIO_ATTRS = {
0 // arg to mdCreateChan
};
/* ======== PIO_init ========
*
*/
Void PIO_init(Void)
{
/*
* Module initialization
*/
}
/*
* ======== PIO_new ========
*/
Void PIO_new(PIO_Handle pio, PIP_Handle pip, String name, Int mode,
PIO_Attrs *attrs)
{
IOM_TiomCallback cbFxn;
DEV_Device *entry;
Int i, status;
if (attrs == NULL) {
attrs = &PIO_ATTRS;
}
/*
* Find device structure in device table for device with name 'name'.
* DEV_match() returns the remaining name string for use by the
* mini-driver's create() function.
*/
name = DEV_match(name, &entry);
if (entry == NULL) {
SYS_abort("PIO_new: DEV_match() failed\n");
}
if (entry->type != DEV_IOMTYPE) {
SYS_abort("PIO_new: invalid device type\n");
}
pio->pip = pip;
pio->fxns = (IOM_Fxns *)entry->fxns;
pio->mode = mode;
pio->submitCount = 0;
/* Initialize queue structures */
QUE_new(&pio->freeList);
/* Initialize the freeList with packets */
for (i=0; i < PIO_MAXPACKETS; i++) {
QUE_put(&pio->freeList, &pio->packet[i]);
}
if (mode == IOM_INPUT) {
cbFxn = (IOM_TiomCallback)rxCallback;
pio->curdesc = PIP_getWriterCurdesc(pip);
}
else {
cbFxn = (IOM_TiomCallback)txCallback;
pio->curdesc = PIP_getReaderCurdesc(pip);
}
/* open the channel */
status = pio->fxns->mdCreateChan(&pio->mdChan, entry->devp,
name, mode, attrs->openArgs, cbFxn, pio);
if (status != IOM_COMPLETED) {
SYS_abort("PIO_new: mdCreateChan failed");
}
}
/*
* ======== transfer ========
* pio->submitCount
* The count of frames submitted to the IO mini-driver is stored
* in pio->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 pio->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 pio->submitCount.
*/
static Void transfer (PIO_Handle pio, Uns numFrames)
{
PIP_Curdesc *curdesc;
IOM_Packet *packet;
IOM_TiomCallback cbFxn;
Int status;
/*
* check to see if we have an available PIP frame and an IOM_Packet
* so that we can submit the I/O request to the mini-driver
*/
if ((numFrames > pio->submitCount) && (pio->submitCount < PIO_MAXPACKETS)) {
packet = QUE_get(&pio->freeList);
/* assert(packet != &pio->freeList); */
curdesc = pio->curdesc; // pipe descriptor
pio->curdesc = curdesc->next; // next pipe descriptor
pio->submitCount++; // increment counter
/* Initialize the packet */
packet->addr = curdesc->addr;
packet->size = curdesc->size * sizeof(Int);
if (pio->mode == IOM_INPUT) {
packet->cmd = IOM_READ;
cbFxn = (IOM_TiomCallback)rxCallback;
}
else if (pio->mode == IOM_OUTPUT) {
packet->cmd = IOM_WRITE;
cbFxn = (IOM_TiomCallback)txCallback;
}
status = pio->fxns->mdSubmitChan(pio->mdChan, packet);
if (status == IOM_COMPLETED) {
/*
* Since the mini-driver completed the I/O, the callback will
* not be called. We need to handle the callback ourselves.
* This call might cause recursive call back to transfer().
*/
cbFxn(pio, packet);
}
else if (status < 0) {
/*
* This should never happen. IOM mini drivers must be able
* to queue all submitted IOM_Packets.
*/
SYS_abort("PIO: mdSubmitChan() failed!");
}
}
}
/*
* ======== rxCallback ========
*/
static Void rxCallback (Arg arg, IOM_Packet *packet)
{
PIO_Handle pio = (PIO_Handle)(arg);
PIP_Handle pip = pio->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, packet->size / sizeof(Int));
PIP_put(pip);
/* decrement count of submitted frames */
pio->submitCount--;
/* Must put the packet back of the freeList */
QUE_put(&pio->freeList, packet);
/* start next transfer */
transfer(pio, PIP_getWriterNumFrames(pio->pip));
}
/*
* ======== txCallback ========
*/
static Void txCallback (Arg arg, IOM_Packet *packet)
{
PIO_Handle pio = (PIO_Handle)(arg);
PIP_Handle pip = pio->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 */
pio->submitCount--;
/* Must put the packet back of the freeList */
QUE_put(&pio->freeList, packet);
/* start next transfer */
transfer(pio, PIP_getReaderNumFrames(pio->pip));
}
/*
* ======== PIO_rxPrime ========
* submit one frame if receive not busy
*/
Void PIO_rxPrime (PIO_Handle pio)
{
Uns imask;
imask = HWI_disable();
transfer(pio, PIP_getWriterNumFrames(pio->pip));
HWI_restore(imask);
}
/*
* ======== PIO_rxStart ========
* submit frames to receiver
*
* CONSTRAINTS:
* - PIO_rxStart() may only be called in main() before interrupts
* are enabled
*/
Void PIO_rxStart (PIO_Handle pio, Uns frameCount)
{
for ( ; frameCount > 0; frameCount--) {
transfer(pio, PIP_getWriterNumFrames(pio->pip));
}
}
/*
* ======== PIO_txPrime ========
* submit one frame if transmit not busy
*/
Void PIO_txPrime (PIO_Handle pio)
{
Uns imask;
imask = HWI_disable();
transfer(pio, PIP_getReaderNumFrames(pio->pip));
HWI_restore(imask);
}
/*
* ======== PIO_txStart ========
* submit initialized frames to transmitter
*
* CONSTRAINTS:
* - PIO_txStart() may only be called in main() before interrupts
* are enabled
*/
Void PIO_txStart (PIO_Handle pio, Uns frameCount, Uns initialValue)
{
PIP_Handle pip = pio->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 + -