vxWorks6.9 vxbIntDynaCtlrLib的匹配bug
问题描述
在使用vxWorks6.9的vxbIntDynaCtlrLib库时,发现调用_func_vxbIntDynaConnect链接的isr没有挂接到指定的中断控制器的中断向量结构体上,而是挂接到了同名的unitNumber为0的中断控制器上
问题定位
STATUS (* _func_vxbIntDynaConnect) (VXB_DEVICE_ID, int, struct vxbIntDynaVecInfo *);
_func_vxbIntDynaConnect为一个函数指针,指向函数vxbIntDynaConnect
STATUS vxbIntDynaConnect(VXB_DEVICE_ID pDev,int vecCount, struct vxbIntDynaVecInfo * pDynaVecIntr);
第一个参数指向设备结构体,第二个参数需要挂接的中断向量个数,第三个参数为指向的中断向量信息结构体指针
struct vxbIntDynaVecInfo
{
void (*isr)(void * ISR);
void * pArg;
UINT64 vecAddr;
UINT32 vecVal;
UINT32 inputPin;
UINT32 vecType;
UINT32 index;
UINT32 count;
};
发现在struct vxbIntDynaVecInfo中有一个为index的成员,但是实际上并没有使用这个成员,通过下面可以看出
info.found = FALSE;
info.pIntCtlr = NULL;
info.inputPin = VXB_INTR_DYNAMIC;
info.pDev = pDev;
info.index = 0;
info.pIsr = pDynaVecIntr->isr;
info.pArg = pDynaVecIntr->pArg;
vxbDevIterate (vxbDynaIntCtlrMatch, &info, VXB_ITERATE_INSTANCES);
在通过vxBus进行中断控制器的匹配时,index参数直接赋值为0,我们再看vxbDynaIntCtlrMatch函数
LOCAL STATUS vxbDynaIntCtlrMatch
(
struct vxbDev * pInst,
void * pArg
)
{
struct vxbintCtlrMgmt * pInfo = (struct vxbintCtlrMgmt *) pArg;
FUNCPTR func;
if (pInfo->found)
return (OK);
func = vxbDevMethodGet (pInst, DEVMETHOD_CALL(vxbIntDynaVecConnect));
if (func == NULL)
return (OK);
pInfo->found = TRUE;
pInfo->pIntCtlr = pInst;
return (OK);
}
该函数直接获取vxbIntDynaVecConnect方法,如果获取到pInfo->found = TRUE,直接返回,因此,如果有两个同名中断控制器,但是unitNumber不同的情况下,总是会将第一个返回
解决思路
1. 可以把vxbIntDynaVecInfo.index参数带入unitNumber信息,修改vxbIntDynaConnect函数
info.found = FALSE;
info.pIntCtlr = NULL;
info.inputPin = VXB_INTR_DYNAMIC;
info.pDev = pDev;
info.index = pDynaVecIntr->index;
info.pIsr = pDynaVecIntr->isr;
info.pArg = pDynaVecIntr->pArg;
在vxbDynaIntCtlrMatch函数中进行匹配
func = vxbDevMethodGet (pInst, DEVMETHOD_CALL(vxbIntDynaVecConnect));
if (func == NULL)
return (OK);
if(pInst->unitNumber != pInfo->index)
return (Ok);
pInfo->found = TRUE;
pInfo->pIntCtlr = pInst;
这样虽然能解决问题,但是确需要在PCI总线控制器中指定中断控制器unitNumber,不符合分层的概念,修改不方便
2. 在vxbDynaIntCtlrMatch函数中调用中断控制器的MatchCallBack方法(属于自定义方法),由中断控制器自己判断是否匹配
func = vxbDevMethodGet (pInst, DEVMETHOD_CALL(vxbIntDynaVecConnect));
if (func == NULL)
return (OK);
func = vxbDevMethodGet (pInst, DEVMETHOD_CALL(vxbIntDynaVecMatchCallBack));
if (func != NULL)
{
if((*func)(pInst, pArg) == OK)
{
pInfo->found = TRUE;
pInfo->pIntCtlr = pInst;
}
return (ok);
}
pInfo->found = TRUE;
pInfo->pIntCtlr = pInst;
在vxbIntDynaVecConnect.c中添加:
DEVMETHOD_DEF(vxbIntDynaVecMatchCallBack, "Dynamic Vector Match Call Back");
在中断控制器中添加一个方法:
METHOD_DECL(vxbIntDynaVecMatchCallBack)
LOCAL device_method_t xxIntCtlr_methods[] =
{
...
DEVMETHOD(vxbIntDynaVecMatchCallBack, vxbxxIntDynaVecMatchCallBack),
...
};
LOCAL STATUS vxbxxIntDynaVecMatchCallBack(VXB_DEVICE_ID pIntCtlr, void * pArg)
{
pVXB_xx_INT_DRV_CTLR pDrvCtlr = pIntCtlr->pDrvCtrl;
/*该处采用驱动中的msiEnable进行判断,该变量在instinit时通过获取hwconf赋值*/
return (pDrvCtlr->msiEnable?OK:ERROR);
}
hwconf.c
const struct hcfResource xxx[] = {
...
{"msiEnable", HCF_RES_INT, {(void *) TRUE}},
/* {"msiEnable", HCF_RES_INT, {(void *) FALSE}},*/
...
}
通过修改hwconf,可以很方便的进行配置