]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/SnpDxe/Transmit.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / SnpDxe / Transmit.c
CommitLineData
a3c5f87a 1/** @file\r
4cda7726 2 Implementation of transmitting a packet.\r
d1102dba
LG
3\r
4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
a3c5f87a 6\r
a3c5f87a 7**/\r
8\r
9#include "Snp.h"\r
10\r
a3c5f87a 11/**\r
f3816027 12 Call UNDI to create the meadia header for the given data buffer.\r
a3c5f87a 13\r
f3816027 14 @param Snp Pointer to SNP driver structure.\r
15 @param MacHeaderPtr Address where the media header will be filled in.\r
16 @param HeaderSize Size of the memory at MacHeaderPtr.\r
17 @param Buffer Data buffer pointer.\r
18 @param BufferSize Size of data in the Buffer\r
19 @param DestAddr Address of the destination mac address buffer.\r
20 @param SrcAddr Address of the source mac address buffer.\r
21 @param ProtocolPtr Address of the protocol type.\r
a3c5f87a 22\r
f3816027 23 @retval EFI_SUCCESS Successfully completed the undi call.\r
24 @retval Other Error return from undi call.\r
a3c5f87a 25\r
26**/\r
a3c5f87a 27EFI_STATUS\r
4cda7726 28PxeFillHeader (\r
d1050b9d
MK
29 SNP_DRIVER *Snp,\r
30 VOID *MacHeaderPtr,\r
31 UINTN HeaderSize,\r
32 VOID *Buffer,\r
33 UINTN BufferSize,\r
34 EFI_MAC_ADDRESS *DestAddr,\r
35 EFI_MAC_ADDRESS *SrcAddr,\r
36 UINT16 *ProtocolPtr\r
a3c5f87a 37 )\r
38{\r
4cda7726 39 PXE_CPB_FILL_HEADER_FRAGMENTED *Cpb;\r
a3c5f87a 40\r
4cda7726 41 Cpb = Snp->Cpb;\r
42 if (SrcAddr != NULL) {\r
a3c5f87a 43 CopyMem (\r
d1050b9d
MK
44 (VOID *)Cpb->SrcAddr,\r
45 (VOID *)SrcAddr,\r
4cda7726 46 Snp->Mode.HwAddressSize\r
a3c5f87a 47 );\r
48 } else {\r
49 CopyMem (\r
d1050b9d
MK
50 (VOID *)Cpb->SrcAddr,\r
51 (VOID *)&(Snp->Mode.CurrentAddress),\r
4cda7726 52 Snp->Mode.HwAddressSize\r
a3c5f87a 53 );\r
54 }\r
55\r
56 CopyMem (\r
d1050b9d
MK
57 (VOID *)Cpb->DestAddr,\r
58 (VOID *)DestAddr,\r
4cda7726 59 Snp->Mode.HwAddressSize\r
a3c5f87a 60 );\r
61\r
62 //\r
63 // we need to do the byte swapping\r
64 //\r
d1050b9d 65 Cpb->Protocol = (UINT16)PXE_SWAP_UINT16 (*ProtocolPtr);\r
a3c5f87a 66\r
d1050b9d
MK
67 Cpb->PacketLen = (UINT32)(BufferSize);\r
68 Cpb->MediaHeaderLen = (UINT16)HeaderSize;\r
a3c5f87a 69\r
d1050b9d
MK
70 Cpb->FragCnt = 2;\r
71 Cpb->reserved = 0;\r
a3c5f87a 72\r
d1050b9d
MK
73 Cpb->FragDesc[0].FragAddr = (UINT64)(UINTN)MacHeaderPtr;\r
74 Cpb->FragDesc[0].FragLen = (UINT32)HeaderSize;\r
75 Cpb->FragDesc[1].FragAddr = (UINT64)(UINTN)Buffer;\r
76 Cpb->FragDesc[1].FragLen = (UINT32)BufferSize;\r
a3c5f87a 77\r
4cda7726 78 Cpb->FragDesc[0].reserved = Cpb->FragDesc[1].reserved = 0;\r
a3c5f87a 79\r
d1050b9d
MK
80 Snp->Cdb.OpCode = PXE_OPCODE_FILL_HEADER;\r
81 Snp->Cdb.OpFlags = PXE_OPFLAGS_FILL_HEADER_FRAGMENTED;\r
a3c5f87a 82\r
d1050b9d
MK
83 Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;\r
84 Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;\r
a3c5f87a 85\r
d1050b9d
MK
86 Snp->Cdb.CPBsize = (UINT16)sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED);\r
87 Snp->Cdb.CPBaddr = (UINT64)(UINTN)Cpb;\r
a3c5f87a 88\r
d1050b9d
MK
89 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
90 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
91 Snp->Cdb.IFnum = Snp->IfNum;\r
92 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a3c5f87a 93\r
94 //\r
95 // Issue UNDI command and check result.\r
96 //\r
c49ca4a2 97 DEBUG ((DEBUG_NET, "\nSnp->undi.fill_header() "));\r
a3c5f87a 98\r
d1050b9d 99 (*Snp->IssueUndi32Command)((UINT64)(UINTN)&Snp->Cdb);\r
a3c5f87a 100\r
4cda7726 101 switch (Snp->Cdb.StatCode) {\r
d1050b9d
MK
102 case PXE_STATCODE_SUCCESS:\r
103 return EFI_SUCCESS;\r
104\r
105 case PXE_STATCODE_INVALID_PARAMETER:\r
106 DEBUG (\r
107 (DEBUG_ERROR,\r
108 "\nSnp->undi.fill_header() %xh:%xh\n",\r
109 Snp->Cdb.StatFlags,\r
110 Snp->Cdb.StatCode)\r
111 );\r
112\r
113 return EFI_INVALID_PARAMETER;\r
114\r
115 default:\r
116 DEBUG (\r
117 (DEBUG_ERROR,\r
118 "\nSnp->undi.fill_header() %xh:%xh\n",\r
119 Snp->Cdb.StatFlags,\r
120 Snp->Cdb.StatCode)\r
121 );\r
122\r
123 return EFI_DEVICE_ERROR;\r
a3c5f87a 124 }\r
125}\r
126\r
a3c5f87a 127/**\r
128 This routine calls undi to transmit the given data buffer\r
129\r
4cda7726 130 @param Snp pointer to SNP driver structure\r
131 @param Buffer data buffer pointer\r
132 @param BufferSize Size of data in the Buffer\r
a3c5f87a 133\r
134 @retval EFI_SUCCESS if successfully completed the undi call\r
135 @retval Other error return from undi call.\r
136\r
137**/\r
a3c5f87a 138EFI_STATUS\r
4cda7726 139PxeTransmit (\r
d1050b9d
MK
140 SNP_DRIVER *Snp,\r
141 VOID *Buffer,\r
142 UINTN BufferSize\r
a3c5f87a 143 )\r
144{\r
4cda7726 145 PXE_CPB_TRANSMIT *Cpb;\r
a3c5f87a 146 EFI_STATUS Status;\r
147\r
d1050b9d
MK
148 Cpb = Snp->Cpb;\r
149 Cpb->FrameAddr = (UINT64)(UINTN)Buffer;\r
150 Cpb->DataLen = (UINT32)BufferSize;\r
a3c5f87a 151\r
4cda7726 152 Cpb->MediaheaderLen = 0;\r
153 Cpb->reserved = 0;\r
a3c5f87a 154\r
d1050b9d 155 Snp->Cdb.OpFlags = PXE_OPFLAGS_TRANSMIT_WHOLE;\r
a3c5f87a 156\r
d1050b9d
MK
157 Snp->Cdb.CPBsize = (UINT16)sizeof (PXE_CPB_TRANSMIT);\r
158 Snp->Cdb.CPBaddr = (UINT64)(UINTN)Cpb;\r
a3c5f87a 159\r
d1050b9d
MK
160 Snp->Cdb.OpCode = PXE_OPCODE_TRANSMIT;\r
161 Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;\r
162 Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;\r
a3c5f87a 163\r
d1050b9d
MK
164 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
165 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
166 Snp->Cdb.IFnum = Snp->IfNum;\r
167 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
a3c5f87a 168\r
169 //\r
170 // Issue UNDI command and check result.\r
171 //\r
c49ca4a2
MK
172 DEBUG ((DEBUG_NET, "\nSnp->undi.transmit() "));\r
173 DEBUG ((DEBUG_NET, "\nSnp->Cdb.OpCode == %x", Snp->Cdb.OpCode));\r
174 DEBUG ((DEBUG_NET, "\nSnp->Cdb.CPBaddr == %LX", Snp->Cdb.CPBaddr));\r
175 DEBUG ((DEBUG_NET, "\nSnp->Cdb.DBaddr == %LX", Snp->Cdb.DBaddr));\r
176 DEBUG ((DEBUG_NET, "\nCpb->FrameAddr == %LX\n", Cpb->FrameAddr));\r
a3c5f87a 177\r
d1050b9d 178 (*Snp->IssueUndi32Command)((UINT64)(UINTN)&Snp->Cdb);\r
a3c5f87a 179\r
c49ca4a2 180 DEBUG ((DEBUG_NET, "\nexit Snp->undi.transmit() "));\r
a3c5f87a 181\r
182 //\r
183 // we will unmap the buffers in get_status call, not here\r
184 //\r
4cda7726 185 switch (Snp->Cdb.StatCode) {\r
d1050b9d
MK
186 case PXE_STATCODE_SUCCESS:\r
187 return EFI_SUCCESS;\r
188\r
189 case PXE_STATCODE_BUFFER_FULL:\r
190 case PXE_STATCODE_QUEUE_FULL:\r
191 case PXE_STATCODE_BUSY:\r
192 Status = EFI_NOT_READY;\r
193 DEBUG (\r
194 (DEBUG_NET,\r
195 "\nSnp->undi.transmit() %xh:%xh\n",\r
196 Snp->Cdb.StatFlags,\r
197 Snp->Cdb.StatCode)\r
198 );\r
199 break;\r
200\r
201 default:\r
202 DEBUG (\r
203 (DEBUG_ERROR,\r
204 "\nSnp->undi.transmit() %xh:%xh\n",\r
205 Snp->Cdb.StatFlags,\r
206 Snp->Cdb.StatCode)\r
207 );\r
208 Status = EFI_DEVICE_ERROR;\r
a3c5f87a 209 }\r
210\r
a3c5f87a 211 return Status;\r
212}\r
213\r
a3c5f87a 214/**\r
4cda7726 215 Places a packet in the transmit queue of a network interface.\r
d1102dba 216\r
4cda7726 217 This function places the packet specified by Header and Buffer on the transmit\r
d1102dba
LG
218 queue. If HeaderSize is nonzero and HeaderSize is not equal to\r
219 This->Mode->MediaHeaderSize, then EFI_INVALID_PARAMETER will be returned. If\r
4cda7726 220 BufferSize is less than This->Mode->MediaHeaderSize, then EFI_BUFFER_TOO_SMALL\r
d1102dba 221 will be returned. If Buffer is NULL, then EFI_INVALID_PARAMETER will be\r
4cda7726 222 returned. If HeaderSize is nonzero and DestAddr or Protocol is NULL, then\r
223 EFI_INVALID_PARAMETER will be returned. If the transmit engine of the network\r
d1102dba
LG
224 interface is busy, then EFI_NOT_READY will be returned. If this packet can be\r
225 accepted by the transmit engine of the network interface, the packet contents\r
226 specified by Buffer will be placed on the transmit queue of the network\r
227 interface, and EFI_SUCCESS will be returned. GetStatus() can be used to\r
228 determine when the packet has actually been transmitted. The contents of the\r
229 Buffer must not be modified until the packet has actually been transmitted.\r
4cda7726 230 The Transmit() function performs nonblocking I/O. A caller who wants to perform\r
d1102dba 231 blocking I/O, should call Transmit(), and then GetStatus() until the\r
4cda7726 232 transmitted buffer shows up in the recycled transmit buffer.\r
233 If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.\r
234\r
235 @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.\r
d1102dba 236 @param HeaderSize The size, in bytes, of the media header to be filled in by the\r
4cda7726 237 Transmit() function. If HeaderSize is nonzero, then it must\r
238 be equal to This->Mode->MediaHeaderSize and the DestAddr and\r
239 Protocol parameters must not be NULL.\r
240 @param BufferSize The size, in bytes, of the entire packet (media header and\r
241 data) to be transmitted through the network interface.\r
d1102dba
LG
242 @param Buffer A pointer to the packet (media header followed by data) to be\r
243 transmitted. This parameter cannot be NULL. If HeaderSize is\r
4cda7726 244 zero, then the media header in Buffer must already be filled\r
d1102dba 245 in by the caller. If HeaderSize is nonzero, then the media\r
4cda7726 246 header will be filled in by the Transmit() function.\r
d1102dba
LG
247 @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this\r
248 parameter is ignored. If HeaderSize is nonzero and SrcAddr\r
249 is NULL, then This->Mode->CurrentAddress is used for the\r
4cda7726 250 source HW MAC address.\r
d1102dba 251 @param DestAddr The destination HW MAC address. If HeaderSize is zero, then\r
4cda7726 252 this parameter is ignored.\r
d1102dba
LG
253 @param Protocol The type of header to build. If HeaderSize is zero, then this\r
254 parameter is ignored. See RFC 1700, section "Ether Types,"\r
4cda7726 255 for examples.\r
256\r
257 @retval EFI_SUCCESS The packet was placed on the transmit queue.\r
258 @retval EFI_NOT_STARTED The network interface has not been started.\r
259 @retval EFI_NOT_READY The network interface is too busy to accept this\r
260 transmit request.\r
261 @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
262 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported\r
263 value.\r
264 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
265 @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
a3c5f87a 266\r
267**/\r
268EFI_STATUS\r
269EFIAPI\r
4cda7726 270SnpUndi32Transmit (\r
d1050b9d
MK
271 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
272 IN UINTN HeaderSize,\r
273 IN UINTN BufferSize,\r
274 IN VOID *Buffer,\r
275 IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
276 IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
277 IN UINT16 *Protocol OPTIONAL\r
a3c5f87a 278 )\r
279{\r
4cda7726 280 SNP_DRIVER *Snp;\r
a3c5f87a 281 EFI_STATUS Status;\r
282 EFI_TPL OldTpl;\r
283\r
4cda7726 284 if (This == NULL) {\r
a3c5f87a 285 return EFI_INVALID_PARAMETER;\r
286 }\r
287\r
4cda7726 288 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
a3c5f87a 289\r
290 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
291\r
4cda7726 292 if (Snp == NULL) {\r
a3c5f87a 293 return EFI_DEVICE_ERROR;\r
294 }\r
295\r
4cda7726 296 switch (Snp->Mode.State) {\r
d1050b9d
MK
297 case EfiSimpleNetworkInitialized:\r
298 break;\r
a3c5f87a 299\r
d1050b9d
MK
300 case EfiSimpleNetworkStopped:\r
301 Status = EFI_NOT_STARTED;\r
302 goto ON_EXIT;\r
a3c5f87a 303\r
d1050b9d
MK
304 default:\r
305 Status = EFI_DEVICE_ERROR;\r
306 goto ON_EXIT;\r
a3c5f87a 307 }\r
308\r
4cda7726 309 if (Buffer == NULL) {\r
a3c5f87a 310 Status = EFI_INVALID_PARAMETER;\r
311 goto ON_EXIT;\r
312 }\r
313\r
4cda7726 314 if (BufferSize < Snp->Mode.MediaHeaderSize) {\r
a3c5f87a 315 Status = EFI_BUFFER_TOO_SMALL;\r
316 goto ON_EXIT;\r
317 }\r
318\r
319 //\r
4cda7726 320 // if the HeaderSize is non-zero, we need to fill up the header and for that\r
a3c5f87a 321 // we need the destination address and the protocol\r
322 //\r
4cda7726 323 if (HeaderSize != 0) {\r
d1050b9d 324 if ((HeaderSize != Snp->Mode.MediaHeaderSize) || (DestAddr == 0) || (Protocol == 0)) {\r
a3c5f87a 325 Status = EFI_INVALID_PARAMETER;\r
326 goto ON_EXIT;\r
327 }\r
328\r
4cda7726 329 Status = PxeFillHeader (\r
d1050b9d
MK
330 Snp,\r
331 Buffer,\r
332 HeaderSize,\r
333 (UINT8 *)Buffer + HeaderSize,\r
334 BufferSize - HeaderSize,\r
335 DestAddr,\r
336 SrcAddr,\r
337 Protocol\r
338 );\r
a3c5f87a 339\r
340 if (EFI_ERROR (Status)) {\r
341 goto ON_EXIT;\r
342 }\r
343 }\r
344\r
4cda7726 345 Status = PxeTransmit (Snp, Buffer, BufferSize);\r
a3c5f87a 346\r
347ON_EXIT:\r
348 gBS->RestoreTPL (OldTpl);\r
349\r
350 return Status;\r
351}\r