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.
 
 
 
 
 
 

758 lines
20 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
asyncsft.h
Abstract:
Author:
Environment:
This driver is expected to work in DOS, OS2 and NT at the equivalent
of kernal mode.
Architecturally, there is an assumption in this driver that we are
on a little endian machine.
Notes:
optional-notes
Revision History:
--*/
#ifndef _ASYNCSFT_
#define _ASYNCSFT_
//
// Memory tags
//
#define ASYNC_IOCTX_TAG '1ysA'
#define ASYNC_INFO_TAG '2ysA'
#define ASYNC_ADAPTER_TAG '3ysA'
#define ASYNC_FRAME_TAG '4ysA'
#define ASYNC_WORKITEM_TAG '5ysA'
#define INLINE __inline
//
// UINT min(UINT a, UINT b)
//
#ifndef min
#define min(a, b) ((a) <= (b) ? (a) : (b))
#endif
//
// UINT max(UINT a, UINT b)
//
#ifndef max
#define max(a, b) ((a) >= (b) ? (a) : (b))
#endif
#define MAKEWORD(l, h) ((USHORT) ((l) | ((h) << 8)))
#define MAKELONG(l, h) ((ULONG) ((l) | ((h) << 16)))
#define MAKE_SIGNATURE(a, b, c, d) MAKELONG(MAKEWORD(a, b), MAKEWORD(c, d))
#define ASYNC_NDIS_MAJOR_VERSION 4
#define ASYNC_NDIS_MINOR_VERSION 0
// change these, just added these to compile.
#define ETHERNET_HEADER_SIZE 14
// what window size to request on the line-up indication
#define ASYNC_WINDOW_SIZE 2
//
// PPP uses CIPX, and VJ TCP/IP header compression
// the frame gets expanded inplace when decompressed.
//
#define PPP_PADDING 128
#define MAC_NAME_SIZE 256
//
// ZZZ These macros are peculiar to NT.
//
#define ASYNC_MOVE_MEMORY(Destination,Source,Length) NdisMoveMemory(Destination,Source,Length)
#define ASYNC_ZERO_MEMORY(Destination,Length) NdisZeroMemory(Destination,Length)
/* Added this macro to eliminate problems caused by Tommy's redefinition and
** hard-coding of MaxFrameSize for PPP.
*/
#define MaxFrameSizeWithPppExpansion(x) (((x)*2)+PPP_PADDING+100)
typedef struct _OID_WORK_ITEM {
WORK_QUEUE_ITEM WorkQueueItem;
PVOID Context;
} OID_WORK_ITEM, *POID_WORK_ITEM;
//
// Used to contain a queued operation.
//
typedef struct _ASYNC_PEND_DATA {
PNDIS_REQUEST Next;
struct _ASYNC_OPEN * Open;
NDIS_REQUEST_TYPE RequestType;
} ASYNC_PEND_DATA, * PASYNC_PEND_DATA;
// o CRC errors are when the 16bit V.41 CRC check fails
// o TimeoutErrors occur when inter-character delays within
// a frame are exceeded
// o AlignmentErrors occur when the SYN byte or ETX bytes which
// mark the beginning and end of frames are not found.
// o The other errors are standard UART errors returned by the serial driver
typedef struct SERIAL_STATS SERIAL_STATS, *PSERIAL_STATS;
struct SERIAL_STATS {
ULONG CRCErrors; // Serial-like info only
ULONG TimeoutErrors; // Serial-like info only
ULONG AlignmentErrors; // Serial-like info only
ULONG SerialOverrunErrors; // Serial-like info only
ULONG FramingErrors; // Serial-like info only
ULONG BufferOverrunErrors; // Serial-like info only
};
// The bytes transmitted, bytes received, frames received, frame transmitted
// are monitored for frame and bytes going to the output device or
// coming from the output device. If software compression used, it
// is on top of this layer.
typedef struct GENERIC_STATS GENERIC_STATS, *PGENERIC_STATS;
struct GENERIC_STATS {
ULONG BytesTransmitted; // Generic info
ULONG BytesReceived; // Generic info
ULONG FramesTransmitted; // Generic info
ULONG FramesReceived; // Generic info
};
//
// This macro will return a pointer to the reserved area of
// a PNDIS_REQUEST.
//
#define PASYNC_PEND_DATA_FROM_PNDIS_REQUEST(Request) \
((PASYNC_PEND_DATA)((PVOID)((Request)->MacReserved)))
//
// This macros returns the enclosing NdisRequest.
//
#define PNDIS_REQUEST_FROM_PASYNC_PEND_DATA(PendOp)\
((PNDIS_REQUEST)((PVOID)(PendOp)))
typedef struct ASYNC_CCB ASYNC_CCB, *PASYNC_CCB;
// Every port will be atomically at some state. Typically states go into
// intermediate states when they go from from closed to open and vice-versa.
typedef enum _ASYNC_PORT_STATE {
PORT_BOGUS, // PORT_BOGUS gets assigned the NULL value
PORT_OPEN, // Port opened
PORT_CLOSED, // Port closed
PORT_CLOSING, // Port closing (cleaning up, deallocating)
PORT_OPENING, // Port opening (checking arguments, allocating)
PORT_FRAMING, // Port opened and sending/reading frames
} ASYNC_PORT_STATE;
#if DBG
typedef struct _PENDING_REQUEST
{
LIST_ENTRY le;
VOID *pvContext;
ULONG Sig;
ULONG lineNum;
} PENDING_REQUEST;
#define REF_ASYNCINFO(_pai, _context) \
{ \
PENDING_REQUEST * _Request; \
ASSERT((_pai)->RefCount > 0); \
InterlockedIncrement(&(_pai)->RefCount); \
_Request = ExAllocatePoolWithTag(NonPagedPool, \
sizeof(PENDING_REQUEST), \
'nepA'); \
if(NULL != _Request) \
{ \
_Request->pvContext = _context; \
_Request->Sig = __FILE_SIG__; \
_Request->lineNum = __LINE__; \
InsertTailList(&_pai->lePendingRequests, &_Request->le); \
} \
} \
#define DEREF_ASYNCINFO(_pai, _context) \
{ \
if(NULL != (_pai)) \
{ \
LIST_ENTRY *_ple; \
NdisAcquireSpinLock(&(_pai)->Lock); \
ASSERT((_pai)->RefCount > 0); \
InterlockedDecrement(&(_pai)->RefCount); \
if((_pai)->RefCount == 0) \
{ \
KeSetEvent(&(_pai)->AsyncEvent, 1, \
FALSE); \
} \
for (_ple = _pai->lePendingRequests.Flink; \
_ple != &_pai->lePendingRequests; \
_ple = _ple->Flink) \
{ \
if(((PENDING_REQUEST *)_ple)->pvContext == _context) \
{ \
RemoveEntryList(_ple); \
ExFreePoolWithTag(_ple, 'nepA'); \
break; \
} \
} \
NdisReleaseSpinLock(&(_pai)->Lock); \
} \
} \
#else
#define REF_ASYNCINFO(_pai, _context) \
{ \
ASSERT((_pai)->RefCount > 0); \
InterlockedIncrement(&(_pai)->RefCount); \
} \
#define DEREF_ASYNCINFO(_pai, _context) \
{ \
if(NULL != (_pai)) \
{ \
NdisAcquireSpinLock(&(_pai)->Lock); \
ASSERT((_pai)->RefCount > 0); \
InterlockedDecrement(&(_pai)->RefCount); \
if((_pai)->RefCount == 0) \
{ \
KeSetEvent(&(_pai)->AsyncEvent, 1, \
FALSE); \
} \
NdisReleaseSpinLock(&(_pai)->Lock); \
} \
} \
#endif
//
// The ASYNC_INFO structure is a per port field. The ASYNC_CONNECTION
// field is embedded in it because it also a per port field.
//
struct ASYNC_INFO {
LIST_ENTRY Linkage;
ULONG RefCount;
ULONG Flags;
#define OID_WORK_SCHEDULED 0x00000001
#define ASYNC_FLAG_CHECK_COMM_STATUS 0x00000002
#define ASYNC_FLAG_ASYNCMAC_OPEN 0x00000004
#define ASYNC_FLAG_SET_LINK_INFO 0x00000008
#define ASYNC_FLAG_SEND_PACKET 0x00000010
#define ASYNC_FLAG_SLIP_READ 0x00000020
#define ASYNC_FLAG_PPP_READ 0x00000040
#define ASYNC_FLAG_WAIT_MASK 0x00000080
PASYNC_ADAPTER Adapter; // Back pointer to ADAPTER struct.
PDEVICE_OBJECT DeviceObject; // Pointer to device object.
ASYNC_PORT_STATE PortState; // OPEN, CLOSED, CLOSING, OPENING
HANDLE Handle; // Port handle
PFILE_OBJECT FileObject; // handle is dereferenced for IRPs
KEVENT ClosingEvent; // we use this event to synch closing
KEVENT DetectEvent; // sync the detect worker
KEVENT AsyncEvent; // async event
UINT QualOfConnect; // Defined by NDIS
ULONG LinkSpeed; // in 100bps
NDIS_HANDLE hNdisEndPoint;
NDIS_HANDLE NdisLinkContext;
LIST_ENTRY DDCDQueue;
ULONG WaitMaskToUse ; // Wait mask used for reads.
union {
NDIS_WAN_GET_LINK_INFO GetLinkInfo; //... For OID requests.
NDIS_WAN_SET_LINK_INFO SetLinkInfo;
};
// use for reading frames
PASYNC_FRAME AsyncFrame; // allocated for READs (one frame only)
WORK_QUEUE_ITEM WorkItem; // use to queue up first read thread
UINT BytesWanted;
UINT BytesRead;
//... Statistics tracking
SERIAL_STATS SerialStats; // Keep track of serial stats
ULONG In;
ULONG Out;
UINT ReadStackCounter;
ULONG ExtendedACCM[8]; //Extended ACCM bit masks (256 bits)
NDIS_SPIN_LOCK Lock;
#if DBG
ULONG Pppreads;
ULONG PppreadsCompleted;
LIST_ENTRY lePendingRequests;
#endif
};
//
// This structure, and it corresponding per port structures are
// allocated when we get AddAdapter.
//
struct ASYNC_ADAPTER {
//
// WAN information. for OID_WAN_GET_INFO request.
//
NDIS_WAN_INFO WanInfo;
//
// Keeps a reference count on the current number of uses of
// this adapter block. Uses is defined to be the number of
// routines currently within the "external" interface.
//
LONG RefCount;
//
// List of active ports
//
LIST_ENTRY ActivePorts;
//
// Spinlock to protect fields in this structure..
//
NDIS_SPIN_LOCK Lock;
//
// Handle given by NDIS at MPInit
//
NDIS_HANDLE MiniportHandle;
//
// Flag that when enabled lets routines know that a reset
// is in progress.
//
BOOLEAN ResetInProgress;
/*
LIST_ENTRY FramePoolHead;
LIST_ENTRY AllocPoolHead;
*/
// It will handle most file operations and transport
// operations known today. You pay about 44 bytes
// per stacksize. The registry parameter 'IrpStackSize'
// will change this default if it exists.
UCHAR IrpStackSize;
// Here we default to the ethernet max frame size
// The regsitry parameter 'MaxFrameSize' will change
// this default if it exists.
/* Note: This is meaningful only for non-PPP framing. For PPP framing the
** value is currently the hard-coded DEFAULT_PPP_MAX_FRAME_SIZE.
** See also DEFAULT_EXPANDED_PPP_MAX_FRAME_SIZE;
*/
ULONG MaxFrameSize;
//
// Number of ports this adapter owns.
//
USHORT NumPorts;
// How many frames to allocate per port.
// The registry parameter 'FramesPerPort' can change this value
USHORT FramesPerPort;
// Minimum inter character timeout
ULONG TimeoutBase;
// Tacked on to TimeoutBase based on the baud rate
ULONG TimeoutBaud;
// Timeout to use to resync if a frame is dropped
ULONG TimeoutReSync;
//
// Serial driver should only complete sends when the
// data hits the wire
//
ULONG WriteBufferingEnabled;
//
// Used to flag if we should escape the XON/XOFF characters
// with the parity bit set (0x91, 0x93)
//
ULONG ExtendedXOnXOff;
NPAGED_LOOKASIDE_LIST AsyncFrameList;
};
//
// Define Maximum number of bytes a protocol can read during a
// receive data indication.
//
#define ASYNC_MAX_LOOKAHEAD DEFAULT_MAX_FRAME_SIZE
typedef struct _ASYNC_IO_CTX {
BOOLEAN Sync;
KEVENT Event; // use this event to signal completion
IO_STATUS_BLOCK IoStatus; // use this to store Irp status
PVOID Context;
union {
SERIAL_STATUS SerialStatus;
SERIAL_QUEUE_SIZE SerialQueueSize;
SERIAL_TIMEOUTS SerialTimeouts;
SERIAL_CHARS SerialChars;
SERIAL_COMMPROP CommProperties;
UCHAR EscapeChar;
UCHAR SerialPurge;
ULONG WaitMask;
ULONG WriteBufferingEnabled;
};
} ASYNC_IO_CTX, *PASYNC_IO_CTX;
//
// This macro will act a "epilogue" to every routine in the
// *interface*. It will check whether any requests need
// to defer their processing. It will also decrement the reference
// count on the adapter.
//
// NOTE: This really does nothing now since there is no DPC for the AsyncMac.
// --tommyd
//
// Note that we don't need to include checking for blocked receives
// since blocked receives imply that there will eventually be an
// interrupt.
//
// NOTE: This macro assumes that it is called with the lock acquired.
//
// ZZZ This routine is NT specific.
//
#define ASYNC_DO_DEFERRED(Adapter) \
{ \
PASYNC_ADAPTER _A = (Adapter); \
_A->References--; \
NdisReleaseSpinLock(&_A->Lock); \
}
//
// We define the external interfaces to the async driver.
// These routines are only external to permit separate
// compilation. Given a truely fast compiler they could
// all reside in a single file and be static.
//
NTSTATUS
AsyncSendPacket(
IN PASYNC_INFO AsyncInfo,
IN PNDIS_WAN_PACKET WanPacket);
VOID
AsyncIndicateFragment(
IN PASYNC_INFO pInfo,
IN ULONG Error);
NTSTATUS
AsyncStartReads(
PASYNC_INFO pInfo);
NTSTATUS
AsyncSetupIrp(
IN PASYNC_FRAME Frame,
IN PIRP irp);
VOID
SetSerialStuff(
PIRP irp,
PASYNC_INFO pInfo,
ULONG linkSpeed);
VOID
CancelSerialRequests(
PASYNC_INFO pInfo);
VOID
SetSerialTimeouts(
PASYNC_INFO pInfo,
ULONG linkSpeed);
VOID
SerialSetEscapeChar(
PASYNC_INFO pInfo,
UCHAR EscapeChar);
VOID
SerialSetWaitMask(
PASYNC_INFO pInfo,
ULONG WaitMask);
VOID
SerialSetEventChar(
PASYNC_INFO pInfo,
UCHAR EventChar);
VOID
InitSerialIrp(
PIRP irp,
PASYNC_INFO pInfo,
ULONG IoControlCode,
ULONG InputBufferLength);
NTSTATUS
AsyncAllocateFrames(
IN PASYNC_ADAPTER Adapter,
IN UINT NumOfFrames);
VOID
AsyncSendLineUp(
PASYNC_INFO pInfo);
//
// mp.c
//
VOID
MpHalt(
IN NDIS_HANDLE MiniportAdapterContext
);
NDIS_STATUS
MpInit(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE WrapperConfigurationContext
);
NDIS_STATUS
MpQueryInfo(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded
);
NDIS_STATUS
MpReconfigure(
OUT PNDIS_STATUS OpenErrorStatus,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE WrapperConfigurationContext
);
NDIS_STATUS
MpReset(
OUT PBOOLEAN AddressingReset,
IN NDIS_HANDLE MiniportAdapterContext
);
NDIS_STATUS
MpSend(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE NdisLinkHandle,
IN PNDIS_WAN_PACKET Packet
);
NDIS_STATUS
MpSetInfo(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded
);
//
// crc.c
//
USHORT
CalcCRC(
PUCHAR Frame,
UINT FrameSize);
//
// pppcrc.c
//
USHORT
CalcCRCPPP(
PUCHAR cp,
UINT len);
//
// init.c
//
VOID
AsyncSetupExternalNaming(
PDRIVER_OBJECT DriverObject
);
VOID
AsyncCleanupExternalNaming(VOID);
//
// io.c
//
PASYNC_IO_CTX
AsyncAllocateIoCtx(
BOOLEAN AllocateSync,
PVOID Context
);
VOID
AsyncFreeIoCtx(
PASYNC_IO_CTX AsyncIoCtx
);
//
// chkcomm.c
//
VOID
AsyncCheckCommStatus(
IN PASYNC_INFO pInfo);
//
// send.c
//
NDIS_STATUS
AsyncTryToSendPacket(
IN NDIS_HANDLE MacBindingHandle,
IN PASYNC_INFO AsyncInfo,
IN PASYNC_ADAPTER Adapter);
//
// pppread.c
//
NTSTATUS
AsyncPPPWaitMask(
IN PASYNC_INFO Info);
NTSTATUS
AsyncPPPRead(
IN PASYNC_INFO Info);
//
// irps.c
//
VOID
AsyncCancelQueued(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
VOID
AsyncCancelAllQueued(
PLIST_ENTRY QueueToCancel);
VOID
AsyncQueueIrp(
PLIST_ENTRY Queue,
PIRP Irp);
BOOLEAN
TryToCompleteDDCDIrp(
PASYNC_INFO pInfo);
//
// pppframe.c
//
VOID
AssemblePPPFrame(
PNDIS_WAN_PACKET Packet);
//
// slipframe.c
//
VOID
AssembleSLIPFrame(
PNDIS_WAN_PACKET Packet);
VOID
AssembleRASFrame(
PNDIS_WAN_PACKET Packet);
//
// serial.c
//
NTSTATUS
SerialIoSyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context);
NTSTATUS
SerialIoAsyncCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context);
//
// asyncmac.c
//
NTSTATUS
AsyncDriverDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
AsyncDriverCreate(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);
NTSTATUS
AsyncDriverCleanup(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);
#endif // _ASYNCSFT_