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