xref: /reactos/drivers/network/dd/e1000/send.c (revision e944dfa7)
13f976713SDmitry Borisov /*
23f976713SDmitry Borisov  * PROJECT:     ReactOS Intel PRO/1000 Driver
3*e944dfa7SHermès Bélusca-Maïto  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
43f976713SDmitry Borisov  * PURPOSE:     Sending packets
53f976713SDmitry Borisov  * COPYRIGHT:   Copyright 2018 Mark Jansen <mark.jansen@reactos.org>
63f976713SDmitry Borisov  *              Copyright 2019 Victor Perevertkin <victor.perevertkin@reactos.org>
73f976713SDmitry Borisov  */
83f976713SDmitry Borisov 
93f976713SDmitry Borisov #include "nic.h"
103f976713SDmitry Borisov 
113f976713SDmitry Borisov #include <debug.h>
123f976713SDmitry Borisov 
133f976713SDmitry Borisov static
143f976713SDmitry Borisov NDIS_STATUS
NICTransmitPacket(_In_ PE1000_ADAPTER Adapter,_In_ PHYSICAL_ADDRESS PhysicalAddress,_In_ ULONG Length)153f976713SDmitry Borisov NICTransmitPacket(
163f976713SDmitry Borisov     _In_ PE1000_ADAPTER Adapter,
173f976713SDmitry Borisov     _In_ PHYSICAL_ADDRESS PhysicalAddress,
183f976713SDmitry Borisov     _In_ ULONG Length)
193f976713SDmitry Borisov {
203f976713SDmitry Borisov     volatile PE1000_TRANSMIT_DESCRIPTOR TransmitDescriptor;
213f976713SDmitry Borisov 
223f976713SDmitry Borisov     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
233f976713SDmitry Borisov 
243f976713SDmitry Borisov     TransmitDescriptor = Adapter->TransmitDescriptors + Adapter->CurrentTxDesc;
253f976713SDmitry Borisov     TransmitDescriptor->Address = PhysicalAddress.QuadPart;
263f976713SDmitry Borisov     TransmitDescriptor->Length = Length;
273f976713SDmitry Borisov     TransmitDescriptor->ChecksumOffset = 0;
283f976713SDmitry Borisov     TransmitDescriptor->Command = E1000_TDESC_CMD_RS | E1000_TDESC_CMD_IFCS |
293f976713SDmitry Borisov                                   E1000_TDESC_CMD_EOP | E1000_TDESC_CMD_IDE;
303f976713SDmitry Borisov     TransmitDescriptor->Status = 0;
313f976713SDmitry Borisov     TransmitDescriptor->ChecksumStartField = 0;
323f976713SDmitry Borisov     TransmitDescriptor->Special = 0;
333f976713SDmitry Borisov 
343f976713SDmitry Borisov     Adapter->CurrentTxDesc = (Adapter->CurrentTxDesc + 1) % NUM_TRANSMIT_DESCRIPTORS;
353f976713SDmitry Borisov 
363f976713SDmitry Borisov     E1000WriteUlong(Adapter, E1000_REG_TDT, Adapter->CurrentTxDesc);
373f976713SDmitry Borisov 
383f976713SDmitry Borisov     if (Adapter->CurrentTxDesc == Adapter->LastTxDesc)
393f976713SDmitry Borisov     {
403f976713SDmitry Borisov         NDIS_DbgPrint(MID_TRACE, ("All TX descriptors are full now\n"));
413f976713SDmitry Borisov         Adapter->TxFull = TRUE;
423f976713SDmitry Borisov     }
433f976713SDmitry Borisov 
443f976713SDmitry Borisov     return NDIS_STATUS_SUCCESS;
453f976713SDmitry Borisov }
463f976713SDmitry Borisov 
473f976713SDmitry Borisov NDIS_STATUS
483f976713SDmitry Borisov NTAPI
MiniportSend(_In_ NDIS_HANDLE MiniportAdapterContext,_In_ PNDIS_PACKET Packet,_In_ UINT Flags)493f976713SDmitry Borisov MiniportSend(
503f976713SDmitry Borisov     _In_ NDIS_HANDLE MiniportAdapterContext,
513f976713SDmitry Borisov     _In_ PNDIS_PACKET Packet,
523f976713SDmitry Borisov     _In_ UINT Flags)
533f976713SDmitry Borisov {
543f976713SDmitry Borisov     PE1000_ADAPTER Adapter = (PE1000_ADAPTER)MiniportAdapterContext;
553f976713SDmitry Borisov     PSCATTER_GATHER_LIST sgList;
563f976713SDmitry Borisov     ULONG TransmitLength;
573f976713SDmitry Borisov     PHYSICAL_ADDRESS TransmitBuffer;
583f976713SDmitry Borisov     NDIS_STATUS Status;
593f976713SDmitry Borisov 
603f976713SDmitry Borisov     sgList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo);
613f976713SDmitry Borisov 
623f976713SDmitry Borisov     ASSERT(sgList != NULL);
633f976713SDmitry Borisov     ASSERT(sgList->NumberOfElements == 1);
643f976713SDmitry Borisov     ASSERT((sgList->Elements[0].Address.LowPart & 3) == 0);
653f976713SDmitry Borisov     ASSERT(sgList->Elements[0].Length <= MAXIMUM_FRAME_SIZE);
663f976713SDmitry Borisov 
673f976713SDmitry Borisov     if (Adapter->TxFull)
683f976713SDmitry Borisov     {
693f976713SDmitry Borisov         NDIS_DbgPrint(MIN_TRACE, ("All TX descriptors are full\n"));
703f976713SDmitry Borisov         return NDIS_STATUS_RESOURCES;
713f976713SDmitry Borisov     }
723f976713SDmitry Borisov 
733f976713SDmitry Borisov     TransmitLength = sgList->Elements[0].Length;
743f976713SDmitry Borisov     TransmitBuffer = sgList->Elements[0].Address;
753f976713SDmitry Borisov     Adapter->TransmitPackets[Adapter->CurrentTxDesc] = Packet;
763f976713SDmitry Borisov 
773f976713SDmitry Borisov     Status = NICTransmitPacket(Adapter, TransmitBuffer, TransmitLength);
783f976713SDmitry Borisov     if (Status != NDIS_STATUS_SUCCESS)
793f976713SDmitry Borisov     {
803f976713SDmitry Borisov         NDIS_DbgPrint(MIN_TRACE, ("Transmit packet failed\n"));
813f976713SDmitry Borisov         return Status;
823f976713SDmitry Borisov     }
833f976713SDmitry Borisov 
843f976713SDmitry Borisov     return NDIS_STATUS_PENDING;
853f976713SDmitry Borisov }
86