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