reactos操作系统实现(89)

键盘驱动程序是一个最基本的驱动程序,通过学习这个简单而实用的驱动程序来了解ReactOS驱动程序的结构,驱动程序的运行流程。在前面的I/O管理器分析里,已经知道操作系统加载驱动程序的过程,也了解了驱动程序在系统里是以驱动程序对象来管理的,也就是通过DRIVER_OBJECT对象来表示一个驱动程序的。

 

键盘驱动程序是一个输入输出的设备,但在ReactOS驱动程序分类里,是分在输入设备类。这个驱动程序的源程序所在的目录是在reactos/drivers/input/i8042prt目录。在分析这个驱动程序,还是采用从程序运行过程来分析它的流程。那么驱动程序加载运行的入口点在那里呢?这是一个最先要解决的问题,其实每个驱动程序都固定有一个函数名称DriverEntry,因此操作系统加载驱动程序时,就会找到这个入口函数,然后就调这个函数,就可以把驱动程序和操作系统内核联系在一起了,就可以调用驱动程序相关的功能了。在内核的I/O管理器里是这样调用这个函数的,如下:

#148      DPRINT("Calling driver entrypoint at %p/n", InitializationFunction);

#149      Status = (*InitializationFunction)(DriverObject, RegistryPath);

通过内核的调用,就知道函数DriverEntry应具备两个参数,第一个参数是驱动程序对象,这是内核表示一个驱动程序的对象。第二个参数是驱动程序文件在注册表里的路径。因此,驱动程序入口函数,就写成下面这样:

#001  NTSTATUS NTAPI

#002  DriverEntry(

#003     IN PDRIVER_OBJECT DriverObject,

#004     IN PUNICODE_STRING RegistryPath)

#005  {

#006     PI8042_DRIVER_EXTENSION DriverExtension;

#007     ULONG i;

#008     NTSTATUS Status;

#009 

#010     /* ROS Hack: ideally, we shouldn't have to initialize debug level this way,

#011        but since the only way is to change it via KDBG, it's better to leave

#012        it here too. */

#013  #if 0

#014     DbgSetDebugFilterState(

#015         DPFLTR_I8042PRT_ID,

#016         (1 << DPFLTR_ERROR_LEVEL) | (1 << DPFLTR_WARNING_LEVEL) |

#017         (1 << DPFLTR_TRACE_LEVEL) /*| (1 << DPFLTR_INFO_LEVEL)*/ | DPFLTR_MASK,

#018         TRUE);

#019  #endif

#020    

#021 

 

调用函数IoAllocateDriverObjectExtension来分配键盘驱动程序的对象内存,以便保存更多扩展的属性。

#022     Status = IoAllocateDriverObjectExtension(

#023         DriverObject,

#024         DriverObject,

#025         sizeof(I8042_DRIVER_EXTENSION),

#026         (PVOID*)&DriverExtension);

#027     if (!NT_SUCCESS(Status))

#028     {

#029         WARN_(I8042PRT, "IoAllocateDriverObjectExtension() failed with status 0x%08lx/n", Status);

#030         return Status;

#031     }

 

初始化扩展分区内存。

#032     RtlZeroMemory(DriverExtension, sizeof(I8042_DRIVER_EXTENSION));

 

初始化扩展的设备列表。

#033     KeInitializeSpinLock(&DriverExtension->Port.SpinLock);

#034     InitializeListHead(&DriverExtension->DeviceListHead);

#035     KeInitializeSpinLock(&DriverExtension->DeviceListLock);

#036 

 

拷贝注册表路径。

#037     Status = DuplicateUnicodeString(

#038         RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,

#039         RegistryPath,

#040         &DriverExtension->RegistryPath);

#041     if (!NT_SUCCESS(Status))

#042     {

#043         WARN_(I8042PRT, "DuplicateUnicodeString() failed with status 0x%08lx/n", Status);

#044         return Status;

#045     }

#046 

 

从注册表里获取驱动程序的资源分配。

#047     Status = ReadRegistryEntries(RegistryPath, &DriverExtension->Port.Settings);

#048     if (!NT_SUCCESS(Status))

#049     {

#050         WARN_(I8042PRT, "ReadRegistryEntries() failed with status 0x%08lx/n", Status);

#051         return Status;

#052     }

#053 

 

添加即插即用调用函数,以便创建这个驱动程序支持的设备。

#054     DriverObject->DriverExtension->AddDevice = i8042AddDevice;

 

指向驱动程序中处理串行I/O请求的函数,I/O管理器自动为驱动程序串行化多个I/O请求。

#055     DriverObject->DriverStartIo = i8042StartIo;

#056

 

缺省地初始化IRP消息为IrpStub函数处理。

#057     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)

#058         DriverObject->MajorFunction[i] = IrpStub;

#059 

 

指定IRP消息IRP_MJ_CREATE的处理函数i8042Create

#060     DriverObject->MajorFunction[IRP_MJ_CREATE]  = i8042Create;

 

清除分配资源的函数i8042Cleanup

#061     DriverObject->MajorFunction[IRP_MJ_CLEANUP] = i8042Cleanup;

 

指定关闭设备时,调用的函数i8042Close

#062     DriverObject->MajorFunction[IRP_MJ_CLOSE]   = i8042Close;

 

通过IO操作函数i8042DeviceControl

#063     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = i8042DeviceControl;

 

指定中断处理函数i8042InternalDeviceControl

#064     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = i8042InternalDeviceControl;

 

指定即插即用时响应函数i8042Pnp

#065     DriverObject->MajorFunction[IRP_MJ_PNP]     = i8042Pnp;

#066 

 

判断驱动程序是否初始化安装时运行,如果是初始化时就调用函数i8042AddLegacyKeyboard处理。

#067     if (IsFirstStageSetup())

#068         return i8042AddLegacyKeyboard(DriverObject, RegistryPath);

#069 

#070     return STATUS_SUCCESS;

#071  }

你可能感兴趣的:(reactos操作系统实现(89))