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} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |