|
|||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
Download LSO-jumbo.support-added.zip - 91.88 KBDownload PM-support-added.zip - 91.65 KBIntroductionFor 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. BackgroundThe approach I took was -- Instead of starting from scratch, port the Microsoft DDK sample e100, from intel to realtek h/w. 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 sampleAbout the driver Code workings BUILD instructions INSTALL instructions 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 * 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. Disclaimer Future and feature additions planned
misc notes 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
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 a NDIS_TCP_LARGE_SEND_OFFLOAD_V1 structure. This is done in MPInitialize ( .,.,.) through InitLSO ( Adapter ) ; /*** 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);
Support OID_OFFLOAD_ENCAPSULATION Here is the code #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
When NDIS calls MPSendNetBufferLists ( .,.,..) to send NBL, use the
SCRATCH area in the NBL to store some context info about the LSO. // 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 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
In send-complete interrupt handler set "TcpPayLoad" in the completed NBL for upper layers' consumption #if OFFLOAD UPDATE_LSO_TCP_PAYLOAD ( NetBufferList ) ; #endif
|
||||||||||||||||||||||||||||||||||
|
||||||
|
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms
of Use
Last Updated: 1 May 2008 Editor: |
Copyright 2008 by alexander suresh Everything else Copyright © CodeProject, 1999-2008 Web19 | Advertise on the Code Project |