2020-09-30 17:12:29 +02:00

348 lines
6.5 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
umi.c
Abstract:
Upper MAC Interface functions for the NDIS 3.0 Western Digital driver.
Author:
Sean Selitrennikoff (seanse) 15-Jan-92
Environment:
Kernel mode, FSD
Revision History:
--*/
#include <ndis.h>
#include <efilter.h>
#include "wdlmi.h"
#include "wdhrd.h"
#include "wdsft.h"
#include "wdumi.h"
#if DBG
extern UCHAR WdDebugLog[];
extern UCHAR WdDebugLogPlace;
#define IF_LOG(A) A
extern
VOID
LOG (UCHAR A);
#else
#define IF_LOG(A)
#endif
LM_STATUS
UM_Send_Complete(
LM_STATUS Status,
Ptr_Adapter_Struc Adapt
)
/*++
Routine Description:
This routine is called back when the packet on the front of
PacketsOnCard has been fully transmitted by the Lower MAC.
NOTE: The lock is held before the LM_ routines are called and
therefore held at the beginning of this call.
Arguments:
Status - Status of the send.
Adapt - A pointer to an LMI adapter structure.
Return:
SUCCESS
EVENTS_DISABLED
--*/
{
PWD_ADAPTER Adapter = PWD_ADAPTER_FROM_Ptr_Adapter_Struc(Adapt);
PWD_OPEN Open;
PNDIS_PACKET Packet;
//
// Remove packet from front of queue. If the complete queue is empty
// then we have nothing to complete. This shouldn't really happen but
// there is a window where it could.
//
IF_LOG(LOG('c'));
if ( (Packet = Adapter->PacketsOnCard) != NULL ) {
Adapter->WakeUpTimeout = FALSE;
Adapter->PacketsOnCard = RESERVED(Packet)->NextPacket;
if ( Adapter->PacketsOnCard == NULL ) {
Adapter->PacketsOnCardTail = NULL;
}
Open = RESERVED(Packet)->Open;
IF_LOUD( DbgPrint("Completing send for open 0x%lx\n",Open);)
if ( RESERVED(Packet)->Loopback ) {
//
// Put packet on loopback
//
if ( Adapter->LoopbackQueue == NULL ) {
Adapter->LoopbackQueue = Adapter->LoopbackQTail = Packet;
} else {
RESERVED(Adapter->LoopbackQTail)->NextPacket = Packet;
Adapter->LoopbackQTail = Packet;
}
RESERVED(Packet)->NextPacket = NULL;
} else {
IF_LOUD( DbgPrint("Not a loopback packet\n");)
//
// Complete send
//
if ( Status == SUCCESS ) {
Adapter->FramesXmitGood++;
} else {
Adapter->FramesXmitBad++;
}
NdisReleaseSpinLock(&Adapter->Lock);
NdisCompleteSend(Open->NdisBindingContext,
Packet,
(Status == SUCCESS ? NDIS_STATUS_SUCCESS
: NDIS_STATUS_FAILURE)
);
NdisAcquireSpinLock(&Adapter->Lock);
WdRemoveReference(Open);
}
}
//
// If there are any sends waiting and there is not a reset to be
// done, queue them up
//
if ( (Adapter->XmitQueue != NULL) && !(Adapter->ResetRequested) ) {
//
// Remove packet from front.
//
Packet = Adapter->XmitQueue;
Adapter->XmitQueue = RESERVED(Packet)->NextPacket;
if (Adapter->XmitQueue == NULL) {
Adapter->XmitQTail = NULL;
}
//
// Start packet send.
//
IF_LOG(LOG('t'));
Status = LM_Send(Packet, Adapt);
if (Status == OUT_OF_RESOURCES) {
IF_LOG(LOG('2'));
//
// Put packet back on xmit queue.
//
if (Adapter->XmitQueue != NULL) {
RESERVED(Packet)->NextPacket = Adapter->XmitQueue;
Adapter->XmitQueue = Packet;
} else {
Adapter->XmitQueue = Packet;
Adapter->XmitQTail = Packet;
}
} else if (Status == SUCCESS) {
//
// Put packet at end of card list.
//
IF_LOG(LOG('3'));
if (Adapter->PacketsOnCard == NULL) {
Adapter->PacketsOnCard = Adapter->PacketsOnCardTail = Packet;
} else {
RESERVED(Adapter->PacketsOnCardTail)->NextPacket = Packet;
Adapter->PacketsOnCardTail = Packet;
}
ASSERT(Adapter->PacketsOnCard != NULL);
RESERVED(Packet)->NextPacket = NULL;
}
}
IF_LOG(LOG('C'));
return(SUCCESS);
}
LM_STATUS
UM_Receive_Packet(
ULONG PacketSize,
Ptr_Adapter_Struc Adapt
)
/*++
Routine Description:
This routine is called whenever the lower MAC receives a packet.
Arguments:
PacketSize - Total size of the packet
Adapt - A pointer to an LMI adapter structure.
Return:
SUCCESS
EVENTS_DISABLED
--*/
{
PWD_ADAPTER Adapter = PWD_ADAPTER_FROM_Ptr_Adapter_Struc(Adapt);
ULONG IndicateLen;
Adapter->WakeUpTimeout = FALSE;
//
// Setup for indication
//
Adapter->IndicatedAPacket = TRUE;
Adapter->IndicatingPacket = (PNDIS_PACKET)NULL;
IndicateLen = ((Adapter->MaxLookAhead + WD_HEADER_SIZE) > PacketSize ?
PacketSize :
Adapter->MaxLookAhead + WD_HEADER_SIZE
);
if (LM_Receive_Lookahead(
IndicateLen,
0,
Adapter->LookAhead,
&(Adapter->LMAdapter)) != SUCCESS) {
return(SUCCESS);
}
//
// Indicate packet
//
Adapter->FramesRcvGood++;
NdisReleaseSpinLock(&Adapter->Lock);
if (PacketSize < WD_HEADER_SIZE) {
if (PacketSize >= ETH_LENGTH_OF_ADDRESS) {
//
// Runt packet
//
EthFilterIndicateReceive(
Adapt->FilterDB,
(NDIS_HANDLE)Adapter,
(PCHAR)Adapter->LookAhead,
Adapter->LookAhead,
PacketSize,
NULL,
0,
0
);
}
} else {
EthFilterIndicateReceive(
Adapt->FilterDB,
(NDIS_HANDLE)Adapter,
(PCHAR)Adapter->LookAhead,
Adapter->LookAhead,
WD_HEADER_SIZE,
Adapter->LookAhead + WD_HEADER_SIZE,
IndicateLen - WD_HEADER_SIZE,
PacketSize - WD_HEADER_SIZE
);
}
NdisAcquireSpinLock(&Adapter->Lock);
return(SUCCESS);
}