📄 dpx_rtos.c
字号:
psDpxDdb = (sDPX_DDB *)duplex;
/* reset the Interrupt Processing Enable Flag in the device DDB */
psDpxDdb->u1IntrProcEn = 0;
u1ActiveDevNumber--;
/* update the IRQ record table */
pSysInfo = (DPX_ADAPTER_PCI_HANDLE *) (psDpxDdb->pSysInfo);
for(i=0; i < DPX_MAX_NUM_DEVS; i++)
{
if(pSysInfo->irq == IrqInstalled[i].irq)
{
/* decrement count for the IRQ */
(IrqInstalled[i].count)--;
/* if all device has been removed for the IRQ */
if(IrqInstalled[i].count == 0)
{
/* uninstall Handler in processor's interrupt vector table */
/* sysIntDisablePIC(pSysInfo->irq); */
pciIntDisconnect(INUM_TO_IVEC(pSysInfo->irq + INT_NUM_IRQ0),
sysDuplexIntHandler );
/* update the record */
IrqInstalled[i].irq = 0;
}
break;
}
}
#if CSW_PV_FLAG
if(i == DPX_MAX_NUM_DEVS)
{
/* we didn't find the Irq in the record table, something is terrible wrong */
printf("Duplex error: not find irq %d in the record\n", pSysInfo->irq);
for(i=0; i < DPX_MAX_NUM_DEVS; i++)
printf(" (%d, %d) ", IrqInstalled[i].irq, IrqInstalled[i].count);
}
#endif
/* No DUPLEX devices are activated for all IRQs */
if(u1ActiveDevNumber == 0)
{
/* kill sysDuplexDPRtask */
if( sDpxDprTsk.i4Id != 0)
{
/* try to graceful shutdown the task */
u1DPRactive = 0;
sysDuplexDelayFn(DPX_TASK_SHUTDOWN_DELAY);
/* then force to delete the task */
taskDelete( sDpxDprTsk.i4Id);
sDpxDprTsk.i4Id = 0;
}
/* delete the message queue */
msgQDelete(IntMsgQId);
}
}
/*******************************************************************************
**
** sysDuplexIntHandler
** ___________________________________________________________________________
**
** DESCRIPTION: This routine is invoked when one or more duplex devices
** interrupts the processor. It invokes duplexISR for each device
** for which interrupt processing is enabled.If at least one valid
** interrupt condition is detected by duplexISR, then this routine
** queues the interrupt context information for later processing
** by sysDuplexDPRtask.
**
** VALID STATES: Not applicable
**
** SIDE EFFECTS:
**
** INPUTS: None
**
** OUTPUTS: None
**
** RETURN CODES:None
**
*******************************************************************************/
VOID sysDuplexIntHandler(INT4 irq)
{
UINT1 u1NextDev;
sDPX_INT_CTXT sIntCtxt;
DPX_ADAPTER_PCI_HANDLE *pSysInfo;
if(psDpxGdd == DPX_NULL)
return;
/* initialize the sDPX_INT_CTXT */
sIntCtxt.u1NumDevs = 0;
for(u1NextDev=0; u1NextDev < DPX_MAX_NUM_DEVS; ++u1NextDev)
{
if(psDpxGdd->pDdb[u1NextDev] != DPX_NULL)
{
pSysInfo = (DPX_ADAPTER_PCI_HANDLE *) (psDpxGdd->pDdb[u1NextDev]->pSysInfo);
/* we only check the Duplex devices with the same IRQ and
their interrupt was enabled */
if((psDpxGdd->pDdb[u1NextDev]->u1IntrProcEn) && (irq == pSysInfo->irq))
{
/* call duplexISR */
if(duplexISR(psDpxGdd->pDdb[u1NextDev]))
{
/* save this device handle */
sIntCtxt.pu4DevHandles[sIntCtxt.u1NumDevs] =
(UINT4 *)(psDpxGdd->pDdb[u1NextDev]);
/* increment the inetrrupting device count */
(sIntCtxt.u1NumDevs)++;
}
}
#if CSW_PV_FLAG
softIntClr(psDpxGdd->pDdb[u1NextDev]->usrCtxt);
#endif
}
}
/* if at least one device has the interrupt conditions */
if(sIntCtxt.u1NumDevs != 0)
{
/* NOTE: You don't need to get an interrupt context buffer under
VxWorks or QNX RTOS. However the interrupt context buffers is
needed when the RTOS does not support message queue buffers
of arbitrary length. (For example, pSOS supports message
sizes of 4 long words only.)
*/
/* send a message to the sysDuplexDPRtask with interrupt cotext
information that consists of the device handlers for interrupting
DUPLEX devices */
msgQSend(IntMsgQId, (char *) &sIntCtxt, sizeof(sDPX_INT_CTXT), NO_WAIT,
MSG_PRI_NORMAL);
}
}
/*******************************************************************************
**
** sysDuplexDPRtask
** ___________________________________________________________________________
**
** DESCRIPTION: This routine is spawned as a sperate task within the RTOS. It
** retrieves interrupt status information saved for it by the
** sysDuplexIntHandler routine and invokes the duplexDPR routine
** for the appropriate device.
**
** VALID STATES: Not applicable
**
** SIDE EFFECTS:
**
** INPUTS: None
**
** OUTPUTS: None
**
** RETURN CODES:None
**
*******************************************************************************/
VOID sysDuplexDPRtask(VOID)
{
UINT1 u1NextDev;
INT4 MsgSize;
sDPX_INT_CTXT sIntCtxt;
sDPX_DDB *psDpxDdb;
do
{
/* wait for message sent from sysDuplexIntHandler */
MsgSize = msgQReceive(IntMsgQId,(char *)&sIntCtxt,sizeof(sDPX_INT_CTXT),
WAIT_FOREVER);
if(MsgSize == ERROR)
continue;
/* check message size consistence */
if(MsgSize != sizeof(sDPX_INT_CTXT))
continue;
/* for each interrupting device, invoke duplexDPR */
for(u1NextDev = 0; u1NextDev < sIntCtxt.u1NumDevs; u1NextDev++)
{
psDpxDdb = (sDPX_DDB *)(sIntCtxt.pu4DevHandles[u1NextDev]);
duplexDPR(psDpxDdb);
}
} while(u1DPRactive);
}
#else /** Polling mode **/
/*******************************************************************************
**
** sysDuplexIntInstallHandler (Polling mode )
** ___________________________________________________________________________
**
** DESCRIPTION: For the polling mode, if this function is called for the first
** time, it will spawn a DPR task, which periodically polls the
** interrupt status and processes the events.
** If the DPR task has already been running, the function will
** simply flag the "u1IntrProcEn" in the DDB structure.
**
** VALID STATES: Not applicable
**
** SIDE EFFECTS:
**
** INPUTS: duplex - device handler
**
** OUTPUTS: None
**
** RETURN CODES:
** DPX_SUCCESS
** DPX_ERR_INVALID_DEVICE (invalid device handle)
** DPX_ERR_INT_ALREADY_INSTALLED
** DPX_ERR_CREATE_MSG_Q
** DPX_ERR_INSTALL_INT_VECTOR
** DPX_ERR_SPAWN_DPR_TASK
**
*******************************************************************************/
INT4 sysDuplexIntInstallHandler(DUPLEX duplex)
{
sDPX_DDB *psDpxDdb;
psDpxDdb = (sDPX_DDB *)duplex;
/* set the Interrupt Processing Enable Flag in the device DDB */
sysDuplexSemTake(psDpxDdb->lockId);
psDpxDdb->u1IntrProcEn = 1;
sysDuplexSemGive(psDpxDdb->lockId);
if(u1ActiveDevNumber == 0)
{
u1DPRactive = 1;
/* spawn sysDuplexDPRtask as a separate task in the RTOS */
sDpxDprTsk.i4Id = taskSpawn(sDpxDprTsk.pi1Name, sDpxDprTsk.i4Pri,
sDpxDprTsk.i4Opt,
sDpxDprTsk.i4StckSz,sDpxDprTsk.FEntryPtr,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if( sDpxDprTsk.i4Id == ERROR)
return DPX_ERR_INT_INSTALL;
}
u1ActiveDevNumber++;
return DPX_SUCCESS;
}
/*******************************************************************************
**
** sysDuplexIntRemoveHandler (Polling mode )
** ___________________________________________________________________________
**
** DESCRIPTION: Remove the specified device from the list of devices for which
** interrupt polling processing will be done.This can be achieved
** by clear the "u1IntrProcEn" flag in the DDB structure.
** If this is the last active device, the sysDuplexDPRtask are
** deleted.
**
** VALID STATES: Not applicable
**
** SIDE EFFECTS:
**
** INPUTS: duplex - device handler
**
** OUTPUTS: None
**
** RETURN CODES:None
**
*******************************************************************************/
VOID sysDuplexIntRemoveHandler(DUPLEX duplex)
{
sDPX_DDB *psDpxDdb;
psDpxDdb = (sDPX_DDB *)duplex;
/* reset the Interrupt Processing Enable Flag in the device DDB */
psDpxDdb->u1IntrProcEn = 0;
u1ActiveDevNumber--;
/* No DUPLEX devices are activated */
if(u1ActiveDevNumber == 0)
{
/* kill sysDuplexDPRtask */
if( sDpxDprTsk.i4Id != 0)
{
/* try to graceful shutdown the task */
u1DPRactive = 0;
sysDuplexDelayFn(2*DPX_POLLING_DELAY);
/* force to delete the task */
taskDelete(sDpxDprTsk.i4Id);
sDpxDprTsk.i4Id = 0;
}
}
}
/*******************************************************************************
**
** sysDuplexDPRtask (Polling mode )
** ___________________________________________________________________________
**
** DESCRIPTION: This routine is spawned as a sperate task within the RTOS. It
** retrieves interrupt status information saved for it by the
** sysDuplexIntHandler routine and invokes the duplexDPR routine
** for the appropriate device.
**
** VALID STATES: Not applicable
**
** SIDE EFFECTS:
**
** INPUTS: None
**
** OUTPUTS: None
**
** RETURN CODES:None
**
*******************************************************************************/
VOID sysDuplexDPRtask(VOID)
{
UINT1 u1NextDev;
sDPX_DDB *psDpxDdb;
UINT1 u1IntrProcEn;
if(psDpxGdd == DPX_NULL)
return;
do
{
for(u1NextDev=0; u1NextDev < DPX_MAX_NUM_DEVS; ++u1NextDev)
{
psDpxDdb = psDpxGdd->pDdb[u1NextDev];
if(psDpxDdb != DPX_NULL)
{
/* check this device has been activated */
u1IntrProcEn = psDpxDdb->u1IntrProcEn;
if(u1IntrProcEn)
duplexDPR(psDpxDdb);
}
}
/** sleep for a few milliseconds */
sysDuplexDelayFn(DPX_POLLING_DELAY);
} while(u1DPRactive);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -