加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

reactos操作系统实现(96)

发布时间:2020-12-15 05:00:28 所属栏目:百科 来源:网络整理
导读:调用函数 IoConnectInterrupt 来设置键中断处理函数。 #028 Status = IoConnectInterrupt( #029 PortDeviceExtension-KeyboardInterrupt.Object, #030 i8042KbdInterruptService, #031 DeviceExtension,PortDeviceExtension-SpinLock, #032 PortDeviceExtens

调用函数IoConnectInterrupt来设置键中断处理函数。

#028 Status = IoConnectInterrupt(

#029 &PortDeviceExtension->KeyboardInterrupt.Object,

#030 i8042KbdInterruptService,

#031 DeviceExtension,&PortDeviceExtension->SpinLock,

#032 PortDeviceExtension->KeyboardInterrupt.Vector,PortDeviceExtension->KeyboardInterrupt.Dirql,DirqlMax,

#033 PortDeviceExtension->KeyboardInterrupt.InterruptMode,PortDeviceExtension->KeyboardInterrupt.ShareInterrupt,

#034 PortDeviceExtension->KeyboardInterrupt.Affinity,FALSE);

#035 if (!NT_SUCCESS(Status))

#036 {

#037 WARN_(I8042PRT,"IoConnectInterrupt() failed with status 0x%08x/n",Status);

#038 return Status;

#039 }

#040

设置最大的请求级别。

#041 if (DirqlMax == PortDeviceExtension->KeyboardInterrupt.Dirql)

#042 PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->KeyboardInterrupt.Object;

设置键盘已经初始化。

#043 PortDeviceExtension->Flags |= KEYBOARD_INITIALIZED;

#044 return STATUS_SUCCESS;

#045 }

其实是调用IO管理器里的中断设置函数IoConnectInterrupt,实现如下:

#001 NTSTATUS

#002 NTAPI

#003 IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject,

#004 IN PKSERVICE_ROUTINE ServiceRoutine,

#005 IN PVOID ServiceContext,

#006 IN PKSPIN_LOCK SpinLock,

#007 IN ULONG Vector,

#008 IN KIRQL Irql,

#009 IN KIRQL SynchronizeIrql,

#010 IN KINTERRUPT_MODE InterruptMode,

#011 IN BOOLEAN ShareVector,

#012 IN KAFFINITY ProcessorEnableMask,

#013 IN BOOLEAN FloatingSave)

#014 {

InterruptObject是返回中断处理对象。

ServiceRoutine是中断调用函数。

ServiceContext是中断调用函数使用的参数。

SpinLock是访问输入参数的自旋锁。

VectorPNP管理器分配的中断号。

Irql是中断请求优先级。

SynchronizeIrql是同步请求优先级。

InterruptMode是中断的模式。

ShareVector是中断资源是否共享。

ProcessorEnableMask是中断允许发生的处理器。

FloatingSave指明是否保存浮点堆栈。

#015 PKINTERRUPT Interrupt;

#016 PKINTERRUPT InterruptUsed;

#017 PIO_INTERRUPT IoInterrupt;

#018 PKSPIN_LOCK SpinLockUsed;

#019 BOOLEAN FirstRun;

#020 CCHAR Count = 0;

#021 KAFFINITY Affinity;

#022 PAGED_CODE();

#023

假定失败的返回结果。

#024 /* Assume failure */

#025 *InterruptObject = NULL;

#026

获取处理器位。

#027 /* Get the affinity */

#028 Affinity = ProcessorEnableMask & KeActiveProcessors;

#029 while (Affinity)

#030 {

#031 /* Increase count */

#032 if (Affinity & 1) Count++;

#033 Affinity >>= 1;

#034 }

#035

确保这个CPU有中断响应。

#036 /* Make sure we have a valid CPU count */

#037 if (!Count) return STATUS_INVALID_PARAMETER;

#038

分配一个IO中断结构。

#039 /* Allocate the array of I/O Interrupts */

#040 IoInterrupt = ExAllocatePoolWithTag(NonPagedPool,

#041 (Count - 1) * sizeof(KINTERRUPT) +

#042 sizeof(IO_INTERRUPT),

#043 TAG_KINTERRUPT);

#044 if (!IoInterrupt) return STATUS_INSUFFICIENT_RESOURCES;

#045

如果驱动程序传入自旋锁,就使用驱动程序的,否则就使用内核分配的。

#046 /* Select which Spinlock to use */

#047 SpinLockUsed = SpinLock ? SpinLock : &IoInterrupt->SpinLock;

#048

设置返回的中断对象。

#049 /* We first start with a built-in Interrupt inside the I/O Structure */

#050 *InterruptObject = &IoInterrupt->FirstInterrupt;

#051 Interrupt = (PKINTERRUPT)(IoInterrupt + 1);

#052 FirstRun = TRUE;

#053

初始化中断对象结构。

#054 /* Start with a fresh structure */

#055 RtlZeroMemory(IoInterrupt,sizeof(IO_INTERRUPT));

#056

开始创建所有CPU的中断。

#057 /* Now create all the interrupts */

#058 Affinity = ProcessorEnableMask & KeActiveProcessors;

#059 for (Count = 0; Affinity; Count++,Affinity >>= 1)

#060 {

检查这个CPU是否有中断设置。

#061 /* Check if it's enabled for this CPU */

#062 if (Affinity & 1)

#063 {

是否第一个CPU中断设置。

#064 /* Check which one we will use */

#065 InterruptUsed = FirstRun ? &IoInterrupt->FirstInterrupt : Interrupt;

#066

设置中断对象。

#067 /* Initialize it */

#068 KeInitializeInterrupt(InterruptUsed,

#069 ServiceRoutine,

#070 ServiceContext,

#071 SpinLockUsed,

#072 Vector,

#073 Irql,

#074 SynchronizeIrql,

#075 InterruptMode,

#076 ShareVector,

#077 Count,

#078 FloatingSave);

#079

#080 /* Connect it */

调用内核函数KeConnectInterrupt设置中断。

#081 if (!KeConnectInterrupt(InterruptUsed))

#082 {

#083 /* Check how far we got */

#084 if (FirstRun)

#085 {

#086 /* We failed early so just free this */

#087 ExFreePool(IoInterrupt);

#088 }

#089 else

#090 {

如果没有设置中断成功,就返回出错。

#091 /* Far enough,so disconnect everything */

#092 IoDisconnectInterrupt(&IoInterrupt->FirstInterrupt);

#093 }

#094

#095 /* And fail */

#096 return STATUS_INVALID_PARAMETER;

#097 }

#098

设置第一个中断响应,已经设置完成。

#099 /* Now we've used up our First Run */

#100 if (FirstRun)

#101 {

#102 FirstRun = FALSE;

#103 }

#104 else

#105 {

把其它CPU的中断放到队列后面。

#106 /* Move on to the next one */

#107 IoInterrupt->Interrupt[(UCHAR)Count] = Interrupt++;

#108 }

#109 }

#110 }

#111

#112 /* Return Success */

#113 return STATUS_SUCCESS;

#114 }

在这个函数主要到两个内核函数来设置中断,它就是函数KeInitializeInterrupt KeConnectInterrupt。下来分析函数KeConnectInterrupt实现,看看它是怎么样把中断服务器与内核连接在一起的,如下:

#001 BOOLEAN

#002 NTAPI

#003 KeConnectInterrupt(IN PKINTERRUPT Interrupt)

#004 {

#005 BOOLEAN Connected,Error,Status;

#006 KIRQL Irql,OldIrql;

#007 UCHAR Number;

#008 ULONG Vector;

#009 DISPATCH_INFO Dispatch;

#010

从中断里获取中断号所在CPU、中断向量、中断优先级。

#011 /* Get data from interrupt */

#012 Number = Interrupt->Number;

#013 Vector = Interrupt->Vector;

#014 Irql = Interrupt->Irql;

#015

检查参数是否有效。

#016 /* Validate the settings */

#017 if ((Irql > HIGH_LEVEL) ||

#018 (Number >= KeNumberProcessors) ||

#019 (Interrupt->SynchronizeIrql < Irql) ||

#020 (Interrupt->FloatingSave))

#021 {

#022 return FALSE;

#023 }

#024

设置缺省状态。

#025 /* Set defaults */

#026 Connected = FALSE;

#027 Error = FALSE;

#028

设置起作用的CPU

#029 /* Set the system affinity and acquire the dispatcher lock */

#030 KeSetSystemAffinityThread(1 << Number);

#031 OldIrql = KiAcquireDispatcherLock();

#032

检查中断是否已经连接到系统里。

#033 /* Check if it's already been connected */

#034 if (!Interrupt->Connected)

#035 {

如果没有连接,就查找分发信息。

#036 /* Get vector dispatching information */

#037 KiGetVectorDispatch(Vector,&Dispatch);

#038

如果分发器也没有连接这个中断。

#039 /* Check if the vector is already connected */

#040 if (Dispatch.Type == NoConnect)

#041 {

开始连接这个中断处理函数。

#042 /* Do the connection */

#043 Interrupt->Connected = Connected = TRUE;

#044

#045 /* Initialize the list */

#046 InitializeListHead(&Interrupt->InterruptListEntry);

#047

连接中断处理,并启动这个中断。

#048 /* Connect and enable the interrupt */

#049 KiConnectVectorToInterrupt(Interrupt,NormalConnect);

#050 Status = HalEnableSystemInterrupt(Vector,Irql,Interrupt->Mode);

#051 if (!Status) Error = TRUE;

#052 }

#053 else if ((Dispatch.Type != UnknownConnect) &&

#054 (Interrupt->ShareVector) &&

#055 (Dispatch.Interrupt->ShareVector) &&

#056 (Dispatch.Interrupt->Mode == Interrupt->Mode))

#057 {

这里是处理共享中断的情况。

#058 /* The vector is shared and the interrupts are compatible */

#059 ASSERT(FALSE); // FIXME: NOT YET SUPPORTED/TESTED

#060 Interrupt->Connected = Connected = TRUE;

#061 ASSERT(Irql <= SYNCH_LEVEL);

#062

是否为第一个连接。

#063 /* Check if this is the first chain */

#064 if (Dispatch.Type != ChainConnect)

#065 {

#066 /* Setup the chainned handler */

#067 KiConnectVectorToInterrupt(Dispatch.Interrupt,ChainConnect);

#068 }

#069

把这个中断放到中断响应列表里。

#070 /* Insert into the interrupt list */

#071 InsertTailList(&Dispatch.Interrupt->InterruptListEntry,

#072 &Interrupt->InterruptListEntry);

#073 }

#074 }

#075

#076 /* Unlock the dispatcher and revert affinity */

#077 KiReleaseDispatcherLock(OldIrql);

#078 KeRevertToUserAffinityThread();

#079

如果连接失败,就准备下一次连接。

#080 /* Check if we failed while trying to connect */

#081 if ((Connected) && (Error))

#082 {

#083 DPRINT1("HalEnableSystemInterrupt failed/n");

#084 KeDisconnectInterrupt(Interrupt);

#085 Connected = FALSE;

#086 }

#087

#088 /* Return to caller */

#089 return Connected;

#090}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读