Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

342 lines
7.8 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
ltsend.c
Abstract:
This module contains the send queue processing routines.
Author:
Stephen Hou ([email protected])
Nikhil Kamkolkar ([email protected])
Revision History:
19 Jun 1992 Initial Version ([email protected])
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;
}