阅读:1357回复:12
改错拿分喽!!!
我是新手,拿DRIVERSTUDIO的范例改了个驱动,我敢肯定里面有一堆错误,还有一些我不明白的地方。现丑了,贴出来给各位大哥给看看,挑一个毛病或是帮我解答一个不明白的地方,立即双手奉上10分现大洋。呵呵,破产也在所不惜。帮帮忙,帮帮忙!
说明:基于PLX9052,这个驱动很简单,中断驱动,来一个中断写一批数据出去,没有其它的功能。里面的注释有些是我的理解,不可能完全正确。 ///////////////////////////////////////////////////////////// #include <vdw.h> #include \"pciwdmdv.h\" // Constructor构造函数 PciwdmDevice::PciwdmDevice(PDEVICE_OBJECT PDO, ULONG instance) : KPnpDevice( PDO, KUnitizedName(L\"Pciwdm\", instance), FILE_DEVICE_UNKNOWN, KUnitizedName(L\"Pciwdm\", instance), 0, DO_DIRECT_IO ), m_Pci(NULL) { if ( NT_SUCCESS(m_ConstructorStatus) ) m_ConstructorStatus = m_Pdo.Initialize(this, PDO); if ( ! NT_SUCCESS(m_ConstructorStatus) ) return; m_Pci.Initialize(m_Pdo.DeviceObject()); SetLowerDevice(&m_Pdo); SetPnpPolicy(); } /////////////////////////////////////////////////////////////////// // Create handler //APP打开设备文件创建句柄时调用 NTSTATUS PciwdmDevice::Create(KIrp I) { I.ForceReuseOfCurrentStackLocationInCalldown(); return m_Pdo.PnpCall(this, I); } /////////////////////////////////////////////////////////////////// // Close handler //APP关闭设备文件句柄时调用 NTSTATUS PciwdmDevice::Close(KIrp I) { I.ForceReuseOfCurrentStackLocationInCalldown(); return m_Pdo.PnpCall(this, I); } /////////////////////////////////////////////////////////////////// //中断服务程序,为保证数据输出尽可能不被干扰,不用DPC, BOOLEAN PciwdmDevice::The_Isr(void) { UCHAR intflag; m_Pci.ReadDeviceSpecificConfig(&intflag,0x4c,1); if (intflag|0x40)//0x40,检查BIT6是否为1,是则是自己的中断 { if(!m_Queue.IsEmpty()) { KIrp PI=m_Queue.CurrentIrp(); //获得队列中当前IRP KMemory Mem(PI.Mdl()); // 声明并初始化一个内存对象 PULONG pBuffer=(PULONG)Mem.VirtualAddress(); //获取内存指针 TotalSize=PI.WriteSize(CURRENT); //获得写数据BYTE总数 m_MemRange.outd(0,pBuffer,16384);//写数据 PI.Information()=TotalSize; m_Queue.PnpNextIrp(PI); } intflag=intflag&0xbf; //将intflag的bit6清0 m_Pci.WriteDeviceSpecificConfig(&intflag,0x4c,1); return TRUE; } else return FALSE;// 这个中断不是我的设备产生的。 } /////////////////////////////////////////////////////////////////// //系统的PNP管理器初始化设备驱动程序时调用,IRP副功能码值为IRP_MN_START_DEVICE NTSTATUS PciwdmDevice::OnStartDevice(KIrp I) { NTSTATUS status; I.Information() = 0; PCM_RESOURCE_LIST pResList = I.TranslatedResources(); PCM_RESOURCE_LIST pRawList = I.AllocatedResources(); //设置内存范围 status = m_MemRange.Initialize(pResList, pRawList, 0); if ( !NT_SUCCESS(status) ) return status; //设置中断 status = m_Interrupt.InitializeAndConnect( pResList, LinkTo(The_Isr), this ); return status; } /////////////////////////////////////////////////////////////////// //停止驱动???? NTSTATUS PciwdmDevice::OnStopDevice(KIrp I) { m_Interrupt.Disconnect(); //断开中断服务程序的映射 m_MemRange.~KMemoryRange(); //消毁内存空间对象 return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////// // DefaultPnp,不清楚这是做什么用的。 NTSTATUS PciwdmDevice::DefaultPnp(KIrp I) { I.ForceReuseOfCurrentStackLocationInCalldown(); return m_Pdo.PnpCall(this, I); } /////////////////////////////////////////////////////////////////// // DefaultPower不清楚这是做什么用的。 NTSTATUS PciwdmDevice::DefaultPower(KIrp I) { I.IndicatePowerIrpProcessed(); I.CopyParametersDown(); return m_Pdo.PnpPowerCall(this, I); } ////////////////////////////////////////////////////////////////// // SystemControl NTSTATUS PciwdmDevice::SystemControl(KIrp I) { I.ForceReuseOfCurrentStackLocationInCalldown(); return m_Pdo.PnpCall(this, I); } //该函数对应于APP的WRITEFILE操作 NTSTATUS PciwdmDevice::Write(KIrp I) { //应先检查IRP的参数是否合法,我的应用中,每次写操作的量是16KDW, //如果SIZE不是64K,则返回,以便APP及时处理,不至于影响下个中断 //返回仍使用\"成功\"标志,但APP可以通过检查写入的字节数判断是否真 //的是成功了。 //一个问题:WriteOffset究竟派什么用场?该怎么用? TotalSize=I.WriteSize(); if (TotalSize != 65536) { I.Information() = 0; return I.PnpComplete(this, STATUS_SUCCESS); } //排队该IRP return m_Queue.QueueIrp(I); } //我不需要在这里做任何处理,设置成空函数 VOID PciwdmQueue::StartIo(KIrp I) { return; } ==================================================================== //pciwdm.cpp 文件//////////////////////////////////////////////////// #define VDW_MAIN #include <vdw.h> #include \"pciwdmdv.h\" // include file for device class #include \"pciwdm.h\" // include file for driver class // Begin INIT time code #pragma code_seg(\"INIT\") DECLARE_DRIVER_CLASS(PciwdmDriver, NULL) /* DriverEntry和AddDevice共同创建了驱动程序对象。而PciwdwDevice类 仅仅是实现对一个设备实例的操作,该类的一个实例即为一个设备对象 并在AddDevice中做为参数加入驱动程序中。 作为驱动程序所必须的派遣函数,由PciwdmDriver的基类KDriver定义 ,在基类定义中,所有的功能函数名如Write或Read均为固定形式,和 驱动向导生成的函数名对应,不可以随意改动。其实中断服务有点特殊 它不是直接派遣到The_Isr中执行,而是用宏间接指向The_Isr()。 */ NTSTATUS PciwdmDriver::DriverEntry(PUNICODE_STRING RegistryPath) { m_instance = 0; // init count of device units created return STATUS_SUCCESS; } // End INIT time code #pragma code_seg() // AddDevice /*系统检测到每一个本驱动程序支持的设备时调用本函数 函数中的参数(PDO)指明由系统创建的FOR设备实例的物理设备对象 注:一个驱动程序可能会支持不只一个物理设备,系统每检测到一个设备, 为之创建一个实例,并在驱动中创建一个设备对象。我的驱动程序是 独占的,故而不存在多设备对象的问题,即本函数只会被调用一次。 */ NTSTATUS PciwdmDriver::AddDevice(PDEVICE_OBJECT PDO) { PciwdmDevice* pD = new (NonPagedPool) PciwdmDevice(PDO, m_instance); if (pD != NULL) { NTSTATUS status = pD->ConstructorStatus(); if ( !NT_SUCCESS(status) ) delete pD; else m_instance++; return status; } else return STATUS_INSUFFICIENT_RESOURCES; } ================================================================== //以下是头文件 ================================================================== /////////////////// PciwdmDriver 类定义//////////////////// class PciwdmDriver : public KDriver { SAFE_DESTRUCTORS public: virtual NTSTATUS DriverEntry(PUNICODE_STRING RegistryPath); virtual NTSTATUS AddDevice(PDEVICE_OBJECT Pdo); ULONG m_instance; }; ==================================================================== /////////////////PciwdmQueue 和 PciwdmDevice 类定义///////////////////// // pciwdmdv.h - include file for device class of PCIWDM driver #define VENDOR_ID 0x7CE0 // #define DEVICE_ID 0x1000 //这两个号是我随便写的 //上面定义的是PCI卡的ID号,用来访问配置空间,必须要换成实际的值 class PciwdmQueue : public KDriverManagedQueueEx //驱动程序自己的IRP队列 { public: SAFE_DESTRUCTORS; VOID StartIo(KIrp I);//虚函数 }; class PciwdmDevice : public KPnpDevice { public: PciwdmDevice(PDEVICE_OBJECT PDO, ULONG instance); DEVMEMBER_DISPATCHERS virtual NTSTATUS DefaultPnp(KIrp I); virtual NTSTATUS DefaultPower(KIrp I); virtual NTSTATUS OnStartDevice(KIrp I); virtual NTSTATUS OnStopDevice(KIrp I); ULONG TotalSize; MEMBER_ISR (PciwdmDevice, The_Isr) #ifdef __COMMENT_ONLY BOOLEAN The_Isr(void); // COMMENT_ONLY virtual NTSTATUS Create(KIrp I); // COMMENT_ONLY virtual NTSTATUS Close(KIrp I); // COMMENT_ONLY virtual NTSTATUS SystemControl(KIrp I); // COMMENT_ONLY virtual NTSTATUS Write(KIrp I); // COMMENT_ONLY #endif KPnpLowerDevice m_Pdo; // The Physical Device Object KInterrupt m_Interrupt; // The device\'s interrupt KMemoryRange m_MemRange; // Memory mapped region on device KPciConfiguration m_Pci; // Config space interface object PciwdmQueue m_Queue; }; :D |
|
最新喜欢:![]()
|
沙发#
发布于:2002-04-09 21:06
用户被禁言,该主题自动屏蔽! |
|
板凳#
发布于:2002-04-09 21:09
用户被禁言,该主题自动屏蔽! |
|
地板#
发布于:2002-04-09 21:11
用户被禁言,该主题自动屏蔽! |
|
地下室#
发布于:2002-04-09 21:16
用户被禁言,该主题自动屏蔽! |
|
5楼#
发布于:2002-04-09 21:21
用户被禁言,该主题自动屏蔽! |
|
6楼#
发布于:2002-04-09 21:22
用户被禁言,该主题自动屏蔽! |
|
7楼#
发布于:2002-04-10 08:23
TOM.CAT大哥,谢谢你,先奉上二十分表示谢意,还请您多帮帮我。
谢谢。 :D |
|
|
8楼#
发布于:2002-04-10 08:52
用户被禁言,该主题自动屏蔽! |
|
9楼#
发布于:2002-04-10 19:04
/------------------------------------------------------
WriteOffset是返回WriteIrp中的Parameters.Write.ByteOffset。 它是一个64位整数,存储在一个LARGE_INTEGER结构中。它的含义是在一个内存页中,起始地址到数据地址的偏移量。 /------------------------------------------------------ 这个参数怎么应用呢?你说的内存页,是不是指PCI的内存空间映射到内存中的那一段?OFFSET就是相对PCI内存空间地址0的偏移量,更直接地说就是把数据写到PCI内存的哪个位置上去!----我怎么这么罗嗦!! :P 这个参数可否直接用于m_MemRange.outd()的第一个参数? |
|
|
10楼#
发布于:2002-04-10 19:08
用户被禁言,该主题自动屏蔽! |
|
11楼#
发布于:2002-04-11 10:13
那问题就来了!假如我要把数据写入PCI内存空间的中间而不是开始位置,那该怎么做?从IRP的哪个参数获取这个偏移量?
|
|
|
12楼#
发布于:2002-04-11 15:13
用户被禁言,该主题自动屏蔽! |
|