]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/receive.c
1. Sync Tcp4 protocol definitions to match UEFI 2.1
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / receive.c
CommitLineData
8a67d61d 1/** @file\r
2Copyright (c) 2004 - 2007, Intel Corporation\r
3All rights reserved. This program and the accompanying materials\r
4are licensed and made available under the terms and conditions of the BSD License\r
5which accompanies this distribution. The full text of the license may be found at\r
6http://opensource.org/licenses/bsd-license.php\r
7\r
8THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10\r
11Module name:\r
12 receive.c\r
13\r
14Abstract:\r
15\r
16Revision history:\r
17 2000-Feb-03 M(f)J Genesis.\r
18\r
19**/\r
20\r
21\r
22#include "Snp.h"\r
23\r
24/**\r
25 this routine calls undi to receive a packet and fills in the data in the\r
26 input pointers!\r
27\r
28 @param snp pointer to snp driver structure\r
29 @param BufferPtr pointer to the memory for the received data\r
30 @param BuffSizePtr is a pointer to the length of the buffer on entry and\r
31 contains the length of the received data on return\r
32 @param HeaderSizePtr pointer to the header portion of the data received.\r
33 @param SourceAddrPtr optional parameter, is a pointer to contain the\r
34 source ethernet address on return\r
35 @param DestinationAddrPtr optional parameter, is a pointer to contain the\r
36 destination ethernet address on return\r
37 @param ProtocolPtr optional parameter, is a pointer to contain the\r
38 protocol type from the ethernet header on return\r
39\r
40\r
41**/\r
42STATIC\r
43EFI_STATUS\r
44pxe_receive (\r
45 SNP_DRIVER *snp,\r
46 VOID *BufferPtr,\r
47 UINTN *BuffSizePtr,\r
48 UINTN *HeaderSizePtr,\r
49 EFI_MAC_ADDRESS *SourceAddrPtr,\r
50 EFI_MAC_ADDRESS *DestinationAddrPtr,\r
51 UINT16 *ProtocolPtr\r
52 )\r
53{\r
54 PXE_CPB_RECEIVE *cpb;\r
55 PXE_DB_RECEIVE *db;\r
56 UINTN buf_size;\r
57 UINT64 TempData;\r
58\r
59 cpb = snp->cpb;\r
60 db = snp->db;\r
61 buf_size = *BuffSizePtr;\r
62 //\r
63 // IMPORTANT NOTE:\r
64 // In case of the older 3.0 UNDI, if the input buffer address is beyond 4GB,\r
65 // DO NOT call the map function on the given buffer, instead use\r
66 // a global buffer. The reason is that UNDI3.0 has some unnecessary check of\r
67 // making sure that all the addresses (whether or not they will be given\r
68 // to the NIC ) supplied to it are below 4GB. It may or may not use\r
69 // the mapped address after all (like in case of CPB and DB)!\r
70 // Instead of using the global buffer whose address is allocated within the\r
71 // 2GB limit if I start mapping the given buffer we lose the data, here is\r
72 // why!!!\r
73 // if our address is > 4GB, the map call creates another buffer below 2GB and\r
74 // copies data to/from the original buffer to the mapped buffer either at\r
75 // map time or unmap time depending on the map direction.\r
76 // UNDI will not complain since we already mapped the buffer to be\r
77 // within the 2GB limit but will not use (I know undi) the mapped address\r
78 // since it does not give the user buffers to the NIC's receive unit,\r
79 // It just copies the received packet into the user buffer using the virtual\r
80 // (CPU) address rather than the mapped (device or physical) address.\r
81 // When the UNDI call returns, if we then unmap the buffer, we will lose\r
82 // the contents because unmap copies the contents of the mapped buffer into\r
83 // the original buffer (since the direction is FROM_DEVICE) !!!\r
84 //\r
85 // this is not a problem in Undi 3.1 because this undi uses it's map callback\r
86 // routine to map a cpu address to device address and it does it only if\r
87 // it is giving the address to the device and unmaps it before using the cpu\r
88 // address!\r
89 //\r
90 TempData = (UINT64) (UINTN) BufferPtr;\r
91 if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {\r
92 cpb->BufferAddr = (UINT64)(UINTN) snp->receive_buf;\r
93 cpb->BufferLen = (UINT32) (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);\r
94 } else {\r
95 cpb->BufferAddr = (UINT64)(UINTN) BufferPtr;\r
96 cpb->BufferLen = (UINT32) *BuffSizePtr;\r
97 }\r
98\r
99 cpb->reserved = 0;\r
100\r
101 snp->cdb.OpCode = PXE_OPCODE_RECEIVE;\r
102 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
103\r
104 snp->cdb.CPBsize = sizeof (PXE_CPB_RECEIVE);\r
105 snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;\r
106\r
107 snp->cdb.DBsize = sizeof (PXE_DB_RECEIVE);\r
108 snp->cdb.DBaddr = (UINT64)(UINTN) db;\r
109\r
110 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
111 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
112 snp->cdb.IFnum = snp->if_num;\r
113 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
114\r
115 //\r
116 // Issue UNDI command and check result.\r
117 //\r
d01c093a 118 DEBUG ((EFI_D_NET, "\nsnp->undi.receive () "));\r
8a67d61d 119\r
120 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);\r
121\r
122 switch (snp->cdb.StatCode) {\r
123 case PXE_STATCODE_SUCCESS:\r
124 break;\r
125\r
126 case PXE_STATCODE_NO_DATA:\r
127 DEBUG (\r
d01c093a 128 (EFI_D_NET,\r
8a67d61d 129 "\nsnp->undi.receive () %xh:%xh\n",\r
130 snp->cdb.StatFlags,\r
131 snp->cdb.StatCode)\r
132 );\r
133\r
134 return EFI_NOT_READY;\r
135\r
136 default:\r
137 DEBUG (\r
138 (EFI_D_ERROR,\r
139 "\nsnp->undi.receive() %xh:%xh\n",\r
140 snp->cdb.StatFlags,\r
141 snp->cdb.StatCode)\r
142 );\r
143\r
144 return EFI_DEVICE_ERROR;\r
145 }\r
146\r
147 *BuffSizePtr = db->FrameLen;\r
148\r
149 if (HeaderSizePtr != NULL) {\r
150 *HeaderSizePtr = db->MediaHeaderLen;\r
151 }\r
152\r
153 if (SourceAddrPtr != NULL) {\r
154 CopyMem (SourceAddrPtr, &db->SrcAddr, snp->mode.HwAddressSize);\r
155 }\r
156\r
157 if (DestinationAddrPtr != NULL) {\r
158 CopyMem (DestinationAddrPtr, &db->DestAddr, snp->mode.HwAddressSize);\r
159 }\r
160\r
161 if (ProtocolPtr != NULL) {\r
162 *ProtocolPtr = (UINT16) PXE_SWAP_UINT16 (db->Protocol); /* we need to do the byte swapping */\r
163 }\r
164\r
165 TempData = (UINT64) (UINTN) BufferPtr;\r
166 if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {\r
167 CopyMem (BufferPtr, snp->receive_buf, snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);\r
168 }\r
169\r
170 return (*BuffSizePtr <= buf_size) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
171}\r
172\r
173\r
174/**\r
175 This is the SNP interface routine for receiving network data.\r
176 This routine basically retrieves snp structure, checks the SNP state and\r
177 calls the pxe_receive routine to actually do the receive!\r
178\r
179 @param this context pointer\r
180 @param HeaderSizePtr optional parameter and is a pointer to the header\r
181 portion of the data received.\r
182 @param BuffSizePtr is a pointer to the length of the buffer on entry and\r
183 contains the length of the received data on return\r
184 @param BufferPtr pointer to the memory for the received data\r
185 @param SourceAddrPtr optional parameter, is a pointer to contain the\r
186 source ethernet address on return\r
187 @param DestinationAddrPtr optional parameter, is a pointer to contain the\r
188 destination ethernet address on return\r
189 @param ProtocolPtr optional parameter, is a pointer to contain the\r
190 protocol type from the ethernet header on return\r
191\r
192\r
193**/\r
194EFI_STATUS\r
195EFIAPI\r
196snp_undi32_receive (\r
197 IN EFI_SIMPLE_NETWORK_PROTOCOL * this,\r
198 OUT UINTN *HeaderSizePtr OPTIONAL,\r
199 IN OUT UINTN *BuffSizePtr,\r
200 OUT VOID *BufferPtr,\r
201 OUT EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL,\r
202 OUT EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL,\r
203 OUT UINT16 *ProtocolPtr OPTIONAL\r
204 )\r
205{\r
206 SNP_DRIVER *snp;\r
207 EFI_TPL OldTpl;\r
208 EFI_STATUS Status;\r
209\r
210 if (this == NULL) {\r
211 return EFI_INVALID_PARAMETER;\r
212 }\r
213\r
214 snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);\r
215\r
216 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
217\r
218 switch (snp->mode.State) {\r
219 case EfiSimpleNetworkInitialized:\r
220 break;\r
221\r
222 case EfiSimpleNetworkStopped:\r
223 Status = EFI_NOT_STARTED;\r
224 goto ON_EXIT;\r
225\r
226 default:\r
227 Status = EFI_DEVICE_ERROR;\r
228 goto ON_EXIT;\r
229 }\r
230\r
231 if ((BuffSizePtr == NULL) || (BufferPtr == NULL)) {\r
232 Status = EFI_INVALID_PARAMETER;\r
233 goto ON_EXIT;\r
234 }\r
235\r
236 if (!snp->mode.ReceiveFilterSetting) {\r
237 Status = EFI_DEVICE_ERROR;\r
238 goto ON_EXIT;\r
239 }\r
240\r
241 Status = pxe_receive (\r
242 snp,\r
243 BufferPtr,\r
244 BuffSizePtr,\r
245 HeaderSizePtr,\r
246 SourceAddrPtr,\r
247 DestinationAddrPtr,\r
248 ProtocolPtr\r
249 );\r
250\r
251ON_EXIT:\r
252 gBS->RestoreTPL (OldTpl);\r
253\r
254 return Status;\r
255}\r