lvhaow
驱动小牛
驱动小牛
  • 注册日期2001-10-31
  • 最后登录2018-05-29
  • 粉丝0
  • 关注0
  • 积分44分
  • 威望35点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
  • 社区居民
阅读:1356回复:12

改错拿分喽!!!

楼主#
更多 发布于:2002-04-09 19:32
我是新手,拿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

最新喜欢:

hapihapi
lvhaow
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2002-04-09 21:06
用户被禁言,该主题自动屏蔽!
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
板凳#
发布于:2002-04-09 21:09
用户被禁言,该主题自动屏蔽!
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
地板#
发布于:2002-04-09 21:11
用户被禁言,该主题自动屏蔽!
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
地下室#
发布于:2002-04-09 21:16
用户被禁言,该主题自动屏蔽!
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
5楼#
发布于:2002-04-09 21:21
用户被禁言,该主题自动屏蔽!
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
6楼#
发布于:2002-04-09 21:22
用户被禁言,该主题自动屏蔽!
lvhaow
驱动小牛
驱动小牛
  • 注册日期2001-10-31
  • 最后登录2018-05-29
  • 粉丝0
  • 关注0
  • 积分44分
  • 威望35点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
  • 社区居民
7楼#
发布于:2002-04-10 08:23
TOM.CAT大哥,谢谢你,先奉上二十分表示谢意,还请您多帮帮我。
谢谢。 :D
lvhaow
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
8楼#
发布于:2002-04-10 08:52
用户被禁言,该主题自动屏蔽!
lvhaow
驱动小牛
驱动小牛
  • 注册日期2001-10-31
  • 最后登录2018-05-29
  • 粉丝0
  • 关注0
  • 积分44分
  • 威望35点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
  • 社区居民
9楼#
发布于:2002-04-10 19:04
/------------------------------------------------------
WriteOffset是返回WriteIrp中的Parameters.Write.ByteOffset。
它是一个64位整数,存储在一个LARGE_INTEGER结构中。它的含义是在一个内存页中,起始地址到数据地址的偏移量。
/------------------------------------------------------
这个参数怎么应用呢?你说的内存页,是不是指PCI的内存空间映射到内存中的那一段?OFFSET就是相对PCI内存空间地址0的偏移量,更直接地说就是把数据写到PCI内存的哪个位置上去!----我怎么这么罗嗦!! :P
这个参数可否直接用于m_MemRange.outd()的第一个参数?
lvhaow
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
10楼#
发布于:2002-04-10 19:08
用户被禁言,该主题自动屏蔽!
lvhaow
驱动小牛
驱动小牛
  • 注册日期2001-10-31
  • 最后登录2018-05-29
  • 粉丝0
  • 关注0
  • 积分44分
  • 威望35点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
  • 社区居民
11楼#
发布于:2002-04-11 10:13
那问题就来了!假如我要把数据写入PCI内存空间的中间而不是开始位置,那该怎么做?从IRP的哪个参数获取这个偏移量?
lvhaow
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
12楼#
发布于:2002-04-11 15:13
用户被禁言,该主题自动屏蔽!
游客

返回顶部