diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/tdi/isn/ipx/loopback.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/ipx/loopback.c b/private/ntos/tdi/isn/ipx/loopback.c new file mode 100644 index 000000000..be44bae5b --- /dev/null +++ b/private/ntos/tdi/isn/ipx/loopback.c @@ -0,0 +1,280 @@ +/*++ + +Copyright (c) 1989-1993 Microsoft Corporation + +Module Name: + + loopback.c + +Abstract: + + This module contains the routines to implement loopback + +Author: + + Sanjay Anand (SanjayAn) 2/6/96 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "precomp.h" +#pragma hdrstop + +// +// Global lock to control access to the Loopback queue +// +DEFINE_LOCK_STRUCTURE(LoopLock) + +// +// Head and tail of the Loopback queue +// +PNDIS_PACKET LoopXmitHead = (PNDIS_PACKET)NULL; +PNDIS_PACKET LoopXmitTail = (PNDIS_PACKET)NULL; + +CTEEvent LoopXmitEvent; +BOOLEAN LoopXmitRtnRunning = 0; + +// +// MaximumPacket sized buffer to hold the lookahead data. +// +// ZZBUGBUG: In PnP this value can change +// +// PUCHAR LookaheadBuffer=NULL; +#define LOOP_LOOKAHEAD_SIZE 128 + sizeof(IPX_HEADER) + 8 + 34 + + +VOID +IpxDoLoopback( + IN CTEEvent *Event, + IN PVOID Context + ) +/*++ + +Routine Description: + + Does the actual loopback. + +Arguments: + + Event - Pointer to event structure. + + Context - Pointer to ZZ + +Return Value: + + None. + +--*/ +{ + PNDIS_PACKET Packet; // Pointer to packet being transmitted + PNDIS_BUFFER Buffer; // Current NDIS buffer being processed. + ULONG TotalLength; // Total length of send. + ULONG LookaheadLength; // Bytes in lookahead. + ULONG Copied; // Bytes copied so far. + PUCHAR CopyPtr; // Pointer to buffer being copied into. + PUCHAR SrcPtr; // Pointer to buffer being copied from. + ULONG SrcLength; // Length of src buffer. + BOOLEAN Rcvd = FALSE; + PIPX_SEND_RESERVED Reserved; + ULONG MacSize; + PNDIS_PACKET *PacketPtr; + UCHAR LookaheadBuffer[LOOP_LOOKAHEAD_SIZE]; + + IPX_DEFINE_LOCK_HANDLE(Handle) + + KIRQL OldIrql; + + CTEAssert(KeGetCurrentIrql() < DISPATCH_LEVEL); + + // + // Raise IRQL so we can acquire locks at DPC level in the receive code. + // Also to be able to ReceiveIndicate at DPC + // + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + + IPX_GET_LOCK(&LoopLock, &Handle); + + if (LoopXmitRtnRunning) { + IPX_FREE_LOCK(&LoopLock, Handle); + KeLowerIrql(OldIrql); + return; + } + + LoopXmitRtnRunning = 1; + + for (;;) { + + // + // Get the next packet from the list. + // + Packet = LoopXmitHead; + + if (Packet != (PNDIS_PACKET)NULL) { + Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved); + LoopXmitHead = (PNDIS_PACKET)(Reserved->PaddingBuffer); + IPX_FREE_LOCK(&LoopLock, Handle); + } else { // Nothing left to do. + LoopXmitRtnRunning = 0; + IPX_FREE_LOCK(&LoopLock, Handle); + break; + } + + // + // We use the PaddingBuffer section as the next ptr. + // + Reserved->PaddingBuffer = NULL; + + IPX_DEBUG(LOOPB, ("Packet: %lx\n", Packet)); + + NdisQueryPacket(Packet, NULL, NULL, &Buffer, &TotalLength); + + NdisQueryBuffer(Buffer, NULL, &MacSize); + + IPX_DEBUG(LOOPB, ("Buffer: %lx Totalpktlen: %lx MacSize: %lx\n", Buffer, TotalLength, MacSize)); + + LookaheadLength = MIN(LOOP_LOOKAHEAD_SIZE, TotalLength); + Copied = 0; + CopyPtr = LookaheadBuffer; + while (Copied < LookaheadLength) { + ULONG ThisCopy; // Bytes to copy this time. + +#ifdef DBG + if (!Buffer) { + DbgBreakPoint(); + IPX_GET_LOCK(&LoopLock, &Handle); + LoopXmitRtnRunning = 0; + IPX_FREE_LOCK(&LoopLock, Handle); + KeLowerIrql(OldIrql); + return; + } +#endif + + NdisQueryBuffer(Buffer, &SrcPtr, &SrcLength); + ThisCopy = MIN(SrcLength, LookaheadLength - Copied); + CTEMemCopy(CopyPtr, SrcPtr, ThisCopy); + Copied += ThisCopy; + CopyPtr += ThisCopy; + NdisGetNextBuffer(Buffer, &Buffer); + } + + Rcvd = TRUE; + +#ifdef BACK_FILL + // + // For Backfill packets, the MAC header is not yet set up; for others, it is the size + // of the first MDL (17). + // + if ((Reserved->Identifier == IDENTIFIER_IPX) && + (Reserved->BackFill)) { + MacSize = 0; + } +#endif + IpxReceiveIndication( (NDIS_HANDLE)IPX_LOOPBACK_COOKIE, // BindingContext + Packet, // ReceiveContext + (MacSize) ? LookaheadBuffer : NULL, // HeaderBuffer + MacSize, // HeaderBufferSize + LookaheadBuffer+MacSize, // LookAheadBuffer + LookaheadLength-MacSize, // LookAheadBufferSize + TotalLength-MacSize); // PacketSize + + IpxSendComplete(Context, Packet, NDIS_STATUS_SUCCESS); + + // + // Give other threads a chance to run. + // + KeLowerIrql(OldIrql); + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + IPX_GET_LOCK(&LoopLock, &Handle); + } + + if (Rcvd) { + IpxReceiveComplete(Context); + } + + KeLowerIrql(OldIrql); +} + + +VOID +IpxInitLoopback() +/*++ + +Routine Description: + + Initializes various loopback structures. + +Arguments: + +Return Value: + + None. + +--*/ +{ + CTEInitLock(&LoopLock); + CTEInitEvent(&LoopXmitEvent, IpxDoLoopback); + return; +} + + +VOID +IpxLoopbackEnque( + IN PNDIS_PACKET Packet, + IN PVOID Context + ) + +/*++ + +Routine Description: + + Enqueues a packet to the loopbackQ + +Arguments: + + Packet - The packet to be enqueued. + + Context - Pointer to the adapter corresp to the first binding. + +Return Value: + + None. + +--*/ +{ + PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved); + IPX_DEFINE_LOCK_HANDLE(LockHandle) + + // + // We use the PaddingBuffer as the next ptr. + // + Reserved->PaddingBuffer = NULL; + + IPX_GET_LOCK(&LoopLock, &LockHandle); + + // + // LoopbackQ is empty + // + if (LoopXmitHead == (PNDIS_PACKET)NULL) { + LoopXmitHead = Packet; + } else { + Reserved = (PIPX_SEND_RESERVED)(LoopXmitTail->ProtocolReserved); + (PNDIS_PACKET)(Reserved->PaddingBuffer) = Packet; + } + LoopXmitTail = Packet; + + IPX_DEBUG(LOOPB, ("Enqued packet: %lx, Reserved: %lx\n", Packet, Reserved)); + + // + // If this routine is not already running, schedule it as a work item. + // + if (!LoopXmitRtnRunning) { + CTEScheduleEvent(&LoopXmitEvent, Context); + } + + IPX_FREE_LOCK(&LoopLock, LockHandle); +} |