寄托天下
查看: 6196|回复: 1

[计算机] NDIS sample - 6.0 miniport driver for realtek 8168/8169/8111/8110(zz) [复制链接]

Rank: 11Rank: 11Rank: 11Rank: 11

声望
3110
寄托币
48275
注册时间
2003-9-1
精华
44
帖子
1491

荣誉版主 GRE斩浪之魂 Golden Apple

发表于 2009-8-1 02:17:18 |显示全部楼层
本帖最后由 DriverEntry 于 2009-8-1 04:47 编辑

http://www.codeproject.com/KB/sy ... niport__driver.aspx

IntroductionFor those who aspire to write an NDIS 6.0 miniport windows ( DesktopPFs ) device driver for a new or existing ethernet controller, the onlysample source code available is the E100BEX found in the Microsoft DDK.There are a couple of other type of NDIS drivers like IM available inthe net, but not any miniport drivers for a NIC, AFAIK.
The E100BEX sample, hereafter referred to as e100, is for the intelline of etherexpress 100Mbs NIC cards. So if one wants to understandthis e100 by live debugging, apart from static code analysis, he/shehas to have this type of card, which is rarely found nowadays IMO.
So, I thought, why not write an NDIS 6 driver for a differentpopular ethernet controller easily found nowadays. I chose the Realtekfamily of gigabit ethernet controllers 8111/8168/8169/8110 found as aPCI card cheaply around $9 ( brands like hawkings, startech )and alsoas LOM ( Lan On Motherboard ) in many of the modern motherboards.
BackgroundThe approach I took was -- Instead of starting from scratch, port the Microsoft DDK sample e100, from intel to realtek h/w.
Thebenefit is -- The well tested e100 core and NDIS-related logic, thevarious state-machines, various synchronization mechanisms are ALLretained and only the h/w portions are changed.
Well, easier said than done. For one thing, though e100 is welldesigned/written, somehow I feel, the NDIS code seems to be tightlycoupled with the h/w related code. Understandable from a performancepoint of view. Other, the intel h/w and drivers are designed to workmostly on linked-list data structures shared between host and device,whereas the realtek h/w seems to be ARRAY oriented. So, the challengeis to adapt e100 meant for linked-lists to array oriented, withoutchanging any of the original code's logic flow.
About the sampleAbout the driver
----------------
DDK build 6001, e100 samplewas used as the baseline. Later some portions from the windows 2008server DDK e100 sample were taken and merged to fix a SEND issue. Moreon this later.
Code workings
-------------
I hope the ample comments found inthe original e100 and my own added comments should be sufficient toexplain things. Still as i get more time, i will keep adding more andmore to this section.
The original e100bex.htm may be a starting point
BUILD instructions
------------------
* DDK build 6000 was used. A straight forward command-line "build -cZ" will do. No batch files
INSTALL instructions
---------------------
The standard unsigned-driver installation way, using the provided RLTK1GIG.INF file
Still for newbies -- Go to DM, select the realtek network device andright click option "update driver". Keep going to the end the manualway, w/o letting the wizard take control of the process anytime.
Test results
-------------
* The driver was tested underVISTA32 free version, under heavy network load/stress conditions. Itperformed well without any crashes for hours together continuosly. Iwish i could test more rigorously with sophisticated test tools and ina chatty network environment, but since i dont have them, hope somebodywill provide such test results later to this forum. I also wish i coulduse "NDISTEST" from Microsoft WLK ( older term - HCT ) butunfortunately as many know the DTM controller can only be run on server2003. Why microsoft made it this way, effectively alienating thesmaller/individual/non-corporate device driver developers, is anybody'sguess.
* I tested this driver for the popular 2 of the realtek family ofgigabit ethernet controllers. One, a hawkings PCI card having realtek8169s and the other, a GIGABYTE-G33 board which has a realtek 8111b asLOM. SUCCESS. NO known issues so far.
NOTE - I tested for both 100M and 1G links.
Disclaimer
----------
Obviously this cannot be used forproduction environments. Just for informational and learning purposes.This author is not responsible for any of the consequences of usingthis code by anybody
Future and feature additions planned
--------------------------------------
* VLAN

Known issues
------------
None so far.
misc notes
----------
* 64-bit readiness -- This code compilesfor 64-bit though i havent tested in VISTA64. I will keep you posted ofthe results when i do that.
UPDATE : 64-bit driver works fine invista64. But, this INF file, i have to modify for both 32 & 64 PFs,in the future. So, time being replace the 32-bit rltkgbit.sys w/ 64-bitrltkgbit.sys, before installation and use the same INF file.
* The realtek h/w datasheet used to create this driver can be foundon the internet. It can also be obtained from realtek w/ a simpleemail. I got one from realtek with the simple message "...you shouldnot reveal to others..." No complicated NDAs, just a simple assuranceto them that you will not make it public w/o their permission.
Otherwise the realtek 8139 data sheet available here
http://www.datasheet4u.com/html/R/T/L/RTL8139DL_RealtekMicroelectronics.pdf.html comes close to understanding this sample, atleast for send/receive operations.
UPDATE
For all these new UPDATES I switched to the latest W2008Server 6001.18000 DDK
Large-Send-Offload ( LSO ) support addedLSO, also referred to as Task-send-ofload ( TSO ). All the relevant code can be found under the conditional compilation directive #if OFFLOAD
Steps needed
Step 1.
NdisMSetMiniportAttributes(.,.,.) MUST be done by initializing aNDIS_TCP_LARGE_SEND_OFFLOAD_V1 structure. This is done in MPInitialize( .,.,.) through InitLSO ( Adapter ) ;
Collapse
/*** Initialize NDIS_OFFLOAD ****/
NdisZeroMemory( NdisOffload,
sizeof(NDIS_OFFLOAD));
NdisOffload->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD ;
NdisOffload->Header.Revision = NDIS_OFFLOAD_REVISION_1 ;
NdisOffload->Header.Size = sizeof(NDIS_OFFLOAD);

//
// Initialize the NDIS_TCP_LARGE_SEND_OFFLOAD_V1 structure
// embedded in NDIS_OFFLOAD
//
LsoV1->IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3 ;
LsoV1->IPv4.MaxOffLoadSize = MP_MAX_TCP_OFFLOAD_SIZE ;
LsoV1->IPv4.MinSegmentCount = TCP_OFFLOAD_MIN_SEGMENTS ;
LsoV1->IPv4.TcpOptions = NDIS_OFFLOAD_SUPPORTED ;
LsoV1->IPv4.IpOptions = NDIS_OFFLOAD_SUPPORTED ;
//
/*** Initialize NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES ****/
//
NdisZeroMemory (
&OffloadAttributes,
sizeof(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->AdapterHandle,
(PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&OffloadAttributes);
Step 2.
Support OID_OFFLOAD_ENCAPSULATION
* If we dont return NDIS_STATUS_SUCCESS, we will not get any BIG packets from NDIS to be LSO-ed.
Here is the code
Collapse
#if OFFLOAD
case OID_OFFLOAD_ENCAPSULATION :
{
PNDIS_OFFLOAD_ENCAPSULATION Encap ;
//
// Verify the length
//
if (InformationBufferLength < sizeof(NDIS_OFFLOAD_ENCAPSULATION) )
{
return(NDIS_STATUS_INVALID_LENGTH);
}
Encap = (PNDIS_OFFLOAD_ENCAPSULATION)InformationBuffer ;
Adapter->NdisOffloadEncapSulation = Encap->IPv4.Enabled ;
if ( NDIS_OFFLOAD_SET_ON == Encap->IPv4.Enabled )
Encap->IPv4.EncapsulationType = NDIS_ENCAPSULATION_IEEE_802_3 ;
Status = NDIS_STATUS_SUCCESS ;
BytesRead = InformationBufferLength;
break ;
}
#endif
#if OFFLOAD
Step 3.
When NDIS calls MPSendNetBufferLists ( .,.,..) to send NBL, use theSCRATCH area in the NBL to store some context info about the LSO.
Here is the code
Collapse
// and initialize some LSO related fields there
MoveLSOinfoFromNBLtoContext ( Adapter, CurrNetBufferList )This function retrieves 2 main items from the NBL ; MSS andTcpHeaderOffset and saves them in a private context area (NBL->SCRATCH )
Step 4
NDIS 6.0 miniport is supposed to return "TcpPayLoad" in the NBL whenit completes(sending) it. But since rtl8169 h/w does NOT return thisvalue ( 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
NBL->TcpPayLoad = TotalBytesInNBL - NBL->TcpHeaderOffset + TcpHeaderLength;
Here is the code
Collapse
#if OFFLOAD
PeekTcpHeader ( pMpTcb->NetBufferList, pMpTcb->NetBuffer ) ;
#endifStep 5
Program the h/w by setting MSS value and LGSEN bit in the realtek 8169 H/W Transmit Buffer Descriptor
Collapse
#if OFFLOAD
if ( bLSOenabled ) {
pHwTbd->status |= (LGSENbit | pNBLcontext->MSS) ;

}
#endif
Step 6
In send-complete interrupt handler set "TcpPayLoad" in the completed NBL for upper layers' consumption
Collapse
#if OFFLOAD
UPDATE_LSO_TCP_PAYLOAD ( NetBufferList ) ;
#endif
JUMBO frame support addedNothing great. just this. No changes to the H/W for send/receive
Collapse
#if JUMBO_FRAME_SUPPORT
#define NIC_MAX_RECV_FRAME_SIZE 6464
#else
#define NIC_MAX_RECV_FRAME_SIZE 1664
#endif
#if OFFLOAD || JUMBO_FRAME_SUPPORT
#define NIC_MAX_XMIT_FRAME_SIZE 7040 // multiple 0f 64
#else
#define NIC_MAX_XMIT_FRAME_SIZE 1664
#endif
Power Managment Capabilities addedNothing done to the H/W at D0 & D3 transition time. We simply indicate to the NDIS we are capable.
Collapse
pPower_Management_Capabilities->Flags = NDIS_DEVICE_WAKE_UP_ENABLE ;
pPower_Management_Capabilities->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateD3;
pPower_Management_Capabilities->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
pPower_Management_Capabilities->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified ;
*pulInfoLen = sizeof (*pPower_Management_Capabilities);
*pStatus = NDIS_STATUS_SUCCESS;
}
TEST : MAGIC packet WOL worked fine with this code
About Copyright* Though this program is copyLEFT and free to be used anywhere, Iretained the copyright notices of INTEL and MICROSOFT found in theoriginal source code. Anyway, since e100 is part of the DDK sample forpublic use, the copyright may not be stringent. Please refer to theoriginal e100bex DDK sample code for copyright issues. I am notresponsible
* Thanks to the linux developer community, i borrowed the initialchip MAC/PHY configuration code from the realtek linux driver and tofairly credit them, I named those files linux_init.c and linux_h.h. Iam not sure how GNU licensing will affect this project FREE license, asi meant it to be.
FinallyAny form of comments and suggestions are welcome to this forum or to alex_@esdsinc.com
remove underscore.
Cheers & good luck

Historyfirst release dated 14 march 2008. version 6.0.6000.31308
second release dated 1 May 2008. Version 6.0.6000.050108. LSO and jumbo support added
Third release dated 2 May 2008. Version 6.0.6000.050208. Power managment capabilities added

                                                
        
                License        This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

                About the Author                                          
        alexander suresh

        
        Member               
        passionate windows device driver developer
                                
Occupation: Software Developer (Senior)
Location: United States

PM-support-added.zip

91.65 KB, 下载次数: 1

LSO-jumbo.support-added.zip

91.88 KB, 下载次数: 2

release.zip

342.43 KB, 下载次数: 1

使用道具 举报

Rank: 9Rank: 9Rank: 9

声望
297
寄托币
9342
注册时间
2009-3-2
精华
2
帖子
110

荣誉版主

发表于 2009-8-1 10:11:56 |显示全部楼层
帮LZ顶一下!

使用道具 举报

RE: NDIS sample - 6.0 miniport driver for realtek 8168/8169/8111/8110(zz) [修改]

问答
Offer
投票
面经
最新
精华
转发
转发该帖子
NDIS sample - 6.0 miniport driver for realtek 8168/8169/8111/8110(zz)
https://bbs.gter.net/thread-990864-1-1.html
复制链接
发送
回顶部