lsshao
驱动牛犊
驱动牛犊
  • 注册日期2004-02-03
  • 最后登录2007-10-29
  • 粉丝0
  • 关注0
  • 积分33分
  • 威望5点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
阅读:4188回复:0

DriverNetwork miniport驱动学习(8)

楼主#
更多 发布于:2004-03-19 09:44
NDIS Miniports实现OID处理
NDIS采用对象标示符OID,在DDK的ntddndis.h中定义,重新定位和设置NDIS miniport驱动的各种配置和操作参数。每一个OID代表了一个32位值,与正确的数据结构一起通过MiniportQueryInformation 和MiniportSetInformation处理程序提交给驱动。
DDK类型NDIS驱动一般都要实现OID处理过程,通过MiniportQueryInformation和MiniportSetInformation内一个比较长的switch statement。另一方面,DriverNetworks开发了一种消息映射方法,将每个OID当作一个消息由特定的OID处理程序处理。
OID消息映射方法允许你将OID请求分析和特殊OID处理过程分开,这样就增强了可读性和可维护性。
1.OID 消息映射
OID 消息映射就是一组宏状态声明支持某种NDIS OIDs并实现OID消息解码cracker 。例如:
// "查询" 映射
BEGIN_OID_QUERY_MAP(MyAdapter)
OID_QUERY_ENTRY (OID_GEN_HARDWARE_STATUS)
OID_QUERY_ENTRY (OID_GEN_MEDIA_SUPPORTED)
. . .
END_OID_QUERY_MAP
// "设置"映射
BEGIN_OID_SET_MAP(MyAdapter)
OID_SET_ENTRY( OID_GEN_CURRENT_LOOKAHEAD)
OID_SET_ENTRY( OID_GEN_CURRENT_PACKET_FILTER)
OID_SET_ENTRY( OID_GEN_PROTOCOL_OPTIONS)
. . .
END_OID_SET_MAP()
NDIS miniport项目包含了两个映射:一个是查询请求,一个是设置请求。 每一个OID映射就是一块在BEGIN_OID_MAP和END_OID_MAP宏状态之间的宏块组成,对应着MyAdapter::QueryInformation()和MyAdapter::SetInformation()处理程序的实现。Network Driver Wizard生成的NDIS Miniport项目包括含有映射定义的XxxOids.cpp文档。
在映射中,OID_QUERY_ENTRY (or OID_SET_ENTRY) 声明支持对特定的OID。因此编译器能生成代码来激活一个相应的OID处理程序。
OID消息映射在内部可以执行必要的样本文件OID分析代码,例如检查输入/输出缓冲大小匹配。OID映射可以实现为一种C switch statement,它与DDK miniport驱动的运行效率一样。
2.OID 处理
DriverNetworks OID处理程序是KNdisMiniAdapter派生类的一个成员函数,用来处理特殊的NDIS OID请求。OID处理程序由OID消息映射中激活。 DriverNetworks 定义了OID处理程序的命名习惯和函数原型。对于OID 常量OID_XXX_YYY的命名习惯是: getOID_XXX_YYY() 是查询信息请求; setOID_XXX_YYY()是设置信息请求。
OID查询(获得)处理程序的三种有效形式:
1) short property(返回一个T类型的值):
T getOID_XXX_YYY ();
2) short handler(返回NDIS_STATUS,如果成功――T类型的值)
NDIS_STATUS getOID_XXX_YYY (T* pValue);
3) variable-size handler(返回NDIS_STATUS,如果成功――变量矩阵)
NDIS_STATUS  getOID_XXX_YYY(T* pValue,IN OUT PULONG ByteCount,       OUT PULONG ByteNeeded);
OID设置处理程序的两种有效形式:
1)short property(接收一个T类型值,返回NDIS_STATUS)
NDIS_STATUS setOID_XXX_YYY (T* pValue);
2)variable handler(接收一个变量矩阵,返回NDIS_STATUS)
NDIS_STATUS setOID_XXX_YYY (T* pValue,IN OUT PULONG ByteCount,                                                                                                                              OUT PULONG ByteNeeded);
为了决定选择哪一种特定OID处理程序,DriverNetworks开发一种C++技术基于OID属性为给定的OID来选择一个处理程序原型。OID属性参考OID Traits。DriverNetworks基于对既定OID的常规处理为大多数NDIS OIDs定义了OID Traits。例如,大多数NDIS miniport驱动都对OID_GEN_MAXIMUM_FRAME_SIZE查询响应并返回某些常数值。查询的第一种形式是OID消息映射激活的默认选择。然而,C++ traits技术允许忽略很多细节。(参看OID Traits)。
DriverNetworks并不限制处理程序怎样实现的,只要它们的特征和上面的一种形式匹配就可以了。例如,short property处理程序(查询和设置的第一种形式)一般都是内联的或者静态的,和DDK的实现具有一样的运行效率。
3.OID Traits
OID Traits声明了NDIS OIDs的属性,也就定义了OID消息映射使用的OID 处理程序的形式。The OID traits可以是可变的和也可以是不可变的。
不可变的Traits声明了OID的本质属性,例如OID代表的值得长度。不可变traits从DDK的定义中派生而来的(参考表1.1 Network Drivers: Windows 2000)。在DriverNetworks中,不可变traits由KNdisOid<oid>模板类描述,并且通过KNdisOidTraitsBase<oid>模板类直接交给用户。这些模板的参数都是OID_XXX_YYY常数值。DriverNetworks定义了下面的不可变traits:
1) 类型:代表给定OID的值的类型。
2) ULONG 长度:值的字节长度 (通常有, sizeof(Type))
3) bool IsVarSize():说明OID是描述一个类型Type的一个单元还是一个变量大小的矩阵。
可变Traits声明了用户可修改的OID的属性。可变OID traits通过KNdisOidTraits<oid,a>模板类直接提供给用户。这个模板由KNdisOidTraitsBase类派生的,并且参数包括OID_XXX_YYY常量值和adapter类的类型。C++ 模板规范经过特殊处理后提供可变性。DriverNetworks定义了下面一些可变trait:
&#8226;bool Failable():说明在给定的miniport驱动中OID查询请求曾经是否失败过。当一个OID查询返回的不是NDIS_STATUS_SUCCESS,就认为它是失败了。
Failable()仅用于查询请求。所有的设置请求都认为是失败的。所有的查询请求默认为非失败的。用户通过为特殊的adapter类型定义Failable(),而不用考虑细节。例如:
inline bool
KNdisOidTraits<OID_GEN_LINK_SPEED, MyAdapter>::Failable() { return true; }
这样一来,对于给定的adapter――MyAdapter,查询链接速率可能会是会失败。因此,OID解码的MyAdapter::getOID_GEN_LINK_SPEED()处理程序运用查询的第二种形式,而不是第一种形式。
OID处理程序的形式根据IsVarSize和Failable traits来决定。下表总结了DriverNetworks基于OID traits选择正确的处理程序的形式。
Request IsVarSize Failable Handler Form Comment/Example
Query F F q1 Trivial const parameter
Query F T q2 Run time read value
Query T F q3 Input size might not be valid
Query T T q3 Data array read from hardware
Set F F N/A Set() can fail by definition
Set T F N/A Set() can fail by definition
Set F T s1 Set a single parameter value
Set T T s2 Set an array of values

4.添加和删除OID支持
1)为专门的OID_XXX_YYY添加支持
下面应该对项目文件XxxOids.cpp进行修改,并假设NDIS Miniport驱动项目由Network Driver Wizard生成的。
1. 在需要支持的OIDs矩阵中添加OID_XXX_YYY 。也就是将OID_XXX_YYY符号插入到静态矩阵sm_OID_GEN_SUPPORTED_LIST[]中。注意:该矩阵OIDs的上升顺序不能被打乱。
2. 如果要实现OID_XXX_YYY 的查询,在OID查询消息映射中插入一行OID_QUERY_ENTRY(OID_XXX_YYY)。如果已经实现了一组OID_XXX_YYY,就将OID_SET_ENTRY(OID_XXX_YYY)插入到OID查询消息映射中。
3. 如果查询请求可能会失败或者是异步完成的,就可以不考虑Failable() trait 。这是可选的。
4. 实现查询,如果可应用,那么基于上表描述的原型设置处理程序。
2)为专门的OID_XXX_YYY删除支持
假设NDIS Miniport驱动项目由Network Driver Wizard生成的。
1. 注释sm_OID_GEN_SUPPORTED_LIST[]矩阵的OID_XXX_YYY;
2. 从OID消息映射中注释OID_QUERY/SET_ENTRY。
注意: 可以选择删除处理程序代码,因为这些代码将被优化掉。

最新喜欢:

ljmmaryljmmar...
游客

返回顶部