Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

621 lines
16 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Copyright (c) 1991 Nokia Data Systems AB
Module Name:
dlctyp.h
Abstract:
This module defines all data structures of the DLC module.
Author:
Antti Saarenheimo 22-Jul-1991
Environment:
Kernel mode
Revision History:
--*/
//
// forward declarations
//
struct _DLC_OBJECT;
typedef struct _DLC_OBJECT DLC_OBJECT, *PDLC_OBJECT;
struct _DLC_EVENT;
typedef struct _DLC_EVENT DLC_EVENT, *PDLC_EVENT;
struct _DLC_COMMAND;
typedef struct _DLC_COMMAND DLC_COMMAND, *PDLC_COMMAND;
struct _DLC_CLOSE_WAIT_INFO;
typedef struct _DLC_CLOSE_WAIT_INFO DLC_CLOSE_WAIT_INFO, *PDLC_CLOSE_WAIT_INFO;
union _DLC_PACKET;
typedef union _DLC_PACKET DLC_PACKET, *PDLC_PACKET;
union _DLC_BUFFER_HEADER;
typedef union _DLC_BUFFER_HEADER DLC_BUFFER_HEADER;
typedef DLC_BUFFER_HEADER *PDLC_BUFFER_HEADER;
struct _DLC_FILE_CONTEXT;
typedef struct _DLC_FILE_CONTEXT DLC_FILE_CONTEXT;
typedef DLC_FILE_CONTEXT *PDLC_FILE_CONTEXT;
enum _DLC_FILE_CONTEXT_STATUS {
DLC_FILE_CONTEXT_OPEN,
DLC_FILE_CONTEXT_CLOSE_PENDING,
DLC_FILE_CONTEXT_CLOSED
};
enum DlcObjectTypes {
DLC_ADAPTER_OBJECT,
DLC_SAP_OBJECT,
DLC_LINK_OBJECT,
DLC_DIRECT_OBJECT
};
//
// DLC structures/objects
//
struct _DLC_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;
//
// single-linked list of link stations if this is a SAP object
//
PDLC_OBJECT pLinkStationList;
//
// pointer to owning FILE_CONTEXT
//
PDLC_FILE_CONTEXT pFileContext;
//
// pointer to RECEIVE command parameters active for this SAP/link station
//
PNT_DLC_PARMS pRcvParms;
//
// 'handle' (aka pointer to) of corresponding object in LLC
//
PVOID hLlcObject;
PDLC_EVENT pReceiveEvent;
PVOID pPrevXmitCcbAddress;
PVOID pFirstChainedCcbAddress;
PDLC_CLOSE_WAIT_INFO pClosingInfo;
ULONG CommittedBufferSpace;
USHORT ChainedTransmitCount;
SHORT PendingLlcRequests;
USHORT StationId; // nn00 or nnss
UCHAR Type;
UCHAR LinkAllCcbs;
UCHAR State;
BOOLEAN LlcObjectExists;
USHORT LlcReferenceCount; // protects LLC objects when used
// Need to have a close packet just in case we are out of resources and
// can't allocate a packet to close.
LLC_PACKET ClosePacket;
UCHAR ClosePacketInUse;
//
// u - variant fields depending on object type: SAP, LINK or DIRECT station
//
union {
struct {
ULONG DlcStatusFlag;
PVOID GlobalGroupSapHandle;
PVOID* GroupSapHandleList;
USHORT GroupSapCount;
USHORT UserStatusValue;
UCHAR LinkStationCount;
UCHAR OptionsPriority;
UCHAR MaxStationCount;
} Sap;
struct {
struct _DLC_OBJECT* pSap;
PDLC_EVENT pStatusEvent; // permanent status event
USHORT MaxInfoFieldLength;
} Link;
struct {
USHORT OpenOptions;
USHORT ProtocolTypeOffset;
ULONG ProtocolTypeMask;
ULONG ProtocolTypeMatch;
} Direct;
} u;
};
typedef
VOID
(*PFCLOSE_COMPLETE)(
IN PDLC_FILE_CONTEXT pFileContext,
IN PDLC_CLOSE_WAIT_INFO pClosingInfo,
IN PVOID pCcbLink
);
typedef
BOOLEAN
(*PFCOMPLETION_HANDLER)(
IN PDLC_FILE_CONTEXT pFileContext,
IN PDLC_OBJECT pDlcObject,
IN PIRP pIrp,
IN ULONG Event,
IN PVOID pEventInformation,
IN ULONG SecondaryInfo
);
//
// DLC_COMMAND and DLC_EVENT structures may be
// overloaded by the code. Do not change the field
// order and add the new fields only to the end.
//
struct _DLC_COMMAND {
//
// !!!!! Keep this fixed - same fields with DLC_EVENT !!!!!
//
LLC_PACKET LlcPacket;
ULONG Event;
USHORT StationId;
USHORT StationIdMask;
//
// !!!!! Keep this fixed - same fields with DLC_EVENT !!!!!
//
PVOID AbortHandle;
PIRP pIrp;
union {
PFCOMPLETION_HANDLER pfCompletionHandler;
ULONG TimerTicks;
} Overlay;
};
struct _DLC_EVENT {
LLC_PACKET LlcPacket;
ULONG Event;
USHORT StationId; // -1 => global event
union {
USHORT StationIdMask;
UCHAR RcvReadOption;
} Overlay;
PDLC_OBJECT pOwnerObject; // if null => no owner
PVOID pEventInformation;
ULONG SecondaryInfo;
BOOLEAN bFreeEventInfo;
};
typedef struct {
LLC_PACKET LlcPacket;
PVOID pCcbAddress;
PDLC_BUFFER_HEADER pReceiveBuffers;
ULONG CommandCompletionFlag;
USHORT CcbCount;
USHORT StationId;
} DLC_COMPLETION_EVENT_INFO, *PDLC_COMPLETION_EVENT_INFO;
//
// CLOSE_WAIT_INFO
//
// The pointer of this structure is provided to CompleteReadRequest in
// the command completion of close/reset commands. The info pointer
// is null for the other command completions.
//
struct _DLC_CLOSE_WAIT_INFO {
PDLC_CLOSE_WAIT_INFO pNext;
PIRP pIrp;
ULONG Event;
PFCLOSE_COMPLETE pfCloseComplete;
PDLC_BUFFER_HEADER pRcvFrames;
PVOID pCcbLink;
PDLC_COMMAND pReadCommand;
PDLC_COMMAND pRcvCommand;
PDLC_COMPLETION_EVENT_INFO pCompletionInfo;
ULONG CancelStatus;
USHORT CcbCount;
USHORT CloseCounter; // event sent when 0
BOOLEAN ChainCommands;
BOOLEAN CancelReceive;
BOOLEAN ClosingAdapter;
BOOLEAN FreeCompletionInfo;
};
//
// This is a queued FlowControl command (the flow control commands
// are completed immediately synchronously, but the local 'out of buffers'
// busy state of the link is cleared when there is enough buffers
// in the buffer pool to receive all expected data.
//
typedef struct {
LIST_ENTRY List;
LONG RequiredBufferSpace;
USHORT StationId;
} DLC_RESET_LOCAL_BUSY_CMD, *PDLC_RESET_LOCAL_BUSY_CMD;
//
// The transmit commands are not queued as a standard commands
// but using the linked buffer headers (each frame has own xmit
// header having links to buffer header list and MDL list).
// The xmit nodes of the same send are queued together.
//
typedef struct {
LLC_PACKET LlcPacket;
PDLC_BUFFER_HEADER pNextSegment;
PDLC_PACKET pTransmitNode;
PIRP pIrp;
ULONG FrameCount;
PMDL pMdl;
} DLC_XMIT_NODE, *PDLC_XMIT_NODE;
//
// DLC driver use the same packet pool for many small packets
// that have approximately the same size.
//
union _DLC_PACKET {
union _DLC_PACKET* pNext;
LLC_PACKET LlcPacket;
DLC_XMIT_NODE Node;
DLC_EVENT Event;
DLC_COMMAND DlcCommand;
DLC_CLOSE_WAIT_INFO ClosingInfo;
DLC_RESET_LOCAL_BUSY_CMD ClearCmd;
struct {
LLC_PACKET LlcPacket;
PDLC_CLOSE_WAIT_INFO pClosingInfo;
} ResetPacket;
};
//
// The buffer pool states protects the app to corrupt the buffer pool!!
// All states are needed because of internal consistency checking code
// and implementation of the receive.
//
enum _DLC_BUFFER_STATES {
//
// major states:
//
BUF_READY = 0x01, // buffer/page locked and ready for I/O
BUF_USER = 0x02, // buffer owned by user
BUF_LOCKED = 0x04, // buffer have been locked for I/O
BUF_RCV_PENDING = 0x08, // buffer not yet chained to other frames!
//
// free xmit buffer when used
//
DEALLOCATE_AFTER_USE = 0x80
};
union _DLC_BUFFER_HEADER {
//
// This struct is the header of the buffers split from a page.
// We save the local and global virtual addresses here.
// The individual offset is always GlobalVa + Index * 256.
// An entry in main page table points to this header,
// if the page has been locked in the memory.
//
struct {
PDLC_BUFFER_HEADER pNextHeader;
PDLC_BUFFER_HEADER pPrevHeader;
PDLC_BUFFER_HEADER pNextChild;
PUCHAR pLocalVa;
PUCHAR pGlobalVa;
UCHAR FreeSegments; // free segments ready for alloc
UCHAR SegmentsOut; // number of segments given to user
UCHAR BufferState; // BUF_READY, BUF_USER, BUF_LOCKED ...
UCHAR Reserved; //
PMDL pMdl;
} Header;
//
// Structure is used in the double linked free lists.
// All segments having the same buffer size have been linked
// to the same link list.
// On another level each segment is linked to the parent (Header)
// and all childs of a parent are also linked together.
//
struct {
PDLC_BUFFER_HEADER pNext;
PDLC_BUFFER_HEADER pPrev;
PDLC_BUFFER_HEADER pParent;
PDLC_BUFFER_HEADER pNextChild;
ULONG ReferenceCount; // number of references to this buffer
UCHAR Size; // size in 256 blocks
UCHAR Index; // offset = Index * 256
UCHAR BufferState; // BUF_READY, BUF_USER, BUF_LOCKED ...
UCHAR FreeListIndex; //
PMDL pMdl;
} FreeBuffer;
//
// The allocated frames are linked in different ways:
// - the segments of the same frame are together
// - the frames are linked together
// These links are discarded, when the frame is given to
// client (the client may free them in any order back to the buffer pool)
// (The last extra pointer doesn't actually take any extra space,
// because packets are round up to next 8 byte boundary)
//
struct {
PDLC_BUFFER_HEADER pReserved;
PDLC_BUFFER_HEADER pNextFrame;
PDLC_BUFFER_HEADER pParent;
PDLC_BUFFER_HEADER pNextChild;
ULONG ReferenceCount; // number of references to this buffer
UCHAR Size; // size in 256 blocks
UCHAR Index; // offset = Index * 256
UCHAR BufferState; // BUF_READY, BUF_USER, BUF_LOCKED ...
UCHAR FreeListIndex;
PMDL pMdl;
PDLC_BUFFER_HEADER pNextSegment;
} FrameBuffer;
PDLC_BUFFER_HEADER pNext;
};
typedef struct _DLC_BUFFER_POOL {
//
// 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;
//
// control fields
//
struct _DLC_BUFFER_POOL* pNext;
KSPIN_LOCK SpinLock;
LONG ReferenceCount; // when -1 => deallocate
//
// buffer pool description fields (addresses, various lengths)
//
PVOID BaseOffset; // page-aligned base address of the pool
PVOID MaxOffset; // maximum byte address in the pool + 1
ULONG MaxBufferSize; // the maximum (free) size
ULONG BufferPoolSize; // size of all memory in the pool
ULONG FreeSpace; // size of free memory in the pool
LONG UncommittedSpace; // size of free and reserved memory
LONG MissingSize; // the size missing the last request
ULONG MaximumIndex; // maximum index of buffer table
PVOID hHeaderPool; // packet pool for buffer headers
LIST_ENTRY PageHeaders; // the allocated blocks
//
// pUnlockedEntryList is a singly-linked list of DLC_BUFFER_HEADERS which
// describe the free pages in the pool
//
PDLC_BUFFER_HEADER pUnlockedEntryList;
//
// FreeLists is an array of doubly-linked lists - one for each size of
// block that can exists in the pool. The blocks start out at a page
// length (4K on x86) and are successively halved until they reach
// 256 bytes which is the smallest buffer that the DLC buffer manager
// can deal with
//
LIST_ENTRY FreeLists[DLC_BUFFER_SEGMENTS];
//
// appended to the DLC_BUFFER_POOL structure is an array of pointers to
// DLC_BUFFER_HEADER structures that describe the pages that comprise
// the pool. There are MaximumIndex of these
//
PDLC_BUFFER_HEADER BufferHeaders[];
} DLC_BUFFER_POOL, *PDLC_BUFFER_POOL;
//
// The buffer header and frame headers have been define in the
// IBM LAN Architecture reference in the end of chapter 2.
// They have also been defined in dlcapi.h, but for cosmetic reason
// I want to use version without those funny prefixes.
//
typedef struct _NEXT_DLC_SEGMENT {
struct _NEXT_DLC_SEGMENT* pNext;
USHORT FrameLength;
USHORT DataLength;
USHORT UserOffset;
USHORT UserLength;
} NEXT_DLC_SEGMENT, *PNEXT_DLC_SEGMENT;
union _FIRST_DLC_SEGMENT;
typedef union _FIRST_DLC_SEGMENT FIRST_DLC_SEGMENT, *PFIRST_DLC_SEGMENT;
typedef struct {
PNEXT_DLC_SEGMENT pNext;
USHORT FrameLength;
USHORT DataLength;
USHORT UserOffset;
USHORT UserLength;
USHORT StationId;
UCHAR Options;
UCHAR MessageType;
USHORT BuffersLeft;
UCHAR RcvFs;
UCHAR AdapterNumber;
PFIRST_DLC_SEGMENT pNextFrame;
} DLC_CONTIGUOUS_RECEIVE, *PDLC_CONTIGUOUS_RECEIVE;
typedef struct {
PNEXT_DLC_SEGMENT pNext;
USHORT FrameLength;
USHORT DataLength;
USHORT UserOffset;
USHORT UserLength;
USHORT StationId;
UCHAR Options;
UCHAR MessageType;
USHORT BuffersLeft;
UCHAR RcvFs;
UCHAR AdapterNumber;
PFIRST_DLC_SEGMENT pNextFrame;
UCHAR LanHeaderLength;
UCHAR DlcHeaderLength;
UCHAR LanHeader[32];
UCHAR DlcHeader[4];
} DLC_NOT_CONTIGUOUS_RECEIVE, *PDLC_NOT_CONTIGUOUS_RECEIVE;
union _FIRST_DLC_SEGMENT {
DLC_CONTIGUOUS_RECEIVE Cont;
DLC_NOT_CONTIGUOUS_RECEIVE NotCont;
};
//
// Each application using DLC create its own file
// context with the DlcOpenAdapter command.
//
struct _DLC_FILE_CONTEXT {
//
// all file contexts are put on single-entry list
//
SINGLE_LIST_ENTRY List; // linked list of file contexts
#if DBG
//
// 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;
#endif
#if !defined(DLC_UNILOCK)
NDIS_SPIN_LOCK SpinLock; // global lock for this file context
#endif
//
// hBufferPool - handle of buffer pool created by BufferPoolCreate
//
PVOID hBufferPool;
PVOID hExternalBufferPool;
PVOID hPacketPool;
PVOID hLinkStationPool;
PVOID pBindingContext;
//
// Notification flags for error situations
//
ULONG AdapterCheckFlag;
ULONG NetworkStatusFlag;
ULONG PcErrorFlag;
ULONG SystemActionFlag;
LIST_ENTRY EventQueue;
LIST_ENTRY CommandQueue;
LIST_ENTRY ReceiveQueue;
LIST_ENTRY FlowControlQueue;
PDLC_COMMAND pTimerQueue;
PVOID pSecurityDescriptor;
PFILE_OBJECT FileObject; // back link to file obejct!
ULONG WaitingTransmitCount;
NDIS_MEDIUM ActualNdisMedium;
LONG ReferenceCount;
ULONG BufferPoolReferenceCount;
ULONG TimerTickCounter;
USHORT DlcObjectCount; // count of all DLC objects
USHORT State;
USHORT MaxFrameLength;
UCHAR AdapterNumber;
UCHAR LinkStationCount;
PDLC_OBJECT SapStationTable[MAX_SAP_STATIONS];
PDLC_OBJECT LinkStationTable[MAX_LINK_STATIONS];
ULONG NdisErrorCounters[ADAPTER_ERROR_COUNTERS];
DLC_CLOSE_WAIT_INFO ClosingPacket; // to close the adapter context
// Event used to make cleanup synchronous and wait for all references on
// DLC_FILE_CONTEXT to be removed before completing.
KEVENT CleanupEvent;
#if DBG
//
// Debug allocation counters
//
MEMORY_USAGE MemoryUsage;
#endif
};
typedef
NTSTATUS
(*PFDLC_COMMAND_HANDLER)(
IN PIRP pIrp,
IN PDLC_FILE_CONTEXT pFileContext,
IN PNT_DLC_PARMS pDlcParms,
IN ULONG InputBufferLength,
IN ULONG OutputBufferLength
);