|
|
/*++
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; KEVENT SyncEvent; 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;
//
// 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;
//
// Data link indication handler prototypes.
// The protocols registering to data link driver
// must provide these entry points.
//
typedef DLC_STATUS (*PFLLC_RECEIVE_INDICATION)( IN PVOID hClientContext, IN PVOID hClientHandle, IN NDIS_HANDLE MacReceiveContext, 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 );
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_
|