⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ndis_6.0_miniport__driver.aspx.htm

📁 实现一个千兆以太网卡的NDIS的miniport驱动实例源代码 对于那些希望写一个NDIS 6.0的miniport设备驱动的开发人员来说
💻 HTM
📖 第 1 页 / 共 5 页
字号:
retained and only the h/w portions are changed. </p>

<p>Well, easier said than done. For one thing, though e100 is well
designed/written, somehow I feel, the NDIS code seems to be tightly
coupled with the h/w related code. Understandable from a performance
point of view. Other, the intel h/w and drivers are designed to work
mostly on linked-list data structures shared between host and device,
whereas the realtek h/w seems to be ARRAY oriented. So, the challenge
is to adapt e100 meant for linked-lists to array oriented, without
changing any of the original code's logic flow. </p>

<h2>About the sample</h2>

<p>About the driver<br>----------------<br>DDK build 6001, e100 sample
was used as the baseline. Later some portions from the windows 2008
server DDK e100 sample were taken and merged to fix a SEND issue. More
on this later.</p>

<p>Code workings<br>-------------<br>I hope the ample comments found in
the original e100 and my own added comments should be sufficient to
explain things. Still as i get more time, i will keep adding more and
more to this section.<br>The original e100bex.htm may be a starting point</p>

<p>BUILD instructions<br>------------------<br>* DDK build 6000 was used. A straight forward command-line "build -cZ" will do. No batch files</p>

<p>INSTALL instructions<br>---------------------<br>The standard unsigned-driver installation way, using the provided RLTK1GIG.INF file</p>

<p>Still for newbies -- Go to DM, select the realtek network device and
right click option "update driver". Keep going to the end the manual
way, w/o letting the wizard take control of the process anytime.</p>

<p>Test results<br>-------------<br>* The driver was tested under
VISTA32 free version, under heavy network load/stress conditions. It
performed well without any crashes for hours together continuosly. I
wish i could test more rigorously with sophisticated test tools and in
a chatty network environment, but since i dont have them, hope somebody
will provide such test results later to this forum. I also wish i could
use "NDISTEST" from Microsoft WLK ( older term - HCT ) but
unfortunately as many know the DTM controller can only be run on server
2003. Why microsoft made it this way, effectively alienating the
smaller/individual/non-corporate device driver developers, is anybody's
guess.</p>

<p>* I tested this driver for the popular 2 of the realtek family of
gigabit ethernet controllers. One, a hawkings PCI card having realtek
8169s and the other, a GIGABYTE-G33 board which has a realtek 8111b as
LOM. SUCCESS. NO known issues so far.<br>NOTE - I tested for both 100M and 1G links.</p>

<p>Disclaimer<br>----------<br>Obviously this cannot be used for
production environments. Just for informational and learning purposes.
This author is not responsible for any of the consequences of using
this code by anybody</p>

<p>Future and feature additions planned<br>--------------------------------------<br>* VLAN</p>

<p><br>Known issues<br>------------<br>None so far.</p>

<p>misc notes<br>----------<br>* 64-bit readiness -- This code compiles
for 64-bit though i havent tested in VISTA64. I will keep you posted of
the results when i do that.</p>

<p><strong><em>UPDATE</em></strong> : 64-bit driver works fine in
vista64. But, this INF file, i have to modify for both 32 &amp; 64 PFs,
in the future. So, time being replace the 32-bit rltkgbit.sys w/ 64-bit
rltkgbit.sys, before installation and use the same INF file.</p>

<p>* The realtek h/w datasheet used to create this driver can be found
on the internet. It can also be obtained from realtek w/ a simple
email. I got one from realtek with the simple message "...you should
not reveal to others..." No complicated NDAs, just a simple assurance
to them that you will not make it public w/o their permission.</p>

<p>Otherwise the realtek 8139 data sheet available here</p>

<p><a href="http://www.datasheet4u.com/html/R/T/L/RTL8139DL_RealtekMicroelectronics.pdf.html">http://www.datasheet4u.com/html/R/T/L/RTL8139DL_RealtekMicroelectronics.pdf.html</a> comes close to understanding this sample, atleast for send/receive operations.</p>

<h2>UPDATE</h2>

<p><br>For all these new UPDATES I switched to the latest W2008Server 6001.18000 DDK</p>

<h4>Large-Send-Offload ( LSO ) support added</h4>

<p>LSO, also referred to as Task-send-ofload ( TSO ). All the relevant code can be found under the conditional compilation <strong>directive #if OFFLOAD</strong></p>

<p>Steps needed</p>

<p>Step 1. </p>

<p>NdisMSetMiniportAttributes(.,.,.) MUST be done by initializing a
NDIS_TCP_LARGE_SEND_OFFLOAD_V1 structure. This is done in MPInitialize
( .,.,.) through InitLSO ( Adapter ) ;</p>

<div class="SmallText" id="premain0" style="width: 100%; cursor: pointer;"><img preid="0" src="NDIS_6.0_miniport__driver.aspx_files/minus.gif" id="preimg0" height="9" width="9"><span preid="0" style="margin-bottom: 0pt;" id="precollapse0"> Collapse</span></div><div style="margin-top: 0pt;" id="pre0" class="no-vmads"><pre> <span class="code-comment">/*</span><span class="code-comment">** Initialize NDIS_OFFLOAD ****/</span>
NdisZeroMemory( NdisOffload, 
<span class="code-keyword">sizeof</span>(NDIS_OFFLOAD));
NdisOffload-<span class="code-keyword">&gt;</span>Header.Type = NDIS_OBJECT_TYPE_OFFLOAD ;
NdisOffload-<span class="code-keyword">&gt;</span>Header.Revision = NDIS_OFFLOAD_REVISION_1 ;
NdisOffload-<span class="code-keyword">&gt;</span>Header.Size = <span class="code-keyword">sizeof</span>(NDIS_OFFLOAD); 

<span class="code-comment">//</span>
<span class="code-comment">//</span><span class="code-comment"> Initialize the NDIS_TCP_LARGE_SEND_OFFLOAD_V1 structure</span>
<span class="code-comment">//</span><span class="code-comment"> embedded in NDIS_OFFLOAD </span>
<span class="code-comment">//</span>
LsoV1-<span class="code-keyword">&gt;</span>IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3 ;
LsoV1-<span class="code-keyword">&gt;</span>IPv4.MaxOffLoadSize = MP_MAX_TCP_OFFLOAD_SIZE ;
LsoV1-<span class="code-keyword">&gt;</span>IPv4.MinSegmentCount = TCP_OFFLOAD_MIN_SEGMENTS ;
LsoV1-<span class="code-keyword">&gt;</span>IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED ;
LsoV1-<span class="code-keyword">&gt;</span>IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED ;
<span class="code-comment">//</span>
<span class="code-comment">/*</span><span class="code-comment">** Initialize NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES ****/</span>
<span class="code-comment">//</span>
NdisZeroMemory ( 
&amp;OffloadAttributes, 
<span class="code-keyword">sizeof</span>(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES)
);
OffloadAttributes.Header.Type = 
NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES ;
OffloadAttributes.Header.Revision = 
NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1 ;
OffloadAttributes.Header.Size = 
NDIS_SIZEOF_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1 ;
OffloadAttributes.HardwareOffloadCapabilities =
OffloadAttributes.DefaultOffloadConfiguration = NdisOffload ;
status = NdisMSetMiniportAttributes( Adapter-<span class="code-keyword">&gt;</span>AdapterHandle,
(PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&amp;OffloadAttributes);</pre></div>

<p><br>Step 2. </p>

<p>Support OID_OFFLOAD_ENCAPSULATION<br>* If we dont return NDIS_STATUS_SUCCESS, we will not get any BIG packets from NDIS to be LSO-ed. </p>

<p>Here is the code</p>

<div class="no-vmads"><pre><span class="code-preprocessor">#if</span> OFFLOAD
<span class="code-keyword">case</span> OID_OFFLOAD_ENCAPSULATION :
{
PNDIS_OFFLOAD_ENCAPSULATION Encap ;
<span class="code-comment">//</span>
<span class="code-comment">//</span><span class="code-comment"> Verify the length</span>
<span class="code-comment">//</span>
<span class="code-keyword">if</span> (InformationBufferLength <span class="code-keyword">&lt;</span> <span class="code-keyword">sizeof</span>(NDIS_OFFLOAD_ENCAPSULATION) ) 
{
<span class="code-keyword">return</span>(NDIS_STATUS_INVALID_LENGTH);
}
Encap = (PNDIS_OFFLOAD_ENCAPSULATION)InformationBuffer ;
Adapter-<span class="code-keyword">&gt;</span>NdisOffloadEncapSulation = Encap-<span class="code-keyword">&gt;</span>IPv4.Enabled ;
<span class="code-keyword">if</span> ( NDIS_OFFLOAD_SET_ON == Encap-<span class="code-keyword">&gt;</span>IPv4.Enabled )
Encap-<span class="code-keyword">&gt;</span>IPv4.EncapsulationType = NDIS_ENCAPSULATION_IEEE_802_3 ;
Status = NDIS_STATUS_SUCCESS ;
BytesRead = InformationBufferLength;
<span class="code-keyword">break</span> ;
}
<span class="code-preprocessor">#endif</span>
<span class="code-preprocessor">#if</span> OFFLOAD</pre></div>

<p><br>Step 3.</p>

<p>When NDIS calls MPSendNetBufferLists ( .,.,..) to send NBL, use the
SCRATCH area in the NBL to store some context info about the LSO.<br>Here is the code</p>

<div class="no-vmads"><pre><span class="code-comment">//</span><span class="code-comment"> and initialize some LSO related fields there</span>
MoveLSOinfoFromNBLtoContext ( Adapter, CurrNetBufferList )</pre></div>

<p>This function retrieves 2 main items from the NBL ; MSS and
TcpHeaderOffset and saves them in a private context area (
NBL-&gt;SCRATCH )</p>

<p>Step 4</p>

<p>NDIS 6.0 miniport is supposed to return "TcpPayLoad" in the NBL when
it completes(sending) it. But since rtl8169 h/w does NOT return this
value ( AFAIK ) , we have to figure it out from the NBL ( NB ) data,
before sending it to the H/W. The way we do this is <br>NBL-&gt;TcpPayLoad = TotalBytesInNBL - NBL-&gt;TcpHeaderOffset + TcpHeaderLength;</p>

<p>Here is the code</p>

<div class="no-vmads"><pre><span class="code-preprocessor">#if</span> OFFLOAD
PeekTcpHeader ( pMpTcb-<span class="code-keyword">&gt;</span>NetBufferList, pMpTcb-<span class="code-keyword">&gt;</span>NetBuffer ) ;
<span class="code-preprocessor">#endif</span></pre></div>

<p>Step 5</p>

<p>Program the h/w by setting MSS value and LGSEN bit in the realtek 8169 H/W Transmit Buffer Descriptor</p>

<div class="no-vmads"><pre><span class="code-preprocessor">#if</span> OFFLOAD
<span class="code-keyword">if</span> ( bLSOenabled ) {
pHwTbd-<span class="code-keyword">&gt;</span>status |= (LGSENbit | pNBLcontext-<span class="code-keyword">&gt;</span>MSS) ;

}
<span class="code-preprocessor">#endif</span></pre></div>

<p><br>Step 6</p>

<p>In send-complete interrupt handler set "TcpPayLoad" in the completed NBL for upper layers' consumption</p>

<div class="no-vmads"><pre><span class="code-preprocessor">#if</span> OFFLOAD
UPDATE_LSO_TCP_PAYLOAD ( NetBufferList ) ;
<span class="code-preprocessor">#endif</span></pre></div>

<h4><br>JUMBO frame support added</h4>

<p>Nothing great. just this. No changes to the H/W for send/receive</p>

<div class="no-vmads"><pre><span class="code-preprocessor">#if</span> JUMBO_FRAME_SUPPORT
<span class="code-preprocessor">#define</span> NIC_MAX_RECV_FRAME_SIZE <span class="code-digit">6464</span>
<span class="code-preprocessor">#else</span>
<span class="code-preprocessor">#define</span> NIC_MAX_RECV_FRAME_SIZE <span class="code-digit">1664</span>
<span class="code-preprocessor">#endif</span>
<span class="code-preprocessor">#if</span> OFFLOAD || JUMBO_FRAME_SUPPORT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -