📄 miniport.c
字号:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS NDIS library
* FILE: ndis/miniport.c
* PURPOSE: Routines used by NDIS miniport drivers
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Vizzini (vizzini@plasmic.com)
* REVISIONS:
* CSH 01/08-2000 Created
* 20 Aug 2003 vizzini - DMA support
* 3 Oct 2003 vizzini - SendPackets support
*/
#include "ndissys.h"
#include "efilter.h"
#ifdef DBG
#include <buffer.h>
#endif /* DBG */
#undef NdisMSendComplete
VOID
EXPORT
NdisMSendComplete(
IN NDIS_HANDLE MiniportAdapterHandle,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status);
/* Root of the scm database */
#define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
/*
* Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
* for each new miniport starting up
*/
#define BREAK_ON_MINIPORT_INIT 0
/*
* This has to be big enough to hold the results of querying the Route value
* from the Linkage key. Please re-code me to determine this dynamically.
*/
#define ROUTE_DATA_SIZE 256
/* Number of media we know */
#define MEDIA_ARRAY_SIZE 15
static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
{
NdisMedium802_3,
NdisMedium802_5,
NdisMediumFddi,
NdisMediumWan,
NdisMediumLocalTalk,
NdisMediumDix,
NdisMediumArcnetRaw,
NdisMediumArcnet878_2,
NdisMediumAtm,
NdisMediumWirelessWan,
NdisMediumIrda,
NdisMediumBpc,
NdisMediumCoWan,
NdisMedium1394,
NdisMediumMax
};
/* global list and lock of Miniports NDIS has registered */
LIST_ENTRY MiniportListHead;
KSPIN_LOCK MiniportListLock;
/* global list and lock of adapters NDIS has registered */
LIST_ENTRY AdapterListHead;
KSPIN_LOCK AdapterListLock;
VOID
MiniDisplayPacket(
PNDIS_PACKET Packet)
{
#ifdef DBG
ULONG i, Length;
UCHAR Buffer[64];
if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
Length = CopyPacketToBuffer(
Buffer,
Packet,
0,
64);
DbgPrint("*** PACKET START ***");
for (i = 0; i < Length; i++) {
if (i % 12 == 0)
DbgPrint("\n%04X ", i);
DbgPrint("%02X ", Buffer[i]);
}
DbgPrint("*** PACKET STOP ***\n");
}
#endif /* DBG */
}
VOID
MiniDisplayPacket2(
PVOID HeaderBuffer,
UINT HeaderBufferSize,
PVOID LookaheadBuffer,
UINT LookaheadBufferSize)
{
#ifdef DBG
if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
ULONG i, Length;
PUCHAR p;
DbgPrint("*** RECEIVE PACKET START ***\n");
DbgPrint("HEADER:");
p = HeaderBuffer;
for (i = 0; i < HeaderBufferSize; i++) {
if (i % 16 == 0)
DbgPrint("\n%04X ", i);
DbgPrint("%02X ", *p++);
}
DbgPrint("\nFRAME:");
p = LookaheadBuffer;
Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
for (i = 0; i < Length; i++) {
if (i % 16 == 0)
DbgPrint("\n%04X ", i);
DbgPrint("%02X ", *p++);
}
DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
}
#endif /* DBG */
}
VOID
MiniIndicateData(
PLOGICAL_ADAPTER Adapter,
NDIS_HANDLE MacReceiveContext,
PVOID HeaderBuffer,
UINT HeaderBufferSize,
PVOID LookaheadBuffer,
UINT LookaheadBufferSize,
UINT PacketSize)
/*
* FUNCTION: Indicate received data to bound protocols
* ARGUMENTS:
* Adapter = Pointer to logical adapter
* MacReceiveContext = MAC receive context handle
* HeaderBuffer = Pointer to header buffer
* HeaderBufferSize = Size of header buffer
* LookaheadBuffer = Pointer to lookahead buffer
* LookaheadBufferSize = Size of lookahead buffer
* PacketSize = Total size of received packet
*/
{
/* KIRQL OldIrql; */
PLIST_ENTRY CurrentEntry;
PADAPTER_BINDING AdapterBinding;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
"HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
/*
* XXX Think about this. This is probably broken. Spinlocks are
* taken out for now until i comprehend the Right Way to do this.
*
* This used to acquire the MiniportBlock spinlock and hold it until
* just before the call to ReceiveHandler. It would then release and
* subsequently re-acquire the lock.
*
* I don't see how this does any good, as it would seem he's just
* trying to protect the packet list. If somebody else dequeues
* a packet, we are in fact in bad shape, but we don't want to
* necessarily call the receive handler at elevated irql either.
*
* therefore: We *are* going to call the receive handler at high irql
* (due to holding the lock) for now, and eventually we have to
* figure out another way to protect this packet list.
*
* UPDATE: this is busted; this results in a recursive lock acquisition.
*/
//NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
//KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
{
CurrentEntry = Adapter->ProtocolListHead.Flink;
NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
if (CurrentEntry == &Adapter->ProtocolListHead)
{
NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
}
while (CurrentEntry != &Adapter->ProtocolListHead)
{
AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
/* see above */
/* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
#ifdef DBG
if(!AdapterBinding)
{
NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding was null\n"));
break;
}
if(!AdapterBinding->ProtocolBinding)
{
NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding was null\n"));
break;
}
if(!AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)
{
NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
break;
}
#endif
NDIS_DbgPrint
(MID_TRACE,
("XXX (%x) %x %x %x %x %x %x %x XXX\n",
*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler,
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookaheadBuffer,
LookaheadBufferSize,
PacketSize));
/* call the receive handler */
(*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookaheadBuffer,
LookaheadBufferSize,
PacketSize);
/* see above */
/* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
CurrentEntry = CurrentEntry->Flink;
}
}
//KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
VOID NTAPI
MiniIndicateReceivePacket(
IN NDIS_HANDLE Miniport,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets)
/*
* FUNCTION: receives miniport packet array indications
* ARGUMENTS:
* Miniport: Miniport handle for the adapter
* PacketArray: pointer to a list of packet pointers to indicate
* NumberOfPackets: number of packets to indicate
* NOTES:
* - This currently is a big temporary hack. In the future this should
* call ProtocolReceivePacket() on each bound protocol if it exists.
* For now it just mimics NdisMEthIndicateReceive.
*/
{
UINT i;
for(i = 0; i < NumberOfPackets; i++)
{
PCHAR PacketBuffer = 0;
UINT PacketLength = 0;
PNDIS_BUFFER NdisBuffer = 0;
#define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
NdisAllocateMemoryWithTag((PVOID)&PacketBuffer, 1518, PACKET_TAG);
if(!PacketBuffer)
{
NDIS_DbgPrint(MIN_TRACE, ("insufficient resources\n"));
return;
}
NdisQueryPacket(PacketArray[i], NULL, NULL, &NdisBuffer, NULL);
while(NdisBuffer)
{
PNDIS_BUFFER CurrentBuffer;
PVOID BufferVa;
UINT BufferLen;
NdisQueryBuffer(NdisBuffer, &BufferVa, &BufferLen);
memcpy(PacketBuffer + PacketLength, BufferVa, BufferLen);
PacketLength += BufferLen;
CurrentBuffer = NdisBuffer;
NdisGetNextBuffer(CurrentBuffer, &NdisBuffer);
}
NDIS_DbgPrint(MID_TRACE, ("indicating a %d-byte packet\n", PacketLength));
MiniIndicateData(Miniport, NULL, PacketBuffer, 14, PacketBuffer+14, PacketLength-14, PacketLength-14);
NdisFreeMemory(PacketBuffer, 0, 0);
}
}
VOID NTAPI
MiniResetComplete(
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_STATUS Status,
IN BOOLEAN AddressingReset)
{
UNIMPLEMENTED
}
VOID NTAPI
MiniRequestComplete(
IN PNDIS_MINIPORT_BLOCK Adapter,
IN PNDIS_REQUEST Request,
IN NDIS_STATUS Status)
{
PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
if( MacBlock->Binding->RequestCompleteHandler ) {
(*MacBlock->Binding->RequestCompleteHandler)(
MacBlock->Binding->ProtocolBindingContext,
Request,
Status);
}
}
VOID NTAPI
MiniSendComplete(
IN NDIS_HANDLE MiniportAdapterHandle,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status)
/*
* FUNCTION: Forwards a message to the initiating protocol saying
* that a packet was handled
* ARGUMENTS:
* NdisAdapterHandle = Handle input to MiniportInitialize
* Packet = Pointer to NDIS packet that was sent
* Status = Status of send operation
*/
{
PADAPTER_BINDING AdapterBinding;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
(*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
Packet,
Status);
}
VOID NTAPI
MiniSendResourcesAvailable(
IN NDIS_HANDLE MiniportAdapterHandle)
{
/*
UNIMPLEMENTED
*/
}
VOID NTAPI
MiniTransferDataComplete(
IN NDIS_HANDLE MiniportAdapterHandle,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status,
IN UINT BytesTransferred)
{
PADAPTER_BINDING AdapterBinding;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
(*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
Packet,
Status);
}
BOOLEAN
MiniAdapterHasAddress(
PLOGICAL_ADAPTER Adapter,
PNDIS_PACKET Packet)
/*
* FUNCTION: Determines whether a packet has the same destination address as an adapter
* ARGUMENTS:
* Adapter = Pointer to logical adapter object
* Packet = Pointer to NDIS packet
* RETURNS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -