/*++ 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 #include #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); }