/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
llcapi.h
Abstract:
This module defined the kernel API of data link driver.
All function prototypes and typedefs of the interface
have been defined here.
Author:
Antti Saarenheimo (o-anttis) 17-MAY-1991
Revision History:
--*/
#ifndef _LLC_API_
#define _LLC_API_
#include "llcmem.h"
//
// The debug switches
//
//
// LLC_DBG:
//
// 0 => No debug code is generated
// 1 => Enables the memory allocation accounting, state machine tracing,
// procedure call tracing and internal consistency checks
// 2 => Enables memory block overflow checking
//
//
#define LLC_DBG 0
#define DBG_MP 0 // enables the MP safe versions of the accounting macros
#define DLC_TRACE_ENABLED 1 // Procedure call tracing, debug only.
extern NDIS_SPIN_LOCK DlcDriverLock;
//
// ANY_IRQL: pseudo value used in ASSUME_IRQL to mean routine is not IRQL sensitive.
// Use this value with ASSUME_IRQL instead of omitting ASSUME_IRQL from a routine
// (shows that we didn't forget this routine)
//
#define ANY_IRQL ((ULONG)-1)
#if defined(LOCK_CHECK)
extern LONG DlcDriverLockLevel;
extern ULONG __line;
extern PCHAR __file;
extern LONG __last;
extern HANDLE __process;
extern HANDLE __thread;
//
// _strip - quick functionette to strip out the path garbage from __FILE__
//
__inline char* _strip(char* s) {
char* e = s + strlen(s) - 1;
while (e != s) {
if (*e == '\\') {
return e + 1;
}
--e;
}
return s;
}
#define $$_PLACE "%s!%d"
#define $$_FILE_AND_LINE _strip(__FILE__), __LINE__
//
// ACQUIRE_DRIVER_LOCK - acquires the global DLC driver Spin Lock, using
// NdisAcquireSpinLock(). We also check for re-entrancy and incorrect ordering
// of spin lock calls
//
#define ACQUIRE_DRIVER_LOCK() \
{ \
KIRQL currentIrql; \
HANDLE hprocess; \
HANDLE hthread; \
\
currentIrql = KeGetCurrentIrql(); \
if (currentIrql == PASSIVE_LEVEL) { \
\
PETHREAD pthread; \
\
pthread = PsGetCurrentThread(); \
hprocess = pthread->Cid.UniqueProcess; \
hthread = pthread->Cid.UniqueThread; \
} else { \
hprocess = (HANDLE)-1; \
hthread = (HANDLE)-1; \
} \
NdisAcquireSpinLock(&DlcDriverLock); \
if (++DlcDriverLockLevel != 1) { \
__last = DlcDriverLockLevel; \
DbgPrint("%d.%d:" $$_PLACE ": ACQUIRE_DRIVER_LOCK: level = %d. Last = %d.%d:" $$_PLACE "\n", \
hprocess, \
hthread, \
$$_FILE_AND_LINE, \
DlcDriverLockLevel, \
__process, \
__thread, \
__file, \
__line \
); \
DbgBreakPoint(); \
} \
__file = _strip(__FILE__); \
__line = __LINE__; \
__process = hprocess; \
__thread = hthread; \
ASSUME_IRQL(DISPATCH_LEVEL); \
}
//
// RELEASE_DRIVER_LOCK - releases the global DLC driver Spin Lock, using
// NdisReleaseSpinLock(). We also check for re-entrancy and incorrect ordering
// of spin lock calls
//
#define RELEASE_DRIVER_LOCK() \
if (DlcDriverLockLevel != 1) { \
DbgPrint($$_PLACE ": RELEASE_DRIVER_LOCK: level = %d. Last = %d.%d:" $$_PLACE "\n", \
$$_FILE_AND_LINE, \
DlcDriverLockLevel, \
__process, \
__thread, \
__file, \
__line \
); \
DbgBreakPoint(); \
} \
--DlcDriverLockLevel; \
__file = _strip(__FILE__); \
__line = __LINE__; \
NdisReleaseSpinLock(&DlcDriverLock);
//
// ASSUME_IRQL - used to check that a routine is being called at the IRQL we
// expect. Due to the design of DLC, most functions are called at raised IRQL
// (DISPATCH_LEVEL). Used mainly to assure that IRQL is at PASSIVE_LEVEL when
// we do something which may incur a page fault e.g.
//
#define ASSUME_IRQL(level) \
if (((level) != ANY_IRQL) && (KeGetCurrentIrql() != (level))) { \
DbgPrint($$_PLACE ": ASSUME_IRQL(%d): Actual is %d\n", \
$$_FILE_AND_LINE, \
level, \
KeGetCurrentIrql() \
); \
DbgBreakPoint(); \
}
//
// MY_ASSERT - since ASSERT only expands to something meaningful in the checked
// build, we use this when we want an assertion check in a free build
//
#define MY_ASSERT(x) \
if (!(x)) { \
DbgPrint($$_PLACE ": Assertion Failed: " # x "\n", \
$$_FILE_AND_LINE \
); \
DbgBreakPoint(); \
}
//
// IF_LOCK_CHECK - conditional compilation made cleaner
//
#define IF_LOCK_CHECK \
if (TRUE)
#else
#define ACQUIRE_DRIVER_LOCK() NdisAcquireSpinLock(&DlcDriverLock)
#define RELEASE_DRIVER_LOCK() NdisReleaseSpinLock(&DlcDriverLock)
#define ASSUME_IRQL(level) /* NOTHING */
#define MY_ASSERT(x) /* NOTHING */
#define IF_LOCK_CHECK if (FALSE)
#endif
//
// in the Unilock DLC, we do not need the LLC spin-lock
//
#if defined(DLC_UNILOCK)
#define ACQUIRE_LLC_LOCK(i)
#define RELEASE_LLC_LOCK(i)
#define ACQUIRE_SPIN_LOCK(p)
#define RELEASE_SPIN_LOCK(p)
#define ALLOCATE_SPIN_LOCK(p)
#define DEALLOCATE_SPIN_LOCK(p)
#else
#define ACQUIRE_LLC_LOCK(i) KeAcquireSpinLock(&LlcSpinLock, (i))
#define RELEASE_LLC_LOCK(i) KeReleaseSpinLock(&LlcSpinLock, (i))
#define ACQUIRE_SPIN_LOCK(p) NdisAcquireSpinLock((p))
#define RELEASE_SPIN_LOCK(p) NdisReleaseSpinLock((p))
#define ALLOCATE_SPIN_LOCK(p) KeInitializeSpinLock(&(p)->SpinLock)
#define DEALLOCATE_SPIN_LOCK(p)
#endif
//
// IS_SNA_DIX_FRAME - TRUE if the frame just received & therefore described in
// the ADAPTER_CONTEXT (p) has DIX framing (SNA)
//
#define IS_SNA_DIX_FRAME(p) \
(((PADAPTER_CONTEXT)(p))->IsSnaDixFrame)
//
// IS_AUTO_BINDING - TRUE if the BINDING_CONTEXT was created with
// LLC_ETHERNET_TYPE_AUTO
//
#define IS_AUTO_BINDING(p) \
(((PBINDING_CONTEXT)(p))->EthernetType == LLC_ETHERNET_TYPE_AUTO)
#define FRAME_MASK_LLC_LOCAL_DEST 0x0001
#define FRAME_MASK_NON_LLC_LOCAL_DEST 0x0002
#define FRAME_MASK_NON_LOCAL_DEST 0x0004
#define FRAME_MASK_ALL_FRAMES 0x0007
#define LLC_EXCLUSIVE_ACCESS 0x0001
#define LLC_HANDLE_XID_COMMANDS 0x0002
//
// Direct station receive flags (bits 0 and 1 are inverted from dlcapi!!!)
//
#define DLC_RCV_SPECIFIC_DIX 0
#define DLC_RCV_MAC_FRAMES 1
#define DLC_RCV_8022_FRAMES 2
#define DLC_RCV_DIX_FRAMES 4
#define LLC_VALID_RCV_MASK 7
#define DLC_RCV_OTHER_DESTINATION 8
#define MAX_LLC_FRAME_TYPES 10
//
// The DLC link states reported by DLC API
//
enum _DATA_LINK_STATES {
//
// Primary states
//
LLC_LINK_CLOSED = 0x80,
LLC_DISCONNECTED = 0x40,
LLC_DISCONNECTING = 0x20,
LLC_LINK_OPENING = 0x10,
LLC_RESETTING = 0x08,
LLC_FRMR_SENT = 0x04,
LLC_FRMR_RECEIVED = 0x02,
LLC_LINK_OPENED = 0x01,
//
// Secondary states (when primary state is LLC_LINK_OPENED)
//
LLC_CHECKPOINTING = 0x80,
LLC_LOCAL_BUSY_USER_SET = 0x40,
LLC_LOCAL_BUSY_BUFFER_SET = 0x20,
LLC_REMOTE_BUSY = 0x10,
LLC_REJECTING = 0x08,
LLC_CLEARING = 0x04,
LLC_DYNMIC_WIN_ALG_RUNNIG = 0x02,
LLC_NO_SECONDARY_STATE = 0
};
//
// LAN802_ADDRESS - 8 bytes of frame address. Typically 6 bytes LAN address
// plus 1 byte destination SAP, plus 1 byte source SAP
//
typedef union {
struct {
UCHAR DestSap;
UCHAR SrcSap;
USHORT usHigh;
ULONG ulLow;
} Address;
struct {
ULONG High;
ULONG Low;
} ul;
struct {
USHORT Raw[4];
} aus;
struct {
UCHAR DestSap;
UCHAR SrcSap;
UCHAR auchAddress[6];
} Node;
UCHAR auchRawAddress[8];
} LAN802_ADDRESS, *PLAN802_ADDRESS;
//
// Structure is used by DlcNdisRequest function
//
typedef struct {
NDIS_STATUS AsyncStatus;
NDIS_REQUEST Ndis;
} LLC_NDIS_REQUEST, *PLLC_NDIS_REQUEST;
#define NDIS_INFO_BUF_SIZE 20
#define DLC_ANY_STATION (-1)
//
// Internal event flags used by Timer, DlcConnect
// and DlcClose commands.
//
#define DLC_REPEATED_FLAGS 0x0700
#define LLC_TIMER_TICK_EVENT 0x0100
#define LLC_STATUS_CHANGE_ON_SAP 0x0800
//
// These enum types are used also as the index of a mapping table!
//
enum _LLC_OBJECT_TYPES {
LLC_DIRECT_OBJECT,
LLC_SAP_OBJECT,
LLC_GROUP_SAP_OBJECT,
LLC_LINK_OBJECT,
LLC_DIX_OBJECT
};
//
// We moved these defines here because the macro is used by data link
//
#define MIN_DLC_BUFFER_SEGMENT 256
////#define MAX_DLC_BUFFER_SEGMENT 4096
//#define MAX_DLC_BUFFER_SEGMENT 8192
#define MAX_DLC_BUFFER_SEGMENT PAGE_SIZE
#define BufGetPacketSize( PacketSize ) \
(((PacketSize) + 2 * MIN_DLC_BUFFER_SEGMENT - 1) & \
-MIN_DLC_BUFFER_SEGMENT)
//
// READ Event flags:
//
#define DLC_READ_FLAGS 0x007f
#define LLC_SYSTEM_ACTION 0x0040
#define LLC_NETWORK_STATUS 0x0020
#define LLC_CRITICAL_EXCEPTION 0x0010
#define LLC_STATUS_CHANGE 0x0008
#define LLC_RECEIVE_DATA 0x0004
#define LLC_TRANSMIT_COMPLETION 0x0002
#define DLC_COMMAND_COMPLETION 0x0001
#define ALL_DLC_EVENTS -1
//
// LLC_STATUS_CHANGE indications:
//
#define INDICATE_LINK_LOST 0x8000
#define INDICATE_DM_DISC_RECEIVED 0x4000
#define INDICATE_FRMR_RECEIVED 0x2000
#define INDICATE_FRMR_SENT 0x1000
#define INDICATE_RESET 0x0800
#define INDICATE_CONNECT_REQUEST 0x0400
#define INDICATE_REMOTE_BUSY 0x0200
#define INDICATE_REMOTE_READY 0x0100
#define INDICATE_TI_TIMER_EXPIRED 0x0080
#define INDICATE_DLC_COUNTER_OVERFLOW 0x0040
#define INDICATE_ACCESS_PRTY_LOWERED 0x0020
#define INDICATE_LOCAL_STATION_BUSY 0x0001
//
// LLC Command completion indications.
//
enum _LLC_COMPLETION_CODES {
LLC_RECEIVE_COMPLETION,
LLC_SEND_COMPLETION,
LLC_REQUEST_COMPLETION,
LLC_CLOSE_COMPLETION,
LLC_RESET_COMPLETION,
LLC_CONNECT_COMPLETION,
LLC_DISCONNECT_COMPLETION
};
typedef union {
LLC_ADAPTER_INFO Adapter;
DLC_LINK_PARAMETERS LinkParms;
LLC_TICKS Timer;
DLC_LINK_LOG LinkLog;
DLC_SAP_LOG SapLog;
UCHAR PermanentAddress[6];
UCHAR auchBuffer[1];
} LLC_QUERY_INFO_BUFFER, *PLLC_QUERY_INFO_BUFFER;
typedef union {
DLC_LINK_PARAMETERS LinkParms;
LLC_TICKS Timers;
UCHAR auchFunctionalAddress[4];
UCHAR auchGroupAddress[4];
UCHAR auchBuffer[1];
} LLC_SET_INFO_BUFFER, *PLLC_SET_INFO_BUFFER;
//
// LLC_FRMR_INFORMATION - 5 bytes of FRaMe Reject code
//
typedef struct {
UCHAR Command; // format: mmmpmm11, m=modifiers, p=poll/final.
UCHAR Ctrl; // control field of rejected frame.
UCHAR Vs; // our next send when error was detected.
UCHAR Vr; // our next receive when error was detected.
UCHAR Reason; // reason for sending FRMR: 000VZYXW.
} LLC_FRMR_INFORMATION, *PLLC_FRMR_INFORMATION;
//
// DLC_STATUS_TABLE - format of status information returned in a READ command
//
typedef struct {
USHORT StatusCode;
LLC_FRMR_INFORMATION FrmrData;
UCHAR uchAccessPriority;
UCHAR auchRemoteNode[6];
UCHAR uchRemoteSap;
UCHAR uchLocalSap;
PVOID hLlcLinkStation;
} DLC_STATUS_TABLE, *PDLC_STATUS_TABLE;
typedef struct {
ULONG IsCompleted;
ULONG Status;
} ASYNC_STATUS, *PASYNC_STATUS;
union _LLC_OBJECT;
typedef union _LLC_OBJECT LLC_OBJECT, *PLLC_OBJECT;
struct _BINDING_CONTEXT;
typedef struct _BINDING_CONTEXT BINDING_CONTEXT, *PBINDING_CONTEXT;
//
// LLC packet headers
//
//
// LLC_XID_INFORMATION - 3 information bytes in a standard LLC XID packet
//
typedef struct {
UCHAR FormatId; // format of this XID frame.
UCHAR Info1; // first information byte.
UCHAR Info2; // second information byte.
} LLC_XID_INFORMATION, *PLLC_XID_INFORMATION;
//
// LLC_TEST_INFORMATION - information field for TEST frame
//
typedef struct {
UCHAR Padding[4];
PMDL pMdl; // we keep test MDL in the same slot as U-MDL
} LLC_TEST_INFORMATION, *PLLC_TEST_INFORMATION;
typedef union {
LLC_XID_INFORMATION Xid; // XID information.
LLC_FRMR_INFORMATION Frmr; // FRMR information.
LLC_TEST_INFORMATION Test; // Test MDL pointer
UCHAR Padding[8]; //
} LLC_RESPONSE_INFO, *PLLC_RESPONSE_INFO;
//
// LLC_U_HEADER - Unnumbered format frame LLC header
//
typedef struct {
UCHAR Dsap; // Destination Service Access Point.
UCHAR Ssap; // Source Service Access Point.
UCHAR Command; // command code.
} LLC_U_HEADER, *PLLC_U_HEADER;
//
// LLC_S_HEADER - Supervisory format frame LLC header
//
typedef struct {
UCHAR Dsap; // Destination Service Access Point.
UCHAR Ssap; // Source Service Access Point.
UCHAR Command; // RR, RNR, REJ command code.
UCHAR Nr; // receive seq #, bottom bit is poll/final.
} LLC_S_HEADER, *PLLC_S_HEADER;
//
// LLC_I_HEADER - Information frame LLC header
//
typedef struct {
UCHAR Dsap; // Destination Service Access Point.
UCHAR Ssap; // Source Service Access Point.
UCHAR Ns; // send sequence number, bottom bit 0.
UCHAR Nr; // rcv sequence number, bottom bit p/f.
} LLC_I_HEADER, *PLLC_I_HEADER;
typedef struct {
LLC_U_HEADER U; // normal U- frame
UCHAR Type; // its lan header conversion type
} LLC_U_PACKET_HEADER, *PLLC_U_PACKET_HEADER;
typedef union {
LLC_S_HEADER S;
LLC_I_HEADER I;
LLC_U_HEADER U;
ULONG ulRawLLc;
UCHAR auchRawBytes[4];
USHORT EthernetType;
} LLC_HEADER, *PLLC_HEADER;
typedef struct _LLC_PACKET {
struct _LLC_PACKET* pNext;
struct _LLC_PACKET* pPrev;
UCHAR CompletionType;
UCHAR cbLlcHeader;
USHORT InformationLength;
PBINDING_CONTEXT pBinding;
union {
struct {
PUCHAR pLanHeader;
LLC_HEADER LlcHeader;
PLLC_OBJECT pLlcObject;
PMDL pMdl;
} Xmit;
struct {
PUCHAR pLanHeader;
UCHAR TranslationType;
UCHAR Dsap;
UCHAR Ssap;
UCHAR Command;
PLLC_OBJECT pLlcObject;
PMDL pMdl;
} XmitU;
struct {
PUCHAR pLanHeader;
UCHAR TranslationType;
UCHAR EthernetTypeHighByte;
UCHAR EthernetTypeLowByte;
UCHAR Padding;
PLLC_OBJECT pLlcObject;
PMDL pMdl;
} XmitDix;
struct {
PUCHAR pLanHeader;
UCHAR TranslationType;
UCHAR Dsap;
UCHAR Ssap;
UCHAR Command;
LLC_RESPONSE_INFO Info;
} Response;
//
// Link station data packet may be acknowledged by the other
// side, before it is completed by NDIS. Ndis completion
// routine expects to find pLlcObject link => we must not change
// that field, when the xmit packet is translated to
// a completion packet. Otherwise is corrupt pFileContext pointer,
// when NdisSendCount is incremented.
//
struct {
ULONG Status;
ULONG CompletedCommand;
PLLC_OBJECT pLlcObject;
PVOID hClientHandle;
} Completion;
} Data;
} LLC_PACKET, *PLLC_PACKET;
//
// Data link indication handler prototypes.
// The protocols registering to data link driver
// must provide these entry points.
//
typedef
UINT
(*PFLLC_RECEIVE_INDICATION)(
IN PVOID hClientContext,
IN PVOID hClientHandle,
IN USHORT FrameType,
IN PVOID pLookBuf,
IN UINT cbLookBuf
);
typedef
VOID
(*PFLLC_COMMAND_COMPLETE)(
IN PVOID hClientContext,
IN PVOID hClientHandle,
IN PVOID hPacket
);
typedef
VOID
(*PFLLC_EVENT_INDICATION)(
IN PVOID hClientContext,
IN PVOID hClientHandle,
IN UINT uiEvent,
IN PVOID pDlcStatus,
IN ULONG SecondaryInformation
);
//
// DLC API return codes
//
// The base value of the error codes is not compatible with the other
// nt error codes, but it doesn't matter because these are internal
// for DLC driver (and its data link layer).
// 16 bit- error codes are used, because in MIPS they need less
// instructions (MIPS cannot load directly over 16 bits constants)
// and this code can also be emuulated on OS/2.
//
typedef enum _DLC_STATUS {
DLC_STATUS_SUCCESS = 0,
DLC_STATUS_ERROR_BASE = 0x6000,
DLC_STATUS_INVALID_COMMAND = 0x01 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_DUPLICATE_COMMAND = 0x02 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_ADAPTER_OPEN = 0x03 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_ADAPTER_CLOSED = 0x04 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_PARAMETER_MISSING = 0x05 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_OPTION = 0x06 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_COMMAND_CANCELLED_FAILURE = 0x07 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_CANCELLED_BY_USER = 0x0A + DLC_STATUS_ERROR_BASE,
DLC_STATUS_SUCCESS_NOT_OPEN = 0x0C + DLC_STATUS_ERROR_BASE,
DLC_STATUS_TIMER_ERROR = 0x11 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_NO_MEMORY = 0x12 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_LOST_LOG_DATA = 0x15 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_BUFFER_SIZE_EXCEEDED = 0x16 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_BUFFER_LENGTH = 0x18 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INADEQUATE_BUFFERS = 0x19 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_USER_LENGTH_TOO_LARGE = 0x1A + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_CCB_POINTER = 0x1B + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_POINTER = 0x1C + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_ADAPTER = 0x1D + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_FUNCTIONAL_ADDRESS = 0x1E + DLC_STATUS_ERROR_BASE,
DLC_STATUS_LOST_DATA_NO_BUFFERS = 0x20 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_TRANSMIT_ERROR_FS = 0x22 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_TRANSMIT_ERROR = 0x23 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_UNAUTHORIZED_MAC = 0x24 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_LINK_NOT_TRANSMITTING = 0x27 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_FRAME_LENGTH = 0x28 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_NODE_ADDRESS = 0x32 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_RECEIVE_BUFFER_LENGTH = 0x33 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_TRANSMIT_BUFFER_LENGTH = 0x34 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_STATION_ID = 0x40 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_LINK_PROTOCOL_ERROR = 0x41 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_PARMETERS_EXCEEDED_MAX = 0x42 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_SAP_VALUE = 0x43 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_ROUTING_INFO = 0x44 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_LINK_STATIONS_OPEN = 0x47 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INCOMPATIBLE_COMMAND_IN_PROGRESS = 0x4A + DLC_STATUS_ERROR_BASE,
DLC_STATUS_CONNECT_FAILED = 0x4D + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_REMOTE_ADDRESS = 0x4F + DLC_STATUS_ERROR_BASE,
DLC_STATUS_CCB_POINTER_FIELD = 0x50 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INADEQUATE_LINKS = 0x57 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_PARAMETER_1 = 0x58 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_DIRECT_STATIONS_NOT_AVAILABLE = 0x5C + DLC_STATUS_ERROR_BASE,
DLC_STATUS_DEVICE_DRIVER_NOT_INSTALLED = 0x5d + DLC_STATUS_ERROR_BASE,
DLC_STATUS_ADAPTER_NOT_INSTALLED = 0x5e + DLC_STATUS_ERROR_BASE,
DLC_STATUS_CHAINED_DIFFERENT_ADAPTERS = 0x5f + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INIT_COMMAND_STARTED = 0x60 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_CANCELLED_BY_SYSTEM_ACTION = 0x62 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_MEMORY_LOCK_FAILED = 0x69 + DLC_STATUS_ERROR_BASE,
//
// New Nt DLC specific error codes begin from 0x80
// These error codes are for new Windows/Nt DLC apps.
// This far we have tried too much use the OS/2 error codes,
// that results often uninformative return codes.
//
DLC_STATUS_INVALID_BUFFER_ADDRESS = 0x80 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_BUFFER_ALREADY_RELEASED = 0x81 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_VERSION = 0xA1 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INVALID_BUFFER_HANDLE = 0xA2 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_NT_ERROR_STATUS = 0xA3 + DLC_STATUS_ERROR_BASE,
//
// These error codes are just internal for LLC- kernel level interface
// and they are not returned to application level.
//
DLC_STATUS_UNKNOWN_MEDIUM = 0xC0 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_DISCARD_INFO_FIELD = 0xC1 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_NO_ACTION = 0xC2 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_ACCESS_DENIED = 0xC3 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_IGNORE_FRAME = 0xC4 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_WAIT_TIMEOUT = 0xC5 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_NO_RECEIVE_COMMAND = 0xC6 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_FILE_CONTEXT_DELETED = 0xC7 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_EXPAND_BUFFER_POOL = 0xC8 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_INTERNAL_ERROR = 0xC9 + DLC_STATUS_ERROR_BASE,
DLC_STATUS_ASYNC_DATA_TRANSFER_FAILED = 0xCA + DLC_STATUS_ERROR_BASE,
DLC_STATUS_OUT_OF_RCV_BUFFERS = 0xCB + DLC_STATUS_ERROR_BASE,
DLC_STATUS_PENDING = 0xFF + DLC_STATUS_ERROR_BASE,
DLC_STATUS_MAX_ERROR = 0xFF + DLC_STATUS_ERROR_BASE
} DLC_STATUS;
UINT
LlcBuildAddressFromLanHeader(
IN NDIS_MEDIUM NdisMedium,
IN PUCHAR pRcvFrameHeader,
IN OUT PUCHAR pLanHeader
);
DLC_STATUS
LlcInitialize(
VOID
);
UINT
LlcBuildAddress(
IN NDIS_MEDIUM NdisMedium,
IN PUCHAR DestinationAddress,
IN PVOID pSrcRouting,
IN OUT PUCHAR pLanHeader
);
USHORT
LlcGetMaxInfoField(
IN NDIS_MEDIUM NdisMedium,
IN PVOID hBinding,
IN PUCHAR pLanHeader
);
DLC_STATUS
LlcQueryInformation(
IN PVOID hObject,
IN UINT InformationType,
IN PLLC_QUERY_INFO_BUFFER pQuery,
IN UINT QueryBufferSize
);
DLC_STATUS
LlcSetInformation(
IN PVOID hObject,
IN UINT InformationType,
IN PLLC_SET_INFO_BUFFER pSetInfo,
IN UINT ParameterBufferSize
);
DLC_STATUS
LlcNdisRequest(
IN PVOID hBindingContext,
IN PLLC_NDIS_REQUEST pDlcParms
);
DLC_STATUS
LlcOpenAdapter(
IN PWSTR pAdapterName,
IN PVOID hClientContext,
IN PFLLC_COMMAND_COMPLETE pfCommandComplete,
IN PFLLC_RECEIVE_INDICATION pfReceiveIndication,
IN PFLLC_EVENT_INDICATION pfEventIndication,
IN NDIS_MEDIUM NdisMedium,
IN LLC_ETHERNET_TYPE EthernetType,
IN UCHAR AdapterNumber,
OUT PVOID *phBindingContext,
OUT PUINT puiOpenStatus,
OUT PUSHORT puiMaxFrameLength,
OUT PNDIS_MEDIUM pActualNdisMedium
);
#define LlcOpenSap(Context, Handle, Sap, Options, phSap) \
LlcOpenStation(Context, Handle, (USHORT)(Sap), LLC_SAP_OBJECT, (USHORT)(Options), phSap)
#define LlcOpenDirectStation(Context, Handle, Sap, phSap) \
LlcOpenStation(Context, Handle, (USHORT)(Sap), LLC_DIRECT_OBJECT, 0, phSap)
#define LlcOpenDixStation(Context, Handle, Sap, phSap) \
LlcOpenStation(Context, Handle, (USHORT)(Sap), LLC_DIX_OBJECT, 0, phSap)
VOID
RemoveFromLinkList(
OUT PVOID* ppBase,
IN PVOID pElement
);
VOID
LlcSleep(
IN LONG lMicroSeconds
);
VOID
LlcTerminate(
VOID
);
VOID
LlcDereferenceObject(
IN PVOID pStation
);
VOID
LlcReferenceObject(
IN PVOID pStation
);
DLC_STATUS
LlcTraceInitialize(
IN PVOID UserTraceBuffer,
IN ULONG UserTraceBufferSize,
IN ULONG TraceFlags
);
VOID
LlcTraceClose(
VOID
);
VOID
LlcTraceWrite(
IN UINT Event,
IN UCHAR AdapterNumber,
IN UINT DataBufferSize,
IN PVOID DataBuffer
);
VOID
LlcTraceDump(
IN UINT LastEvents,
IN UINT AdapterNumber,
IN PUCHAR pRemoteNode
);
VOID
LlcTraceDumpAndReset(
IN UINT LastEvents,
IN UINT AdapterNumber,
IN PUCHAR pRemoteNode
);
#if DBG
typedef struct {
USHORT Input;
USHORT Time;
PVOID pLink;
} LLC_SM_TRACE;
#define LLC_INPUT_TABLE_SIZE 500
extern ULONG AllocatedNonPagedPool;
extern ULONG LockedPageCount;
extern ULONG AllocatedMdlCount;
extern ULONG AllocatedPackets;
extern NDIS_SPIN_LOCK MemCheckLock;
extern ULONG cExAllocatePoolFailed;
extern ULONG FailedMemoryLockings;
VOID PrintMemStatus(VOID);
extern ULONG cFramesReceived;
extern ULONG cFramesIndicated;
extern ULONG cFramesReleased;
extern ULONG cLockedXmitBuffers;
extern ULONG cUnlockedXmitBuffers;
extern LLC_SM_TRACE aLast[];
extern UINT InputIndex;
#endif
//
// The inline memcpy and memset functions are faster,
// in x386 than RtlMoveMemory
//
#if defined(i386)
#define LlcMemCpy(Dest, Src, Len) memcpy(Dest, Src, Len)
#define LlcZeroMem(Ptr, Len) memset(Ptr, 0, Len)
#else
#define LlcMemCpy(Dest, Src, Len) RtlMoveMemory(Dest, Src, Len)
#define LlcZeroMem(Ptr, Len) RtlZeroMemory(Ptr, Len)
#endif
//
//
// PVOID
// PopEntryList(
// IN PQUEUE_PACKET ListHead,
// );
//
#define PopFromList(ListHead) \
(PVOID)(ListHead); \
(ListHead) = (PVOID)(ListHead)->pNext;
//
// VOID
// PushToList(
// IN PQUEUE_PACKET ListHead,
// IN PQUEUE_PACKET Entry
// );
//
#define PushToList(ListHead,Entry) { \
(Entry)->pNext = (PVOID)(ListHead); \
(ListHead) = (Entry); \
}
//
// About 30% of all bugs are related with the invalid operations with
// packets. A packet may be inserted to another list before it
// has been removed from the previous one, etc.
// The debug version of the list macroes reset the next pointer
// every time it is removed from the list and check it when it is
// inserted to a new list or released to a packet pool. The packet
// alloc will reset the next pointer automatically.
// Problem: the packets are used for many other purposes as well =>
// we must do quite a lot conditional code.
//
#if LLC_DBG
#if LLC_DBG_MP
#define DBG_INTERLOCKED_INCREMENT(Count) \
InterlockedIncrement( \
(PLONG)&(Count) \
)
#define DBG_INTERLOCKED_DECREMENT(Count) \
InterlockedDecrement( \
(PLONG)&(Count) \
)
#define DBG_INTERLOCKED_ADD(Added, Value) \
ExInterlockedAddUlong( \
(PULONG)&(Added), \
(ULONG)(Value), \
&MemCheckLock.SpinLock \
)
#else
#define DBG_INTERLOCKED_INCREMENT(Count) (Count)++
#define DBG_INTERLOCKED_DECREMENT(Count) (Count)--
#define DBG_INTERLOCKED_ADD(Added, Value) (Added) += (Value)
#endif // LLC_DBG_MP
#else
#define DBG_INTERLOCKED_INCREMENT(Count)
#define DBG_INTERLOCKED_DECREMENT(Count)
#define DBG_INTERLOCKED_ADD(Added, Value)
#endif // LLC_DBG
#if LLC_DBG
VOID LlcBreakListCorrupt( VOID );
#define LlcRemoveHeadList(ListHead) \
(PVOID)(ListHead)->Flink; \
{ \
PLIST_ENTRY FirstEntry; \
FirstEntry = (ListHead)->Flink; \
FirstEntry->Flink->Blink = (ListHead); \
(ListHead)->Flink = FirstEntry->Flink; \
FirstEntry->Flink = NULL; \
}
#define LlcRemoveTailList(ListHead) \
(ListHead)->Blink; \
{ \
PLIST_ENTRY FirstEntry; \
FirstEntry = (ListHead)->Blink; \
FirstEntry->Blink->Flink = (ListHead); \
(ListHead)->Blink = FirstEntry->Blink; \
FirstEntry->Flink = NULL; \
}
#define LlcRemoveEntryList(Entry) \
{ \
RemoveEntryList((PLIST_ENTRY)Entry); \
((PLIST_ENTRY)(Entry))->Flink = NULL; \
}
#define LlcInsertTailList(ListHead,Entry) \
if (((PLIST_ENTRY)(Entry))->Flink != NULL){ \
LlcBreakListCorrupt(); \
} \
InsertTailList(ListHead, (PLIST_ENTRY)Entry)
#define LlcInsertHeadList(ListHead,Entry) \
if (((PLIST_ENTRY)(Entry))->Flink != NULL) { \
LlcBreakListCorrupt(); \
} \
InsertHeadList(ListHead,(PLIST_ENTRY)Entry)
/*
#define DeallocatePacket( PoolHandle, pBlock ) { \
if (((PLIST_ENTRY)pBlock)->Flink != NULL) { \
LlcBreakListCorrupt(); \
} \
DBG_INTERLOCKED_DECREMENT( AllocatedPackets ); \
ExFreeToZone( \
&(((PEXTENDED_ZONE_HEADER)PoolHandle)->Zone), \
pBlock); \
}
*/
#else
//
// PVOID
// LlcRemoveHeadList(
// IN PLIST_ENTRY ListHead
// );
//
#define LlcRemoveHeadList(ListHead) (PVOID)RemoveHeadList(ListHead)
//
// PLIST_ENTRY
// LlcRemoveTailList(
// IN PLIST_ENTRY ListHead
// );
//
#define LlcRemoveTailList(ListHead) \
(ListHead)->Blink; { \
PLIST_ENTRY FirstEntry; \
FirstEntry = (ListHead)->Blink; \
FirstEntry->Blink->Flink = (ListHead); \
(ListHead)->Blink = FirstEntry->Blink; \
}
//
// VOID
// LlcRemoveEntryList(
// IN PVOID Entry
// );
//
#define LlcRemoveEntryList(Entry) RemoveEntryList((PLIST_ENTRY)Entry)
//
// VOID
// LlcInsertTailList(
// IN PLIST_ENTRY ListHead,
// IN PVOID Entry
// );
//
#define LlcInsertTailList(ListHead,Entry) \
InsertTailList(ListHead, (PLIST_ENTRY)Entry)
//
// VOID
// LlcInsertHeadList(
// IN PLIST_ENTRY ListHead,
// IN PVOID Entry
// );
//
#define LlcInsertHeadList(ListHead,Entry) \
InsertHeadList(ListHead,(PLIST_ENTRY)Entry)
//
// VOID
// DeallocatePacket(
// PEXTENDED_ZONE_HEADER PoolHandle,
// PVOID pBlock
// );
//
/*
#define DeallocatePacket( PoolHandle, pBlock ) { \
ExFreeToZone( &(((PEXTENDED_ZONE_HEADER)PoolHandle)->Zone), \
pBlock); \
}
*/
#endif // DBG
#if LLC_DBG == 2
VOID LlcMemCheck(VOID);
#define MEM_CHECK() LlcMemCheck()
#else
#define MEM_CHECK()
#endif
VOID LlcInvalidObjectType(VOID);
/*++
Trace codes
Big letters are reserved for actions, small letters are used to identify
objects and packet types. The trace macroes simply writes to DLC
trace tree (remember: we have another trace for the state machine!!!)
'a' = dix stations
'b' = direct station
'c' = link station
'd' = sap station
'e' = Connect command
'f' = Close command
'g' = Disconnect command
'h' = Receive command
'i' = transmit command
'j' = Type1 packet
'k' = type 2 packet
'l' = data link packet
'A' = CompleteSendAndLock
'B' = LlcCommandCompletion
'C' = LlcCloseStation
'D' = LlcReceiveIndication
'E' = LlcEventIndication
'F' = DlcDeviceIoControl
'G' = DlcDeviceIoControl sync exit
'H' = DlcDeviceIoControl async exit
'I' = LlcSendI
'J' = DirCloseAdapter
'K' = CompleteDirCloseAdapter
'L' = LlcDereferenceObject
'M' = LlcReferenceObject
'N' = CompleteCloseStation (final)
'O' = DereferenceLlcObject (in dlc)
'P' = CompleteLlcObjectClose (final)
'Q' = DlcReadCancel
'R' =
'S' =
'T' = DlcTransmit
'U' = LlcSendU
'V' =
'W' =
'X' =
'Y' =
'Z' =
--*/
#if DBG & DLC_TRACE_ENABLED
#define LLC_TRACE_TABLE_SIZE 0x400 // this must be exponent of 2!
extern UINT LlcTraceIndex;
extern UCHAR LlcTraceTable[];
#define DLC_TRACE(a) {\
LlcTraceTable[LlcTraceIndex] = (a);\
LlcTraceIndex = (LlcTraceIndex + 1) & (LLC_TRACE_TABLE_SIZE - 1);\
}
#else
#define DLC_TRACE(a)
#endif // LLC_DBG
//
// the following functions can be macros if DLC and LLC live in the same driver
// and each knows about the other's structures
//
#if DLC_AND_LLC
//
// UINT
// LlcGetReceivedLanHeaderLength(
// IN PVOID pBinding
// );
//
#if 0
//
// this gives the wrong length for DIX lan header
//
#define LlcGetReceivedLanHeaderLength(pBinding) \
((((PBINDING_CONTEXT)(pBinding))->pAdapterContext->NdisMedium == NdisMedium802_3) \
? (((PBINDING_CONTEXT)(pBinding))->pAdapterContext->FrameType == LLC_DIRECT_ETHERNET_TYPE) \
? 12 \
: 14 \
: (((PBINDING_CONTEXT)(pBinding))->pAdapterContext->NdisMedium == NdisMediumFddi) \
? 14 \
: ((PBINDING_CONTEXT)(pBinding))->pAdapterContext->RcvLanHeaderLength)
#else
//
// this always returns 14 as the DIX lan header length
//
#define LlcGetReceivedLanHeaderLength(pBinding) \
((((PBINDING_CONTEXT)(pBinding))->pAdapterContext->NdisMedium == NdisMedium802_3) \
? 14 \
: (((PBINDING_CONTEXT)(pBinding))->pAdapterContext->NdisMedium == NdisMediumFddi) \
? 14 \
: ((PBINDING_CONTEXT)(pBinding))->pAdapterContext->RcvLanHeaderLength)
#endif
//
// USHORT
// LlcGetEthernetType(
// IN PVOID hContext
// );
//
#define LlcGetEthernetType(hContext) \
(((PBINDING_CONTEXT)(hContext))->pAdapterContext->EthernetType)
//
// UINT
// LlcGetCommittedSpace(
// IN PVOID hLink
// );
//
#define LlcGetCommittedSpace(hLink) \
(((PDATA_LINK)(hLink))->BufferCommitment)
#else
//
// separation of church and state, or DLC and LLC even
//
UINT
LlcGetReceivedLanHeaderLength(
IN PVOID pBinding
);
USHORT
LlcGetEthernetType(
IN PVOID hContext
);
UINT
LlcGetCommittedSpace(
IN PVOID hLink
);
#endif // DLC_AND_LLC
#endif // _LLC_API_