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