专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »编程综合 » 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  }




标签:reactos
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: