/*++ Copyright (c) 1991 Microsoft Corporation Module Name: dltyp.h Abstract: This module includes all internal typedefs and constats of data link driver. Author: Antti Saarenheimo (o-anttis) 17-MAY-1991 Revision History: --*/ #include "refcnt.h" // // Design notes: // All data structures are designed at first for // multiple clients to make the interface very clean. // This implements also a simple kernel level interface // of data link layer to be used by somebody that needs it. // struct _LLC_NDIS_PACKET; typedef struct _LLC_NDIS_PACKET LLC_NDIS_PACKET, *PLLC_NDIS_PACKET; struct _LLC_SAP; typedef struct _LLC_SAP LLC_SAP, *PLLC_SAP; struct _DATA_LINK; typedef struct _DATA_LINK DATA_LINK, *PDATA_LINK; struct _ADAPTER_CONTEXT; typedef struct _ADAPTER_CONTEXT ADAPTER_CONTEXT, *PADAPTER_CONTEXT; // // LLC_GENERIC_OBJECT - these fields are common in all LLC objects // struct _LLC_GENERIC_OBJECT { // // DEBUG version - we have a 16-byte identifier header for consistency // checking and to help when looking at DLC using the kernel debugger // // DBG_OBJECT_ID; // // pointer to singly-linked list of same-type structures // PLLC_OBJECT pNext; // // ObjectType - SAP, DIRECT or LINK // UCHAR ObjectType; // // EthernetType - if we have opened the adapter binding in AUTO mode then // for SAPs and Link Stations we need to determine whether to talk 802.3 // or DIX // UCHAR EthernetType; // // usReserved - just aligns to DWORD (not necessary) // USHORT usReserved; PADAPTER_CONTEXT pAdapterContext; PBINDING_CONTEXT pLlcBinding; // // hClientHandle - handle to LINK object in upper layer // PVOID hClientHandle; PLLC_PACKET pCompletionPackets; ULONG ReferenceCount; }; typedef struct _LLC_GENERIC_OBJECT LLC_GENERIC_OBJECT, *PLLC_GENERIC_OBJECT; // // LLC_U_RESPONSE - LLC header for U-type response frame // typedef struct _LLC_U_RESPONSE { UCHAR Dsap; // Destination Service Access Point. UCHAR Ssap; // Source Service Access Point. UCHAR Command; // command code. UCHAR Info[1]; // respomse table } LLC_U_RESPONSE, *PLLC_U_RESPONSE; // // QUEUE_PACKET - generic doubly-linked list header // typedef struct _QUEUE_PACKET { struct _QUEUE_PACKET* pNext; struct _QUEUE_PACKET* pPrev; } QUEUE_PACKET, *PQUEUE_PACKET; // // LLC_QUEUE - // typedef struct _LLC_QUEUE { LIST_ENTRY ListEntry; LIST_ENTRY ListHead; // the list head PVOID pObject; // owner handle (used if element is linked) } LLC_QUEUE, *PLLC_QUEUE; // // This information is a part of the DLC.STATISTICS // information for a link station. The whole // strcuture can be reseted. // typedef struct _LINK_STATION_STATISTICS { USHORT I_FramesTransmitted; USHORT I_FramesReceived; UCHAR I_FrameReceiveErrors; UCHAR I_FrameTransmissionErrors; USHORT T1_ExpirationCount; // not in data xfer mode } LINK_STATION_STATISTICS, *PLINK_STATION_STATISTICS; typedef struct _SAP_STATISTICS { ULONG FramesTransmitted; ULONG FramesReceived; ULONG FramesDiscardedNoRcv; ULONG DataLostCounter; } SAP_STATISTICS, *PSAP_STATISTICS; struct _LLC_SAP { LLC_GENERIC_OBJECT Gen; USHORT SourceSap; // THIS MUST OVERLAY ObjectAddress USHORT OpenOptions; SAP_STATISTICS Statistics; // // KEEP THIS SAME IN SAP STATION AND GENERIC OBJECT // DLC_LINK_PARAMETERS DefaultParameters; NDIS_SPIN_LOCK FlowControlLock; PDATA_LINK pActiveLinks; // all link stations of this sap }; struct _TIMER_TICK; typedef struct _TIMER_TICK TIMER_TICK, *PTIMER_TICK; typedef struct _LLC_TIMER { struct _LLC_TIMER* pNext; struct _LLC_TIMER* pPrev; PTIMER_TICK pTimerTick; ULONG ExpirationTime; PVOID hContext; #if defined(LOCK_CHECK) ULONG Disabled; #endif } LLC_TIMER, *PLLC_TIMER; struct _TIMER_TICK { struct _TIMER_TICK* pNext; // struct _TIMER_TICK* pPrev; PLLC_TIMER pFront; UINT DeltaTime; USHORT Input; USHORT ReferenceCount; }; // // DATA_LINK - these 'objects' are from a two level data storage. The hash table // provides a very fast access to links, when there are less than 100 links // (about 99 % of the cases). The binary tree keeps the search times still quite // small, when there are very many connections from/to the same server. // struct _DATA_LINK { LLC_GENERIC_OBJECT Gen; // // Data link station state machine variables, *2 means the value // to be used as 2 increments, because modulo 256 is much easier // to handle than modulo 128. UCHAR wraps around automatically. // SHORT Is_Ct; // Max number of I retries (Update_Va & xxx_Chkpt) USHORT Ia_Ct; // Number of LPDU acknowledgements since Ww was incr. UCHAR State; // current state of the finite state machine UCHAR Ir_Ct; // LPDUs possible to send before next acknowledgement UCHAR Vs; // *2, Send state variable (Ns of next sent LPDU) UCHAR VsMax; // *2, Max Send state variable (Ns of next sent LPDU) UCHAR Vr; // *2, Receive state variable( Nr of next sent LPDU) UCHAR Pf; // value of PollFinal bit in last command UCHAR Va; // *2, Last valid Nr received (ack state variable) UCHAR Vp; // *2, Poll state var. (Ns of last sent cmd with P-bit) UCHAR Vb; // Busy state (Vl, Vb, Vlb) UCHAR Vc; // Stacked command variable (only DISC is possible) UCHAR Vi; // initialization state variable // // BEGIN OF DLC_LINK_PARAMETERS (same as llc_params struct) // DON'T TOUCH !!!! // UCHAR TimerT1; // Timer T1 value UCHAR TimerT2; // Timer T2 value UCHAR TimerTi; // Timer Ti value UCHAR MaxOut; // *2, maximum transmit window size (MaxOut) UCHAR RW; // maximum receive window size (MaxIn) UCHAR Nw; // number of LPDUs acknowledged, before Ww is incr.) UCHAR N2; // Number of retires allowed (both Polls and I LPDSs) UCHAR AccessPrty; // access priority USHORT MaxIField; // maximum received info field (not used in LLC) // // End of DLC_LINK_PARAMETERS // UCHAR Ww; // *2, working window size UCHAR N3; // number of I format LPDUs between acks (with Ir_Ct) UCHAR P_Ct; // Poll retry count UCHAR Nr; // last Nr of the received frame // // Variables needed to maintain dynamic response base time for timers. // USHORT LastTimeWhenCmdPollWasSent; USHORT AverageResponseTime; UCHAR cbLanHeaderLength; UCHAR VrDuringLocalBusy; UCHAR Flags; UCHAR TW; // dynamic MaxOut value USHORT FullWindowTransmits; // succeeded Polls of full window xmits UCHAR T1_Timeouts; // T1 timeouts after I-c1 UCHAR RemoteOpen; // // The link status flags contains these status bits: // // DLC_WAITING_RESPONSE_TO_POLL // DLC_FIRST_POLL // DLC_ACTIVE_REMOTE_CONECT_REQUEST // DLC_COMMAND_POLL_PENDING_IN_NDIS; // DLC_SEND_DISABLED // DLC_SEND_ACTIVE // DLC_LOCAL_BUSY_BUFFER // DLC_LOCAL_BUSY_USER // // // the timer objects // LLC_TIMER T1; LLC_TIMER T2; LLC_TIMER Ti; LLC_QUEUE SendQueue; // untransmitted queue for the I frames LIST_ENTRY SentQueue; // the sent but not acknowledged I- frames PDATA_LINK pNextNode; // for the hash table LAN802_ADDRESS LinkAddr;// 64 bit lan address of the link PLLC_SAP pSap; // link to the SAP object of this link DLC_STATUS_TABLE DlcStatus; // // Resetable link station statistics counters // LINK_STATION_STATISTICS Statistics; UCHAR LastCmdOrRespSent; UCHAR LastCmdOrRespReceived; UCHAR Dsap; // Destination SAP UCHAR Ssap; // Source SAP // // some link statistics (don't reset this) // ULONG BufferCommitment; // // FramingType - type of framing (802.3/DIX/don't care) that we should use // for this connection. Required because in AUTO mode, the actual framing // type may be different than that in the BINDING_CONTEXT, and since the // BINDING_CONTEXT is per-adapter, we cannot rely on it (this whole thing // is messed up) // ULONG FramingType; // // Network frame header (includes the full address information) // UCHAR auchLanHeader[1]; // // LAN HEADER OVERFLOWS HERE !!!! // }; typedef struct _LLC_STATION_OBJECT { LLC_GENERIC_OBJECT Gen; USHORT ObjectAddress; USHORT OpenOptions; SAP_STATISTICS Statistics; } LLC_STATION_OBJECT, *PLLC_STATION_OBJECT; union _LLC_OBJECT { // // KEEP THIS SAME AS DIRECT AND SAP STATIONS // LLC_GENERIC_OBJECT Gen; DATA_LINK Link; LLC_SAP Sap; LLC_STATION_OBJECT Group; LLC_STATION_OBJECT Dix; LLC_STATION_OBJECT Dir; }; //***************************************************************** typedef struct _NDIS_MAC_PACKET { NDIS_PACKET_PRIVATE private; UCHAR auchMacReserved[16]; } NDIS_MAC_PACKET; struct _LLC_NDIS_PACKET { NDIS_PACKET_PRIVATE private; // we accesss this also directly UCHAR auchMacReserved[16]; PMDL pMdl; // MDL for LAN and LLC headers // // request handle and command completion handler are saved to // the packet until NDIS has completed the command // PLLC_PACKET pCompletionPacket; #if LLC_DBG ULONG ReferenceCount; #endif UCHAR auchLanHeader[LLC_MAX_LAN_HEADER + sizeof(LLC_U_HEADER) + sizeof(LLC_RESPONSE_INFO)]; }; typedef struct _LLC_TRANSFER_PACKET { NDIS_PACKET_PRIVATE private; UCHAR auchMacReserved[16]; PLLC_PACKET pPacket; } LLC_TRANSFER_PACKET, *PLLC_TRANSFER_PACKET; typedef struct _EVENT_PACKET { struct _EVENT_PACKET* pNext; struct _EVENT_PACKET* pPrev; PBINDING_CONTEXT pBinding; PVOID hClientHandle; PVOID pEventInformation; UINT Event; UINT SecondaryInfo; } EVENT_PACKET, *PEVENT_PACKET; // // The next structure is used only in the allocating packets to the pool // typedef union _UNITED_PACKETS { QUEUE_PACKET queue; EVENT_PACKET event; LLC_PACKET XmitPacket; UCHAR auchLanHeader[LLC_MAX_LAN_HEADER]; } UNITED_PACKETS, *PUNITED_PACKETS; // // NODE_ADDRESS - 6 byte MAC address expressed as bytes or ULONG & USHORT for // minimal comparisons/moves on 32-bit architecture // typedef union { UCHAR Bytes[6]; struct { ULONG Top4; USHORT Bottom2; } Words; } NODE_ADDRESS, *PNODE_ADDRESS; // // FRAMING_DISCOVERY_CACHE_ENTRY - the solution to the LLC_ETHERNET_TYPE_AUTO // problem (where we can end up proliferating TEST/XIDs and SABME/UAs) is to // keep a cache of destinations we have 'ping'ed with TEST/XID/SABME. We send // both frame types - DIX and 802.3. We indicate the first received response // and create a cache entry, recording the remote MAC address and the framing // type. If another response frame arrives from the cached MAC address with // the other framing type, it is discarded // typedef struct { NODE_ADDRESS NodeAddress; // the remote MAC address BOOLEAN InUse; // TRUE if in use (could use TimeStamp == 0) UCHAR FramingType; // DIX or 802.3 LARGE_INTEGER TimeStamp; // used for LRU throw-out } FRAMING_DISCOVERY_CACHE_ENTRY, *PFRAMING_DISCOVERY_CACHE_ENTRY; #define FRAMING_TYPE_DIX 0x1d // arbitrary value #define FRAMING_TYPE_802_3 0x83 // " " // // BINDING_CONTEXT - one of these created for each client (app/open driver // handle instance) opening the adapter. We only perform an open adapter at // NDIS level once, which creates the ADAPTER_CONTEXT for the NDIS open // adapter instance. Subsequent open adapter requests from processes cause // a BINDING_CONTEXT to be created and linked to the ADAPTER_CONTEXT // struct _BINDING_CONTEXT { // // DEBUG version - we have a 16-byte identifier header for consistency // checking and to help when looking at DLC using the kernel debugger // // DBG_OBJECT_ID; // // pointer to singly-linked list of BINDING_CONTEXT structures for this // ADAPTER_CONTEXT // struct _BINDING_CONTEXT* pNext; // // pointer to ADAPTER_CONTEXT structure for this BINDING_CONTEXT // PADAPTER_CONTEXT pAdapterContext; // // handle of/pointer to FILE_CONTEXT structure // PVOID hClientContext; // // pointers to command completion, receive and event indication functions // PFLLC_COMMAND_COMPLETE pfCommandComplete; PFLLC_RECEIVE_INDICATION pfReceiveIndication; PFLLC_EVENT_INDICATION pfEventIndication; // // Functional - functional address applied to this binding by the app // TR_BROADCAST_ADDRESS Functional; // // ulFunctionalZeroBits - mask of bits which should be off for functional // address/multicast address // ULONG ulFunctionalZeroBits; // // 0.5 second timer used for DIR.TIMER functions // LLC_TIMER DlcTimer; // // NdisMedium - the actual medium that the adapter to which we are bound talks // UINT NdisMedium; // // AddressTranslation - how the bits in addresses should be represented at // the top and bottom edges of LLC // USHORT AddressTranslation; // // BroadCastAddress - 6 byte broadcast address treated as USHORT and ULONG // entities. Used for checking promiscuous packets // USHORT usBroadcastAddress; ULONG ulBroadcastAddress; // // InternalAddressTranslation - // USHORT InternalAddressTranslation; // // EthernetType - value which determines the format of an Ethernet frame. // Different for 802.3 vs. DIX vs. ... // USHORT EthernetType; // // SwapCopiedLanAddresses - TRUE if we bit-swap LAN addresses when copying // up or down the layers // BOOLEAN SwapCopiedLanAddresses; // // The big substructures should be in the end // to produce optimal code for x86 // LLC_TRANSFER_PACKET TransferDataPacket; // // FramingDiscoveryCacheEntries - maximum number of elements that can be // in DiscoveryFramingCache. Will be zero if the adapter is not ethernet and // LLC_ETHERNET_TYPE_AUTO was not requested, else number determined from // registry or default value. Number from registry may also be 0, indicating // caching is not to be used (old semantics) // ULONG FramingDiscoveryCacheEntries; // // FramingDiscoveryCache - if this EthernetType == LLC_ETHERNET_TYPE_AUTO, // we create a cache of destination MAC addresses and the DIX/802.3 framing // type they use. This array is FramingDiscoveryCacheEntries long // FRAMING_DISCOVERY_CACHE_ENTRY FramingDiscoveryCache[]; }; // // ADAPTER_CONTEXT - the device context of an NDIS driver. It includes links to // all dynamic data structures of the data link driver. // // This version does not support the group SAPs // #define LINK_HASH_SIZE 128 struct _ADAPTER_CONTEXT { // // DEBUG version - we have a 16-byte identifier header for consistency // checking and to help when looking at DLC using the kernel debugger // // DBG_OBJECT_ID; // // pointer to singly-linked list of ADAPTER_CONTEXT structures opened by // all clients of this driver // struct _ADAPTER_CONTEXT* pNext; #if !defined(DLC_UNILOCK) NDIS_SPIN_LOCK SendSpinLock; // locked when accessing send queues NDIS_SPIN_LOCK ObjectDataBase; // used also with sap/direct create #endif PLLC_STATION_OBJECT pDirectStation; // link list of direct stations PBINDING_CONTEXT pBindings; // link list of all bindings NDIS_HANDLE NdisBindingHandle; PVOID hLinkPool; // pool for link station structs PVOID hPacketPool; // pool for usr/small LLC packets // // circular link list is free NDIS packets for send (initially maybe 5) // PLLC_NDIS_PACKET pNdisPacketPool; NDIS_HANDLE hNdisPacketPool; // // Some stuff for asynchronous receive indications // PVOID hReceiveCompletionRequest; PLLC_PACKET pResetPackets; // // pHeadBuf - pointer to the MAC header buffer, containing: // // FDDI: // 1 Byte Frame Control (FDDI) // 6 Bytes Destination MAC Address (ALL) // 6 Bytes Source MAC Address (ALL) // // Token Ring: // 1 Byte Access Control (Token Ring) // 1 Byte Frame Control (Token Ring) // 6 Bytes Destination MAC Address (ALL) // 6 Bytes Source MAC Address (ALL) // 0-18 Bytes Source Routing // // Ethernet: // 6 Bytes Destination MAC Address (ALL) // 6 Bytes Source MAC Address (ALL) // 2 Bytes Length or DIX Type // PUCHAR pHeadBuf; // // cbHeadBuf - number of bytes in pHeadBuf // UINT cbHeadBuf; // // pLookBuf - pointer to the MAC look-ahead buffer which contains the rest // of the data for this frame or as much as the MAC could fit into the look // ahead buffer (in which case NdisTransferData must be used to get the // rest) // PUCHAR pLookBuf; // // cbLookBuf - number of bytes in pLookBuf // UINT cbLookBuf; // // cbPacketSize - actual size of the whole frame. Calculated from information // in the header or supplied by the MAC, depending on the medium // UINT cbPacketSize; // // IsSnaDixFrame - true if the frame just received (on ethernet) is a DIX // frame and the DIX identifier is 0x80D5 (big-endian) // UINT IsSnaDixFrame; LAN802_ADDRESS Adapter; ULONG MaxFrameSize; ULONG LinkSpeed; // // We use UINTs, because (Move mem, ULONG) may not be an // atomic operation (in theory) // UINT NdisMedium; UINT XidTestResponses; ULONG ObjectCount; // must be zero, when adapter closed // // ConfigInfo - holds the SwapAddressBits and UseDixOverEthernet flags and // the timer tick values // ADAPTER_CONFIGURATION_INFO ConfigInfo; // // the original node addresses // ULONG ulBroadcastAddress; USHORT usBroadcastAddress; USHORT BackgroundProcessRequests; UCHAR NodeAddress[6]; // Current network format USHORT cbMaxFrameHeader; UCHAR PermanentAddress[6]; USHORT OpenOptions; USHORT AddressTranslationMode; USHORT FrameType; USHORT usRcvMask; USHORT EthernetType; USHORT RcvLanHeaderLength; USHORT BindingCount; USHORT usHighFunctionalBits; // // Keep UCHAR alignment // BOOLEAN boolTranferDataNotComplete; BOOLEAN IsDirty; BOOLEAN ResetInProgress; UCHAR Unused1; #ifndef NDIS40 // Not used. UCHAR AdapterNumber; #endif // NDIS40 UCHAR IsBroadcast; BOOLEAN SendProcessIsActive; BOOLEAN LlcPacketInSendQueue; // // We keep the big structures and tables in the end, // that makes most x86 offsets 1 byte instead of 4. // The compiler aligns the fields naturally, whenever // it is necessary. // // // the next elements will be linked to circular // end process link list, if there are any frames to send // LIST_ENTRY NextSendTask; // pointer to active sends LIST_ENTRY QueueEvents; LIST_ENTRY QueueCommands; LLC_QUEUE QueueI; LLC_QUEUE QueueDirAndU; LLC_QUEUE QueueExpidited; UNICODE_STRING Name; // current adapter name PTIMER_TICK pTimerTicks; NDIS_STATUS AsyncOpenStatus; // used to wait async open NDIS_STATUS AsyncCloseResetStatus; // used to wait async close NDIS_STATUS OpenCompleteStatus; // used to wait the first open NDIS_STATUS LinkRcvStatus; // link state machine ret status NDIS_STATUS NdisRcvStatus; // NdisRcvIndication ret status NDIS_STATUS OpenErrorStatus; // special adapter open status // // NDIS calls back when adapter open completes. Use a Kernel Event to // synchronize LLC with NDIS // KEVENT Event; // // the following are reasonably large arrays (like 256 pointers to SAP // objects...) // PLLC_SAP apSapBindings[256]; // the clients bound to the SAPs PDATA_LINK aLinkHash[LINK_HASH_SIZE]; // hash table to links PLLC_STATION_OBJECT aDixStations[MAX_DIX_TABLE]; LLC_TRANSFER_PACKET TransferDataPacket; #if DBG // // memory usage counters for memory owned by this ADAPTER_CONTEXT // MEMORY_USAGE MemoryUsage; MEMORY_USAGE StringUsage; #endif #ifdef NDIS40 #define BIND_STATE_UNBOUND 1 #define BIND_STATE_UNBINDING 2 #define BIND_STATE_BOUND 3 LONG BindState; REF_CNT AdapterRefCnt; KEVENT CloseAdapterEvent; #endif // NDIS40 }; typedef PLLC_PACKET (*PF_GET_PACKET)(IN PADAPTER_CONTEXT pAdapterContext);