Notify_registerEvent的实现过程

来源:互联网 发布:如何保持身材 知乎 编辑:程序博客网 时间:2024/05/21 14:55

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结构对应的eventIdeventList链表上,然后进入_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结构中对应eventIdcallbacks中,而后进入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));

.....................................

}

原创粉丝点击