/*
IO_Card 驱动
1、系统找到DriverEntry()函数,初始化驱动程序。
2、系统调用AddDevice例程添加设备对象。
3、FDO收到 IRP_MN_START_DEVICE IRP,将其设置完成例程(实际设置在下个IO堆栈)后传递给PDO。接着FDO等待同步。(实际上PDO完成资源分配)
4、当PDO完成 IRP_MN_START_DEVICE IRP,设备堆栈回滚时。执行完成例程,并将IRP再次交给FDO。
5、FDO根据IRP提供的IO堆栈得到设备资源,并完成例程。
6、等待各种IRP和中断
6.1、中断(主要用于操作)
6.2、PNP IRP(主要用于配置)
6.3、普通IRP(主要用于操作)
7、当驱动处理完IRP_MN_REMOVE_DEVICE例程后,系统调用HelloWDMUnload例程完成后续工作。
*/
#include <initguid.h>
#include "Guid.h"
#include "IO_Card.h"
#include "Ioctls.h"
#pragma INITCODE
// INIT指明该函数只用于初始化,用完后就释放。(节约内存)
// 代码放在代码段,数据放在数据段。
extern "C" NTSTATUS DriverEntry(
// IN、OUT和INOUT是空宏定义,主要起注释作用。
IN PDRIVER_OBJECT pDriverObject, // I/O管理器传递过来的驱动对象。
IN PUNICODE_STRING pRegistryPath // 驱动对象注册表路径。
)
// extern "C"用于在CPP模式下引用C代码,保证符号链接的正确性。
{
KdPrint(("Enter DriverEntry\n")); // 调试信息打印函数,它只在check版本中生效。
pDriverObject->DriverExtension->AddDevice = IO_CardAddDevice; // 设置添加设备回调函数。
pDriverObject->MajorFunction[IRP_MJ_PNP] = IO_CardPnp; // 设置PNP IRP处理回调函数。
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl; // 设置IO操作回调函数。
pDriverObject->MajorFunction[IRP_MJ_CREATE] = IO_CardDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = IO_CardDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_READ] = IO_CardDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = IO_CardDispatchRoutine; // 设置缺省IRP处理回调函数。
pDriverObject->DriverUnload = IO_CardUnload; // 卸载驱动,设置删除设备回调函数(实际上在PNP IRP中就被处理了)。
KdPrint(("Leave DriverEntry\n")); // 调试信息打印函数,它只在check版本中生效。
return STATUS_SUCCESS;
}
#pragma PAGEDCODE
// IRQL优先级高的使用分页内存,反之使用非分页内存。(维持系统稳定性)
// 代码放在代码段,数据放在数据段。
NTSTATUS IO_CardAddDevice(
// IN、OUT和INOUT是空宏定义,主要起注释作用。
IN PDRIVER_OBJECT DriverObject, // I/O管理器传递过来的驱动对象。
IN PDEVICE_OBJECT PhysicalDeviceObject // 从I/O管理器传递过来的物理设备对象。
)
{
PAGED_CODE(); // 它会检查当前函数是否运行低于DISPATCH_LEVEL的中断请求级,如果等于或高于这个中断请求级,将产生一个断言。它只在check版本中生效。
KdPrint(("Enter IO_CardAddDevice\n")); // 调试信息打印函数,它只在check版本中生效。
NTSTATUS status;
PDEVICE_OBJECT fdo;
// 创建设备驱动。
status = IoCreateDevice(DriverObject,sizeof(DEVICE_EXTENSION),NULL,FILE_DEVICE_UNKNOWN,0,FALSE,&fdo);
// 是否创建成功。
if( !NT_SUCCESS(status))
return status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension; // 获取设备扩展对象的指针。
pdx->fdo = fdo; // 当前设备。
pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject); // 附着FDO到PDO上,并且把返回的PDO记录在FDO的扩展对象中。
// 创建设备接口。(不能指定设备名)
status = IoRegisterDeviceInterface(PhysicalDeviceObject, &IO_CARD_DEVICE, NULL, &pdx->interfaceName);
if( !NT_SUCCESS(status))
{
IoDeleteDevice(fdo); // 失败则删除FDO。
return status;
}
IoSetDeviceInterfaceState(&pdx->interfaceName, TRUE); // 使设备名有效。
if( !NT_SUCCESS(status))
{
if( !NT_SUCCESS(status))
{
return status;
}
}
KdPrint(("%wZ\n",&pdx->interfaceName)); // 调试信息打印函数,它只在check版本中生效。
// 设置标志位。
fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
KdPrint(("Leave IO_CardAddDevice\n")); // 调试信息打印函数,它只在check版本中生效。
return STATUS_SUCCESS;
}
// 中断响应例程。
BOOLEAN OnInterrupt(PKINTERRUPT InterruptObject, PDEVICE_EXTENSION pdx)
{
// 关中断。
UCHAR HSR = READ_PORT_UCHAR(pdx->portbase);
HSR = HSR | 0x04;
WRITE_PORT_UCHAR(pdx->portbase,HSR);
KdPrint(("==============interrupt!!!\n"));
// 恢复中断信号电平。
WRITE_REGISTER_UCHAR((PUCHAR)pdx->MemBar0+0x400000,0x10);
IoRequestDpc(pdx->fdo, NULL, pdx); // 中断处理标志,DPC处理事件。
return TRUE;
}
#pragma PAGEDCODE
// IRQL优先级高的使用分页内存,反之使用非分页内存。(维持系统稳定性)
// 代码放在代码段,数据放在数据段。
NTSTATUS InitMyPCI(IN PDEVICE_EXTENSION pdx,IN PCM_PARTIAL_RESOURCE_LIST list) // 主要用于将系统分配的资源初始化。
{
PHYSICAL_ADDRESS portbase; // 端口物理地址。
BOOLEAN gotport = FALSE;
ULONG vector; // 中断向量。
KIRQL irql; // 中断请求级。
KINTERRUPT_MODE mode; // 中断模式。
KAFFINITY affinity; // CPU的亲缘关系。
BOOLEAN irqshare; // 是否共享中断。
BOOLEAN gotinterrupt = FALSE;
ULONG nres = list->Count; // 资源总数。
PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = &list->PartialDescriptors[0];
// 每次循环获取一种资源。
for (ULONG i = 0; i < nres; ++i, ++resource)
{
// 判断是何种资源。
switch(resource->Type)
{
// I/O端口资源。
case CmResourceTypePort:
// I/O端口地址。
portbase = resource->u.Port.Start;
// I/O端口地址长度。
pdx->nports = resource->u.Port.Length;
// 是否需要地址映射。
pdx->mappedport = (resource->Flags & CM_RESOURCE_PORT_IO) == 0;
// 表示已经得到I/O端口资源。
gotport = TRUE;
break;
// 物理内存资源。
case CmResourceTypeMemory:
pdx->MemBar0 = (PUCHAR)MmMapIoSpace(resource->u.Memory.Start,resource->u.Memory.Length,MmNonCached);
pdx->nMem0 = resource->u.Memory.Length;
break;
// 中断资源。
case CmResourceTypeInterrupt:
// 获得中断请求级。
irql = (KIRQL) resource->u.Interrupt.Level;
// 获得中断向量。
vector = resource->u.Interrupt.Vector;
// 获取CPU亲缘关系。
affinity = resource->u.Interrupt.Affinity;
// 获得中断模式。
mode = (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
// 判断是否需要共享中断。
irqshare = resource->ShareDisposition == CmResourceShareShared;
// 表示已经得到中断。
gotinterrupt = TRUE;
break;
default:
KdPrint(("Unexpected I/O resource type %d\n", resource->Type));
break;
}
}
if (!(TRUE&& gotport&& gotinterrupt))
{
KdPrint((" Didn't get expected I/O resources\n"));
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
// 判断是够需要I/O端口映射。(为了操作方便,把IO空间映射到MEM空间)
if (pdx->mappedport)
{
// 获得I/O端口地址。
pdx->portbase = (PUCHAR) MmMapIoSpace(portbase, pdx->nports, MmNonCached);
if (!pdx->mappedport)
{
KdPrint(("Unable to map port range %I64X, length %X\n", portbase, pdx->nports));
return STATUS_INSUFFICIENT_RESOURCES;
}
}
else
// 获得I/O端口地址。
pdx->portbase = (PUCHAR) portbase.QuadPart;
// 链接中断。(中断对象与中断响应例程链接)
NTSTATUS status = IoConnectInterrupt(&pdx->InterruptObject, (PKSERVICE_ROUTINE)OnInterrupt, (PVOID)pdx, NULL, vector, irql, irql, LevelSensitive, TRUE, affinity, FALSE);
if (!NT_SUCCESS(status))
{
KdPrint(("IoConnectInterrupt failed - %X\n", status));
if (pdx->portbase && pdx->mappedport)
MmUnmapIoSpace(pdx->portbase, pdx->nports);
pdx->portbase = NULL;
return status;
}
return STATUS_SUCCESS;
}
#pragma LOCKEDCODE
// IRQL优先级高的使用分页内存,反之使用非分页内存。(维持系统稳定性)
// 代码放在代码段,数据放在数据段。
NTSTATUS OnRequestComplete(PDEVICE_OBJECT junk, PIRP Irp, PKEVENT pev)
{
KeSetEvent(pev, 0, FALSE); // 把IRP事件设置为完成。
return STATUS_MORE_PROCESSING_REQUIRED; // 再次完成IRP事件 。
}
#pragma PAGEDCODE
// IRQL优先级高的使用分页内存,反之使用非分页内存。(维持系统稳定性)
// 代码放在代码段,数据放在数据段。
// 上层设备的完成例程设置在下层设备IO堆栈。
NTSTATUS ForwardAndWait(PDEVICE_EXTENSION pdx, PIRP Irp)
{
PAGED_CODE(); // 它会检查当前函数是否运行低于
没有合适的资源?快使用搜索试试~ 我知道了~
IO_Card_Dev.zip_http://dev-io
共12个文件
h:3个
inf:1个
cpp:1个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 2 浏览量
2022-09-23
17:16:08
上传
评论
收藏 57KB ZIP 举报
温馨提示
DDK下,IO_Card windows驱动。
资源推荐
资源详情
资源评论
收起资源包目录
IO_Card_Dev.zip (12个子文件)
IO_Card_Dev______test
Guid.h 169B
IO_Card.h 2KB
buildchk.log 2KB
obj
_objects.mac 229B
i386
objchk
i386
io_card.obj 64KB
IO_Card.sys 8KB
IO_Card.pdb 75KB
Ioctls.h 709B
IO_Card.inf 5KB
Sources 153B
Makefile 265B
IO_Card.cpp 17KB
共 12 条
- 1
资源评论
alvarocfc
- 粉丝: 105
- 资源: 1万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 技术面试最后反问面试官的话 校招面试非技术问题有哪些 非技术问题如何回答.png
- NB-IOT-BC26全网通模块Altium+ CADENCE +PADS三种格式(原理图SCH+PCB封装库)文件.zip
- 基于微信小程序开发的校园失物招领系统源码毕业设计(优质项目源码).zip
- 词向量是一种将自然语言中的单词转换为数值向量的技术,它能够捕捉词义和上下文信息
- nmap与masscan的简单使用
- MyBatis动态SQL.pdf
- 基于stm32单片机protues仿真的温湿度控制系统设计(仿真图、源代码)
- 词向量:自然语言处理的基石
- mybatis动态sql
- 40G微信小程序开发教程(工具插件+视频教程)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功