|
|
/*++
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_
|