]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Network/Snp32_64/Dxe/transmit.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[mirror_edk2.git] / EdkModulePkg / Universal / Network / Snp32_64 / Dxe / transmit.c
CommitLineData
878ddf1f 1/*++\r
2Copyright (c) 2006, 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
4cbd855e 22#include "Snp.h"\r
878ddf1f 23\r
1cc8ee78 24STATIC\r
878ddf1f 25EFI_STATUS\r
26pxe_fillheader (\r
27 SNP_DRIVER *snp,\r
28 VOID *MacHeaderPtr,\r
29 UINTN MacHeaderSize,\r
30 VOID *BufferPtr,\r
31 UINTN BufferLength,\r
32 EFI_MAC_ADDRESS *DestinationAddrPtr,\r
33 EFI_MAC_ADDRESS *SourceAddrPtr,\r
34 UINT16 *ProtocolPtr\r
35 )\r
36/*++\r
37\r
38Routine Description:\r
39 This routine calls undi to create the meadia header for the given data buffer.\r
40 \r
41Arguments:\r
42 snp - pointer to SNP driver structure\r
43 MacHeaderPtr - address where the media header will be filled in.\r
44 MacHeaderSize - size of the memory at MacHeaderPtr\r
45 BufferPtr - data buffer pointer\r
46 BufferLength - Size of data in the BufferPtr\r
47 DestinationAddrPtr - address of the destination mac address buffer\r
48 SourceAddrPtr - address of the source mac address buffer\r
49 ProtocolPtr - address of the protocol type\r
50 \r
51Returns:\r
52 EFI_SUCCESS - if successfully completed the undi call\r
53 Other - error return from undi call.\r
54 \r
55--*/\r
56{\r
57 PXE_CPB_FILL_HEADER_FRAGMENTED *cpb;\r
58 EFI_STATUS Status;\r
59 struct s_v2p *pkt_v2p;\r
60 UINT64 TempData;\r
61\r
62 cpb = snp->cpb;\r
63 if (SourceAddrPtr) {\r
64 CopyMem (\r
65 (VOID *) cpb->SrcAddr,\r
66 (VOID *) SourceAddrPtr,\r
67 snp->mode.HwAddressSize\r
68 );\r
69 } else {\r
70 CopyMem (\r
71 (VOID *) cpb->SrcAddr,\r
72 (VOID *) &(snp->mode.CurrentAddress),\r
73 snp->mode.HwAddressSize\r
74 );\r
75 }\r
76\r
77 CopyMem (\r
78 (VOID *) cpb->DestAddr,\r
79 (VOID *) DestinationAddrPtr,\r
80 snp->mode.HwAddressSize\r
81 );\r
82\r
83 //\r
84 // we need to do the byte swapping\r
85 //\r
86 cpb->Protocol = (UINT16) PXE_SWAP_UINT16 (*ProtocolPtr);\r
87\r
88 cpb->PacketLen = (UINT32) (BufferLength);\r
89 cpb->MediaHeaderLen = (UINT16) MacHeaderSize;\r
90\r
91 cpb->FragCnt = 2;\r
92 cpb->reserved = 0;\r
93\r
94 cpb->FragDesc[0].FragAddr = (UINT64) (UINTN) MacHeaderPtr;\r
95 cpb->FragDesc[0].FragLen = (UINT32) MacHeaderSize;\r
96 cpb->FragDesc[1].FragAddr = (UINT64) (UINTN) BufferPtr;\r
97 cpb->FragDesc[1].FragLen = (UINT32) BufferLength;\r
98\r
99 cpb->FragDesc[0].reserved = cpb->FragDesc[1].reserved = 0;\r
100\r
101 if (snp->IsOldUndi) {\r
102 TempData = (UINT64) (UINTN) MacHeaderPtr;\r
103 if (TempData >= FOUR_GIGABYTES) {\r
104 cpb->FragDesc[0].FragAddr = (UINT64) (UINTN) snp->fill_hdr_buf;\r
105 cpb->FragDesc[0].FragLen = (UINT32) snp->init_info.MediaHeaderLen;\r
106 }\r
107\r
108 TempData = (UINT64) (UINTN) (BufferPtr);\r
109 if (TempData >= FOUR_GIGABYTES) {\r
110 //\r
111 // Let the device just read this buffer\r
112 //\r
113 Status = add_v2p (\r
114 &pkt_v2p,\r
115 EfiPciIoOperationBusMasterRead,\r
116 BufferPtr,\r
117 BufferLength\r
118 );\r
119 if (Status != EFI_SUCCESS) {\r
120 return Status;\r
121 }\r
122 //\r
123 // give the virtual address to UNDI and it will call back on Virt2Phys\r
124 // to get the mapped address, if it needs it\r
125 //\r
126 cpb->FragDesc[1].FragLen = (UINT32) pkt_v2p->bsize;\r
127 }\r
128 }\r
129\r
130 snp->cdb.OpCode = PXE_OPCODE_FILL_HEADER;\r
131 snp->cdb.OpFlags = PXE_OPFLAGS_FILL_HEADER_FRAGMENTED;\r
132\r
133 snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;\r
134 snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;\r
135\r
136 snp->cdb.CPBsize = sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED);\r
137 snp->cdb.CPBaddr = (UINT64) (UINTN) cpb;\r
138\r
139 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
140 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
141 snp->cdb.IFnum = snp->if_num;\r
142 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
143\r
144 //\r
145 // Issue UNDI command and check result.\r
146 //\r
147 DEBUG ((EFI_D_NET, "\nsnp->undi.fill_header() "));\r
148\r
149 (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);\r
150\r
151 if (snp->IsOldUndi) {\r
152 TempData = (UINT64) (UINTN) (BufferPtr);\r
153 if (TempData >= FOUR_GIGABYTES) {\r
154 del_v2p (BufferPtr);\r
155 }\r
156 //\r
157 // if we used the global buffer for header, copy the contents\r
158 //\r
159 TempData = (UINT64) (UINTN) MacHeaderPtr;\r
160 if (TempData >= FOUR_GIGABYTES) {\r
161 CopyMem (\r
162 MacHeaderPtr,\r
163 snp->fill_hdr_buf,\r
164 snp->init_info.MediaHeaderLen\r
165 );\r
166 }\r
167 }\r
168\r
169 switch (snp->cdb.StatCode) {\r
170 case PXE_STATCODE_SUCCESS:\r
171 return EFI_SUCCESS;\r
172\r
173 case PXE_STATCODE_INVALID_PARAMETER:\r
174 DEBUG (\r
175 (EFI_D_ERROR,\r
176 "\nsnp->undi.fill_header() %xh:%xh\n",\r
177 snp->cdb.StatFlags,\r
178 snp->cdb.StatCode)\r
179 );\r
180\r
181 return EFI_INVALID_PARAMETER;\r
182\r
183 default:\r
184 DEBUG (\r
185 (EFI_D_ERROR,\r
186 "\nsnp->undi.fill_header() %xh:%xh\n",\r
187 snp->cdb.StatFlags,\r
188 snp->cdb.StatCode)\r
189 );\r
190\r
191 return EFI_DEVICE_ERROR;\r
192 }\r
193}\r
194\r
1cc8ee78 195STATIC\r
878ddf1f 196EFI_STATUS\r
197pxe_transmit (\r
198 SNP_DRIVER *snp,\r
199 VOID *BufferPtr,\r
200 UINTN BufferLength\r
201 )\r
202/*++\r
203\r
204Routine Description:\r
205 This routine calls undi to transmit the given data buffer\r
206 \r
207Arguments:\r
208 snp - pointer to SNP driver structure\r
209 BufferPtr - data buffer pointer\r
210 BufferLength - Size of data in the BufferPtr\r
211 \r
212Returns:\r
213 EFI_SUCCESS - if successfully completed the undi call\r
214 Other - error return from undi call.\r
215 \r
216--*/\r
217{\r
218 PXE_CPB_TRANSMIT *cpb;\r
219 EFI_STATUS Status;\r
220 struct s_v2p *v2p;\r
221 UINT64 TempData;\r
222\r
223 cpb = snp->cpb;\r
224 cpb->FrameAddr = (UINT64) (UINTN) BufferPtr;\r
225 cpb->DataLen = (UINT32) BufferLength;\r
226 \r
227 TempData = (UINT64) (UINTN) BufferPtr;\r
228 if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {\r
229 //\r
230 // we need to create a mapping now and give it to the undi when it calls\r
231 // the Virt2Phys on this address.\r
232 // this is a transmit, just map it for the device to READ\r
233 //\r
234 Status = add_v2p (\r
235 &v2p,\r
236 EfiPciIoOperationBusMasterRead,\r
237 BufferPtr,\r
238 BufferLength\r
239 );\r
240 if (Status != EFI_SUCCESS) {\r
241 return Status;\r
242 }\r
243\r
244 cpb->DataLen = (UINT32) v2p->bsize;\r
245 }\r
246\r
247 cpb->MediaheaderLen = 0;\r
248 cpb->reserved = 0;\r
249\r
250 snp->cdb.OpFlags = PXE_OPFLAGS_TRANSMIT_WHOLE;\r
251\r
252 snp->cdb.CPBsize = sizeof (PXE_CPB_TRANSMIT);\r
253 snp->cdb.CPBaddr = (UINT64) (UINTN) cpb;\r
254\r
255 snp->cdb.OpCode = PXE_OPCODE_TRANSMIT;\r
256 snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;\r
257 snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;\r
258\r
259 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
260 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
261 snp->cdb.IFnum = snp->if_num;\r
262 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
263\r
264 //\r
265 // Issue UNDI command and check result.\r
266 //\r
267 DEBUG ((EFI_D_NET, "\nsnp->undi.transmit() "));\r
268 DEBUG ((EFI_D_NET, "\nsnp->cdb.OpCode == %x", snp->cdb.OpCode));\r
269 DEBUG ((EFI_D_NET, "\nsnp->cdb.CPBaddr == %X", snp->cdb.CPBaddr));\r
270 DEBUG ((EFI_D_NET, "\nsnp->cdb.DBaddr == %X", snp->cdb.DBaddr));\r
271 DEBUG ((EFI_D_NET, "\ncpb->FrameAddr == %X\n", cpb->FrameAddr));\r
272\r
273 (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);\r
274\r
275 DEBUG ((EFI_D_NET, "\nexit snp->undi.transmit() "));\r
276 DEBUG ((EFI_D_NET, "\nsnp->cdb.StatCode == %r", snp->cdb.StatCode));\r
277\r
278 //\r
279 // we will unmap the buffers in get_status call, not here\r
280 //\r
281 switch (snp->cdb.StatCode) {\r
282 case PXE_STATCODE_SUCCESS:\r
283 return EFI_SUCCESS;\r
284\r
285 case PXE_STATCODE_QUEUE_FULL:\r
286 case PXE_STATCODE_BUSY:\r
287 Status = EFI_NOT_READY;\r
288 break;\r
289\r
290 default:\r
291 Status = EFI_DEVICE_ERROR;\r
292 }\r
293\r
294 DEBUG (\r
295 (EFI_D_ERROR,\r
296 "\nsnp->undi.transmit() %xh:%xh\n",\r
297 snp->cdb.StatFlags,\r
298 snp->cdb.StatCode)\r
299 );\r
300\r
301 return Status;\r
302}\r
303\r
304EFI_STATUS\r
305EFIAPI\r
306snp_undi32_transmit (\r
307 IN EFI_SIMPLE_NETWORK_PROTOCOL * this,\r
308 IN UINTN MacHeaderSize,\r
309 IN UINTN BufferLength,\r
310 IN VOID *BufferPtr,\r
311 IN EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL,\r
312 IN EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL,\r
313 IN UINT16 *ProtocolPtr OPTIONAL\r
314 )\r
315/*++\r
316\r
317Routine Description:\r
318 This is the snp interface routine for transmitting a packet. this routine \r
319 basically retrieves the snp structure, checks the snp state and calls\r
320 pxe_fill_header and pxe_transmit calls to complete the transmission.\r
321 \r
322Arguments:\r
323 this - pointer to SNP driver context\r
324 MacHeaderSize - size of the memory at MacHeaderPtr\r
325 BufferLength - Size of data in the BufferPtr\r
326 BufferPtr - data buffer pointer\r
327 SourceAddrPtr - address of the source mac address buffer\r
328 DestinationAddrPtr - address of the destination mac address buffer\r
329 ProtocolPtr - address of the protocol type\r
330 \r
331Returns:\r
332 EFI_SUCCESS - if successfully completed the undi call\r
333 Other - error return from undi call.\r
334 \r
335--*/\r
336{\r
337 SNP_DRIVER *snp;\r
338 EFI_STATUS Status;\r
339\r
340 if (this == NULL) {\r
341 return EFI_INVALID_PARAMETER;\r
342 }\r
343\r
344 snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);\r
345\r
346 if (snp == NULL) {\r
347 return EFI_DEVICE_ERROR;\r
348 }\r
349\r
350 switch (snp->mode.State) {\r
351 case EfiSimpleNetworkInitialized:\r
352 break;\r
353\r
354 case EfiSimpleNetworkStopped:\r
355 return EFI_NOT_STARTED;\r
356\r
357 case EfiSimpleNetworkStarted:\r
358 return EFI_DEVICE_ERROR;\r
359\r
360 default:\r
361 return EFI_DEVICE_ERROR;\r
362 }\r
363\r
364 if (BufferPtr == NULL) {\r
365 return EFI_INVALID_PARAMETER;\r
366 }\r
367\r
368 if (BufferLength < snp->mode.MediaHeaderSize) {\r
369 return EFI_BUFFER_TOO_SMALL;\r
370 }\r
371\r
372 //\r
373 // if the MacHeaderSize is non-zero, we need to fill up the header and for that\r
374 // we need the destination address and the protocol\r
375 //\r
376 if (MacHeaderSize != 0) {\r
377 if (MacHeaderSize != snp->mode.MediaHeaderSize || DestinationAddrPtr == 0 || ProtocolPtr == 0) {\r
378 return EFI_INVALID_PARAMETER;\r
379 }\r
380\r
381 Status = pxe_fillheader (\r
382 snp,\r
383 BufferPtr,\r
384 MacHeaderSize,\r
385 (UINT8 *) BufferPtr + MacHeaderSize,\r
386 BufferLength - MacHeaderSize,\r
387 DestinationAddrPtr,\r
388 SourceAddrPtr,\r
389 ProtocolPtr\r
390 );\r
391\r
392 if (Status != EFI_SUCCESS) {\r
393 return Status;\r
394 }\r
395 }\r
396\r
397 return pxe_transmit (snp, BufferPtr, BufferLength);\r
398}\r