]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Receive.c
Enhance SNP to be compatible with UNDI driver which doesn’t report correct network...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Receive.c
CommitLineData
3bb7aff3 1/** @file\r
4140a663 2 Implementation of receiving a packet from a network interface.\r
5fe48e54 3\r
4140a663 4Copyright (c) 2004 - 2010, Intel Corporation. <BR>\r
5fe48e54 5All rights reserved. This program and the accompanying materials are licensed\r
6and made available under the terms and conditions of the BSD License which\r
7accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
3bb7aff3 9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
3bb7aff3 13**/\r
14\r
15\r
16#include "Snp.h"\r
17\r
18/**\r
f3816027 19 Call UNDI to receive a packet and fills in the data in the input pointers.\r
20\r
21 @param Snp Pointer to snp driver structure\r
22 @param Buffer Pointer to the memory for the received data\r
23 @param BufferSize Pointer to the length of the buffer on entry and contains\r
24 the length of the received data on return\r
25 @param HeaderSize Pointer to the header portion of the data received.\r
5fe48e54 26 @param SrcAddr Pointer to contain the source ethernet address on return\r
27 @param DestAddr Pointer to contain the destination ethernet address on\r
f3816027 28 return\r
5fe48e54 29 @param Protocol Pointer to contain the protocol type from the ethernet\r
f3816027 30 header on return\r
31\r
32\r
5fe48e54 33 @retval EFI_SUCCESS The received data was stored in Buffer, and\r
34 BufferSize has been updated to the number of\r
f3816027 35 bytes received.\r
5fe48e54 36 @retval EFI_DEVICE_ERROR Fail to execute UNDI command.\r
37 @retval EFI_NOT_READY No packets have been received on the network\r
f3816027 38 interface.\r
5fe48e54 39 @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received\r
f3816027 40 packets. BufferSize has been updated to the\r
41 required size.\r
3bb7aff3 42\r
43**/\r
3bb7aff3 44EFI_STATUS\r
4cda7726 45PxeReceive (\r
46 SNP_DRIVER *Snp,\r
47 VOID *Buffer,\r
48 UINTN *BufferSize,\r
49 UINTN *HeaderSize,\r
50 EFI_MAC_ADDRESS *SrcAddr,\r
51 EFI_MAC_ADDRESS *DestAddr,\r
52 UINT16 *Protocol\r
3bb7aff3 53 )\r
54{\r
4cda7726 55 PXE_CPB_RECEIVE *Cpb;\r
56 PXE_DB_RECEIVE *Db;\r
57 UINTN BuffSize;\r
3bb7aff3 58\r
4cda7726 59 Cpb = Snp->Cpb;\r
60 Db = Snp->Db;\r
61 BuffSize = *BufferSize;\r
3bb7aff3 62\r
4cda7726 63 Cpb->BufferAddr = (UINT64)(UINTN) Buffer;\r
64 Cpb->BufferLen = (UINT32) *BufferSize;\r
3bb7aff3 65\r
4cda7726 66 Cpb->reserved = 0;\r
3bb7aff3 67\r
4cda7726 68 Snp->Cdb.OpCode = PXE_OPCODE_RECEIVE;\r
69 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
3bb7aff3 70\r
4cda7726 71 Snp->Cdb.CPBsize = sizeof (PXE_CPB_RECEIVE);\r
72 Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb;\r
3bb7aff3 73\r
4cda7726 74 Snp->Cdb.DBsize = sizeof (PXE_DB_RECEIVE);\r
75 Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;\r
3bb7aff3 76\r
4cda7726 77 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
78 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
79 Snp->Cdb.IFnum = Snp->IfNum;\r
80 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
3bb7aff3 81\r
82 //\r
83 // Issue UNDI command and check result.\r
84 //\r
5fe48e54 85 DEBUG ((EFI_D_NET, "\nsnp->undi.receive () "));\r
3bb7aff3 86\r
4cda7726 87 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
3bb7aff3 88\r
4cda7726 89 switch (Snp->Cdb.StatCode) {\r
3bb7aff3 90 case PXE_STATCODE_SUCCESS:\r
91 break;\r
92\r
93 case PXE_STATCODE_NO_DATA:\r
94 DEBUG (\r
5fe48e54 95 (EFI_D_NET,\r
3bb7aff3 96 "\nsnp->undi.receive () %xh:%xh\n",\r
4cda7726 97 Snp->Cdb.StatFlags,\r
98 Snp->Cdb.StatCode)\r
3bb7aff3 99 );\r
100\r
101 return EFI_NOT_READY;\r
102\r
103 default:\r
104 DEBUG (\r
9cff2f8d 105 (EFI_D_ERROR,\r
3bb7aff3 106 "\nsnp->undi.receive() %xh:%xh\n",\r
4cda7726 107 Snp->Cdb.StatFlags,\r
108 Snp->Cdb.StatCode)\r
3bb7aff3 109 );\r
110\r
111 return EFI_DEVICE_ERROR;\r
112 }\r
113\r
4cda7726 114 *BufferSize = Db->FrameLen;\r
3bb7aff3 115\r
4cda7726 116 if (HeaderSize != NULL) {\r
117 *HeaderSize = Db->MediaHeaderLen;\r
3bb7aff3 118 }\r
119\r
4cda7726 120 if (SrcAddr != NULL) {\r
121 CopyMem (SrcAddr, &Db->SrcAddr, Snp->Mode.HwAddressSize);\r
3bb7aff3 122 }\r
123\r
4cda7726 124 if (DestAddr != NULL) {\r
125 CopyMem (DestAddr, &Db->DestAddr, Snp->Mode.HwAddressSize);\r
3bb7aff3 126 }\r
127\r
4cda7726 128 if (Protocol != NULL) {\r
f3816027 129 //\r
130 // We need to do the byte swapping\r
131 //\r
132 *Protocol = (UINT16) PXE_SWAP_UINT16 (Db->Protocol);\r
3bb7aff3 133 }\r
134\r
553472f6 135 //\r
136 // We have received a packet from network interface, which implies that the\r
137 // network cable should be present. While, some UNDI driver may not report\r
138 // correct media status during Snp->Initialize(). So, we need ensure\r
139 // MediaPresent in SNP mode data is set to correct value.\r
140 //\r
141 if (Snp->Mode.MediaPresentSupported && !Snp->Mode.MediaPresent) {\r
142 Snp->Mode.MediaPresent = TRUE;\r
143 }\r
144\r
4cda7726 145 return (*BufferSize <= BuffSize) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
3bb7aff3 146}\r
147\r
3bb7aff3 148/**\r
4cda7726 149 Receives a packet from a network interface.\r
150\r
151 This function retrieves one packet from the receive queue of a network interface.\r
5fe48e54 152 If there are no packets on the receive queue, then EFI_NOT_READY will be\r
4cda7726 153 returned. If there is a packet on the receive queue, and the size of the packet\r
154 is smaller than BufferSize, then the contents of the packet will be placed in\r
155 Buffer, and BufferSize will be updated with the actual size of the packet.\r
156 In addition, if SrcAddr, DestAddr, and Protocol are not NULL, then these values\r
5fe48e54 157 will be extracted from the media header and returned. EFI_SUCCESS will be\r
4cda7726 158 returned if a packet was successfully received.\r
159 If BufferSize is smaller than the received packet, then the size of the receive\r
160 packet will be placed in BufferSize and EFI_BUFFER_TOO_SMALL will be returned.\r
161 If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.\r
162\r
163 @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.\r
5fe48e54 164 @param HeaderSize The size, in bytes, of the media header received on the network\r
165 interface. If this parameter is NULL, then the media header size\r
4cda7726 166 will not be returned.\r
5fe48e54 167 @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in\r
4cda7726 168 bytes, of the packet that was received on the network interface.\r
169 @param Buffer A pointer to the data buffer to receive both the media\r
170 header and the data.\r
171 @param SrcAddr The source HW MAC address. If this parameter is NULL, the HW\r
5fe48e54 172 MAC source address will not be extracted from the media header.\r
173 @param DestAddr The destination HW MAC address. If this parameter is NULL,\r
174 the HW MAC destination address will not be extracted from\r
4cda7726 175 the media header.\r
5fe48e54 176 @param Protocol The media header type. If this parameter is NULL, then the\r
177 protocol will not be extracted from the media header. See\r
4cda7726 178 RFC 1700 section "Ether Types" for examples.\r
179\r
5fe48e54 180 @retval EFI_SUCCESS The received data was stored in Buffer, and\r
181 BufferSize has been updated to the number of\r
4cda7726 182 bytes received.\r
183 @retval EFI_NOT_STARTED The network interface has not been started.\r
184 @retval EFI_NOT_READY No packets have been received on the network interface.\r
5fe48e54 185 @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received packets.\r
4cda7726 186 BufferSize has been updated to the required size.\r
187 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
188 * The This parameter is NULL\r
5fe48e54 189 * The This parameter does not point to a valid\r
4cda7726 190 EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
191 * The BufferSize parameter is NULL\r
192 * The Buffer parameter is NULL\r
193 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
3bb7aff3 194\r
195**/\r
196EFI_STATUS\r
197EFIAPI\r
4cda7726 198SnpUndi32Receive (\r
199 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
200 OUT UINTN *HeaderSize OPTIONAL,\r
201 IN OUT UINTN *BufferSize,\r
202 OUT VOID *Buffer,\r
203 OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
204 OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
205 OUT UINT16 *Protocol OPTIONAL\r
3bb7aff3 206 )\r
207{\r
4cda7726 208 SNP_DRIVER *Snp;\r
3bb7aff3 209 EFI_TPL OldTpl;\r
210 EFI_STATUS Status;\r
211\r
4cda7726 212 if (This == NULL) {\r
3bb7aff3 213 return EFI_INVALID_PARAMETER;\r
214 }\r
215\r
4cda7726 216 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
3bb7aff3 217\r
218 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
219\r
4cda7726 220 switch (Snp->Mode.State) {\r
3bb7aff3 221 case EfiSimpleNetworkInitialized:\r
222 break;\r
223\r
224 case EfiSimpleNetworkStopped:\r
225 Status = EFI_NOT_STARTED;\r
226 goto ON_EXIT;\r
227\r
228 default:\r
229 Status = EFI_DEVICE_ERROR;\r
230 goto ON_EXIT;\r
231 }\r
232\r
4cda7726 233 if ((BufferSize == NULL) || (Buffer == NULL)) {\r
3bb7aff3 234 Status = EFI_INVALID_PARAMETER;\r
235 goto ON_EXIT;\r
236 }\r
237\r
4140a663 238 if (Snp->Mode.ReceiveFilterSetting == 0) {\r
3bb7aff3 239 Status = EFI_DEVICE_ERROR;\r
240 goto ON_EXIT;\r
241 }\r
242\r
4cda7726 243 Status = PxeReceive (\r
244 Snp,\r
245 Buffer,\r
246 BufferSize,\r
247 HeaderSize,\r
248 SrcAddr,\r
249 DestAddr,\r
250 Protocol\r
3bb7aff3 251 );\r
252\r
253ON_EXIT:\r
254 gBS->RestoreTPL (OldTpl);\r
255\r
256 return Status;\r
257}\r