|
|
/*++
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 );
|