Click here to Skip to main content
15,881,380 members
Articles / Programming Languages / C

NDIS sample - 6.0 miniport driver for realtek 8168/8169/8111/8110

Rate me:
Please Sign up or sign in to vote.
4.26/5 (12 votes)
1 May 2008CPOL7 min read 92.6K   42   22
NDIS 6.0 miniport driver for realtek 8168/8169/8111/8110 family of gigabit ethernet controllers

Introduction

For those who aspire to write an NDIS 6.0 miniport windows ( Desktop PFs ) device driver for a new or existing ethernet controller, the only sample source code available is the E100BEX found in the Microsoft DDK. There are a couple of other type of NDIS drivers like IM available in the net, but not any miniport drivers for a NIC, AFAIK.

The E100BEX sample, hereafter referred to as e100, is for the intel line of etherexpress 100Mbs NIC cards. So if one wants to understand this e100 by live debugging, apart from static code analysis, he/she has to have this type of card, which is rarely found nowadays IMO.

So, I thought, why not write an NDIS 6 driver for a different popular ethernet controller easily found nowadays. I chose the Realtek family of gigabit ethernet controllers 8111/8168/8169/8110 found as a PCI card cheaply around $9 ( brands like hawkings, startech )and also as LOM ( Lan On Motherboard ) in many of the modern motherboards.

Background

The approach I took was -- Instead of starting from scratch, port the Microsoft DDK sample e100, from intel to realtek h/w.
The benefit is -- The well tested e100 core and NDIS-related logic, the various state-machines, various synchronization mechanisms are ALL retained and only the h/w portions are changed.

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.

About the sample

About the driver

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.

Code workings

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.
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 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.

Test results

  • 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.
  • 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.

NOTE - I tested for both 100M and 1G links.

Disclaimer

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

Future and feature additions planned

  • VLAN

Known issues

None so far.

misc notes

  • 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.

UPDATE : 64-bit driver works fine in vista64. 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-bit rltkgbit.sys, before installation and use the same INF file.

  • 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.

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 added

LSO, 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 a NDIS_TCP_LARGE_SEND_OFFLOAD_V1 structure. This is done in MPInitialize ( .,.,.) through InitLSO ( Adapter ) ;

C++
 /*** 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

C++
#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 the SCRATCH area in the NBL to store some context info about the LSO.
Here is the code

C++
// and initialize some LSO related fields there
MoveLSOinfoFromNBLtoContext ( Adapter, CurrNetBufferList )

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

Step 4

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
NBL->TcpPayLoad = TotalBytesInNBL - NBL->TcpHeaderOffset + TcpHeaderLength;

Here is the code

#if OFFLOAD
PeekTcpHeader ( pMpTcb->NetBufferList, pMpTcb->NetBuffer ) ;
#endif

Step 5

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

#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

#if OFFLOAD
UPDATE_LSO_TCP_PAYLOAD ( NetBufferList ) ;
#endif


JUMBO frame support added

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

#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 added

Nothing done to the H/W at D0 & D3 transition time. We simply indicate to the NDIS we are capable.

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, I retained the copyright notices of INTEL and MICROSOFT found in the original source code. Anyway, since e100 is part of the DDK sample for public use, the copyright may not be stringent. Please refer to the original e100bex DDK sample code for copyright issues. I am not responsible
  • Thanks to the linux developer community, i borrowed the initial chip MAC/PHY configuration code from the realtek linux driver and to fairly credit them, I named those files linux_init.c and linux_h.h. I am not sure how GNU licensing will affect this project FREE license, as i meant it to be.

Finally

Any form of comments and suggestions are welcome to this forum or to alex_@esdsinc.com
remove underscore.

Cheers & good luck

History

  • first 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)


Written By
Software Developer (Senior)
United States United States
passionate windows device driver developer

Comments and Discussions

 
QuestionBroken link Pin
Tim Chan15-Jul-21 17:36
Tim Chan15-Jul-21 17:36 
QuestionBroken link Pin
RedScreen24-Feb-21 3:06
RedScreen24-Feb-21 3:06 
Questionbroken link, any zip file (No download file was specified.) Pin
woreno7-Mar-20 5:53
woreno7-Mar-20 5:53 
QuestionLink is broken, the download of the zip is not possible Pin
Member 1406453622-Nov-18 23:08
Member 1406453622-Nov-18 23:08 
AnswerRe: Link is broken, the download of the zip is not possible Pin
Member 1406453622-Nov-18 23:32
Member 1406453622-Nov-18 23:32 
Questionbroken link Pin
Manoj Singhii27-Dec-16 14:20
Manoj Singhii27-Dec-16 14:20 
AnswerRe: broken link Pin
SoMad28-Dec-16 11:32
professionalSoMad28-Dec-16 11:32 
Questiondownload broken? Pin
alexquisi24-Jun-15 10:42
alexquisi24-Jun-15 10:42 
GeneralMy vote of 4 Pin
Amir Mohammad Nasrollahi9-Aug-13 20:10
professionalAmir Mohammad Nasrollahi9-Aug-13 20:10 
Questiondma buffer Pin
zxyzxzy25-Jun-13 0:32
zxyzxzy25-Jun-13 0:32 
AnswerRe: dma buffer Pin
rgraham827-Jun-13 4:01
rgraham827-Jun-13 4:01 
QuestionHelp in understanding NDIS Pin
User17999-Dec-12 13:59
User17999-Dec-12 13:59 
Questionhow to lad it in win 7 64 bit? Pin
zaganic4-Feb-11 23:45
zaganic4-Feb-11 23:45 
AnswerRe: how to lad it in win 7 64 bit? Pin
wangyongbogood2-Apr-13 1:41
wangyongbogood2-Apr-13 1:41 
GeneralComplie error in Windows DDK 2600 & WDK 7600.16385.1 at WinXp Pin
itechnology25-Oct-10 8:38
itechnology25-Oct-10 8:38 
Thanks for your excellent job.
Complie errors founded in Windows DDK 2600 & WDK 7600.16385.1 at WinXp SP3
1. errors in Windows DDK 2600 @ WinXP SP3

LSO-jumbo[1][1].support-added>build -cz
BUILD: Object root set to: ==> objchk
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: /i switch ignored
BUILD: Using 2 child processes
BUILD: Compile and Link for i386
BUILD: k:\20101024windriverdev\8139d_miniport_driver\codes\lso-jumbo[1][1].support-added\sources.(0): Unknown TARGETPATH value
BUILD: Examining k:\20101024windriverdev\8139d_miniport_driver\codes\lso-jumbo[1][1].support-added directory for files to compile.
BUILD: Compiling k:\20101024windriverdev\8139d_miniport_driver\codes\lso-jumbo[1][1].support-added directory
BUILD: nmake.exe /c BUILDMSG=Stop. -i NTTEST= UMTEST= NOLINK=1 386=1 failed - rc = 2
BUILD: Linking k:\20101024windriverdev\8139d_miniport_driver\codes\lso-jumbo[1][1].support-added directory
BUILD: nmake.exe /c BUILDMSG=Stop. -i LINKONLY=1 NOPASS0=1 NTTEST= UMTEST= 386=1 failed - rc = 2
BUILD: Done

PM-support-added>build -cz
BUILD: Object root set to: ==> objchk
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: /i switch ignored
BUILD: Using 2 child processes
BUILD: Compile and Link for i386
BUILD: k:\20101024windriverdev\8139d_miniport_driver\codes\pm-support-added\sources.(0): Unknown TARGETPATH value
BUILD: Examining k:\20101024windriverdev\8139d_miniport_driver\codes\pm-support-added directory for files to compile.
BUILD: Compiling k:\20101024windriverdev\8139d_miniport_driver\codes\pm-support-added directory
BUILD: nmake.exe /c BUILDMSG=Stop. -i NTTEST= UMTEST= NOLINK=1 386=1 failed - rc = 2
BUILD: Linking k:\20101024windriverdev\8139d_miniport_driver\codes\pm-support-added directory
BUILD: nmake.exe /c BUILDMSG=Stop. -i LINKONLY=1 NOPASS0=1 NTTEST= UMTEST= 386=1 failed - rc = 2
BUILD: Done

2. errors in WDK 7600.16385.1 at WinXp SP3
LSO-jumbo[1][1].support-added>build -cz
BUILD: Compile and Link for x86
BUILD: Start time: Tue Oct 26 02:33:29 2010
BUILD: Examining k:\20101024windriverdev\8139d_miniport_driver\codes\lso-jumbo[1][1].support-added directory for files to compile.
BUILD: Compiling and Linking k:\20101024windriverdev\8139d_miniport_driver\codes\lso-jumbo[1][1].support-added directory
Configuring OACR for 'root:x86chk' - <OACR on>
BUILD: Finish time: Tue Oct 26 02:33:29 2010
BUILD: Done
and found _objects.mac in objchk_wxp_x86\i386

PM-support-added>build -cz
BUILD: Compile and Link for x86
BUILD: Start time: Tue Oct 26 02:35:31 2010
BUILD: Examining k:\20101024windriverdev\8139d_miniport_driver\codes\pm-support-added directory for files to compile.
BUILD: Compiling and Linking k:\20101024windriverdev\8139d_miniport_driver\codes\pm-support-added directory
Configuring OACR for 'root:x86chk' - <OACR on>
BUILD: Finish time: Tue Oct 26 02:35:31 2010
BUILD: Done

and found _objects.mac in objchk_wxp_x86\i386

Can you give me some helps,thank you.
Generalvirtual NDIS miniport driver Pin
Philip Stuyck15-Feb-10 10:13
Philip Stuyck15-Feb-10 10:13 
GeneralRSS - Receive Side Scaling Pin
ale.capu806-Apr-09 6:36
ale.capu806-Apr-09 6:36 
GeneralRLTKGBIT.sys not in zip file Pin
kunhao17-Mar-09 5:05
kunhao17-Mar-09 5:05 
GeneralRe: RLTKGBIT.sys not in zip file Pin
alexander suresh30-Mar-09 8:02
alexander suresh30-Mar-09 8:02 
GeneralThank you so much Pin
Member 257690730-Oct-08 20:41
Member 257690730-Oct-08 20:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.