From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/lt200/ltsend.c | 342 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 private/ntos/ndis/lt200/ltsend.c (limited to 'private/ntos/ndis/lt200/ltsend.c') 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; +} -- cgit v1.2.3