2 Implementation of receiving a packet from a network interface.
4 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed
6 and made available under the terms and conditions of the BSD License which
7 accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Call UNDI to receive a packet and fills in the data in the input pointers.
21 @param Snp Pointer to snp driver structure
22 @param Buffer Pointer to the memory for the received data
23 @param BufferSize Pointer to the length of the buffer on entry and contains
24 the length of the received data on return
25 @param HeaderSize Pointer to the header portion of the data received.
26 @param SrcAddr Pointer to contain the source ethernet address on return
27 @param DestAddr Pointer to contain the destination ethernet address on
29 @param Protocol Pointer to contain the protocol type from the ethernet
33 @retval EFI_SUCCESS The received data was stored in Buffer, and
34 BufferSize has been updated to the number of
36 @retval EFI_DEVICE_ERROR Fail to execute UNDI command.
37 @retval EFI_NOT_READY No packets have been received on the network
39 @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received
40 packets. BufferSize has been updated to the
50 EFI_MAC_ADDRESS
*SrcAddr
,
51 EFI_MAC_ADDRESS
*DestAddr
,
61 BuffSize
= *BufferSize
;
63 Cpb
->BufferAddr
= (UINT64
)(UINTN
) Buffer
;
64 Cpb
->BufferLen
= (UINT32
) *BufferSize
;
68 Snp
->Cdb
.OpCode
= PXE_OPCODE_RECEIVE
;
69 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
71 Snp
->Cdb
.CPBsize
= (UINT16
) sizeof (PXE_CPB_RECEIVE
);
72 Snp
->Cdb
.CPBaddr
= (UINT64
)(UINTN
) Cpb
;
74 Snp
->Cdb
.DBsize
= (UINT16
) sizeof (PXE_DB_RECEIVE
);
75 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) Db
;
77 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
78 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
79 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
80 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
83 // Issue UNDI command and check result.
85 DEBUG ((EFI_D_NET
, "\nsnp->undi.receive () "));
87 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
89 switch (Snp
->Cdb
.StatCode
) {
90 case PXE_STATCODE_SUCCESS
:
93 case PXE_STATCODE_NO_DATA
:
96 "\nsnp->undi.receive () %xh:%xh\n",
101 return EFI_NOT_READY
;
106 "\nsnp->undi.receive() %xh:%xh\n",
111 return EFI_DEVICE_ERROR
;
114 *BufferSize
= Db
->FrameLen
;
116 if (HeaderSize
!= NULL
) {
117 *HeaderSize
= Db
->MediaHeaderLen
;
120 if (SrcAddr
!= NULL
) {
121 CopyMem (SrcAddr
, &Db
->SrcAddr
, Snp
->Mode
.HwAddressSize
);
124 if (DestAddr
!= NULL
) {
125 CopyMem (DestAddr
, &Db
->DestAddr
, Snp
->Mode
.HwAddressSize
);
128 if (Protocol
!= NULL
) {
130 // We need to do the byte swapping
132 *Protocol
= (UINT16
) PXE_SWAP_UINT16 (Db
->Protocol
);
136 // We have received a packet from network interface, which implies that the
137 // network cable should be present. While, some UNDI driver may not report
138 // correct media status during Snp->Initialize(). So, we need ensure
139 // MediaPresent in SNP mode data is set to correct value.
141 if (Snp
->Mode
.MediaPresentSupported
&& !Snp
->Mode
.MediaPresent
) {
142 Snp
->Mode
.MediaPresent
= TRUE
;
145 return (*BufferSize
<= BuffSize
) ? EFI_SUCCESS
: EFI_BUFFER_TOO_SMALL
;
149 Receives a packet from a network interface.
151 This function retrieves one packet from the receive queue of a network interface.
152 If there are no packets on the receive queue, then EFI_NOT_READY will be
153 returned. If there is a packet on the receive queue, and the size of the packet
154 is smaller than BufferSize, then the contents of the packet will be placed in
155 Buffer, and BufferSize will be updated with the actual size of the packet.
156 In addition, if SrcAddr, DestAddr, and Protocol are not NULL, then these values
157 will be extracted from the media header and returned. EFI_SUCCESS will be
158 returned if a packet was successfully received.
159 If BufferSize is smaller than the received packet, then the size of the receive
160 packet will be placed in BufferSize and EFI_BUFFER_TOO_SMALL will be returned.
161 If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
163 @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
164 @param HeaderSize The size, in bytes, of the media header received on the network
165 interface. If this parameter is NULL, then the media header size
166 will not be returned.
167 @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
168 bytes, of the packet that was received on the network interface.
169 @param Buffer A pointer to the data buffer to receive both the media
171 @param SrcAddr The source HW MAC address. If this parameter is NULL, the HW
172 MAC source address will not be extracted from the media header.
173 @param DestAddr The destination HW MAC address. If this parameter is NULL,
174 the HW MAC destination address will not be extracted from
176 @param Protocol The media header type. If this parameter is NULL, then the
177 protocol will not be extracted from the media header. See
178 RFC 1700 section "Ether Types" for examples.
180 @retval EFI_SUCCESS The received data was stored in Buffer, and
181 BufferSize has been updated to the number of
183 @retval EFI_NOT_STARTED The network interface has not been started.
184 @retval EFI_NOT_READY No packets have been received on the network interface.
185 @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received packets.
186 BufferSize has been updated to the required size.
187 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
188 * The This parameter is NULL
189 * The This parameter does not point to a valid
190 EFI_SIMPLE_NETWORK_PROTOCOL structure.
191 * The BufferSize parameter is NULL
192 * The Buffer parameter is NULL
193 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
199 IN EFI_SIMPLE_NETWORK_PROTOCOL
*This
,
200 OUT UINTN
*HeaderSize OPTIONAL
,
201 IN OUT UINTN
*BufferSize
,
203 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
204 OUT EFI_MAC_ADDRESS
*DestAddr OPTIONAL
,
205 OUT UINT16
*Protocol OPTIONAL
213 return EFI_INVALID_PARAMETER
;
216 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This
);
218 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
220 switch (Snp
->Mode
.State
) {
221 case EfiSimpleNetworkInitialized
:
224 case EfiSimpleNetworkStopped
:
225 Status
= EFI_NOT_STARTED
;
229 Status
= EFI_DEVICE_ERROR
;
233 if ((BufferSize
== NULL
) || (Buffer
== NULL
)) {
234 Status
= EFI_INVALID_PARAMETER
;
238 if (Snp
->Mode
.ReceiveFilterSetting
== 0) {
239 Status
= EFI_DEVICE_ERROR
;
243 Status
= PxeReceive (
254 gBS
->RestoreTPL (OldTpl
);