Notify_registerEvent的实现过程
同样我们从用户态下的Notify_registerEvent函数开始:
Int Notify_registerEvent (UInt16 procId,
UInt16 lineId,
UInt32 eventId,
Notify_FnNotifyCbck fnNotifyCbck,
UArg cbckArg)
{
Notify_CmdArgsRegisterEvent cmdArgs;
cmdArgs.procId = procId;
cmdArgs.lineId = lineId;
cmdArgs.eventId = eventId;
cmdArgs.fnNotifyCbck = fnNotifyCbck;
cmdArgs.cbckArg = cbckArg;
cmdArgs.pid = getpid ();
status = NotifyDrvUsr_ioctl (CMD_NOTIFY_REGISTEREVENT, &cmdArgs);
.........................
}
Int NotifyDrvUsr_ioctl (UInt32 cmd, Ptr args)
{
osStatus = ioctl (NotifyDrvUsr_handle, cmd, args);
.................
}
这样即通过ioctl函数进入内核态,对应的ioctl命令主要有这几条语句:
Notify_CmdArgsRegisterEvent srcArgs;
NotifyDrv_EventCbck * cbck;
cbck = Memory_alloc (NULL,
sizeof (NotifyDrv_EventCbck),
0u,
NULL);
cbck->procId = srcArgs.procId;
cbck->lineId = srcArgs.lineId;
cbck->eventId = srcArgs.eventId;
cbck->func = srcArgs.fnNotifyCbck;
cbck->param = srcArgs.cbckArg;
cbck->pid = srcArgs.pid;
status = Notify_registerEvent (srcArgs.procId,
srcArgs.lineId,
srcArgs.eventId,
_Notify_drvCallback,
(UArg) cbck);
即进入了内核态的Notify_registerEvent函数:
Int Notify_registerEvent (UInt16 procId,
UInt16 lineId,
UInt32 eventId,
Notify_FnNotifyCbck fnNotifyCbck,
UArg cbckArg)
{
obj = Notify_module->notifyHandles [procId][lineId];
driverHandle = obj->driverHandle;
listener = Memory_alloc (NULL,
sizeof (Notify_EventListener),
0,
NULL);
listener->callback.fnNotifyCbck = fnNotifyCbck;
listener->callback.cbckArg = cbckArg;
eventList = &(obj->eventList [strippedEventId]);
List_put (eventList, (List_Elem *) listener);
_Notify_registerEventSingle (procId, lineId, eventId, Notify_execMany, (UArg) obj, FALSE);
.....................................
}
显然该函数将上次传来的函数和参数保存在listener中,并将其挂在Notify_Object结构对应的eventId的eventList链表上,然后进入_Notify_registerEventSingle函数。
static inline Int _Notify_registerEventSingle (UInt16 procId,
UInt16 lineId,
UInt32 eventId,
Notify_FnNotifyCbck fnNotifyCbck,
UArg cbckArg,
bool acqGate)
{
INotifyDriver_Handle driverHandle;
Notify_Object * obj;
obj = Notify_module->notifyHandles [procId][lineId];
driverHandle = obj->driverHandle;
obj->callbacks [strippedEventId].fnNotifyCbck = fnNotifyCbck;
obj->callbacks [strippedEventId].cbckArg = cbckArg;
status = INotifyDriver_registerEvent (driverHandle, strippedEventId);
...........................
}
同样将传来的函数和参数,放入Notify_Object结构中对应eventId的callbacks中,而后进入INotifyDriver_registerEvent函数。
static inline Int INotifyDriver_registerEvent (INotifyDriver_Handle handle,
UInt32 eventId)
{
INotifyDriver_Object * obj = (INotifyDriver_Object *) handle;
status = obj->fxnTable.registerEvent (obj->obj, eventId);
..............
}
上面的参数我们已经介绍过,即进入NotifyDriverShm_registerEvent函数
Int NotifyDriverShm_registerEvent (NotifyDriverShm_Handle handle, UInt32 eventId)
{
NotifyDriverShm_Object * obj;
volatile NotifyDriverShm_EventEntry * eventEntry;
obj = (NotifyDriverShm_Object *) handle;
NotifyDriverShm_disable (obj);
for (i = 0 ; i < obj->numEvents ; i++)
{
if (obj->regChart [i] == (UInt32) -1) /*该循环的功能
{ 即是将eventId
for (j = (i - 1); j >= 0; j--) 从小到大将放
{ 在regChart这
if (eventId < obj->regChart [j]) 个数组中.*/
{
obj->regChart [j + 1] = obj->regChart [j];
i = j;
}
else
{
j = -1;
}
}
obj->regChart [i] = eventId;
}
}
eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize, eventId)
eventEntry->flag = NotifyDriverShm_DOWN;
NotifyDriverShm_enable (obj);
.........................
}
这个函数实现的功能就是将enventId从小到大放入regChart数组中,因为产生中断后会通过regChart数组去遍历eventId,这个暂时不管。我们看看NotifyDriverShm_enable函数:
Void NotifyDriverShm_enable (NotifyDriverShm_Handle handle)
{
NotifyDriverShm_Object * obj;
obj = (NotifyDriverShm_Object *) handle;
ArchIpcInt_interruptEnable (obj->remoteProcId, obj->params.localIntId);
..................
}
Void ArchIpcInt_interruptEnable (UInt16 procId, UInt32 intId)
{
ArchIpcInt_object.fxnTable->interruptEnable (procId, intId);
.......................
}
Void Dm8168IpcInt_interruptEnable (UInt16 procId, UInt32 intId)
{
REG32 (Dm8168IpcInt_state.mailboxBase + MAILBOX_IRQENABLE_SET_OFFSET) =
(0x1 << ((MAILBOX_NUMBER_8) * 2));
.....................................
}