1024 lines
29 KiB
C
1024 lines
29 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1992-2001 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
mux.h
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Data structures, defines and function prototypes for the MUX driver.
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Kernel mode only.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#ifdef NDIS51_MINIPORT
|
||
|
#define MUX_MAJOR_NDIS_VERSION 5
|
||
|
#define MUX_MINOR_NDIS_VERSION 1
|
||
|
#else
|
||
|
#define MUX_MAJOR_NDIS_VERSION 4
|
||
|
#define MUX_MINOR_NDIS_VERSION 0
|
||
|
#endif
|
||
|
|
||
|
#ifdef NDIS51
|
||
|
#define MUX_PROT_MAJOR_NDIS_VERSION 5
|
||
|
#define MUX_PROT_MINOR_NDIS_VERSION 0
|
||
|
#else
|
||
|
#define MUX_PROT_MAJOR_NDIS_VERSION 4
|
||
|
#define MUX_PROT_MINOR_NDIS_VERSION 0
|
||
|
#endif
|
||
|
|
||
|
#define TAG 'SxuM'
|
||
|
#define WAIT_INFINITE 0
|
||
|
|
||
|
#if DBG
|
||
|
//
|
||
|
// Debug levels: lower values indicate higher urgency
|
||
|
//
|
||
|
#define MUX_EXTRA_LOUD 20
|
||
|
#define MUX_VERY_LOUD 10
|
||
|
#define MUX_LOUD 8
|
||
|
#define MUX_INFO 6
|
||
|
#define MUX_WARN 4
|
||
|
#define MUX_ERROR 2
|
||
|
#define MUX_FATAL 0
|
||
|
|
||
|
extern INT muxDebugLevel;
|
||
|
|
||
|
|
||
|
#define DBGPRINT(lev, Fmt) \
|
||
|
{ \
|
||
|
if ((lev) <= muxDebugLevel) \
|
||
|
{ \
|
||
|
DbgPrint("MUX-IM: "); \
|
||
|
DbgPrint Fmt; \
|
||
|
} \
|
||
|
}
|
||
|
#else
|
||
|
|
||
|
#define DBGPRINT(lev, Fmt)
|
||
|
|
||
|
#endif //DBG
|
||
|
|
||
|
// forward declarations
|
||
|
typedef struct _ADAPT ADAPT, *PADAPT;
|
||
|
typedef struct _VELAN VELAN, *PVELAN;
|
||
|
typedef struct _MUX_NDIS_REQUEST MUX_NDIS_REQUEST, *PMUX_NDIS_REQUEST;
|
||
|
|
||
|
|
||
|
typedef
|
||
|
VOID
|
||
|
(*PMUX_REQ_COMPLETE_HANDLER) (
|
||
|
IN PADAPT pAdapt,
|
||
|
IN struct _MUX_NDIS_REQUEST * pMuxRequest,
|
||
|
IN NDIS_STATUS Status
|
||
|
);
|
||
|
|
||
|
// This OID specifies the NDIS version in use by the
|
||
|
// virtual miniport driver. The high byte is the major version.
|
||
|
// The low byte is the minor version.
|
||
|
#define VELAN_DRIVER_VERSION ((MUX_MAJOR_NDIS_VERSION << 8) + \
|
||
|
(MUX_MINOR_NDIS_VERSION))
|
||
|
|
||
|
// media type, we use ethernet, change if necessary
|
||
|
#define VELAN_MEDIA_TYPE NdisMedium802_3
|
||
|
|
||
|
// change to your company name instead of using Microsoft
|
||
|
#define VELAN_VENDOR_DESC "Microsoft"
|
||
|
|
||
|
// Highest byte is the NIC byte plus three vendor bytes, they are normally
|
||
|
// obtained from the NIC
|
||
|
#define VELAN_VENDOR_ID 0x00FFFFFF
|
||
|
|
||
|
#define VELAN_MAX_MCAST_LIST 32
|
||
|
#define VELAN_MAX_SEND_PKTS 5
|
||
|
|
||
|
#define ETH_MAX_PACKET_SIZE 1514
|
||
|
#define ETH_MIN_PACKET_SIZE 60
|
||
|
#define ETH_HEADER_SIZE 14
|
||
|
|
||
|
|
||
|
#define VELAN_SUPPORTED_FILTERS ( \
|
||
|
NDIS_PACKET_TYPE_DIRECTED | \
|
||
|
NDIS_PACKET_TYPE_MULTICAST | \
|
||
|
NDIS_PACKET_TYPE_BROADCAST | \
|
||
|
NDIS_PACKET_TYPE_PROMISCUOUS | \
|
||
|
NDIS_PACKET_TYPE_ALL_MULTICAST)
|
||
|
|
||
|
#define MUX_ADAPTER_PACKET_FILTER \
|
||
|
NDIS_PACKET_TYPE_PROMISCUOUS
|
||
|
|
||
|
//
|
||
|
// Define flag bits we set on send packets to prevent
|
||
|
// loopback from occurring on the lower binding.
|
||
|
//
|
||
|
#ifdef NDIS51
|
||
|
|
||
|
#define MUX_SEND_PACKET_FLAGS NDIS_FLAGS_DONT_LOOPBACK
|
||
|
|
||
|
#else
|
||
|
|
||
|
#define NDIS_FLAGS_SKIP_LOOPBACK_WIN2K 0x400
|
||
|
#define MUX_SEND_PACKET_FLAGS (NDIS_FLAGS_DONT_LOOPBACK | \
|
||
|
NDIS_FLAGS_SKIP_LOOPBACK_WIN2K)
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define MIN_PACKET_POOL_SIZE 255
|
||
|
#define MAX_PACKET_POOL_SIZE 4096
|
||
|
|
||
|
typedef UCHAR MUX_MAC_ADDRESS[6];
|
||
|
|
||
|
//
|
||
|
// Our context stored in packets sent down to the
|
||
|
// lower binding. Note that this sample driver only forwards
|
||
|
// sends down; it does not originate sends itself.
|
||
|
// These packets are allocated from the SendPacketPool.
|
||
|
//
|
||
|
typedef struct _MUX_SEND_RSVD
|
||
|
{
|
||
|
PVELAN pVElan; // originating ELAN
|
||
|
PNDIS_PACKET pOriginalPacket; // original packet
|
||
|
|
||
|
} MUX_SEND_RSVD, *PMUX_SEND_RSVD;
|
||
|
|
||
|
#define MUX_RSVD_FROM_SEND_PACKET(_pPkt) \
|
||
|
((PMUX_SEND_RSVD)(_pPkt)->ProtocolReserved)
|
||
|
|
||
|
//
|
||
|
// Our context stored in each packet forwarded up to an
|
||
|
// ELAN from a lower binding. The original packet refers to
|
||
|
// a packet indicated up to us that should be returned via
|
||
|
// NdisReturnPackets when our packet is returned to us. This
|
||
|
// is set to NULL there isn't such a packet.
|
||
|
// These packets are allocated from the RecvPacketPool.
|
||
|
//
|
||
|
typedef struct _MUX_RECV_RSVD
|
||
|
{
|
||
|
PNDIS_PACKET pOriginalPacket;
|
||
|
|
||
|
} MUX_RECV_RSVD, *PMUX_RECV_RSVD;
|
||
|
|
||
|
#define MUX_RSVD_FROM_RECV_PACKET(_pPkt) \
|
||
|
((PMUX_RECV_RSVD)(_pPkt)->MiniportReserved)
|
||
|
|
||
|
//
|
||
|
// Make sure we don't attempt to use more than the allowed
|
||
|
// room in MiniportReserved on received packets.
|
||
|
//
|
||
|
C_ASSERT(sizeof(MUX_RECV_RSVD) <= sizeof(((PNDIS_PACKET)0)->MiniportReserved));
|
||
|
|
||
|
|
||
|
//
|
||
|
// Out context stored in each packet that we use to forward
|
||
|
// a TransferData request to the lower binding.
|
||
|
// These packets are allocated from the RecvPacketPool.
|
||
|
//
|
||
|
typedef struct _MUX_TD_RSVD
|
||
|
{
|
||
|
PVELAN pVElan;
|
||
|
PNDIS_PACKET pOriginalPacket;
|
||
|
} MUX_TD_RSVD, *PMUX_TD_RSVD;
|
||
|
|
||
|
#define MUX_RSVD_FROM_TD_PACKET(_pPkt) \
|
||
|
((PMUX_TD_RSVD)(_pPkt)->ProtocolReserved)
|
||
|
|
||
|
|
||
|
//
|
||
|
// Default values:
|
||
|
//
|
||
|
#define MUX_DEFAULT_LINK_SPEED 100000 // in 100s of bits/sec
|
||
|
#define MUX_DEFAULT_LOOKAHEAD_SIZE 512
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
DriverEntry(
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PUNICODE_STRING RegistryPath
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
PtDispatch(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
);
|
||
|
|
||
|
NDIS_STATUS
|
||
|
PtRegisterDevice(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
NDIS_STATUS
|
||
|
PtDeregisterDevice(
|
||
|
VOID
|
||
|
);
|
||
|
//
|
||
|
// Protocol proto-types
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
PtOpenAdapterComplete(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN NDIS_STATUS Status,
|
||
|
IN NDIS_STATUS OpenErrorStatus
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtQueryAdapterInfo(
|
||
|
IN PADAPT pAdapt
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtQueryAdapterSync(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN NDIS_OID Oid,
|
||
|
IN PVOID InformationBuffer,
|
||
|
IN ULONG InformationBufferLength
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtRequestAdapterAsync(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN NDIS_REQUEST_TYPE RequestType,
|
||
|
IN NDIS_OID Oid,
|
||
|
IN PVOID InformationBuffer,
|
||
|
IN ULONG InformationBufferLength,
|
||
|
IN PMUX_REQ_COMPLETE_HANDLER pCallback
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
PtCloseAdapterComplete(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN NDIS_STATUS Status
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtResetComplete(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN NDIS_STATUS Status
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtRequestComplete(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN PNDIS_REQUEST NdisRequest,
|
||
|
IN NDIS_STATUS Status
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtCompleteForwardedRequest(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN PMUX_NDIS_REQUEST pMuxNdisRequest,
|
||
|
IN NDIS_STATUS Status
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
PtPostProcessPnPCapabilities(
|
||
|
IN PVELAN pVElan,
|
||
|
IN PVOID InformationBuffer,
|
||
|
IN ULONG InformationBufferLength
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
PtCompleteBlockingRequest(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN PMUX_NDIS_REQUEST pMuxNdisRequest,
|
||
|
IN NDIS_STATUS Status
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
PtDiscardCompletedRequest(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN PMUX_NDIS_REQUEST pMuxNdisRequest,
|
||
|
IN NDIS_STATUS Status
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtStatus(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN NDIS_STATUS GeneralStatus,
|
||
|
IN PVOID StatusBuffer,
|
||
|
IN UINT StatusBufferSize
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtStatusComplete(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtSendComplete(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN PNDIS_PACKET Packet,
|
||
|
IN NDIS_STATUS Status
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtTransferDataComplete(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN PNDIS_PACKET Packet,
|
||
|
IN NDIS_STATUS Status,
|
||
|
IN UINT BytesTransferred
|
||
|
);
|
||
|
|
||
|
|
||
|
NDIS_STATUS
|
||
|
PtReceive(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN NDIS_HANDLE MacReceiveContext,
|
||
|
IN PVOID HeaderBuffer,
|
||
|
IN UINT HeaderBufferSize,
|
||
|
IN PVOID LookAheadBuffer,
|
||
|
IN UINT LookaheadBufferSize,
|
||
|
IN UINT PacketSize
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtReceiveComplete(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext
|
||
|
);
|
||
|
|
||
|
|
||
|
INT
|
||
|
PtReceivePacket(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN PNDIS_PACKET Packet
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtBindAdapter(
|
||
|
OUT PNDIS_STATUS Status,
|
||
|
IN NDIS_HANDLE BindContext,
|
||
|
IN PNDIS_STRING DeviceName,
|
||
|
IN PVOID SystemSpecific1,
|
||
|
IN PVOID SystemSpecific2
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtUnbindAdapter(
|
||
|
OUT PNDIS_STATUS Status,
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN NDIS_HANDLE UnbindContext
|
||
|
);
|
||
|
|
||
|
|
||
|
|
||
|
NDIS_STATUS
|
||
|
PtPNPHandler(
|
||
|
IN NDIS_HANDLE ProtocolBindingContext,
|
||
|
IN PNET_PNP_EVENT pNetPnPEvent
|
||
|
);
|
||
|
|
||
|
|
||
|
NDIS_STATUS
|
||
|
PtCreateAndStartVElan(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN PNDIS_STRING pVElanKey
|
||
|
);
|
||
|
|
||
|
PVELAN
|
||
|
PtAllocateAndInitializeVElan(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN PNDIS_STRING pVElanKey
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
PtDeallocateVElan(
|
||
|
IN PVELAN pVElan
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
PtStopVElan(
|
||
|
IN PVELAN pVElan
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
PtUnlinkVElanFromAdapter(
|
||
|
IN PVELAN pVElan
|
||
|
);
|
||
|
|
||
|
PVELAN
|
||
|
PtFindVElan(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN PNDIS_STRING pElanKey
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PtBootStrapVElans(
|
||
|
IN PADAPT pAdapt
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
PtReferenceVElan(
|
||
|
IN PVELAN pVElan,
|
||
|
IN PUCHAR String
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
PtDereferenceVElan(
|
||
|
IN PVELAN pVElan,
|
||
|
IN PUCHAR String
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
PtReferenceAdapter(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN PUCHAR String
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
PtDereferenceAdapter(
|
||
|
IN PADAPT pAdapt,
|
||
|
IN PUCHAR String
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Miniport proto-types
|
||
|
//
|
||
|
NDIS_STATUS
|
||
|
MPInitialize(
|
||
|
OUT PNDIS_STATUS OpenErrorStatus,
|
||
|
OUT PUINT SelectedMediumIndex,
|
||
|
IN PNDIS_MEDIUM MediumArray,
|
||
|
IN UINT MediumArraySize,
|
||
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
||
|
IN NDIS_HANDLE WrapperConfigurationContext
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
MPSendPackets(
|
||
|
IN NDIS_HANDLE MiniportAdapterContext,
|
||
|
IN PPNDIS_PACKET PacketArray,
|
||
|
IN UINT NumberOfPackets
|
||
|
);
|
||
|
|
||
|
NDIS_STATUS
|
||
|
MPQueryInformation(
|
||
|
IN NDIS_HANDLE MiniportAdapterContext,
|
||
|
IN NDIS_OID Oid,
|
||
|
IN PVOID InformationBuffer,
|
||
|
IN ULONG InformationBufferLength,
|
||
|
OUT PULONG BytesWritten,
|
||
|
OUT PULONG BytesNeeded
|
||
|
);
|
||
|
|
||
|
NDIS_STATUS
|
||
|
MPSetInformation(
|
||
|
IN NDIS_HANDLE MiniportAdapterContext,
|
||
|
IN NDIS_OID Oid,
|
||
|
IN PVOID InformationBuffer,
|
||
|
IN ULONG InformationBufferLength,
|
||
|
OUT PULONG BytesRead,
|
||
|
OUT PULONG BytesNeeded
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
MPReturnPacket(
|
||
|
IN NDIS_HANDLE MiniportAdapterContext,
|
||
|
IN PNDIS_PACKET Packet
|
||
|
);
|
||
|
|
||
|
NDIS_STATUS
|
||
|
MPTransferData(
|
||
|
OUT PNDIS_PACKET Packet,
|
||
|
OUT PUINT BytesTransferred,
|
||
|
IN NDIS_HANDLE MiniportAdapterContext,
|
||
|
IN NDIS_HANDLE MiniportReceiveContext,
|
||
|
IN UINT ByteOffset,
|
||
|
IN UINT BytesToTransfer
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
MPHalt(
|
||
|
IN NDIS_HANDLE MiniportAdapterContext
|
||
|
);
|
||
|
|
||
|
|
||
|
NDIS_STATUS
|
||
|
MPSetPacketFilter(
|
||
|
IN PVELAN pVElan,
|
||
|
IN ULONG PacketFilter
|
||
|
);
|
||
|
|
||
|
NDIS_STATUS
|
||
|
MPSetMulticastList(
|
||
|
IN PVELAN pVElan,
|
||
|
IN PVOID InformationBuffer,
|
||
|
IN ULONG InformationBufferLength,
|
||
|
OUT PULONG pBytesRead,
|
||
|
OUT PULONG pBytesNeeded
|
||
|
);
|
||
|
|
||
|
PUCHAR
|
||
|
MacAddrToString(PVOID In
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
MPGenerateMacAddr(
|
||
|
PVELAN pVElan
|
||
|
);
|
||
|
|
||
|
#ifdef NDIS51_MINIPORT
|
||
|
|
||
|
VOID
|
||
|
MPCancelSendPackets(
|
||
|
IN NDIS_HANDLE MiniportAdapterContext,
|
||
|
IN PVOID CancelId
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
MPDevicePnPEvent(
|
||
|
IN NDIS_HANDLE MiniportAdapterContext,
|
||
|
IN NDIS_DEVICE_PNP_EVENT DevicePnPEvent,
|
||
|
IN PVOID InformationBuffer,
|
||
|
IN ULONG InformationBufferLength
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
MPAdapterShutdown(
|
||
|
IN NDIS_HANDLE MiniportAdapterContext
|
||
|
);
|
||
|
|
||
|
#endif //NDIS51_MINIPORT
|
||
|
|
||
|
VOID
|
||
|
MPUnload(
|
||
|
IN PDRIVER_OBJECT DriverObject
|
||
|
);
|
||
|
|
||
|
NDIS_STATUS
|
||
|
MPForwardRequest(
|
||
|
IN PVELAN pVElan,
|
||
|
IN NDIS_REQUEST_TYPE RequestType,
|
||
|
IN NDIS_OID Oid,
|
||
|
IN PVOID InformationBuffer,
|
||
|
IN ULONG InformationBufferLength,
|
||
|
OUT PULONG BytesReadOrWritten,
|
||
|
OUT PULONG BytesNeeded
|
||
|
);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Super-structure for NDIS_REQUEST, to allow us to keep context
|
||
|
// about requests sent down to a lower binding.
|
||
|
//
|
||
|
typedef struct _MUX_NDIS_REQUEST
|
||
|
{
|
||
|
PVELAN pVElan; // Set iff this is a forwarded
|
||
|
// request from a VELAN.
|
||
|
NDIS_STATUS Status; // Completion status
|
||
|
NDIS_EVENT Event; // Used to block for completion.
|
||
|
PMUX_REQ_COMPLETE_HANDLER pCallback; // Called on completion of request
|
||
|
NDIS_REQUEST Request;
|
||
|
|
||
|
} MUX_NDIS_REQUEST, *PMUX_NDIS_REQUEST;
|
||
|
|
||
|
|
||
|
//
|
||
|
// The ADAPT object represents a binding to a lower adapter by
|
||
|
// the protocol edge of this driver. Based on the configured
|
||
|
// Upper bindings, zero or more virtual miniport devices (VELANs)
|
||
|
// are created above this binding.
|
||
|
//
|
||
|
typedef struct _ADAPT
|
||
|
{
|
||
|
// Chain adapters. Access to this is protected by the global lock.
|
||
|
LIST_ENTRY Link;
|
||
|
|
||
|
// References to this adapter.
|
||
|
ULONG RefCount;
|
||
|
|
||
|
// Handle to the lower adapter, used in NDIS calls referring
|
||
|
// to this adapter.
|
||
|
NDIS_HANDLE BindingHandle;
|
||
|
|
||
|
// List of all the virtual ELANs created on this lower binding
|
||
|
LIST_ENTRY VElanList;
|
||
|
|
||
|
// Length of above list.
|
||
|
ULONG VElanCount;
|
||
|
|
||
|
// String used to access configuration for this binding.
|
||
|
NDIS_STRING ConfigString;
|
||
|
|
||
|
// Open Status. Used by bind/halt for Open/Close Adapter status.
|
||
|
NDIS_STATUS Status;
|
||
|
|
||
|
NDIS_EVENT Event;
|
||
|
|
||
|
//
|
||
|
// Packet filter set to the underlying adapter. This is
|
||
|
// a combination (union) of filter bits set on all
|
||
|
// attached VELAN miniports.
|
||
|
//
|
||
|
ULONG PacketFilter;
|
||
|
|
||
|
// Medium of the underlying Adapter.
|
||
|
NDIS_MEDIUM Medium;
|
||
|
|
||
|
// Link speed of the underlying adapter.
|
||
|
ULONG LinkSpeed;
|
||
|
|
||
|
// Max lookahead size for the underlying adapter.
|
||
|
ULONG MaxLookAhead;
|
||
|
|
||
|
// Power state of the underlying adapter
|
||
|
NDIS_DEVICE_POWER_STATE PtDevicePowerState;
|
||
|
|
||
|
// Ethernet address of the underlying adapter.
|
||
|
UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS];
|
||
|
|
||
|
#ifndef WIN9X
|
||
|
//
|
||
|
// Read/Write lock: allows multiple readers but only a single
|
||
|
// writer. Used to protect the VELAN list and fields (e.g. packet
|
||
|
// filter) shared on an ADAPT by multiple VELANs. Code that
|
||
|
// needs to traverse the VELAN list safely acquires a READ lock.
|
||
|
// Code that needs to safely modify the VELAN list or shared
|
||
|
// fields acquires a WRITE lock (which also excludes READers).
|
||
|
//
|
||
|
// See macros MUX_ACQUIRE_ADAPT_xxx/MUX_RELEASE_ADAPT_xxx below.
|
||
|
//
|
||
|
// TBD - if we want to support this on Win9X, reimplement this!
|
||
|
//
|
||
|
NDIS_RW_LOCK ReadWriteLock;
|
||
|
#endif // WIN9X
|
||
|
|
||
|
} ADAPT, *PADAPT;
|
||
|
|
||
|
|
||
|
//
|
||
|
// VELAN object represents a virtual ELAN instance and its
|
||
|
// corresponding virtual miniport adapter.
|
||
|
//
|
||
|
typedef struct _VELAN
|
||
|
{
|
||
|
// Link into parent adapter's VELAN list.
|
||
|
LIST_ENTRY Link;
|
||
|
|
||
|
// References to this VELAN.
|
||
|
ULONG RefCount;
|
||
|
|
||
|
// Parent ADAPT.
|
||
|
PADAPT pAdapt;
|
||
|
|
||
|
// Copy of BindingHandle from ADAPT.
|
||
|
NDIS_HANDLE BindingHandle;
|
||
|
|
||
|
// Adapter handle for NDIS up-calls related to this virtual miniport.
|
||
|
NDIS_HANDLE MiniportAdapterHandle;
|
||
|
|
||
|
// Virtual miniport's power state.
|
||
|
NDIS_DEVICE_POWER_STATE MPDevicePowerState;
|
||
|
|
||
|
// Has our Halt entry point been called?
|
||
|
BOOLEAN MiniportHalting;
|
||
|
|
||
|
// Do we need to indicate receive complete?
|
||
|
BOOLEAN IndicateRcvComplete;
|
||
|
|
||
|
// Do we need to indicate status complete?
|
||
|
BOOLEAN IndicateStatusComplete;
|
||
|
|
||
|
// Synchronization fields
|
||
|
BOOLEAN MiniportInitPending;
|
||
|
NDIS_EVENT MiniportInitEvent;
|
||
|
|
||
|
// Uncompleted Sends/Requests to the adapter below.
|
||
|
ULONG OutstandingSends;
|
||
|
|
||
|
// Count outstanding indications, including received
|
||
|
// packets, passed up to protocols on this VELAN.
|
||
|
ULONG OutstandingReceives;
|
||
|
|
||
|
// Packet pool for send packets
|
||
|
NDIS_HANDLE SendPacketPoolHandle;
|
||
|
|
||
|
// Packet pool for receive packets
|
||
|
NDIS_HANDLE RecvPacketPoolHandle;
|
||
|
|
||
|
// A request block that is used to forward a request presented
|
||
|
// to the virtual miniport, to the lower binding. Since NDIS
|
||
|
// serializes requests to a miniport, we only need one of these
|
||
|
// per VELAN.
|
||
|
//
|
||
|
MUX_NDIS_REQUEST Request;
|
||
|
PULONG BytesNeeded;
|
||
|
PULONG BytesReadOrWritten;
|
||
|
// Have we queued a request because the lower binding is
|
||
|
// at a low power state?
|
||
|
BOOLEAN QueuedRequest;
|
||
|
|
||
|
// Have we started to deinitialize this VELAN?
|
||
|
BOOLEAN DeInitializing;
|
||
|
|
||
|
// configuration
|
||
|
UCHAR PermanentAddress[ETH_LENGTH_OF_ADDRESS];
|
||
|
UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS];
|
||
|
|
||
|
NDIS_STRING CfgDeviceName; // used as the unique
|
||
|
// ID for the VELAN
|
||
|
ULONG VElanNumber; // logical Elan number
|
||
|
|
||
|
|
||
|
//
|
||
|
// ----- Buffer Management: Header buffers and Protocol buffers ----
|
||
|
//
|
||
|
|
||
|
// Some standard miniport parameters (OID values).
|
||
|
ULONG PacketFilter;
|
||
|
ULONG LookAhead;
|
||
|
ULONG LinkSpeed;
|
||
|
|
||
|
ULONG MaxBusySends;
|
||
|
ULONG MaxBusyRecvs;
|
||
|
|
||
|
// Packet counts
|
||
|
ULONG64 GoodTransmits;
|
||
|
ULONG64 GoodReceives;
|
||
|
ULONG NumTxSinceLastAdjust;
|
||
|
|
||
|
// Count of transmit errors
|
||
|
ULONG TxAbortExcessCollisions;
|
||
|
ULONG TxLateCollisions;
|
||
|
ULONG TxDmaUnderrun;
|
||
|
ULONG TxLostCRS;
|
||
|
ULONG TxOKButDeferred;
|
||
|
ULONG OneRetry;
|
||
|
ULONG MoreThanOneRetry;
|
||
|
ULONG TotalRetries;
|
||
|
ULONG TransmitFailuresOther;
|
||
|
|
||
|
// Count of receive errors
|
||
|
ULONG RcvCrcErrors;
|
||
|
ULONG RcvAlignmentErrors;
|
||
|
ULONG RcvResourceErrors;
|
||
|
ULONG RcvDmaOverrunErrors;
|
||
|
ULONG RcvCdtFrames;
|
||
|
ULONG RcvRuntErrors;
|
||
|
#if IEEE_VLAN_SUPPORT
|
||
|
ULONG RcvFormatErrors;
|
||
|
ULONG RcvVlanIdErrors;
|
||
|
#endif
|
||
|
ULONG RegNumTcb;
|
||
|
|
||
|
// Multicast list
|
||
|
MUX_MAC_ADDRESS McastAddrs[VELAN_MAX_MCAST_LIST];
|
||
|
ULONG McastAddrCount;
|
||
|
#if IEEE_VLAN_SUPPORT
|
||
|
ULONG VlanId;
|
||
|
NDIS_HANDLE BufferPoolHandle;
|
||
|
NPAGED_LOOKASIDE_LIST TagLookaside;
|
||
|
#endif
|
||
|
NDIS_STATUS LastIndicatedStatus;
|
||
|
NDIS_STATUS LatestUnIndicateStatus;
|
||
|
|
||
|
|
||
|
} VELAN, *PVELAN;
|
||
|
|
||
|
#if IEEE_VLAN_SUPPORT
|
||
|
|
||
|
#define TPID 0x0081
|
||
|
//
|
||
|
// Define tag_header structure
|
||
|
//
|
||
|
typedef struct _VLAN_TAG_HEADER
|
||
|
{
|
||
|
UCHAR TagInfo[2];
|
||
|
} VLAN_TAG_HEADER, *PVLAN_TAG_HEADER;
|
||
|
|
||
|
//
|
||
|
// Define context struct that used when the lower driver
|
||
|
// uses non-packet indication. It contains the original
|
||
|
// context, the tagging information and the tag-header
|
||
|
// length
|
||
|
//
|
||
|
typedef struct _MUX_RCV_CONTEXT
|
||
|
{
|
||
|
ULONG TagHeaderLen;
|
||
|
NDIS_PACKET_8021Q_INFO NdisPacket8021QInfo;
|
||
|
PVOID MacRcvContext;
|
||
|
}MUX_RCV_CONTEXT, *PMUX_RCV_CONTEXT;
|
||
|
|
||
|
//
|
||
|
// Macro definitions for VLAN support
|
||
|
//
|
||
|
#define VLAN_TAG_HEADER_SIZE 4
|
||
|
|
||
|
#define VLANID_DEFAULT 0
|
||
|
#define VLAN_ID_MAX 0xfff
|
||
|
#define VLAN_ID_MIN 0x0
|
||
|
|
||
|
#define USER_PRIORITY_MASK 0xe0
|
||
|
#define CANONICAL_FORMAT_ID_MASK 0x10
|
||
|
#define HIGH_VLAN_ID_MASK 0x0F
|
||
|
|
||
|
//
|
||
|
// Get information for tag headre
|
||
|
//
|
||
|
#define GET_CANONICAL_FORMAT_ID_FROM_TAG(_pTagHeader) \
|
||
|
( _pTagHeader->TagInfo[0] & CANONICAL_FORMAT_ID_MASK)
|
||
|
|
||
|
#define GET_USER_PRIORITY_FROM_TAG(_pTagHeader) \
|
||
|
( _pTagHeader->TagInfo[0] & USER_PRIORITY_MASK)
|
||
|
|
||
|
#define GET_VLAN_ID_FROM_TAG(_pTagHeader) \
|
||
|
(((USHORT)(_pTagHeader->TagInfo[0] & HIGH_VLAN_ID_MASK) << 8) | (USHORT)(_pTagHeader->TagInfo[1]))
|
||
|
|
||
|
//
|
||
|
// Clear the tag header struct
|
||
|
//
|
||
|
#define INITIALIZE_TAG_HEADER_TO_ZERO(_pTagHeader) \
|
||
|
{ \
|
||
|
_pTagHeader->TagInfo[0] = 0; \
|
||
|
_pTagHeader->TagInfo[1] = 0; \
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set VLAN information to tag header
|
||
|
// Before we called all the set macro, first we need to initialize pTagHeader to be 0
|
||
|
//
|
||
|
#define SET_CANONICAL_FORMAT_ID_TO_TAG(_pTagHeader, CanonicalFormatId) \
|
||
|
_pTagHeader->TagInfo[0] |= ((UCHAR)CanonicalFormatId << 4)
|
||
|
|
||
|
#define SET_USER_PRIORITY_TO_TAG(_pTagHeader, UserPriority) \
|
||
|
_pTagHeader->TagInfo[0] |= ((UCHAR)UserPriority << 5)
|
||
|
|
||
|
#define SET_VLAN_ID_TO_TAG(_pTagHeader, VlanId) \
|
||
|
{ \
|
||
|
_pTagHeader->TagInfo[0] |= (((UCHAR)VlanId >> 8) & 0x0f); \
|
||
|
_pTagHeader->TagInfo[1] |= (UCHAR)VlanId;\
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy tagging information in the indicated frame to per packet info
|
||
|
//
|
||
|
#define COPY_TAG_INFO_FROM_HEADER_TO_PACKET_INFO(_Ieee8021qInfo, _pTagHeader) \
|
||
|
{ \
|
||
|
(_Ieee8021qInfo).TagHeader.UserPriority = ((_pTagHeader->TagInfo[0] & USER_PRIORITY_MASK) >> 5); \
|
||
|
(_Ieee8021qInfo).TagHeader.CanonicalFormatId = ((_pTagHeader->TagInfo[0] & CANONICAL_FORMAT_ID_MASK) >> 4); \
|
||
|
(_Ieee8021qInfo).TagHeader.VlanId = (((USHORT)(_pTagHeader->TagInfo[0] & HIGH_VLAN_ID_MASK) << 8)| (USHORT)(_pTagHeader->TagInfo[1])); \
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function to handle tagging on sending side
|
||
|
//
|
||
|
NDIS_STATUS
|
||
|
MPHandleSendTagging(
|
||
|
IN PVELAN pVElan,
|
||
|
IN PNDIS_PACKET Packet,
|
||
|
IN OUT PNDIS_PACKET MyPacket
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Functions to handle tagging on receiving side with packet indication
|
||
|
//
|
||
|
NDIS_STATUS
|
||
|
PtHandleRcvTagging(
|
||
|
IN PVELAN pVElan,
|
||
|
IN PNDIS_PACKET Packet,
|
||
|
IN OUT PNDIS_PACKET MyPacket
|
||
|
);
|
||
|
|
||
|
#endif //IEEE_VLAN_SUPPORT
|
||
|
|
||
|
//
|
||
|
// Macro definitions for others.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Is a given power state a low-power state?
|
||
|
//
|
||
|
#define MUX_IS_LOW_POWER_STATE(_PwrState) \
|
||
|
((_PwrState) > NdisDeviceStateD0)
|
||
|
|
||
|
#define MUX_INIT_ADAPT_RW_LOCK(_pAdapt) \
|
||
|
NdisInitializeReadWriteLock(&(_pAdapt)->ReadWriteLock)
|
||
|
|
||
|
|
||
|
#define MUX_ACQUIRE_ADAPT_READ_LOCK(_pAdapt, _pLockState) \
|
||
|
NdisAcquireReadWriteLock(&(_pAdapt)->ReadWriteLock, \
|
||
|
FALSE, \
|
||
|
_pLockState)
|
||
|
|
||
|
#define MUX_RELEASE_ADAPT_READ_LOCK(_pAdapt, _pLockState) \
|
||
|
NdisReleaseReadWriteLock(&(_pAdapt)->ReadWriteLock, \
|
||
|
_pLockState)
|
||
|
|
||
|
#define MUX_ACQUIRE_ADAPT_WRITE_LOCK(_pAdapt, _pLockState) \
|
||
|
NdisAcquireReadWriteLock(&(_pAdapt)->ReadWriteLock, \
|
||
|
TRUE, \
|
||
|
_pLockState)
|
||
|
|
||
|
#define MUX_RELEASE_ADAPT_WRITE_LOCK(_pAdapt, _pLockState) \
|
||
|
NdisReleaseReadWriteLock(&(_pAdapt)->ReadWriteLock, \
|
||
|
_pLockState)
|
||
|
|
||
|
#define MUX_INCR_PENDING_RECEIVES(_pVElan) \
|
||
|
NdisInterlockedIncrement(&pVElan->OutstandingReceives)
|
||
|
|
||
|
#define MUX_DECR_PENDING_RECEIVES(_pVElan) \
|
||
|
NdisInterlockedDecrement(&pVElan->OutstandingReceives)
|
||
|
|
||
|
#define MUX_INCR_PENDING_SENDS(_pVElan) \
|
||
|
NdisInterlockedIncrement(&pVElan->OutstandingSends)
|
||
|
|
||
|
#define MUX_DECR_PENDING_SENDS(_pVElan) \
|
||
|
NdisInterlockedDecrement(&pVElan->OutstandingSends)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#define MUX_INCR_STATISTICS(_pUlongVal) \
|
||
|
NdisInterlockedIncrement(_pUlongVal)
|
||
|
|
||
|
#define MUX_INCR_STATISTICS64(_pUlong64Val) \
|
||
|
{ \
|
||
|
PLARGE_INTEGER _pLargeInt = (PLARGE_INTEGER)_pUlong64Val;\
|
||
|
if (NdisInterlockedIncrement(&_pLargeInt->LowPart) == 0) \
|
||
|
{ \
|
||
|
NdisInterlockedIncrement(&_pLargeInt->HighPart); \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#define ASSERT_AT_PASSIVE() \
|
||
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL)
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Simple Mutual Exclusion constructs used in preference to
|
||
|
// using KeXXX calls since we don't have Mutex calls in NDIS.
|
||
|
// These can only be called at passive IRQL.
|
||
|
//
|
||
|
|
||
|
typedef struct _MUX_MUTEX
|
||
|
{
|
||
|
ULONG Counter;
|
||
|
ULONG ModuleAndLine; // useful for debugging
|
||
|
|
||
|
} MUX_MUTEX, *PMUX_MUTEX;
|
||
|
|
||
|
#define MUX_INIT_MUTEX(_pMutex) \
|
||
|
{ \
|
||
|
(_pMutex)->Counter = 0; \
|
||
|
(_pMutex)->ModuleAndLine = 0; \
|
||
|
}
|
||
|
|
||
|
#define MUX_ACQUIRE_MUTEX(_pMutex) \
|
||
|
{ \
|
||
|
while (NdisInterlockedIncrement(&((_pMutex)->Counter)) != 1)\
|
||
|
{ \
|
||
|
NdisInterlockedDecrement(&((_pMutex)->Counter)); \
|
||
|
NdisMSleep(10000); \
|
||
|
} \
|
||
|
(_pMutex)->ModuleAndLine = (MODULE_NUMBER << 16) | __LINE__;\
|
||
|
}
|
||
|
|
||
|
#define MUX_RELEASE_MUTEX(_pMutex) \
|
||
|
{ \
|
||
|
(_pMutex)->ModuleAndLine = 0; \
|
||
|
NdisInterlockedDecrement(&(_pMutex)->Counter); \
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Global variables
|
||
|
//
|
||
|
extern NDIS_HANDLE ProtHandle, DriverHandle;
|
||
|
extern NDIS_MEDIUM MediumArray[1];
|
||
|
extern NDIS_SPIN_LOCK GlobalLock;
|
||
|
extern MUX_MUTEX GlobalMutex;
|
||
|
extern LIST_ENTRY AdapterList;
|
||
|
extern ULONG NextVElanNumber;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Module numbers for debugging
|
||
|
//
|
||
|
#define MODULE_MUX 'X'
|
||
|
#define MODULE_PROT 'P'
|
||
|
#define MODULE_MINI 'M'
|