首页 »编程综合 » reactos:reactos操作系统实现(96) »正文
reactos:reactos操作系统实现(96)
来源: 发布时间:星期一, 2009年9月28日 浏览:0次 评论:0
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 (!NT_SUCCESS(Status)) #036 { #037 WARN_(I8042PRT, "IoConnectInterrupt failed with status 0x%08x\n", Status); #038 Status; #039 } #040 设置最大 请求级别 #041 (DirqlMax PortDeviceExtension->KeyboardInterrupt.Dirql) #042 PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->KeyboardInterrupt.Object; 设置键盘已经 化 #043 PortDeviceExtension->Flags |= KEYBOARD_INITIALIZED; #044 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是访问输入参数 自旋锁 Vector是PNP管理器分配 中断号 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 (Affinity & 1) Count; #033 Affinity >>= 1; #034 } #035 确保这个CPU有中断响应 #036 /* Make sure we have a valid CPU count */ #037 (!Count) STATUS_INVALID_PARAMETER; #038 分配 个IO中断结构 #039 /* Allocate the .gif' /> of I/O Interrupts */ #040 IoInterrupt = ExAllocatePoolWithTag(NonPagedPool, #041 (Count - 1) * (KINTERRUPT) + #042 (IO_INTERRUPT), #043 TAG_KINTERRUPT); #044 (!IoInterrupt) 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, (IO_INTERRUPT)); #056 开始创建所有CPU 中断 #057 /* Now create all the errupts */ #058 Affinity = ProcessorEnableMask & KeActiveProcessors; #059 for (Count = 0; Affinity; Count, Affinity >>= 1) #060 { 检查这个CPU是否有中断设置 #061 /* Check it's enabled for this CPU */ #062 (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 (!KeConnectInterrupt(InterruptUsed)) #082 { #083 /* Check how far we got */ #084 (FirstRun) #085 { #086 /* We failed early so just free this */ #087 ExFreePool(IoInterrupt); #088 } #089 #090 {
如果没有设置中断成功 就返回出错 #091 /* Far enough, so disconnect everything */ #092 IoDisconnectInterrupt(&IoInterrupt->FirstInterrupt); #093 } #094 #095 /* And fail */ #096 STATUS_INVALID_PARAMETER; #097 } #098 设置第 个中断响应 已经设置完成 #099 /* Now we've used up our First Run */ #100 (FirstRun) #101 { #102 FirstRun = FALSE; #103 } #104 #105 { 把其它CPU 中断放到队列后面 #106 /* Move on to the next one */ #107 IoInterrupt->Interrupt[(UCHAR)Count] = Interrupt; #108 } #109 } #110 } #111 #112 /* Return Success */ #113 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 errupt */ #012 Number = Interrupt->Number; #013 Vector = Interrupt->Vector; #014 Irql = Interrupt->Irql; #015 检查参数是否有效 #016 /* Validate the tings */ #017 ((Irql > HIGH_LEVEL) || #018 (Number >= KeNumberProcessors) || #019 (Interrupt->SynchronizeIrql < Irql) || #020 (Interrupt->FloatingSave)) #021 { #022 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 KeSetAffinityThread(1 << Number); #031 OldIrql = KiAcquireDispatcherLock; #032
检查中断是否已经连接到系统里 #033 /* Check it's already been connected */ #034 (!Interrupt->Connected) #035 { 如果没有连接 就查找分发信息 #036 /* Get vector dispatching information */ #037 KiGetVectorDispatch(Vector, &Dispatch); #038 如果分发器也没有连接这个中断 #039 /* Check the vector is already connected */ #040 (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 errupt */ #049 KiConnectVectorToInterrupt(Interrupt, NormalConnect); #050 Status = HalEnableInterrupt(Vector, Irql, Interrupt->Mode); #051 (!Status) Error = TRUE; #052 } #053 ((Dispatch.Type != UnknownConnect) && #054 (Interrupt->ShareVector) && #055 (Dispatch.Interrupt->ShareVector) && #056 (Dispatch.Interrupt->Mode Interrupt->Mode)) #057 {
这里是处理共享中断 情况 #058 /* The vector is shared and the errupts are compatible */ #059 ASSERT(FALSE); // FIXME: NOT YET SUPPORTED/TESTED #060 Interrupt->Connected = Connected = TRUE; #061 ASSERT(Irql <= SYNCH_LEVEL); #062 是否为第 个连接 #063 /* Check this is the first chain */ #064 (Dispatch.Type != ChainConnect) #065 { #066 /* Setup the chainned handler */ #067 KiConnectVectorToInterrupt(Dispatch.Interrupt, ChainConnect); #068 } #069 把这个中断放到中断响应列表里 #070 /* Insert o the errupt 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 we failed while trying to connect */ #081 ((Connected) && (Error)) #082 { #083 DPRINT1("HalEnableInterrupt failed\n"); #084 KeDisconnectInterrupt(Interrupt); #085 Connected = FALSE; #086 } #087 #088 /* Return to caller */ #089 Connected; #090 }
相关文章
读者评论
发表评论
|
|