中断处理
首先在獲得PCI配置空間資源的時候,就要獲得中斷資源,根據(jù)CM_PARTIAL_RESOURCE_DESCRIPTOR 結(jié)構(gòu)的 Type 域來區(qū)分需要獲得什么樣的中斷資源的時候,如果Type類型為:CmResourceTypeInterrupt,此時需要將中斷資源從CM_PARTIAL_RESOURCE_DESCRIPTOR中取出:
irql = (KIRQL) resource->u.Interrupt.Level;????????????? //中斷級別
??????????????????????????? vector = resource->u.Interrupt.Vector;???????????????????? // 中斷向量
??????????????????????????? affinity = resource->u.Interrupt.Affinity;
??????????????????????????? mode = (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
???????????????????????????????????? ? Latched : LevelSensitive;
??????????????????????????? irqshare = resource->ShareDisposition == CmResourceShareShared;
??????????????????????????? gotinterrupt = TRUE;
?
獲取以上這些信心之后我們就可以注冊中斷,通過IoConnectInterrupt()函數(shù)來實現(xiàn):
函數(shù)定義如下:
IoConnectInterrupt(
OUT PKINTERRUPT *InterruptObject,//指向驅(qū)動程序提供的中斷對象存儲地址,該參數(shù)隨后
//要傳遞給KeSynchronizeExecution。
OUT PKSERVICE_ROUTINE ServiceRoutine,//中斷服務(wù)例程的入口
IN PVOID ServiceContext,//指向驅(qū)動指定的即將傳遞給ISR的參數(shù),ServiceContext必須在
//常駐內(nèi)存中,可以是驅(qū)動程序創(chuàng)建的設(shè)備驅(qū)動的設(shè)備擴展,也可
//以是驅(qū)動創(chuàng)建的控制對象的控制拓展,還可以是設(shè)備驅(qū)動分配的
//非分頁內(nèi)存。
IN PKSPIN_LOCK SpinLock OPTIONAL,//指向已經(jīng)初始化的自旋所,驅(qū)動程序負責(zé)自旋所的存
//儲,并且該自旋所將用來同步被驅(qū)動程序其它例程共
//享的數(shù)據(jù)的訪問,該參數(shù)在ISR處理多個中斷向量或
//者驅(qū)動程序包含不止一個ISR時需要設(shè)置,否則,驅(qū)
//動程序不需要為中斷自旋所分配存儲空間,參數(shù)設(shè)置
//為NULL。
IN ULONG Vector,??????????????? //輸入獲取的中斷向量
IN KIRQL Irql,??????????????????? //輸入獲取的中斷優(yōu)先級DIRQL
IN KIRQL SynchronizeIrql,???????? //指明ISR執(zhí)行所在的DIRQL,當ISR需要處理多個中斷
//向量或者驅(qū)動程序有多個ISR的時候,該值選擇全部中
//斷資源的u.Interrupt.Level中的最高值,否則和上面的
//Irql變量相等。
IN KINTERRUPT_MODE InterruptMode,//電平觸發(fā)或者邊沿觸發(fā)
IN BOOLEAN ShareVector,?????????? //指明中斷向量是否是可共享的。
IN KAFFINITY ProcessorEnableMask,//指定一個KAFFINITY值,用來說明設(shè)備中斷可以在什
//么樣的處理器平臺上發(fā)生。
IN BOOLEAN FloatingSave???????? ?//指明是否需要保存設(shè)備中斷時的浮點堆棧,在X86平
//臺下,該值必須是FALSE。
);
實際使用時:
status = IoConnectInterrupt(&pdx->InterruptObject, (PKSERVICE_ROUTINE) ISRInterrupt,
?????????????????? (PVOID) pdx, NULL, vector, irql, irql, mode, irqshare, affinity, FALSE);
第二個參數(shù)為我們自定義的中斷服務(wù)例程,當驅(qū)動通過這個函數(shù)接收中斷,之后調(diào)用相應(yīng)的DPC(deferred procedure calls,延遲過程調(diào)用)處理函數(shù),DPC的使用主要是為了提高處理效率。但是首先要注冊DPC處理函數(shù),通過:
VOID KeInitializeDpc(
? __out???? PRKDPC Dpc,
? __in????? PKDEFERRED_ROUTINE DeferredRoutine,
? __in_opt? PVOID DeferredContext
);
來實現(xiàn)注冊DPC處理函數(shù)。
實際應(yīng)用:
KeInitializeDpc(&pdx->fdo->Dpc,DPCForISR,NULL);
?
BOOLEAN ISRInterrupt(PKINTERRUPT InterruptObject, PDEVICE_EXTENSION pdx)
{???????????????????????????????????????????????????????????????
???????? //中斷響應(yīng),通知硬件該中斷已經(jīng)處理,不用再發(fā)該中斷
???????? WRITE_REGISTER_ULONG((PULONG) &pdx->pHBARegs->IntrMask,0x00000001);
???????? pdx->inthw_cnt++;
???????? KeInsertQueueDpc(&pdx->fdo->Dpc,pdx->fdo,pdx->fdo->CurrentIrp );
???????? return TRUE;
}
在該函數(shù)中,將中斷請求插入到中斷處理隊列中,交由DPC來處理
BOOLEAN KeInsertQueueDpc(
? __inout?? PRKDPC Dpc,
? __in_opt? PVOID SystemArgument1,
? __in_opt? PVOID SystemArgument2
);
?
DPC的標準格式為:
KDEFERRED_ROUTINE CustomDpc;
?
VOID CustomDpc(
? __in????? struct _KDPC *Dpc,
? __in_opt? PVOID DeferredContext,
? __in_opt? PVOID SystemArgument1,
? __in_opt? PVOID SystemArgument2
)
{ ... }
其中參數(shù)(注意來源):
Dpc [in]
Caller-supplied pointer to a KDPC structure, which represents the DPC object that is associated with this CustomDpc routine.
DeferredContext [in, optional]
Caller-supplied pointer to driver-defined context information that was specified in a previous call to KeInitializeDpc.
SystemArgument1 [in, optional]
Caller-supplied pointer to driver-supplied information that was specified in a previous call to KeInsertQueueDpc.
SystemArgument2 [in, optional]
Caller-supplied pointer to driver-supplied information that was specified in a previous call to KeInsertQueueDpc.
?
?
?
這里DPC可以這樣設(shè)計:
VOID DPCForISR(IN PKDPC Dpc,IN PVOID Context,IN? PVOID fdo,IN PVOID pIrp)
{
???????? PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)
((PDEVICE_OBJECT)fdo)->DeviceExtension;
????????
???????? KeAcquireSpinLock(&pdx->spinLock,&pdx->oldIrql);
//Int_stat 寄存器由硬件填寫的
???????? int_status = READ_REGISTER_ULONG((PULONG) &pdx->pHBARegs->Int_stat);
???????? KdPrint(("interrupt!int status is 0x%0x\n",int_status));
???????? while(int_status) //循環(huán)處理中斷,直到處理完
???????? {
??????????????????
?????????????????? if(int_status >= INT_RECV_0 && int_status <= INT_RECV_23)
?????????????????? {
??????????????????????????? RecvTask(pdx,int_status-1);
??????????????????????????? pdx->recint_cnt[int_status-1]++;
?????????????????? }
?????????????????? if(int_status >= INT_LINK0_BUILD && int_status <= INT_LINK3_BUILD)
?????????????????? {
??????????????????????????? pdx->rx_fc_desc_buf_virt[int_status-25]->link_state=1;
??????????????????????????? pdx->bldint_cnt[int_status-25]++;
??????????????????????????? KdPrint(("Build!int status is 0x%0x\n",int_status));
?????????????????? }
??????????????????
?????????????????? if(int_status >= INT_LINK0_BREAK && int_status <= INT_LINK3_BREAK)
?????????????????? {
??????????????????????????? pdx->rx_fc_desc_buf_virt[int_status-29]->link_state=0;
??????????????????????????? pdx->brkint_cnt[int_status-29]++;
?????????????????? }
?????????????????? pdx->intsw_cnt++;
?????????????????? int_status = READ_REGISTER_ULONG((PULONG) &pdx->pHBARegs->Int_stat);
?????????????????? KdPrint(("interrupt!int status is 0x%0x\n",int_status));
???????? }
????????
???????? return ;?????????????
}
在DPC中完成具體的操作,這樣中斷處理就結(jié)束了。
?
轉(zhuǎn)載于:https://www.cnblogs.com/zhuyp1015/archive/2012/03/14/2396630.html
總結(jié)
- 上一篇: memcache 原理 监测 查看状
- 下一篇: 使用模块优化工资计算器