ReactOS 0.4.15-dev-7994-gb388cb6
send.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS DC21x4 Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Packet sending
5 * COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "dc21x4.h"
11
12#include <debug.h>
13
14/* FUNCTIONS ******************************************************************/
15
16static
17VOID
19 _In_ PDC21X4_ADAPTER Adapter,
20 _In_ PDC_TCB Tcb,
22{
23 PDC_TBD Tbd, NextTbd, FirstTbd, LastTbd;
24 ULONG i, TbdStatus;
25
26 TbdStatus = 0;
27 Tbd = Adapter->CurrentTbd;
28
29 for (i = 0; i < SgList->NumberOfElements; ++i)
30 {
32
33 LastTbd = Tbd;
34
35 /* Not owned by NIC */
36 ASSERT(!(((i % 2) == 0) && (Tbd->Status & DC_TBD_STATUS_OWNED)));
37
38 Tbd->Status = TbdStatus;
39
40 /* 32-bit DMA */
41 ASSERT(SgList->Elements[i].Address.HighPart == 0);
42
43 Address = SgList->Elements[i].Address.LowPart;
44 Length = SgList->Elements[i].Length;
45
46 /* Two data buffers per descriptor */
47 if ((i % 2) == 0)
48 {
50
51 Tbd->Control |= Length;
52 Tbd->Address1 = Address;
53
54 NextTbd = DC_NEXT_TBD(Adapter, Tbd);
55 }
56 else
57 {
59 Tbd->Address2 = Address;
60
61 Tbd = NextTbd;
62 TbdStatus = DC_TBD_STATUS_OWNED;
63 }
64 }
65
66 /* Enable IRQ on last element */
68
69 Tcb->Tbd = LastTbd;
70
71 FirstTbd = Adapter->CurrentTbd;
72 Adapter->CurrentTbd = NextTbd;
73
74 /* Not owned by NIC */
75 ASSERT(!(FirstTbd->Status & DC_TBD_STATUS_OWNED));
76
79 FirstTbd->Status = DC_TBD_STATUS_OWNED;
80}
81
82static
85 _In_ PDC21X4_ADAPTER Adapter,
88{
91 UINT CurrentLength, PacketLength;
93
96 &Address,
97 &CurrentLength,
98 &PacketLength,
100 if (!Address)
101 return FALSE;
102
103 Destination = Buffer->VirtualAddress;
104
105 while (TRUE)
106 {
107 NdisMoveMemory(Destination, Address, CurrentLength);
108 Destination += CurrentLength;
109
111 if (!CurrentBuffer)
112 break;
113
115 &Address,
116 &CurrentLength,
118 if (!Address)
119 return FALSE;
120 }
121
122 return TRUE;
123}
124
125static
128 _In_ NDIS_HANDLE MiniportAdapterContext,
130{
131 PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
133 PDC_TCB Tcb;
134 ULONG SlotsUsed;
135
136 if (!Adapter->TcbSlots)
138
140
141 if (SgList->NumberOfElements > DC_FRAGMENTATION_THRESHOLD)
142 {
143 PDC_COALESCE_BUFFER CoalesceBuffer;
144 UINT PacketLength;
145
146 if (!Adapter->TbdSlots || !Adapter->SendBufferList.Next)
147 {
149 }
150
151 NdisQueryPacketLength(Packet, &PacketLength);
152
153 CoalesceBuffer = (PDC_COALESCE_BUFFER)PopEntryList(&Adapter->SendBufferList);
154
155 if (!DcCopyPacket(Adapter, Packet, CoalesceBuffer))
156 {
157 PushEntryList(&Adapter->SendBufferList, &CoalesceBuffer->ListEntry);
159 }
160
161 SgList = &Adapter->LocalSgList;
162 SgList->Elements[0].Address.LowPart = CoalesceBuffer->PhysicalAddress;
163 SgList->Elements[0].Length = PacketLength;
164 SgList->NumberOfElements = 1;
165 SlotsUsed = 1;
166
167 Tcb = Adapter->CurrentTcb;
168 Tcb->SlotsUsed = 1;
169 Tcb->Buffer = CoalesceBuffer;
170 }
171 else
172 {
173 /* We use two data buffers per descriptor */
174 SlotsUsed = (SgList->NumberOfElements + 1) / 2;
175
176 if (SlotsUsed > Adapter->TbdSlots)
178
179 Tcb = Adapter->CurrentTcb;
180 Tcb->SlotsUsed = SlotsUsed;
181 Tcb->Buffer = NULL;
182 }
183
184 --Adapter->TcbSlots;
185
186 Adapter->CurrentTcb = DC_NEXT_TCB(Adapter, Tcb);
187
188 Tcb->Packet = Packet;
189
190 ASSERT(Adapter->TbdSlots >= Tcb->SlotsUsed);
191 Adapter->TbdSlots -= SlotsUsed;
192
193 DcTransmitPacket(Adapter, Tcb, SgList);
194
196
197 return NDIS_STATUS_PENDING;
198}
199
200VOID
202 _In_ PDC21X4_ADAPTER Adapter)
203{
207
208 ASSERT(!IsListEmpty(&Adapter->SendQueueList));
209
210 do
211 {
212 Entry = RemoveHeadList(&Adapter->SendQueueList);
213
215
216 Status = DcSendPacket(Adapter, Packet);
218 {
219 InsertHeadList(&Adapter->SendQueueList, DC_LIST_ENTRY_FROM_PACKET(Packet));
220 break;
221 }
222 }
223 while (!IsListEmpty(&Adapter->SendQueueList));
224}
225
226VOID
227NTAPI
229 _In_ NDIS_HANDLE MiniportAdapterContext,
232{
233 PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
235 ULONG i;
236
237 NdisAcquireSpinLock(&Adapter->SendLock);
238
239 if (!(Adapter->Flags & DC_ACTIVE))
240 {
241 NdisReleaseSpinLock(&Adapter->SendLock);
242
243 for (i = 0; i < NumberOfPackets; ++i)
244 {
246 PacketArray[i],
248 }
249
250 return;
251 }
252
253 TRACE("Send packets %u\n", NumberOfPackets);
254
255 for (i = 0; i < NumberOfPackets; ++i)
256 {
258
259 Status = DcSendPacket(Adapter, Packet);
261 {
263 }
264 }
265
266 NdisReleaseSpinLock(&Adapter->SendLock);
267}
268
269VOID
270NTAPI
272 _In_ NDIS_HANDLE MiniportAdapterContext,
274{
275 PDC21X4_ADAPTER Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
276 LIST_ENTRY DoneList;
277 PLIST_ENTRY Entry, NextEntry;
278
279 TRACE("Called\n");
280
281 InitializeListHead(&DoneList);
282
283 NdisAcquireSpinLock(&Adapter->SendLock);
284
285 NextEntry = Adapter->SendQueueList.Flink;
286 while (NextEntry != &Adapter->SendQueueList)
287 {
289
290 Entry = NextEntry;
291 NextEntry = NextEntry->Flink;
292
294
296 {
298
300 }
301 }
302
303 NdisReleaseSpinLock(&Adapter->SendLock);
304
305 while (!IsListEmpty(&DoneList))
306 {
307 Entry = RemoveHeadList(&DoneList);
308
312 }
313}
static ACPI_BUFFER CurrentBuffer
unsigned char BOOLEAN
Definition: bufpool.h:45
#define DC_FRAGMENTATION_THRESHOLD
Definition: dc21x4.h:44
struct _DC21X4_ADAPTER * PDC21X4_ADAPTER
Definition: dc21x4.h:61
struct _DC_COALESCE_BUFFER * PDC_COALESCE_BUFFER
Definition: dc21x4.h:64
#define DC_ACTIVE
Definition: dc21x4.h:120
#define DC_WRITE(Adapter, Register, Value)
Definition: dc21x4.h:272
@ DcCsr1_TxPoll
Definition: dc21x4hw.h:173
#define DC_TBD_STATUS_OWNED
Definition: dc21x4hw.h:71
#define DC_TBD_CONTROL_REQUEST_INTERRUPT
Definition: dc21x4hw.h:87
#define DC_TX_POLL_DOORBELL
Definition: dc21x4hw.h:244
#define DC_TBD_CONTROL_LENGTH_2_SHIFT
Definition: dc21x4hw.h:93
#define DC_TBD_CONTROL_FIRST_FRAGMENT
Definition: dc21x4hw.h:85
#define DC_TBD_CONTROL_END_OF_RING
Definition: dc21x4hw.h:82
#define DC_TBD_CONTROL_LAST_FRAGMENT
Definition: dc21x4hw.h:86
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static VOID DcTransmitPacket(_In_ PDC21X4_ADAPTER Adapter, _In_ PDC_TCB Tcb, _In_ PSCATTER_GATHER_LIST SgList)
Definition: send.c:18
VOID NTAPI DcCancelSendPackets(_In_ NDIS_HANDLE MiniportAdapterContext, _In_ PVOID CancelId)
Definition: send.c:271
static BOOLEAN DcCopyPacket(_In_ PDC21X4_ADAPTER Adapter, _In_ PNDIS_PACKET Packet, _In_ PDC_COALESCE_BUFFER Buffer)
Definition: send.c:84
static NDIS_STATUS DcSendPacket(_In_ NDIS_HANDLE MiniportAdapterContext, _In_ PNDIS_PACKET Packet)
Definition: send.c:127
VOID DcProcessPendingPackets(_In_ PDC21X4_ADAPTER Adapter)
Definition: send.c:201
VOID NTAPI DcSendPackets(_In_ NDIS_HANDLE MiniportAdapterContext, _In_ PPNDIS_PACKET PacketArray, _In_ UINT NumberOfPackets)
Definition: send.c:228
#define DC_WRITE_BARRIER()
Definition: util.h:30
LONG CancelId
Definition: main.c:23
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ASSERT(a)
Definition: mode.c:44
@ HighPagePriority
Definition: imports.h:57
#define _In_
Definition: ms_sal.h:308
#define NdisReleaseSpinLock(_SpinLock)
Definition: ndis.h:4115
#define NdisGetNextBuffer(CurrentBuffer, NextBuffer)
Definition: ndis.h:3386
#define NDIS_STATUS_PENDING
Definition: ndis.h:347
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
#define NdisQueryPacketLength(_Packet, _TotalPacketLength)
Definition: ndis.h:3645
unsigned int UINT
Definition: ndis.h:50
#define NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, InfoType)
Definition: ndis.h:1351
#define NDIS_STATUS_REQUEST_ABORTED
Definition: ndis.h:476
_In_ PPNDIS_PACKET _In_ UINT NumberOfPackets
Definition: ndis.h:5121
#define NdisQueryBufferSafe(_Buffer, _VirtualAddress, _Length, _Priority)
Definition: ndis.h:5283
_In_ PPNDIS_PACKET PacketArray
Definition: ndis.h:5120
MDL * PNDIS_BUFFER
Definition: ndis.h:343
#define NdisGetFirstBufferFromPacketSafe(_Packet, _FirstBuffer, _FirstBufferVA, _FirstBufferLength, _TotalBufferLength, _Priority)
Definition: ndis.h:3056
@ ScatterGatherListPacketInfo
Definition: ndis.h:1183
#define NDIS_STATUS_NOT_ACCEPTED
Definition: ndis.h:350
#define NDIS_GET_PACKET_CANCEL_ID(Packet)
Definition: ndis.h:1333
#define NdisMSendComplete(MiniportAdapterHandle, Packet, Status)
Definition: ndis.h:5689
#define NdisAcquireSpinLock(_SpinLock)
Definition: ndis.h:4106
#define NdisMoveMemory(Destination, Source, Length)
Definition: ndis.h:3896
#define NDIS_STATUS_RESOURCES
Definition: ndis.h:466
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3004
int NDIS_STATUS
Definition: ntddndis.h:475
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
static WCHAR Address[46]
Definition: ping.c:68
#define DC_PACKET_FROM_LIST_ENTRY(ListEntry)
Definition: sendrcv.h:13
FORCEINLINE PDC_TBD DC_NEXT_TBD(_In_ PDC21X4_ADAPTER Adapter, _In_ PDC_TBD Tbd)
Definition: sendrcv.h:86
FORCEINLINE PDC_TCB DC_NEXT_TCB(_In_ PDC21X4_ADAPTER Adapter, _In_ PDC_TCB Tcb)
Definition: sendrcv.h:74
#define DC_LIST_ENTRY_FROM_PACKET(Packet)
Definition: sendrcv.h:10
#define TRACE(s)
Definition: solgame.cpp:4
base of all file and directory entries
Definition: entries.h:83
ULONG TcbSlots
Definition: dc21x4.h:137
SINGLE_LIST_ENTRY SendBufferList
Definition: dc21x4.h:142
PDC_TCB CurrentTcb
Definition: dc21x4.h:132
NDIS_HANDLE AdapterHandle
Definition: dc21x4.h:158
LIST_ENTRY SendQueueList
Definition: dc21x4.h:136
DECLSPEC_CACHEALIGN NDIS_SPIN_LOCK SendLock
Definition: dc21x4.h:129
ULONG TbdSlots
Definition: dc21x4.h:138
SCATTER_GATHER_LIST LocalSgList
Definition: dc21x4.h:143
ULONG Flags
Definition: dc21x4.h:119
SINGLE_LIST_ENTRY ListEntry
Definition: sendrcv.h:25
ULONG PhysicalAddress
Definition: sendrcv.h:28
ULONG Status
Definition: dc21x4hw.h:59
ULONG Address1
Definition: dc21x4hw.h:95
ULONG Control
Definition: dc21x4hw.h:77
ULONG Address2
Definition: dc21x4hw.h:96
ULONG SlotsUsed
Definition: sendrcv.h:36
PDC_COALESCE_BUFFER Buffer
Definition: sendrcv.h:35
PNDIS_PACKET Packet
Definition: sendrcv.h:34
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
#define NTAPI
Definition: typedefs.h:36
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION _In_ PSCATTER_GATHER_LIST SgList
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2204
FORCEINLINE VOID PushEntryList(_Inout_ PSINGLE_LIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PSINGLE_LIST_ENTRY Entry)
Definition: rtlfuncs.h:253
FORCEINLINE PSINGLE_LIST_ENTRY PopEntryList(_Inout_ PSINGLE_LIST_ENTRY ListHead)
Definition: rtlfuncs.h:240