Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

681 lines
18 KiB

/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
wrapper.h
Abstract:
NDIS wrapper definitions
Author:
Environment:
Kernel mode, FSD
Revision History:
Jun-95 Jameel Hyder Split up from a monolithic file
--*/
#ifndef _WRAPPPER_
#define _WRAPPPER_
#include <ntos.h>
#include <ndismain.h>
#include <ndisprot.h>
#include <ndismac.h>
#include <ndismini.h>
#include <ndisco.h>
#include <zwapi.h>
#include <ndisdbg.h>
#include <ndistags.h>
extern UCHAR ndisValidProcessors[];
extern ULONG ndisMaximumProcessor;
extern ULONG ndisCurrentProcessor;
extern UCHAR ndisInternalEaName[4];
extern UCHAR ndisInternalEaValue[8];
extern TDI_REGISTER_CALLBACK ndisTdiRegisterCallback;
extern BOOLEAN ndisSkipProcessorAffinity;
extern BOOLEAN ndisMediaTypeCl[NdisMediumMax];
#define BYTE_SWAP(_word) ((USHORT) (((_word) >> 8) | ((_word) << 8)))
#define LOW_WORD(_dword) ((USHORT) ((_dword) & 0x0000FFFF))
#define HIGH_WORD(_dword) ((USHORT) (((_dword) >> 16) & 0x0000FFFF))
#define BYTE_SWAP_ULONG(_ulong) ((ULONG)((ULONG)(BYTE_SWAP(LOW_WORD(_ulong)) << 16) + \
BYTE_SWAP(HIGH_WORD(_ulong))))
//
// A set of macros to manipulate bitmasks.
//
//VOID
//CLEAR_BIT_IN_MASK(
// IN UINT Offset,
// IN OUT PMASK MaskToClear
// )
//
///*++
//
//Routine Description:
//
// Clear a bit in the bitmask pointed to by the parameter.
//
//Arguments:
//
// Offset - The offset (from 0) of the bit to altered.
//
// MaskToClear - Pointer to the mask to be adjusted.
//
//Return Value:
//
// None.
//
//--*/
//
#define CLEAR_BIT_IN_MASK(Offset, MaskToClear) *(MaskToClear) &= (~(1 << Offset))
//VOID
//SET_BIT_IN_MASK(
// IN UINT Offset,
// IN OUT PMASK MaskToSet
// )
//
///*++
//
//Routine Description:
//
// Set a bit in the bitmask pointed to by the parameter.
//
//Arguments:
//
// Offset - The offset (from 0) of the bit to altered.
//
// MaskToSet - Pointer to the mask to be adjusted.
//
//Return Value:
//
// None.
//
//--*/
#define SET_BIT_IN_MASK(Offset, MaskToSet) *(MaskToSet) |= (1 << Offset)
//BOOLEAN
//IS_BIT_SET_IN_MASK(
// IN UINT Offset,
// IN MASK MaskToTest
// )
//
///*++
//
//Routine Description:
//
// Tests if a particular bit in the bitmask pointed to by the parameter is
// set.
//
//Arguments:
//
// Offset - The offset (from 0) of the bit to test.
//
// MaskToTest - The mask to be tested.
//
//Return Value:
//
// Returns TRUE if the bit is set.
//
//--*/
#define IS_BIT_SET_IN_MASK(Offset, MaskToTest) ((MaskToTest & (1 << Offset)) ? TRUE : FALSE)
//BOOLEAN
//IS_MASK_CLEAR(
// IN MASK MaskToTest
// )
//
///*++
//
//Routine Description:
//
// Tests whether there are *any* bits enabled in the mask.
//
//Arguments:
//
// MaskToTest - The bit mask to test for all clear.
//
//Return Value:
//
// Will return TRUE if no bits are set in the mask.
//
//--*/
#define IS_MASK_CLEAR(MaskToTest) ((MaskToTest) ? FALSE : TRUE)
//VOID
//CLEAR_MASK(
// IN OUT PMASK MaskToClear
// );
//
///*++
//
//Routine Description:
//
// Clears a mask.
//
//Arguments:
//
// MaskToClear - The bit mask to adjust.
//
//Return Value:
//
// None.
//
//--*/
#define CLEAR_MASK(MaskToClear) *(MaskToClear) = 0
//
// This constant is used for places where NdisAllocateMemory
// needs to be called and the HighestAcceptableAddress does
// not matter.
//
#define RetrieveUlong(Destination, Source) \
{ \
PUCHAR _S = (Source); \
*(Destination) = ((ULONG)(*_S) << 24) | \
((ULONG)(*(_S+1)) << 16) | \
((ULONG)(*(_S+2)) << 8) | \
((ULONG)(*(_S+3))); \
}
//
// This is the number of extra OIDs that ARCnet with Ethernet encapsulation
// supports.
//
#define ARC_NUMBER_OF_EXTRA_OIDS 2
//
// ZZZ NonPortable definitions.
//
#define AllocPhys(s, l) NdisAllocateMemory((PVOID *)(s), (l), 0, HighestAcceptableMax)
#define FreePhys(s, l) NdisFreeMemory((PVOID)(s), (l), 0)
//
// Internal wrapper data structures.
//
//
// NDIS_WRAPPER_CONTEXT
//
// This data structure contains internal data items for use by the wrapper.
//
typedef struct _NDIS_WRAPPER_CONTEXT
{
//
// Mac/miniport defined shutdown context.
//
PVOID ShutdownContext;
//
// Mac/miniport registered shutdown handler.
//
ADAPTER_SHUTDOWN_HANDLER ShutdownHandler;
//
// Kernel bugcheck record for bugcheck handling.
//
KBUGCHECK_CALLBACK_RECORD BugcheckCallbackRecord;
//
// Miniport assigned resources for PCI, PCMCIA, EISA, etc.
//
PCM_RESOURCE_LIST AssignedSlotResources;
//
// HAL common buffer cache.
//
PVOID SharedMemoryPage[2];
ULONG SharedMemoryLeft[2];
NDIS_PHYSICAL_ADDRESS SharedMemoryAddress[2];
} NDIS_WRAPPER_CONTEXT, *PNDIS_WRAPPER_CONTEXT;
//
// Arcnet specific stuff
//
#define WRAPPER_ARC_BUFFERS 8
#define WRAPPER_ARC_HEADER_SIZE 4
//
// Define constants used internally to identify regular opens from
// query global statistics ones.
//
#define NDIS_OPEN_INTERNAL 1
#define NDIS_OPEN_QUERY_STATISTICS 2
//
// This is the structure pointed to by the FsContext of an
// open used for query statistics.
//
typedef struct _NDIS_USER_OPEN_CONTEXT
{
PDEVICE_OBJECT DeviceObject;
union
{
PNDIS_MINIPORT_BLOCK MiniportBlock;
PNDIS_ADAPTER_BLOCK AdapterBlock;
};
ULONG OidCount;
PNDIS_OID OidArray;
ULONG FullOidCount;
PNDIS_OID FullOidArray;
} NDIS_USER_OPEN_CONTEXT, *PNDIS_USER_OPEN_CONTEXT;
//
// An active query single statistic request.
//
typedef struct _NDIS_QUERY_GLOBAL_REQUEST
{
PIRP Irp;
NDIS_REQUEST Request;
} NDIS_QUERY_GLOBAL_REQUEST, *PNDIS_QUERY_GLOBAL_REQUEST;
//
// An active query all statistics request.
//
typedef struct _NDIS_QUERY_ALL_REQUEST
{
PIRP Irp;
NDIS_REQUEST Request;
NDIS_STATUS NdisStatus;
KEVENT Event;
} NDIS_QUERY_ALL_REQUEST, *PNDIS_QUERY_ALL_REQUEST;
//
// An temporary request used during an open.
//
typedef struct _NDIS_QUERY_OPEN_REQUEST
{
PIRP Irp;
NDIS_REQUEST Request;
NDIS_STATUS NdisStatus;
KEVENT Event;
} NDIS_QUERY_OPEN_REQUEST, *PNDIS_QUERY_OPEN_REQUEST;
//
// An temporary request used during init
//
typedef struct _NDIS_QS_REQUEST
{
NDIS_REQUEST Request;
NDIS_STATUS NdisStatus;
KEVENT Event;
} NDIS_QS_REQUEST, *PNDIS_QS_REQUEST;
//
// Used to queue configuration parameters
//
typedef struct _NDIS_CONFIGURATION_PARAMETER_QUEUE
{
struct _NDIS_CONFIGURATION_PARAMETER_QUEUE* Next;
NDIS_CONFIGURATION_PARAMETER Parameter;
} NDIS_CONFIGURATION_PARAMETER_QUEUE, *PNDIS_CONFIGURATION_PARAMETER_QUEUE;
//
// Configuration Handle
//
typedef struct _NDIS_CONFIGURATION_HANDLE
{
PRTL_QUERY_REGISTRY_TABLE KeyQueryTable;
PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterList;
} NDIS_CONFIGURATION_HANDLE, *PNDIS_CONFIGURATION_HANDLE;
typedef struct _NDIS_REQUEST_RESERVED
{
PNDIS_REQUEST Next;
struct _NDIS_M_OPEN_BLOCK * Open;
} NDIS_REQUEST_RESERVED, *PNDIS_REQUEST_RESERVED;
#define PNDIS_RESERVED_FROM_PNDIS_REQUEST(_request) ((PNDIS_REQUEST_RESERVED)((_request)->MacReserved))
//
// This is used to keep track of pci/eisa/mca cards in the system so that
// if they move, then the bus#/slot# can be fixed up appropriately.
//
typedef struct _BUS_SLOT_DB
{
struct _BUS_SLOT_DB *Next;
NDIS_INTERFACE_TYPE BusType;
ULONG BusNumber;
ULONG SlotNumber;
ULONG BusId;
} BUS_SLOT_DB, *PBUS_SLOT_DB;
extern PBUS_SLOT_DB ndisGlobalDb;
extern KSPIN_LOCK ndisGlobalDbLock;
//
// This is used during addadapter/miniportinitialize so that when the
// driver calls any NdisImmediatexxx routines we can access its driverobj.
//
typedef struct _NDIS_WRAPPER_CONFIGURATION_HANDLE
{
RTL_QUERY_REGISTRY_TABLE ParametersQueryTable[5];
PDRIVER_OBJECT DriverObject;
PUNICODE_STRING DriverBaseName;
BUS_SLOT_DB Db;
} NDIS_WRAPPER_CONFIGURATION_HANDLE, *PNDIS_WRAPPER_CONFIGURATION_HANDLE;
//
// Describes an open NDIS file
//
//
// Context for Bind Adapter.
//
typedef struct _NDIS_BIND_CONTEXT
{
struct _NDIS_BIND_CONTEXT * Next;
PNDIS_PROTOCOL_BLOCK Protocol;
NDIS_STRING ProtocolSection;
PNDIS_STRING DeviceName;
WORK_QUEUE_ITEM WorkItem;
NDIS_STATUS BindStatus;
KEVENT Event;
KEVENT ThreadDoneEvent;
} NDIS_BIND_CONTEXT, *PNDIS_BIND_CONTEXT;
typedef struct _NDIS_FILE_DESCRIPTOR
{
PVOID Data;
KSPIN_LOCK Lock;
BOOLEAN Mapped;
} NDIS_FILE_DESCRIPTOR, *PNDIS_FILE_DESCRIPTOR;
//
// The following structure is used to queue openadapter/closeadapter calls to
// worker threads so that they can complete at LOW_LEVEL.
//
typedef struct _QUEUED_OPEN_CLOSE
{
PNDIS_OPEN_BLOCK OpenP;
NDIS_STATUS Status;
NDIS_STATUS OpenErrorStatus;
WORK_QUEUE_ITEM WorkItem;
BOOLEAN FreeIt;
} QUEUED_OPEN_CLOSE, *PQUEUED_OPEN_CLOSE;
typedef struct _QueuedProtocolNotification
{
WORK_QUEUE_ITEM WorkItem;
PNDIS_M_DRIVER_BLOCK MiniBlock;
UNICODE_STRING UpCaseDeviceInstance;
WCHAR Buffer[1];
} QUEUED_PROTOCOL_NOTIFICATION, *PQUEUED_PROTOCOL_NOTIFICATION;
#if defined(_ALPHA_)
typedef struct _NDIS_LOOKAHEAD_ELEMENT
{
ULONG Length;
struct _NDIS_LOOKAHEAD_ELEMENT *Next;
} NDIS_LOOKAHEAD_ELEMENT, *PNDIS_LOOKAHEAD_ELEMENT;
#endif
typedef struct _PKG_REF
{
KSPIN_LOCK ReferenceLock;
ULONG ReferenceCount;
PVOID ImageHandle;
KEVENT PagedInEvent;
} PKG_REF, *PPKG_REF;
//
// Structures for dealing with making the module specific routines pagable
//
extern PKG_REF ProtocolPkg;
extern PKG_REF MacPkg;
extern PKG_REF CoPkg;
extern PKG_REF InitPkg;
extern PKG_REF PnPPkg;
extern PKG_REF MiniportPkg;
extern PKG_REF ArcPkg;
extern PKG_REF EthPkg;
extern PKG_REF TrPkg;
extern PKG_REF FddiPkg;
extern PNDIS_PROTOCOL_BLOCK ndisProtocolList;
//
// Work item structure
//
typedef struct _NDIS_MINIPORT_WORK_ITEM
{
//
// Link for the list of work items of this type.
//
SINGLE_LIST_ENTRY Link;
//
// type of work item and context information.
//
NDIS_WORK_ITEM_TYPE WorkItemType;
PVOID WorkItemContext1;
PVOID WorkItemContext2;
} NDIS_MINIPORT_WORK_ITEM, *PNDIS_MINIPORT_WORK_ITEM;
//
// This does most of the work of dequeueing a workitem.
//
#define NDISM_DEQUEUE_WORK_ITEM_MACRO(_M, _WT, _pWC1, _pWC2) \
{ \
}
#define NDISM_QUEUE_WORK_ITEM_MACRO(_M, _WT, _WC1, _WC2, _pS) \
{ \
PSINGLE_LIST_ENTRY _Link; \
PNDIS_MINIPORT_WORK_ITEM _WorkItem; \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("==>ndisMQueueWorkItem()\n")); \
\
_Link = PopEntryList(&(_M)->SingleWorkItems[(_WT)]); \
if (NULL != _Link) \
{ \
_WorkItem = CONTAINING_RECORD(_Link, NDIS_MINIPORT_WORK_ITEM, Link); \
_WorkItem->WorkItemType = (_WT); \
_WorkItem->WorkItemContext1 = (_WC1); \
_WorkItem->WorkItemContext2 = (_WC2); \
PushEntryList(&(_M)->WorkQueue[(_WT)], _Link); \
*(_pS) = NDIS_STATUS_SUCCESS; \
} \
else \
{ \
*(_pS) = NDIS_STATUS_NOT_ACCEPTED; \
} \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("<==ndisMQueueWorkItem()\n")); \
}
#define NDISM_QUEUE_WORK_ITEM_FULL_DUPLEX_MACRO(_M, _WT, _WC1, _WC2, _pS) \
{ \
PSINGLE_LIST_ENTRY _Link; \
PNDIS_MINIPORT_WORK_ITEM _WorkItem; \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("==>ndisMQueueWorkItemFullDuplex()\n")); \
\
ACQUIRE_SPIN_LOCK_DPC(&(_M)->WorkLock); \
\
_Link = PopEntryList(&(_M)->SingleWorkItems[(_WT)]); \
if (NULL != _Link) \
{ \
_WorkItem = CONTAINING_RECORD(_Link, NDIS_MINIPORT_WORK_ITEM, Link); \
_WorkItem->WorkItemType = (_WT); \
_WorkItem->WorkItemContext1 = (_WC1); \
_WorkItem->WorkItemContext2 = (_WC2); \
PushEntryList(&(_M)->WorkQueue[(_WT)], \
_Link); \
\
*(_pS) = NDIS_STATUS_SUCCESS; \
} \
else \
{ \
*(_pS) = NDIS_STATUS_NOT_ACCEPTED; \
} \
\
RELEASE_SPIN_LOCK_DPC(&(_M)->WorkLock); \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("<==ndisMQueueWorkItemFullDuplex()\n")); \
}
#define NDISM_QUEUE_NEW_WORK_ITEM_MACRO(_M, _WT, _WC1, _WC2, _pS) \
{ \
PSINGLE_LIST_ENTRY _Link; \
PNDIS_MINIPORT_WORK_ITEM _WorkItem; \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("==>ndisMQueueNewWorkItem()\n")); \
\
ASSERT(((_WT) < NUMBER_OF_WORK_ITEM_TYPES) && ((_WT) > NUMBER_OF_SINGLE_WORK_ITEMS)); \
\
do \
{ \
_Link = PopEntryList(&(_M)->WorkItemFreeQueue); \
if (NULL == _Link) \
{ \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("Allocate a workitem from the pool.\n")); \
\
_WorkItem = ALLOC_FROM_POOL(sizeof(NDIS_MINIPORT_WORK_ITEM), NDIS_TAG_WORK_ITEM);\
if (NULL == _WorkItem) \
{ \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL, \
("Failed to allocate a workitem from the pool!\n")); \
DBGBREAK(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL); \
\
*(_pS) = NDIS_STATUS_FAILURE; \
\
break; \
} \
(_M)->NumberOfAllocatedWorkItems++; \
} \
else \
{ \
_WorkItem = CONTAINING_RECORD(_Link, NDIS_MINIPORT_WORK_ITEM, Link); \
} \
\
ZeroMemory(_WorkItem, sizeof(NDIS_MINIPORT_WORK_ITEM)); \
_WorkItem->WorkItemType = (_WT); \
_WorkItem->WorkItemContext1 = (_WC1); \
_WorkItem->WorkItemContext2 = (_WC2); \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("WorkItem 0x%x\n", _WorkItem)); \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("WorkItem Type 0x%x\n", (_WT))); \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("WorkItem Context2 0x%x\n", (_WC1))); \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("WorkItem Context1 0x%x\n", (_WC2))); \
\
PushEntryList(&(_M)->WorkQueue[(_WT)], &_WorkItem->Link); \
\
*(_pS) = NDIS_STATUS_SUCCESS; \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("<==ndisMQueueNewWorkItem()\n")); \
} while (FALSE); \
}
#define NDISM_QUEUE_NEW_WORK_ITEM_FULL_DUPLEX_MACRO(_M, _WT, _WC1, _WC2, _pS) \
{ \
PSINGLE_LIST_ENTRY _Link; \
PNDIS_MINIPORT_WORK_ITEM _WorkItem; \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("==>ndisMQueueNewWorkItemFullDuplex()\n")); \
\
ASSERT(((_WT) < NUMBER_OF_WORK_ITEM_TYPES) && ((_WT) > NUMBER_OF_SINGLE_WORK_ITEMS)); \
\
ACQUIRE_SPIN_LOCK_DPC(&(_M)->WorkLock); \
\
do \
{ \
_Link = PopEntryList(&(_M)->WorkItemFreeQueue); \
if (NULL == _Link) \
{ \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("Allocate a workitem from the pool.\n")); \
\
_WorkItem = ALLOC_FROM_POOL(sizeof(NDIS_MINIPORT_WORK_ITEM), NDIS_TAG_WORK_ITEM);\
if (NULL == _WorkItem) \
{ \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL, \
("Failed to allocate a workitem from the pool!\n")); \
DBGBREAK(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL); \
\
*(_pS) = NDIS_STATUS_FAILURE; \
\
break; \
} \
\
(_M)->NumberOfAllocatedWorkItems++; \
} \
else \
{ \
_WorkItem = CONTAINING_RECORD(_Link, NDIS_MINIPORT_WORK_ITEM, Link); \
} \
\
ZeroMemory(_WorkItem, sizeof(NDIS_MINIPORT_WORK_ITEM)); \
_WorkItem->WorkItemType = (_WT); \
_WorkItem->WorkItemContext1 = (_WC1); \
_WorkItem->WorkItemContext2 = (_WC2); \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("WorkItem 0x%x\n", _WorkItem)); \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("WorkItem Type 0x%x\n", (_WT))); \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("WorkItem Context2 0x%x\n", (_WC1))); \
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("WorkItem Context1 0x%x\n", (_WC2))); \
\
PushEntryList(&(_M)->WorkQueue[(_WT)], &_WorkItem->Link); \
\
DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO, \
("<==ndisMQueueNewWorkItemFullDuplex()\n")); \
} while (FALSE); \
\
RELEASE_SPIN_LOCK_DPC(&(_M)->WorkLock); \
}
#define NDISM_QUEUE_WORK_ITEM(_M, _WT, _WC1, _WC2) (_M)->QueueWorkItemHandler(_M, _WT, _WC1, _WC2)
#define NDISM_QUEUE_NEW_WORK_ITEM(_M, _WT, _WC1, _WC2) (_M)->QueueNewWorkItemHandler(_M, _WT, _WC1, _WC2)
#define NDISM_DEQUEUE_WORK_ITEM(_M, _WT, _pWC1, _pWC2) (_M)->DeQueueWorkItemHandler(_M, _WT, _pWC1, _pWC2)
#define NDISM_PROCESS_DEFERRED(_M) (_M)->ProcessDeferredHandler((_M))
#endif // _WRAPPPER_