summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/lt200/ltsend.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/lt200/ltsend.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/ndis/lt200/ltsend.c')
-rw-r--r--private/ntos/ndis/lt200/ltsend.c342
1 files changed, 342 insertions, 0 deletions
diff --git a/private/ntos/ndis/lt200/ltsend.c b/private/ntos/ndis/lt200/ltsend.c
new file mode 100644
index 000000000..f3246ba3b
--- /dev/null
+++ b/private/ntos/ndis/lt200/ltsend.c
@@ -0,0 +1,342 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ltsend.c
+
+Abstract:
+
+ This module contains the send queue processing routines.
+
+Author:
+
+ Stephen Hou (stephh@microsoft.com)
+ Nikhil Kamkolkar (nikhilk@microsoft.com)
+
+Revision History:
+ 19 Jun 1992 Initial Version (dch@pacvax.pacersoft.com)
+
+Notes: Tab stop: 4
+--*/
+
+#define LTSEND_H_LOCALS
+#include "ltmain.h"
+
+// Define file id for errorlogging
+#define FILENUM LTSEND
+
+
+NDIS_STATUS
+LtSend(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_PACKET Packet
+ )
+/*++
+
+Routine Description:
+
+ This routine is called by NDIS to send a packet.
+
+Arguments:
+
+ MacBindingHandle : Passed as context to NDIS in OpenAdapter.
+ Packet : Ndis Packet to send.
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS : If successful, else error.
+
+--*/
+{
+ NDIS_STATUS Status;
+ UINT PacketSize;
+
+ BOOLEAN DerefAdapter = FALSE;
+ PLT_OPEN Binding = (PLT_OPEN)MacBindingHandle;
+ PLT_ADAPTER Adapter = Binding->LtAdapter;
+
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ENTRY,
+ ("LtSend: Entering...\n"));
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ // This will go away, when the entry is taken off the adapter transmit queue
+ LtReferenceAdapterNonInterlock(Adapter, &Status);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ DerefAdapter = TRUE;
+ do
+ {
+ // Check to see if there is a reset in progress
+ if (Adapter->Flags & ADAPTER_RESET_IN_PROGRESS)
+ {
+ Status = NDIS_STATUS_RESET_IN_PROGRESS;
+ break;
+ }
+
+ // If binding is closing down, we get out.
+ if (Binding->Flags & BINDING_CLOSING)
+ {
+ Status = NDIS_STATUS_CLOSING;
+ break;
+ }
+
+ // Try to reference the binding. This will go away after
+ // the send completes.
+ LtReferenceBindingNonInterlock(Binding, &Status);
+
+ } while (FALSE);
+ }
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ if (DerefAdapter)
+ LtDeReferenceAdapter(Adapter);
+
+ return(Status);
+ }
+
+
+ do
+ {
+ Status = NDIS_STATUS_PENDING;
+
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ NULL,
+ NULL,
+ &PacketSize);
+
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
+ ("LtSend: Packet %lx Length %lx\n", Packet, PacketSize));
+
+ if ((PacketSize < LT_MIN_PACKET_SIZE ) ||
+ (PacketSize > LT_MAX_PACKET_SIZE)) {
+
+ Status = NDIS_STATUS_RESOURCES;
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ ++Adapter->GeneralMandatory[GM_TRANSMIT_BAD];
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ break;
+
+ }
+ else
+ {
+ PLT_PACKET_RESERVED Reserved = (PLT_PACKET_RESERVED)Packet->MacReserved;
+
+ // Initialize the reserved portion
+ Reserved->MacBindingHandle = MacBindingHandle;
+ InitializeListHead(&Reserved->Linkage);
+
+ if (LtUtilsPacketType(Packet) != LT_LOOPBACK)
+ {
+ // The packet needs to go onto the wire.
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
+ ("LtSend: Queuing %lx on transmit q\n", Packet));
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ InsertTailList(&Adapter->Transmit, &Reserved->Linkage);
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ }
+ else
+ {
+ // Put on the loopback queue
+ NdisAcquireSpinLock(&Adapter->Lock);
+ InsertTailList(&Adapter->LoopBack, &Reserved->Linkage);
+
+ // Since we are doing a Loopback send, lets add up the stats now.
+ ++Adapter->GeneralMandatory[GM_TRANSMIT_GOOD];
+ ++Adapter->GeneralOptionalFrameCount[GO_DIRECTED_TRANSMITS];
+
+ Adapter ->GeneralOptionalByteCount[GO_DIRECTED_TRANSMITS] =
+ LtAddLongToLargeInteger(
+ Adapter ->GeneralOptionalByteCount[GO_DIRECTED_TRANSMITS],
+ PacketSize);
+
+ NdisReleaseSpinLock(&Adapter->Lock);
+ }
+ }
+
+ } while (FALSE);
+
+ // Process send queue. We also process the send queue in the timer
+ // in case, some sends have pended and ndis does no further sends.
+ // !!! Send's get very high priority. In total, the queue is processed
+ // !!! three times, twice in the timer and once in LtSend
+ LtSendProcessQueue(Adapter);
+
+ if (Status != NDIS_STATUS_PENDING)
+ {
+ // Send unsuccessful. Remove the binding reference and adapter reference
+ LtDeReferenceBinding(Binding);
+ LtDeReferenceAdapter(Adapter);
+ }
+
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ENTRY,
+ ("LtSend: Leaving...\n"));
+
+ return Status;
+}
+
+
+
+VOID
+LtSendProcessQueue(
+ IN PLT_ADAPTER Adapter
+ )
+/*++
+
+Routine Description:
+
+ SendProcessQueue processes, yeah, you guessed it. The SendQueue.
+
+Arguments:
+
+ Adapter : Pointer to the adapter structure.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PNDIS_PACKET Packet;
+ PLT_PACKET_RESERVED Reserved;
+ PLT_OPEN Binding;
+ UINT BufferCount, TotalLength, BufLength;
+ PNDIS_BUFFER Buffer;
+ UCHAR Data;
+ PUCHAR Address;
+ PLIST_ENTRY p;
+
+ // Use this to avoid multiple threads from calling this routine.
+ static BOOLEAN QueueActive = FALSE;
+
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ENTRY,
+ ("LtSendProcessTransmit: Entering...\n"));
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ if (QueueActive)
+ {
+ NdisReleaseSpinLock(&Adapter->Lock);
+ return;
+ }
+ QueueActive = TRUE;
+
+ while((!IsListEmpty(&Adapter->Transmit)) &&
+ ((Adapter->Flags & ADAPTER_RESET_IN_PROGRESS) == 0))
+ {
+ // Ok, Can we trasnmit a packet now?
+ NdisRawReadPortUchar(SC_PORT, &Data);
+
+ if ((Data & TX_READY) == 0)
+ {
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_WARN,
+ ("LtSendProcessTransmit: Media not ready...\n"));
+
+ Adapter->MediaOptional[MO_TRANSMIT_DEFERS]++;
+ break;
+ }
+
+ p = RemoveHeadList(&Adapter->Transmit);
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ Packet = CONTAINING_RECORD(
+ p,
+ NDIS_PACKET,
+ MacReserved);
+
+ Reserved = (PLT_PACKET_RESERVED)Packet->MacReserved;
+
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
+ ("LtSendProcessTransmit: Dequeued %lx-%lx\n", Packet, Reserved));
+
+ NdisQueryPacket(
+ Packet,
+ NULL,
+ &BufferCount,
+ &Buffer,
+ &TotalLength);
+
+ // Ok, Output the packet length.
+ NdisRawWritePortUchar(XFER_PORT, (UCHAR)(TotalLength & 0xFF));
+
+ NdisRawWritePortUchar(XFER_PORT, (UCHAR)((TotalLength >> 8) & 0xFF));
+
+ NdisRawWritePortUchar(XFER_PORT, (UCHAR)LT_CMD_LAP_WRITE);
+
+ while (BufferCount-- > 0)
+ {
+ NdisQueryBuffer(
+ Buffer,
+ &Address,
+ &BufLength);
+
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
+ ("LtSendProcessTransmit: Buffer #%d\n", BufferCount));
+
+ NdisRawWritePortBufferUchar(XFER_PORT,
+ Address,
+ BufLength);
+
+ NdisGetNextBuffer(Buffer, &Buffer);
+ }
+
+ if (LtUtilsPacketType(Packet) == LT_DIRECTED)
+ {
+ Binding = (PLT_OPEN)Reserved->MacBindingHandle;
+
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
+ ("LtSendProcessTransmit: Process xmit: Packet %p\n", Packet));
+
+ NdisCompleteSend(
+ Binding->NdisBindingContext,
+ Packet,
+ NDIS_STATUS_SUCCESS);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+ ++Adapter->GeneralMandatory[GM_TRANSMIT_GOOD];
+ ++Adapter->GeneralOptionalFrameCount[GO_DIRECTED_TRANSMITS];
+ Adapter ->GeneralOptionalByteCount[GO_DIRECTED_TRANSMITS] =
+ LtAddLongToLargeInteger(
+ Adapter ->GeneralOptionalByteCount[GO_DIRECTED_TRANSMITS],
+ TotalLength);
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ // Dereference the adapter and the binding for this completed
+ // send.
+ LtDeReferenceBinding(Binding);
+ LtDeReferenceAdapter(Adapter);
+
+ NdisAcquireSpinLock(&Adapter->Lock);
+
+ }
+ else
+ {
+ // This was a broadcast, loop it back.
+ NdisAcquireSpinLock(&Adapter->Lock);
+ ++Adapter->GeneralOptionalFrameCount[GO_BROADCAST_TRANSMITS];
+ ++Adapter->GeneralMandatory[GM_TRANSMIT_GOOD];
+ Adapter ->GeneralOptionalByteCount[GO_BROADCAST_TRANSMITS] =
+ LtAddLongToLargeInteger(
+ Adapter ->GeneralOptionalByteCount[GO_BROADCAST_TRANSMITS],
+ TotalLength);
+ InsertTailList(&Adapter->LoopBack, &Reserved->Linkage);
+ }
+ }
+
+ QueueActive = FALSE;
+ NdisReleaseSpinLock(&Adapter->Lock);
+
+ DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_ENTRY,
+ ("LtSendProcessTransmit: Leaving...\n"));
+
+ return;
+}