mirror of https://github.com/lianthony/NT4.0
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
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;
|
|
}
|