883 lines
23 KiB
C
883 lines
23 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1990-1995 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
miniport.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
NDIS wrapper functions
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Sean Selitrennikoff (SeanSe) 05-Oct-93
|
||
|
Jameel Hyder (JameelH) Re-organization 01-Jun-95
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Kernel mode, FSD
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
//
|
||
|
// Define the module number for debug code.
|
||
|
//
|
||
|
#define MODULE_NUMBER MODULE_MINISUB
|
||
|
|
||
|
VOID
|
||
|
NdisAllocateSpinLock(
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
INITIALIZE_SPIN_LOCK(&SpinLock->SpinLock);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisFreeSpinLock(
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(SpinLock);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisAcquireSpinLock(
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
NDIS_ACQUIRE_SPIN_LOCK(SpinLock, &SpinLock->OldIrql);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisReleaseSpinLock(
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
NDIS_RELEASE_SPIN_LOCK(SpinLock, SpinLock->OldIrql);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisDprAcquireSpinLock(
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
NDIS_ACQUIRE_SPIN_LOCK_DPC(SpinLock);
|
||
|
SpinLock->OldIrql = DISPATCH_LEVEL;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisDprReleaseSpinLock(
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
NDIS_RELEASE_SPIN_LOCK_DPC(SpinLock);
|
||
|
}
|
||
|
|
||
|
#undef NdisFreeBuffer
|
||
|
VOID
|
||
|
NdisFreeBuffer(
|
||
|
IN PNDIS_BUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
IoFreeMdl(Buffer);
|
||
|
}
|
||
|
|
||
|
#undef NdisQueryBuffer
|
||
|
VOID
|
||
|
NdisQueryBuffer(
|
||
|
IN PNDIS_BUFFER Buffer,
|
||
|
OUT PVOID * VirtualAddress OPTIONAL,
|
||
|
OUT PUINT Length
|
||
|
)
|
||
|
{
|
||
|
if (ARGUMENT_PRESENT(VirtualAddress))
|
||
|
{
|
||
|
*VirtualAddress = MDL_ADDRESS(Buffer);
|
||
|
}
|
||
|
*Length = MDL_SIZE(Buffer);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisQueryBufferSafe(
|
||
|
IN PNDIS_BUFFER Buffer,
|
||
|
OUT PVOID * VirtualAddress OPTIONAL,
|
||
|
OUT PUINT Length,
|
||
|
IN MM_PAGE_PRIORITY Priority
|
||
|
)
|
||
|
{
|
||
|
if (ARGUMENT_PRESENT(VirtualAddress))
|
||
|
{
|
||
|
*VirtualAddress = MDL_ADDRESS_SAFE(Buffer, Priority);
|
||
|
}
|
||
|
*Length = MDL_SIZE(Buffer);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisQueryBufferOffset(
|
||
|
IN PNDIS_BUFFER Buffer,
|
||
|
OUT PUINT Offset,
|
||
|
OUT PUINT Length
|
||
|
)
|
||
|
{
|
||
|
*Offset = MDL_OFFSET(Buffer);
|
||
|
*Length = MDL_SIZE(Buffer);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisGetFirstBufferFromPacket(
|
||
|
IN PNDIS_PACKET Packet,
|
||
|
OUT PNDIS_BUFFER * FirstBuffer,
|
||
|
OUT PVOID * FirstBufferVA,
|
||
|
OUT PUINT FirstBufferLength,
|
||
|
OUT PUINT TotalBufferLength
|
||
|
)
|
||
|
{
|
||
|
PNDIS_BUFFER pBuf;
|
||
|
|
||
|
pBuf = Packet->Private.Head;
|
||
|
*FirstBuffer = pBuf;
|
||
|
if (pBuf)
|
||
|
{
|
||
|
*FirstBufferVA = MmGetSystemAddressForMdl(pBuf);
|
||
|
*FirstBufferLength = *TotalBufferLength = MmGetMdlByteCount(pBuf);
|
||
|
for (pBuf = pBuf->Next;
|
||
|
pBuf != NULL;
|
||
|
pBuf = pBuf->Next)
|
||
|
{
|
||
|
*TotalBufferLength += MmGetMdlByteCount(pBuf);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*FirstBufferVA = 0;
|
||
|
*FirstBufferLength = 0;
|
||
|
*TotalBufferLength = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// safe version of NdisGetFirstBufferFromPacket
|
||
|
// if the memory described by the first buffer can not be mapped
|
||
|
// this function will return NULL for FirstBuferVA
|
||
|
//
|
||
|
VOID
|
||
|
NdisGetFirstBufferFromPacketSafe(
|
||
|
IN PNDIS_PACKET Packet,
|
||
|
OUT PNDIS_BUFFER * FirstBuffer,
|
||
|
OUT PVOID * FirstBufferVA,
|
||
|
OUT PUINT FirstBufferLength,
|
||
|
OUT PUINT TotalBufferLength,
|
||
|
IN MM_PAGE_PRIORITY Priority
|
||
|
)
|
||
|
{
|
||
|
PNDIS_BUFFER pBuf;
|
||
|
|
||
|
pBuf = Packet->Private.Head;
|
||
|
*FirstBuffer = pBuf;
|
||
|
if (pBuf)
|
||
|
{
|
||
|
*FirstBufferVA = MmGetSystemAddressForMdlSafe(pBuf, Priority);
|
||
|
*FirstBufferLength = *TotalBufferLength = MmGetMdlByteCount(pBuf);
|
||
|
for (pBuf = pBuf->Next;
|
||
|
pBuf != NULL;
|
||
|
pBuf = pBuf->Next)
|
||
|
{
|
||
|
*TotalBufferLength += MmGetMdlByteCount(pBuf);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*FirstBufferVA = 0;
|
||
|
*FirstBufferLength = 0;
|
||
|
*TotalBufferLength = 0;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
ULONG
|
||
|
NdisBufferLength(
|
||
|
IN PNDIS_BUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
return (MmGetMdlByteCount(Buffer));
|
||
|
}
|
||
|
|
||
|
PVOID
|
||
|
NdisBufferVirtualAddress(
|
||
|
IN PNDIS_BUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
return (MDL_ADDRESS_SAFE(Buffer, HighPagePriority));
|
||
|
}
|
||
|
|
||
|
ULONG
|
||
|
NDIS_BUFFER_TO_SPAN_PAGES(
|
||
|
IN PNDIS_BUFFER Buffer
|
||
|
)
|
||
|
{
|
||
|
if (MDL_SIZE(Buffer) == 0)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
return ADDRESS_AND_SIZE_TO_SPAN_PAGES(MDL_VA(Buffer), MDL_SIZE(Buffer));
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisGetBufferPhysicalArraySize(
|
||
|
IN PNDIS_BUFFER Buffer,
|
||
|
OUT PUINT ArraySize
|
||
|
)
|
||
|
{
|
||
|
if (MDL_SIZE(Buffer) == 0)
|
||
|
{
|
||
|
*ArraySize = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ArraySize = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MDL_VA(Buffer), MDL_SIZE(Buffer));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NDIS_STATUS
|
||
|
NdisAnsiStringToUnicodeString(
|
||
|
IN OUT PUNICODE_STRING DestinationString,
|
||
|
IN PANSI_STRING SourceString
|
||
|
)
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
|
||
|
Status = RtlAnsiStringToUnicodeString(DestinationString,
|
||
|
SourceString,
|
||
|
FALSE);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
NDIS_STATUS
|
||
|
NdisUnicodeStringToAnsiString(
|
||
|
IN OUT PANSI_STRING DestinationString,
|
||
|
IN PUNICODE_STRING SourceString
|
||
|
)
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
|
||
|
Status = RtlUnicodeStringToAnsiString(DestinationString,
|
||
|
SourceString,
|
||
|
FALSE);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
NDIS_STATUS
|
||
|
NdisUpcaseUnicodeString(
|
||
|
OUT PUNICODE_STRING DestinationString,
|
||
|
IN PUNICODE_STRING SourceString
|
||
|
)
|
||
|
{
|
||
|
return(RtlUpcaseUnicodeString(DestinationString, SourceString, FALSE));
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisMStartBufferPhysicalMapping(
|
||
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
||
|
IN PNDIS_BUFFER Buffer,
|
||
|
IN ULONG PhysicalMapRegister,
|
||
|
IN BOOLEAN WriteToDevice,
|
||
|
OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray,
|
||
|
OUT PUINT ArraySize
|
||
|
)
|
||
|
{
|
||
|
NdisMStartBufferPhysicalMappingMacro(MiniportAdapterHandle,
|
||
|
Buffer,
|
||
|
PhysicalMapRegister,
|
||
|
WriteToDevice,
|
||
|
PhysicalAddressArray,
|
||
|
ArraySize);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
NdisMCompleteBufferPhysicalMapping(
|
||
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
||
|
IN PNDIS_BUFFER Buffer,
|
||
|
IN ULONG PhysicalMapRegister
|
||
|
)
|
||
|
{
|
||
|
NdisMCompleteBufferPhysicalMappingMacro(MiniportAdapterHandle,
|
||
|
Buffer,
|
||
|
PhysicalMapRegister);
|
||
|
}
|
||
|
|
||
|
#undef NdisInterlockedIncrement
|
||
|
ULONG
|
||
|
NdisInterlockedIncrement(
|
||
|
IN PULONG Addend
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
(eax) < 0 (but not necessarily -1) if result of add < 0
|
||
|
(eax) == 0 if result of add == 0
|
||
|
(eax) > 0 (but not necessarily +1) if result of add > 0
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
return(InterlockedIncrement(Addend));
|
||
|
}
|
||
|
|
||
|
#undef NdisInterlockedDecrement
|
||
|
ULONG
|
||
|
NdisInterlockedDecrement(
|
||
|
IN PULONG Addend
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
(eax) < 0 (but not necessarily -1) if result of add < 0
|
||
|
(eax) == 0 if result of add == 0
|
||
|
(eax) > 0 (but not necessarily +1) if result of add > 0
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
return(InterlockedDecrement(Addend));
|
||
|
}
|
||
|
|
||
|
#undef NdisInterlockedAddUlong
|
||
|
ULONG
|
||
|
NdisInterlockedAddUlong(
|
||
|
IN PULONG Addend,
|
||
|
IN ULONG Increment,
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
return(ExInterlockedAddUlong(Addend,Increment, &SpinLock->SpinLock));
|
||
|
|
||
|
}
|
||
|
|
||
|
#undef NdisInterlockedInsertHeadList
|
||
|
PLIST_ENTRY
|
||
|
NdisInterlockedInsertHeadList(
|
||
|
IN PLIST_ENTRY ListHead,
|
||
|
IN PLIST_ENTRY ListEntry,
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
|
||
|
return(ExInterlockedInsertHeadList(ListHead,ListEntry,&SpinLock->SpinLock));
|
||
|
|
||
|
}
|
||
|
|
||
|
#undef NdisInterlockedInsertTailList
|
||
|
PLIST_ENTRY
|
||
|
NdisInterlockedInsertTailList(
|
||
|
IN PLIST_ENTRY ListHead,
|
||
|
IN PLIST_ENTRY ListEntry,
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
return(ExInterlockedInsertTailList(ListHead,ListEntry,&SpinLock->SpinLock));
|
||
|
}
|
||
|
|
||
|
#undef NdisInterlockedRemoveHeadList
|
||
|
PLIST_ENTRY
|
||
|
NdisInterlockedRemoveHeadList(
|
||
|
IN PLIST_ENTRY ListHead,
|
||
|
IN PNDIS_SPIN_LOCK SpinLock
|
||
|
)
|
||
|
{
|
||
|
return(ExInterlockedRemoveHeadList(ListHead, &SpinLock->SpinLock));
|
||
|
}
|
||
|
|
||
|
#undef NdisInterlockedPushEntryList
|
||
|
PSINGLE_LIST_ENTRY
|
||
|
NdisInterlockedPushEntryList(
|
||
|
IN PSINGLE_LIST_ENTRY ListHead,
|
||
|
IN PSINGLE_LIST_ENTRY ListEntry,
|
||
|
IN PNDIS_SPIN_LOCK Lock
|
||
|
)
|
||
|
{
|
||
|
return(ExInterlockedPushEntryList(ListHead, ListEntry, &Lock->SpinLock));
|
||
|
}
|
||
|
|
||
|
#undef NdisInterlockedPopEntryList
|
||
|
PSINGLE_LIST_ENTRY
|
||
|
NdisInterlockedPopEntryList(
|
||
|
IN PSINGLE_LIST_ENTRY ListHead,
|
||
|
IN PNDIS_SPIN_LOCK Lock
|
||
|
)
|
||
|
{
|
||
|
return(ExInterlockedPopEntryList(ListHead, &Lock->SpinLock));
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Logging support for miniports
|
||
|
//
|
||
|
NDIS_STATUS
|
||
|
NdisMCreateLog(
|
||
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
||
|
IN UINT Size,
|
||
|
OUT PNDIS_HANDLE LogHandle
|
||
|
)
|
||
|
{
|
||
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
|
||
|
PNDIS_LOG Log = NULL;
|
||
|
NDIS_STATUS Status;
|
||
|
KIRQL OldIrql;
|
||
|
|
||
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
|
||
|
|
||
|
if (Miniport->Log != NULL)
|
||
|
{
|
||
|
Status = NDIS_STATUS_FAILURE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Log = ALLOC_FROM_POOL(sizeof(NDIS_LOG) + Size, NDIS_TAG_DBG_LOG);
|
||
|
if (Log != NULL)
|
||
|
{
|
||
|
Status = NDIS_STATUS_SUCCESS;
|
||
|
Miniport->Log = Log;
|
||
|
INITIALIZE_SPIN_LOCK(&Log->LogLock);
|
||
|
Log->Miniport = Miniport;
|
||
|
Log->Irp = NULL;
|
||
|
Log->TotalSize = Size;
|
||
|
Log->CurrentSize = 0;
|
||
|
Log->InPtr = 0;
|
||
|
Log->OutPtr = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Status = NDIS_STATUS_RESOURCES;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*LogHandle = Log;
|
||
|
|
||
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisMCloseLog(
|
||
|
IN NDIS_HANDLE LogHandle
|
||
|
)
|
||
|
{
|
||
|
PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
|
||
|
PNDIS_MINIPORT_BLOCK Miniport;
|
||
|
KIRQL OldIrql;
|
||
|
|
||
|
Miniport = Log->Miniport;
|
||
|
|
||
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
|
||
|
Miniport->Log = NULL;
|
||
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
|
||
|
|
||
|
FREE_POOL(Log);
|
||
|
}
|
||
|
|
||
|
|
||
|
NDIS_STATUS
|
||
|
NdisMWriteLogData(
|
||
|
IN NDIS_HANDLE LogHandle,
|
||
|
IN PVOID LogBuffer,
|
||
|
IN UINT LogBufferSize
|
||
|
)
|
||
|
{
|
||
|
PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
|
||
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
||
|
KIRQL OldIrql;
|
||
|
UINT AmtToCopy;
|
||
|
|
||
|
IoAcquireCancelSpinLock(&OldIrql);
|
||
|
|
||
|
ACQUIRE_SPIN_LOCK_DPC(&Log->LogLock);
|
||
|
|
||
|
if (LogBufferSize <= Log->TotalSize)
|
||
|
{
|
||
|
if (LogBufferSize <= (Log->TotalSize - Log->InPtr))
|
||
|
{
|
||
|
//
|
||
|
// Can copy the entire buffer
|
||
|
//
|
||
|
CopyMemory(Log->LogBuf+Log->InPtr, LogBuffer, LogBufferSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// We are going to wrap around. Copy it in two chunks.
|
||
|
//
|
||
|
AmtToCopy = Log->TotalSize - Log->InPtr;
|
||
|
CopyMemory(Log->LogBuf+Log->InPtr,
|
||
|
LogBuffer,
|
||
|
AmtToCopy);
|
||
|
CopyMemory(Log->LogBuf + 0,
|
||
|
(PUCHAR)LogBuffer+AmtToCopy,
|
||
|
LogBufferSize - AmtToCopy);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update the current size
|
||
|
//
|
||
|
Log->CurrentSize += LogBufferSize;
|
||
|
if (Log->CurrentSize > Log->TotalSize)
|
||
|
Log->CurrentSize = Log->TotalSize;
|
||
|
|
||
|
//
|
||
|
// Update the InPtr and possibly the outptr
|
||
|
//
|
||
|
Log->InPtr += LogBufferSize;
|
||
|
if (Log->InPtr >= Log->TotalSize)
|
||
|
{
|
||
|
Log->InPtr -= Log->TotalSize;
|
||
|
}
|
||
|
|
||
|
if (Log->CurrentSize == Log->TotalSize)
|
||
|
{
|
||
|
Log->OutPtr = Log->InPtr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check if there is a pending Irp to complete
|
||
|
//
|
||
|
if (Log->Irp != NULL)
|
||
|
{
|
||
|
PIRP Irp = Log->Irp;
|
||
|
PUCHAR Buffer;
|
||
|
|
||
|
Log->Irp = NULL;
|
||
|
|
||
|
//
|
||
|
// If the InPtr is lagging the OutPtr. then we can simply
|
||
|
// copy the data over in one shot.
|
||
|
//
|
||
|
AmtToCopy = MDL_SIZE(Irp->MdlAddress);
|
||
|
if (AmtToCopy > Log->CurrentSize)
|
||
|
AmtToCopy = Log->CurrentSize;
|
||
|
if ((Log->TotalSize - Log->OutPtr) >= AmtToCopy)
|
||
|
{
|
||
|
Buffer = MDL_ADDRESS_SAFE(Irp->MdlAddress, LowPagePriority);
|
||
|
|
||
|
if (Buffer != NULL)
|
||
|
{
|
||
|
CopyMemory(Buffer,
|
||
|
Log->LogBuf+Log->OutPtr,
|
||
|
AmtToCopy);
|
||
|
}
|
||
|
else Status = NDIS_STATUS_RESOURCES;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Buffer = MDL_ADDRESS_SAFE(Irp->MdlAddress, LowPagePriority);
|
||
|
|
||
|
if (Buffer != NULL)
|
||
|
{
|
||
|
CopyMemory(Buffer,
|
||
|
Log->LogBuf+Log->OutPtr,
|
||
|
Log->TotalSize-Log->OutPtr);
|
||
|
CopyMemory(Buffer+Log->TotalSize-Log->OutPtr,
|
||
|
Log->LogBuf,
|
||
|
AmtToCopy - (Log->TotalSize-Log->OutPtr));
|
||
|
}
|
||
|
else Status = NDIS_STATUS_RESOURCES;
|
||
|
}
|
||
|
Log->CurrentSize -= AmtToCopy;
|
||
|
Log->OutPtr += AmtToCopy;
|
||
|
if (Log->OutPtr >= Log->TotalSize)
|
||
|
Log->OutPtr -= Log->TotalSize;
|
||
|
Irp->IoStatus.Information = AmtToCopy;
|
||
|
IoSetCancelRoutine(Irp, NULL);
|
||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||
|
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Status = NDIS_STATUS_BUFFER_OVERFLOW;
|
||
|
}
|
||
|
|
||
|
RELEASE_SPIN_LOCK_DPC(&Log->LogLock);
|
||
|
|
||
|
IoReleaseCancelSpinLock(OldIrql);
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
NDIS_STATUS
|
||
|
FASTCALL
|
||
|
ndisMGetLogData(
|
||
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
||
|
IN PIRP Irp
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
KIRQL OldIrql;
|
||
|
PNDIS_LOG Log;
|
||
|
UINT AmtToCopy;
|
||
|
|
||
|
IoAcquireCancelSpinLock(&OldIrql);
|
||
|
|
||
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
|
||
|
|
||
|
if ((Log = Miniport->Log) != NULL)
|
||
|
{
|
||
|
ACQUIRE_SPIN_LOCK_DPC(&Log->LogLock);
|
||
|
|
||
|
if (Log->CurrentSize != 0)
|
||
|
{
|
||
|
PUCHAR Buffer;
|
||
|
|
||
|
//
|
||
|
// If the InPtr is lagging the OutPtr. then we can simply
|
||
|
// copy the data over in one shot.
|
||
|
//
|
||
|
AmtToCopy = MDL_SIZE(Irp->MdlAddress);
|
||
|
if (AmtToCopy > Log->CurrentSize)
|
||
|
AmtToCopy = Log->CurrentSize;
|
||
|
Buffer = MDL_ADDRESS_SAFE(Irp->MdlAddress, LowPagePriority);
|
||
|
|
||
|
if (Buffer != NULL)
|
||
|
{
|
||
|
if ((Log->TotalSize - Log->OutPtr) >= AmtToCopy)
|
||
|
{
|
||
|
CopyMemory(Buffer,
|
||
|
Log->LogBuf+Log->OutPtr,
|
||
|
AmtToCopy);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CopyMemory(Buffer,
|
||
|
Log->LogBuf+Log->OutPtr,
|
||
|
Log->TotalSize-Log->OutPtr);
|
||
|
CopyMemory(Buffer+Log->TotalSize-Log->OutPtr,
|
||
|
Log->LogBuf,
|
||
|
AmtToCopy - (Log->TotalSize-Log->OutPtr));
|
||
|
}
|
||
|
Log->CurrentSize -= AmtToCopy;
|
||
|
Log->OutPtr += AmtToCopy;
|
||
|
if (Log->OutPtr >= Log->TotalSize)
|
||
|
Log->OutPtr -= Log->TotalSize;
|
||
|
Irp->IoStatus.Information = AmtToCopy;
|
||
|
Status = STATUS_SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
}
|
||
|
else if (Log->Irp != NULL)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
IoSetCancelRoutine(Irp, ndisCancelLogIrp);
|
||
|
Log->Irp = Irp;
|
||
|
Status = STATUS_PENDING;
|
||
|
}
|
||
|
|
||
|
RELEASE_SPIN_LOCK_DPC(&Log->LogLock);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
|
||
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
|
||
|
IoReleaseCancelSpinLock(OldIrql);
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisMFlushLog(
|
||
|
IN NDIS_HANDLE LogHandle
|
||
|
)
|
||
|
{
|
||
|
PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
|
||
|
KIRQL OldIrql;
|
||
|
|
||
|
ACQUIRE_SPIN_LOCK(&Log->LogLock, &OldIrql);
|
||
|
Log->InPtr = 0;
|
||
|
Log->OutPtr = 0;
|
||
|
Log->CurrentSize = 0;
|
||
|
RELEASE_SPIN_LOCK(&Log->LogLock, OldIrql);
|
||
|
}
|
||
|
|
||
|
NDIS_STATUS
|
||
|
NdisMQueryAdapterInstanceName(
|
||
|
OUT PNDIS_STRING pAdapterInstanceName,
|
||
|
IN NDIS_HANDLE NdisAdapterHandle
|
||
|
)
|
||
|
{
|
||
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)NdisAdapterHandle;
|
||
|
USHORT cbSize;
|
||
|
PVOID ptmp = NULL;
|
||
|
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
|
||
|
NTSTATUS NtStatus;
|
||
|
|
||
|
DBGPRINT(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
|
||
|
("==>NdisMQueryAdapterInstanceName\n"));
|
||
|
|
||
|
//
|
||
|
// If we failed to create the adapter instance name then fail this call.
|
||
|
//
|
||
|
if (NULL != Miniport->pAdapterInstanceName)
|
||
|
{
|
||
|
//
|
||
|
// Allocate storage for the copy of the adapter instance name.
|
||
|
//
|
||
|
cbSize = Miniport->pAdapterInstanceName->MaximumLength;
|
||
|
|
||
|
//
|
||
|
// Allocate storage for the new string.
|
||
|
//
|
||
|
ptmp = ALLOC_FROM_POOL(cbSize, NDIS_TAG_NAME_BUF);
|
||
|
if (NULL != ptmp)
|
||
|
{
|
||
|
RtlZeroMemory(ptmp, cbSize);
|
||
|
pAdapterInstanceName->Buffer = ptmp;
|
||
|
pAdapterInstanceName->Length = 0;
|
||
|
pAdapterInstanceName->MaximumLength = cbSize;
|
||
|
|
||
|
NtStatus = RtlAppendUnicodeStringToString(
|
||
|
pAdapterInstanceName,
|
||
|
Miniport->pAdapterInstanceName);
|
||
|
if (NT_SUCCESS(NtStatus))
|
||
|
{
|
||
|
Status = NDIS_STATUS_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Status = NDIS_STATUS_RESOURCES;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NDIS_STATUS_SUCCESS != Status)
|
||
|
{
|
||
|
if (NULL != ptmp)
|
||
|
{
|
||
|
FREE_POOL(ptmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DBGPRINT(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
|
||
|
("<==NdisMQueryAdapterInstanceName: 0x%x\n", Status));
|
||
|
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
EXPORT
|
||
|
VOID
|
||
|
NdisInitializeReadWriteLock(
|
||
|
IN PNDIS_RW_LOCK Lock
|
||
|
)
|
||
|
{
|
||
|
NdisZeroMemory(Lock, sizeof(NDIS_RW_LOCK));
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisAcquireReadWriteLock(
|
||
|
IN PNDIS_RW_LOCK Lock,
|
||
|
IN BOOLEAN fWrite,
|
||
|
IN PLOCK_STATE LockState
|
||
|
)
|
||
|
{
|
||
|
if (fWrite)
|
||
|
{
|
||
|
LockState->LockState = WRITE_LOCK_STATE_UNKNOWN;
|
||
|
{
|
||
|
UINT i, refcount;
|
||
|
ULONG Prc;
|
||
|
|
||
|
/*
|
||
|
* This means we need to attempt to acquire the lock,
|
||
|
* if we do not already own it.
|
||
|
* Set the state accordingly.
|
||
|
*/
|
||
|
if ((Lock)->Context == CURRENT_THREAD)
|
||
|
{
|
||
|
(LockState)->LockState = LOCK_STATE_ALREADY_ACQUIRED;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ACQUIRE_SPIN_LOCK(&(Lock)->SpinLock, &(LockState)->OldIrql);
|
||
|
|
||
|
Prc = KeGetCurrentProcessorNumber();
|
||
|
refcount = (Lock)->RefCount[Prc].RefCount;
|
||
|
(Lock)->RefCount[Prc].RefCount = 0;
|
||
|
|
||
|
/* wait for all readers to exit */
|
||
|
for (i=0; i < ndisNumberOfProcessors; i++)
|
||
|
{
|
||
|
volatile UINT *_p = &(Lock)->RefCount[i].RefCount;
|
||
|
|
||
|
while (*_p != 0)
|
||
|
NDIS_INTERNAL_STALL(50);
|
||
|
}
|
||
|
|
||
|
(Lock)->RefCount[Prc].RefCount = refcount;
|
||
|
(Lock)->Context = CURRENT_THREAD;
|
||
|
(LockState)->LockState = WRITE_LOCK_STATE_FREE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LockState->LockState = READ_LOCK;
|
||
|
{
|
||
|
UINT refcount;
|
||
|
ULONG Prc;
|
||
|
|
||
|
RAISE_IRQL_TO_DISPATCH(&(LockState)->OldIrql);
|
||
|
|
||
|
/* go ahead and bump up the ref count IF no writes are underway */
|
||
|
Prc = CURRENT_PROCESSOR;
|
||
|
refcount = InterlockedIncrement(&Lock->RefCount[Prc].RefCount);
|
||
|
|
||
|
/* Test if spin lock is held, i.e., write is underway */
|
||
|
/* if (KeTestSpinLock(&(_L)->SpinLock) == TRUE) */
|
||
|
/* This processor already is holding the lock, just */
|
||
|
/* allow him to take it again or else we run into a */
|
||
|
/* dead-lock situation with the writer */
|
||
|
if (TEST_SPIN_LOCK((Lock)->SpinLock) &&
|
||
|
(refcount == 1) &&
|
||
|
((Lock)->Context != CURRENT_THREAD))
|
||
|
{
|
||
|
(Lock)->RefCount[Prc].RefCount--;
|
||
|
ACQUIRE_SPIN_LOCK_DPC(&(Lock)->SpinLock);
|
||
|
(Lock)->RefCount[Prc].RefCount++;
|
||
|
RELEASE_SPIN_LOCK_DPC(&(Lock)->SpinLock);
|
||
|
}
|
||
|
(LockState)->LockState = READ_LOCK_STATE_FREE;
|
||
|
}
|
||
|
}
|
||
|
// LockState->LockState = fWrite ? WRITE_LOCK_STATE_UNKNOWN : READ_LOCK;
|
||
|
// xLockHandler(Lock, LockState);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisReleaseReadWriteLock(
|
||
|
IN PNDIS_RW_LOCK Lock,
|
||
|
IN PLOCK_STATE LockState
|
||
|
)
|
||
|
{
|
||
|
xLockHandler(Lock, LockState);
|
||
|
}
|
||
|
|