summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isn/ipx/loopback.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/tdi/isn/ipx/loopback.c280
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);
+}