]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/transmit.c
Remove gEfiNetworkInterfaceIdentifierProtocolGuid reference from code base. Only...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / transmit.c
CommitLineData
8a67d61d 1/** @file\r
2Copyright (c) 2004 - 2007, Intel Corporation\r
3All rights reserved. This program and the accompanying materials\r
4are licensed and made available under the terms and conditions of the BSD License\r
5which accompanies this distribution. The full text of the license may be found at\r
6http://opensource.org/licenses/bsd-license.php\r
7\r
8THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10\r
11Module name:\r
12\r
13 transmit.c\r
14\r
15Abstract:\r
16\r
17Revision history:\r
18 2000-Feb-03 M(f)J Genesis.\r
19\r
20**/\r
21\r
22#include "Snp.h"\r
23\r
24\r
25/**\r
26 This routine calls undi to create the meadia header for the given data buffer.\r
27\r
28 @param snp pointer to SNP driver structure\r
29 @param MacHeaderPtr address where the media header will be filled in.\r
30 @param MacHeaderSize size of the memory at MacHeaderPtr\r
31 @param BufferPtr data buffer pointer\r
32 @param BufferLength Size of data in the BufferPtr\r
33 @param DestinationAddrPtr address of the destination mac address buffer\r
34 @param SourceAddrPtr address of the source mac address buffer\r
35 @param ProtocolPtr address of the protocol type\r
36\r
37 @retval EFI_SUCCESS if successfully completed the undi call\r
38 @retval Other error return from undi call.\r
39\r
40**/\r
41STATIC\r
42EFI_STATUS\r
43pxe_fillheader (\r
44 SNP_DRIVER *snp,\r
45 VOID *MacHeaderPtr,\r
46 UINTN MacHeaderSize,\r
47 VOID *BufferPtr,\r
48 UINTN BufferLength,\r
49 EFI_MAC_ADDRESS *DestinationAddrPtr,\r
50 EFI_MAC_ADDRESS *SourceAddrPtr,\r
51 UINT16 *ProtocolPtr\r
52 )\r
53{\r
54 PXE_CPB_FILL_HEADER_FRAGMENTED *cpb;\r
8a67d61d 55\r
56 cpb = snp->cpb;\r
57 if (SourceAddrPtr) {\r
58 CopyMem (\r
59 (VOID *) cpb->SrcAddr,\r
60 (VOID *) SourceAddrPtr,\r
61 snp->mode.HwAddressSize\r
62 );\r
63 } else {\r
64 CopyMem (\r
65 (VOID *) cpb->SrcAddr,\r
66 (VOID *) &(snp->mode.CurrentAddress),\r
67 snp->mode.HwAddressSize\r
68 );\r
69 }\r
70\r
71 CopyMem (\r
72 (VOID *) cpb->DestAddr,\r
73 (VOID *) DestinationAddrPtr,\r
74 snp->mode.HwAddressSize\r
75 );\r
76\r
77 //\r
78 // we need to do the byte swapping\r
79 //\r
80 cpb->Protocol = (UINT16) PXE_SWAP_UINT16 (*ProtocolPtr);\r
81\r
82 cpb->PacketLen = (UINT32) (BufferLength);\r
83 cpb->MediaHeaderLen = (UINT16) MacHeaderSize;\r
84\r
85 cpb->FragCnt = 2;\r
86 cpb->reserved = 0;\r
87\r
88 cpb->FragDesc[0].FragAddr = (UINT64)(UINTN) MacHeaderPtr;\r
89 cpb->FragDesc[0].FragLen = (UINT32) MacHeaderSize;\r
90 cpb->FragDesc[1].FragAddr = (UINT64)(UINTN) BufferPtr;\r
91 cpb->FragDesc[1].FragLen = (UINT32) BufferLength;\r
92\r
93 cpb->FragDesc[0].reserved = cpb->FragDesc[1].reserved = 0;\r
94\r
8a67d61d 95 snp->cdb.OpCode = PXE_OPCODE_FILL_HEADER;\r
96 snp->cdb.OpFlags = PXE_OPFLAGS_FILL_HEADER_FRAGMENTED;\r
97\r
98 snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;\r
99 snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;\r
100\r
101 snp->cdb.CPBsize = sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED);\r
102 snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;\r
103\r
104 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
105 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
106 snp->cdb.IFnum = snp->if_num;\r
107 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
108\r
109 //\r
110 // Issue UNDI command and check result.\r
111 //\r
112 DEBUG ((EFI_D_NET, "\nsnp->undi.fill_header() "));\r
113\r
114 (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);\r
115\r
8a67d61d 116 switch (snp->cdb.StatCode) {\r
117 case PXE_STATCODE_SUCCESS:\r
118 return EFI_SUCCESS;\r
119\r
120 case PXE_STATCODE_INVALID_PARAMETER:\r
121 DEBUG (\r
122 (EFI_D_ERROR,\r
123 "\nsnp->undi.fill_header() %xh:%xh\n",\r
124 snp->cdb.StatFlags,\r
125 snp->cdb.StatCode)\r
126 );\r
127\r
128 return EFI_INVALID_PARAMETER;\r
129\r
130 default:\r
131 DEBUG (\r
132 (EFI_D_ERROR,\r
133 "\nsnp->undi.fill_header() %xh:%xh\n",\r
134 snp->cdb.StatFlags,\r
135 snp->cdb.StatCode)\r
136 );\r
137\r
138 return EFI_DEVICE_ERROR;\r
139 }\r
140}\r
141\r
142\r
143/**\r
144 This routine calls undi to transmit the given data buffer\r
145\r
146 @param snp pointer to SNP driver structure\r
147 @param BufferPtr data buffer pointer\r
148 @param BufferLength Size of data in the BufferPtr\r
149\r
150 @retval EFI_SUCCESS if successfully completed the undi call\r
151 @retval Other error return from undi call.\r
152\r
153**/\r
154STATIC\r
155EFI_STATUS\r
156pxe_transmit (\r
157 SNP_DRIVER *snp,\r
158 VOID *BufferPtr,\r
159 UINTN BufferLength\r
160 )\r
161{\r
162 PXE_CPB_TRANSMIT *cpb;\r
163 EFI_STATUS Status;\r
8a67d61d 164\r
165 cpb = snp->cpb;\r
166 cpb->FrameAddr = (UINT64) (UINTN) BufferPtr;\r
167 cpb->DataLen = (UINT32) BufferLength;\r
8a67d61d 168\r
169 cpb->MediaheaderLen = 0;\r
170 cpb->reserved = 0;\r
171\r
172 snp->cdb.OpFlags = PXE_OPFLAGS_TRANSMIT_WHOLE;\r
173\r
174 snp->cdb.CPBsize = sizeof (PXE_CPB_TRANSMIT);\r
175 snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;\r
176\r
177 snp->cdb.OpCode = PXE_OPCODE_TRANSMIT;\r
178 snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;\r
179 snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;\r
180\r
181 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
182 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
183 snp->cdb.IFnum = snp->if_num;\r
184 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
185\r
186 //\r
187 // Issue UNDI command and check result.\r
188 //\r
189 DEBUG ((EFI_D_NET, "\nsnp->undi.transmit() "));\r
190 DEBUG ((EFI_D_NET, "\nsnp->cdb.OpCode == %x", snp->cdb.OpCode));\r
191 DEBUG ((EFI_D_NET, "\nsnp->cdb.CPBaddr == %X", snp->cdb.CPBaddr));\r
192 DEBUG ((EFI_D_NET, "\nsnp->cdb.DBaddr == %X", snp->cdb.DBaddr));\r
193 DEBUG ((EFI_D_NET, "\ncpb->FrameAddr == %X\n", cpb->FrameAddr));\r
194\r
195 (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);\r
196\r
197 DEBUG ((EFI_D_NET, "\nexit snp->undi.transmit() "));\r
198 DEBUG ((EFI_D_NET, "\nsnp->cdb.StatCode == %r", snp->cdb.StatCode));\r
199\r
200 //\r
201 // we will unmap the buffers in get_status call, not here\r
202 //\r
203 switch (snp->cdb.StatCode) {\r
204 case PXE_STATCODE_SUCCESS:\r
205 return EFI_SUCCESS;\r
206\r
207 case PXE_STATCODE_QUEUE_FULL:\r
208 case PXE_STATCODE_BUSY:\r
209 Status = EFI_NOT_READY;\r
210 break;\r
211\r
212 default:\r
213 Status = EFI_DEVICE_ERROR;\r
214 }\r
215\r
216 DEBUG (\r
217 (EFI_D_ERROR,\r
218 "\nsnp->undi.transmit() %xh:%xh\n",\r
219 snp->cdb.StatFlags,\r
220 snp->cdb.StatCode)\r
221 );\r
222\r
223 return Status;\r
224}\r
225\r
226\r
227/**\r
228 This is the snp interface routine for transmitting a packet. this routine\r
229 basically retrieves the snp structure, checks the snp state and calls\r
230 pxe_fill_header and pxe_transmit calls to complete the transmission.\r
231\r
232 @param this pointer to SNP driver context\r
233 @param MacHeaderSize size of the memory at MacHeaderPtr\r
234 @param BufferLength Size of data in the BufferPtr\r
235 @param BufferPtr data buffer pointer\r
236 @param SourceAddrPtr address of the source mac address buffer\r
237 @param DestinationAddrPtr address of the destination mac address buffer\r
238 @param ProtocolPtr address of the protocol type\r
239\r
240 @retval EFI_SUCCESS if successfully completed the undi call\r
241 @retval Other error return from undi call.\r
242\r
243**/\r
244EFI_STATUS\r
245EFIAPI\r
246snp_undi32_transmit (\r
247 IN EFI_SIMPLE_NETWORK_PROTOCOL * this,\r
248 IN UINTN MacHeaderSize,\r
249 IN UINTN BufferLength,\r
250 IN VOID *BufferPtr,\r
251 IN EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL,\r
252 IN EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL,\r
253 IN UINT16 *ProtocolPtr OPTIONAL\r
254 )\r
255{\r
256 SNP_DRIVER *snp;\r
257 EFI_STATUS Status;\r
258 EFI_TPL OldTpl;\r
259\r
260 if (this == NULL) {\r
261 return EFI_INVALID_PARAMETER;\r
262 }\r
263\r
264 snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);\r
265\r
266 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
267\r
268 if (snp == NULL) {\r
269 return EFI_DEVICE_ERROR;\r
270 }\r
271\r
272 switch (snp->mode.State) {\r
273 case EfiSimpleNetworkInitialized:\r
274 break;\r
275\r
276 case EfiSimpleNetworkStopped:\r
277 Status = EFI_NOT_STARTED;\r
278 goto ON_EXIT;\r
279\r
280 default:\r
281 Status = EFI_DEVICE_ERROR;\r
282 goto ON_EXIT;\r
283 }\r
284\r
285 if (BufferPtr == NULL) {\r
286 Status = EFI_INVALID_PARAMETER;\r
287 goto ON_EXIT;\r
288 }\r
289\r
290 if (BufferLength < snp->mode.MediaHeaderSize) {\r
291 Status = EFI_BUFFER_TOO_SMALL;\r
292 goto ON_EXIT;\r
293 }\r
294\r
295 //\r
296 // if the MacHeaderSize is non-zero, we need to fill up the header and for that\r
297 // we need the destination address and the protocol\r
298 //\r
299 if (MacHeaderSize != 0) {\r
300 if (MacHeaderSize != snp->mode.MediaHeaderSize || DestinationAddrPtr == 0 || ProtocolPtr == 0) {\r
301 Status = EFI_INVALID_PARAMETER;\r
302 goto ON_EXIT;\r
303 }\r
304\r
305 Status = pxe_fillheader (\r
306 snp,\r
307 BufferPtr,\r
308 MacHeaderSize,\r
309 (UINT8 *) BufferPtr + MacHeaderSize,\r
310 BufferLength - MacHeaderSize,\r
311 DestinationAddrPtr,\r
312 SourceAddrPtr,\r
313 ProtocolPtr\r
314 );\r
315\r
316 if (EFI_ERROR (Status)) {\r
317 goto ON_EXIT;\r
318 }\r
319 }\r
320\r
321 Status = pxe_transmit (snp, BufferPtr, BufferLength);\r
322\r
323ON_EXIT:\r
324 gBS->RestoreTPL (OldTpl);\r
325\r
326 return Status;\r
327}\r