]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c
Fix a bug for vlan ping failure.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpIo.c
CommitLineData
8a67d61d 1/** @file\r
3e8c18da 2 Implementation of Managed Network Protocol I/O functions.\r
779ae357 3\r
bdebd2ce 4Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
779ae357 6are licensed and made available under the terms and conditions\r
7of the BSD License which accompanies this distribution. The full\r
8text of the license may be found at<BR>\r
8a67d61d 9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
8a67d61d 14**/\r
15\r
19034421 16#include "MnpImpl.h"\r
779ae357 17#include "MnpVlan.h"\r
8a67d61d 18\r
19/**\r
20 Validates the Mnp transmit token.\r
21\r
6e4bac4d 22 @param[in] Instance Pointer to the Mnp instance context data.\r
23 @param[in] Token Pointer to the transmit token to check.\r
8a67d61d 24\r
25 @return The Token is valid or not.\r
26\r
27**/\r
28BOOLEAN\r
29MnpIsValidTxToken (\r
779ae357 30 IN MNP_INSTANCE_DATA *Instance,\r
31 IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token\r
8a67d61d 32 )\r
33{\r
34 MNP_SERVICE_DATA *MnpServiceData;\r
8a67d61d 35 EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;\r
36 UINT32 Index;\r
37 UINT32 TotalLength;\r
38 EFI_MANAGED_NETWORK_FRAGMENT_DATA *FragmentTable;\r
39\r
40 MnpServiceData = Instance->MnpServiceData;\r
41 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
42\r
779ae357 43 TxData = Token->Packet.TxData;\r
8a67d61d 44\r
45 if ((Token->Event == NULL) || (TxData == NULL) || (TxData->FragmentCount == 0)) {\r
46 //\r
47 // The token is invalid if the Event is NULL, or the TxData is NULL, or\r
48 // the fragment count is zero.\r
49 //\r
e48e37fc 50 DEBUG ((EFI_D_WARN, "MnpIsValidTxToken: Invalid Token.\n"));\r
8a67d61d 51 return FALSE;\r
52 }\r
53\r
54 if ((TxData->DestinationAddress != NULL) && (TxData->HeaderLength != 0)) {\r
55 //\r
56 // The token is invalid if the HeaderLength isn't zero while the DestinationAddress\r
57 // is NULL (The destination address is already put into the packet).\r
58 //\r
e48e37fc 59 DEBUG ((EFI_D_WARN, "MnpIsValidTxToken: DestinationAddress isn't NULL, HeaderLength must be 0.\n"));\r
8a67d61d 60 return FALSE;\r
61 }\r
62\r
63 TotalLength = 0;\r
64 FragmentTable = TxData->FragmentTable;\r
65 for (Index = 0; Index < TxData->FragmentCount; Index++) {\r
66\r
67 if ((FragmentTable[Index].FragmentLength == 0) || (FragmentTable[Index].FragmentBuffer == NULL)) {\r
68 //\r
69 // The token is invalid if any FragmentLength is zero or any FragmentBuffer is NULL.\r
70 //\r
e48e37fc 71 DEBUG ((EFI_D_WARN, "MnpIsValidTxToken: Invalid FragmentLength or FragmentBuffer.\n"));\r
8a67d61d 72 return FALSE;\r
73 }\r
74\r
75 TotalLength += FragmentTable[Index].FragmentLength;\r
76 }\r
77\r
78 if ((TxData->DestinationAddress == NULL) && (FragmentTable[0].FragmentLength < TxData->HeaderLength)) {\r
79 //\r
80 // Media header is split between fragments.\r
81 //\r
82 return FALSE;\r
83 }\r
84\r
85 if (TotalLength != (TxData->DataLength + TxData->HeaderLength)) {\r
86 //\r
87 // The length calculated from the fragment information doesn't equal to the\r
88 // sum of the DataLength and the HeaderLength.\r
89 //\r
e48e37fc 90 DEBUG ((EFI_D_WARN, "MnpIsValidTxData: Invalid Datalength compared with the sum of fragment length.\n"));\r
8a67d61d 91 return FALSE;\r
92 }\r
93\r
94 if (TxData->DataLength > MnpServiceData->Mtu) {\r
95 //\r
96 // The total length is larger than the MTU.\r
97 //\r
e48e37fc 98 DEBUG ((EFI_D_WARN, "MnpIsValidTxData: TxData->DataLength exceeds Mtu.\n"));\r
8a67d61d 99 return FALSE;\r
100 }\r
101\r
102 return TRUE;\r
103}\r
104\r
105\r
106/**\r
107 Build the packet to transmit from the TxData passed in.\r
108\r
6e4bac4d 109 @param[in] MnpServiceData Pointer to the mnp service context data.\r
779ae357 110 @param[in] TxData Pointer to the transmit data containing the information\r
6e4bac4d 111 to build the packet.\r
112 @param[out] PktBuf Pointer to record the address of the packet.\r
779ae357 113 @param[out] PktLen Pointer to a UINT32 variable used to record the packet's\r
6e4bac4d 114 length.\r
115\r
8a67d61d 116**/\r
117VOID\r
118MnpBuildTxPacket (\r
779ae357 119 IN MNP_SERVICE_DATA *MnpServiceData,\r
120 IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData,\r
121 OUT UINT8 **PktBuf,\r
122 OUT UINT32 *PktLen\r
8a67d61d 123 )\r
124{\r
125 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
126 UINT8 *DstPos;\r
127 UINT16 Index;\r
779ae357 128 MNP_DEVICE_DATA *MnpDerviceData;\r
8a67d61d 129\r
779ae357 130 MnpDerviceData = MnpServiceData->MnpDeviceData;\r
8a67d61d 131 if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {\r
132 //\r
bdebd2ce 133 // Reserve space for vlan tag,if necessary.\r
8a67d61d 134 //\r
bdebd2ce
WJ
135 if (MnpServiceData->VlanId != 0) {\r
136 *PktBuf = MnpDerviceData->TxBuf + NET_VLAN_TAG_LEN;\r
137 } else {\r
138 *PktBuf = MnpDerviceData->TxBuf;\r
139 } \r
140 \r
141 CopyMem (\r
142 *PktBuf,\r
143 TxData->FragmentTable[0].FragmentBuffer,\r
144 TxData->FragmentTable[0].FragmentLength\r
145 );\r
146 \r
8a67d61d 147 *PktLen = TxData->FragmentTable[0].FragmentLength;\r
148 } else {\r
149 //\r
150 // Either media header isn't in FragmentTable or there is more than\r
151 // one fragment, copy the data into the packet buffer. Reserve the\r
152 // media header space if necessary.\r
153 //\r
779ae357 154 SnpMode = MnpDerviceData->Snp->Mode;\r
155 DstPos = MnpDerviceData->TxBuf;\r
8a67d61d 156\r
157 *PktLen = 0;\r
158 if (TxData->DestinationAddress != NULL) {\r
159 //\r
160 // If dest address is not NULL, move DstPos to reserve space for the\r
161 // media header. Add the media header length to buflen.\r
162 //\r
163 DstPos += SnpMode->MediaHeaderSize;\r
164 *PktLen += SnpMode->MediaHeaderSize;\r
165 }\r
166\r
167 for (Index = 0; Index < TxData->FragmentCount; Index++) {\r
168 //\r
169 // Copy the data.\r
170 //\r
e48e37fc 171 CopyMem (\r
8a67d61d 172 DstPos,\r
173 TxData->FragmentTable[Index].FragmentBuffer,\r
174 TxData->FragmentTable[Index].FragmentLength\r
175 );\r
176 DstPos += TxData->FragmentTable[Index].FragmentLength;\r
177 }\r
178\r
179 //\r
180 // Set the buffer pointer and the buffer length.\r
181 //\r
779ae357 182 *PktBuf = MnpDerviceData->TxBuf;\r
8a67d61d 183 *PktLen += TxData->DataLength + TxData->HeaderLength;\r
184 }\r
185}\r
186\r
187\r
188/**\r
189 Synchronously send out the packet.\r
190\r
6e4bac4d 191 @param[in] MnpServiceData Pointer to the mnp service context data.\r
192 @param[in] Packet Pointer to the pakcet buffer.\r
193 @param[in] Length The length of the packet.\r
194 @param[in, out] Token Pointer to the token the packet generated from.\r
8a67d61d 195\r
6e4bac4d 196 @retval EFI_SUCCESS The packet is sent out.\r
197 @retval EFI_TIMEOUT Time out occurs, the packet isn't sent.\r
198 @retval EFI_DEVICE_ERROR An unexpected network error occurs.\r
8a67d61d 199\r
200**/\r
201EFI_STATUS\r
202MnpSyncSendPacket (\r
779ae357 203 IN MNP_SERVICE_DATA *MnpServiceData,\r
204 IN UINT8 *Packet,\r
205 IN UINT32 Length,\r
206 IN OUT EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token\r
8a67d61d 207 )\r
208{\r
209 EFI_STATUS Status;\r
210 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
211 EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;\r
212 UINT32 HeaderSize;\r
213 UINT8 *TxBuf;\r
779ae357 214 MNP_DEVICE_DATA *MnpDeviceData;\r
215 UINT16 ProtocolType;\r
8a67d61d 216\r
779ae357 217 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
218 Snp = MnpDeviceData->Snp;\r
219 TxData = Token->Packet.TxData;\r
8a67d61d 220\r
779ae357 221 HeaderSize = Snp->Mode->MediaHeaderSize - TxData->HeaderLength;\r
8a67d61d 222\r
dd29f3ed 223 //\r
224 // Check media status before transmit packet.\r
225 // Note: media status will be updated by periodic timer MediaDetectTimer.\r
226 //\r
412d1ed9 227 if (Snp->Mode->MediaPresentSupported && !Snp->Mode->MediaPresent) {\r
dd29f3ed 228 //\r
229 // Media not present, skip packet transmit and report EFI_NO_MEDIA\r
230 //\r
412d1ed9 231 DEBUG ((EFI_D_WARN, "MnpSyncSendPacket: No network cable detected.\n"));\r
dd29f3ed 232 Status = EFI_NO_MEDIA;\r
233 goto SIGNAL_TOKEN;\r
234 }\r
235\r
8a67d61d 236 //\r
237 // Start the timeout event.\r
238 //\r
239 Status = gBS->SetTimer (\r
779ae357 240 MnpDeviceData->TxTimeoutEvent,\r
8a67d61d 241 TimerRelative,\r
242 MNP_TX_TIMEOUT_TIME\r
243 );\r
244 if (EFI_ERROR (Status)) {\r
8a67d61d 245 goto SIGNAL_TOKEN;\r
246 }\r
247\r
bdebd2ce
WJ
248 \r
249 if (MnpServiceData->VlanId != 0) {\r
250 //\r
251 // Insert VLAN tag\r
252 //\r
253 MnpInsertVlanTag (MnpServiceData, TxData, &ProtocolType, &Packet, &Length);\r
254 } else {\r
255 ProtocolType = TxData->ProtocolType;\r
256 }\r
779ae357 257\r
8a67d61d 258 for (;;) {\r
259 //\r
260 // Transmit the packet through SNP.\r
261 //\r
262 Status = Snp->Transmit (\r
263 Snp,\r
264 HeaderSize,\r
265 Length,\r
266 Packet,\r
267 TxData->SourceAddress,\r
268 TxData->DestinationAddress,\r
779ae357 269 &ProtocolType\r
8a67d61d 270 );\r
271 if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {\r
8a67d61d 272 Status = EFI_DEVICE_ERROR;\r
273 break;\r
274 }\r
275\r
276 //\r
277 // If Status is EFI_SUCCESS, the packet is put in the transmit queue.\r
278 // if Status is EFI_NOT_READY, the transmit engine of the network interface is busy.\r
279 // Both need to sync SNP.\r
280 //\r
281 TxBuf = NULL;\r
282 do {\r
283 //\r
284 // Get the recycled transmit buffer status.\r
285 //\r
4eb65aff 286 Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);\r
8a67d61d 287\r
779ae357 288 if (!EFI_ERROR (gBS->CheckEvent (MnpDeviceData->TxTimeoutEvent))) {\r
8a67d61d 289 Status = EFI_TIMEOUT;\r
290 break;\r
291 }\r
292 } while (TxBuf == NULL);\r
293\r
294 if ((Status == EFI_SUCCESS) || (Status == EFI_TIMEOUT)) {\r
8a67d61d 295 break;\r
296 } else {\r
297 //\r
298 // Status is EFI_NOT_READY. Restart the timer event and call Snp->Transmit again.\r
299 //\r
300 gBS->SetTimer (\r
779ae357 301 MnpDeviceData->TxTimeoutEvent,\r
8a67d61d 302 TimerRelative,\r
303 MNP_TX_TIMEOUT_TIME\r
304 );\r
305 }\r
306 }\r
307\r
308 //\r
309 // Cancel the timer event.\r
310 //\r
779ae357 311 gBS->SetTimer (MnpDeviceData->TxTimeoutEvent, TimerCancel, 0);\r
8a67d61d 312\r
313SIGNAL_TOKEN:\r
314\r
315 Token->Status = Status;\r
316 gBS->SignalEvent (Token->Event);\r
317\r
36ee91ca 318 //\r
319 // Dispatch the DPC queued by the NotifyFunction of Token->Event.\r
320 //\r
d8d26fb2 321 DispatchDpc ();\r
36ee91ca 322\r
8a67d61d 323 return EFI_SUCCESS;\r
324}\r
325\r
326\r
327/**\r
328 Try to deliver the received packet to the instance.\r
329\r
6e4bac4d 330 @param[in, out] Instance Pointer to the mnp instance context data.\r
8a67d61d 331\r
332 @retval EFI_SUCCESS The received packet is delivered, or there is no\r
333 packet to deliver, or there is no available receive\r
334 token.\r
335 @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.\r
336\r
337**/\r
338EFI_STATUS\r
339MnpInstanceDeliverPacket (\r
779ae357 340 IN OUT MNP_INSTANCE_DATA *Instance\r
8a67d61d 341 )\r
342{\r
779ae357 343 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 344 MNP_RXDATA_WRAP *RxDataWrap;\r
345 NET_BUF *DupNbuf;\r
346 EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;\r
347 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
348 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *RxToken;\r
349\r
779ae357 350 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
351 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 352\r
e48e37fc 353 if (NetMapIsEmpty (&Instance->RxTokenMap) || IsListEmpty (&Instance->RcvdPacketQueue)) {\r
8a67d61d 354 //\r
355 // No pending received data or no available receive token, return.\r
356 //\r
357 return EFI_SUCCESS;\r
358 }\r
359\r
360 ASSERT (Instance->RcvdPacketQueueSize != 0);\r
361\r
362 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);\r
363 if (RxDataWrap->Nbuf->RefCnt > 2) {\r
364 //\r
365 // There are other instances share this Nbuf, duplicate to get a\r
366 // copy to allow the instance to do R/W operations.\r
367 //\r
779ae357 368 DupNbuf = MnpAllocNbuf (MnpDeviceData);\r
8a67d61d 369 if (DupNbuf == NULL) {\r
e48e37fc 370 DEBUG ((EFI_D_WARN, "MnpDeliverPacket: Failed to allocate a free Nbuf.\n"));\r
8a67d61d 371\r
372 return EFI_OUT_OF_RESOURCES;\r
373 }\r
374\r
375 //\r
376 // Duplicate the net buffer.\r
377 //\r
378 NetbufDuplicate (RxDataWrap->Nbuf, DupNbuf, 0);\r
779ae357 379 MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);\r
8a67d61d 380 RxDataWrap->Nbuf = DupNbuf;\r
381 }\r
382\r
383 //\r
384 // All resources are OK, remove the packet from the queue.\r
385 //\r
386 NetListRemoveHead (&Instance->RcvdPacketQueue);\r
387 Instance->RcvdPacketQueueSize--;\r
388\r
389 RxData = &RxDataWrap->RxData;\r
779ae357 390 SnpMode = MnpDeviceData->Snp->Mode;\r
8a67d61d 391\r
392 //\r
393 // Set all the buffer pointers.\r
394 //\r
395 RxData->MediaHeader = NetbufGetByte (RxDataWrap->Nbuf, 0, NULL);\r
396 RxData->DestinationAddress = RxData->MediaHeader;\r
397 RxData->SourceAddress = (UINT8 *) RxData->MediaHeader + SnpMode->HwAddressSize;\r
398 RxData->PacketData = (UINT8 *) RxData->MediaHeader + SnpMode->MediaHeaderSize;\r
399\r
400 //\r
401 // Insert this RxDataWrap into the delivered queue.\r
402 //\r
e48e37fc 403 InsertTailList (&Instance->RxDeliveredPacketQueue, &RxDataWrap->WrapEntry);\r
8a67d61d 404\r
405 //\r
406 // Get the receive token from the RxTokenMap.\r
407 //\r
408 RxToken = NetMapRemoveHead (&Instance->RxTokenMap, NULL);\r
409\r
410 //\r
411 // Signal this token's event.\r
412 //\r
413 RxToken->Packet.RxData = &RxDataWrap->RxData;\r
414 RxToken->Status = EFI_SUCCESS;\r
415 gBS->SignalEvent (RxToken->Event);\r
416\r
417 return EFI_SUCCESS;\r
418}\r
419\r
420\r
421/**\r
422 Deliver the received packet for the instances belonging to the MnpServiceData.\r
423\r
6e4bac4d 424 @param[in] MnpServiceData Pointer to the mnp service context data.\r
8a67d61d 425\r
8a67d61d 426**/\r
8a67d61d 427VOID\r
428MnpDeliverPacket (\r
779ae357 429 IN MNP_SERVICE_DATA *MnpServiceData\r
8a67d61d 430 )\r
431{\r
e48e37fc 432 LIST_ENTRY *Entry;\r
8a67d61d 433 MNP_INSTANCE_DATA *Instance;\r
434\r
435 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
436\r
437 NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {\r
438 Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);\r
439 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
440\r
441 //\r
442 // Try to deliver packet for this instance.\r
443 //\r
444 MnpInstanceDeliverPacket (Instance);\r
445 }\r
446}\r
447\r
448\r
449/**\r
450 Recycle the RxData and other resources used to hold and deliver the received\r
451 packet.\r
452\r
6e4bac4d 453 @param[in] Event The event this notify function registered to.\r
454 @param[in] Context Pointer to the context data registerd to the Event.\r
455\r
8a67d61d 456**/\r
457VOID\r
458EFIAPI\r
459MnpRecycleRxData (\r
779ae357 460 IN EFI_EVENT Event,\r
461 IN VOID *Context\r
8a67d61d 462 )\r
463{\r
779ae357 464 MNP_RXDATA_WRAP *RxDataWrap;\r
465 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 466\r
467 ASSERT (Context != NULL);\r
468\r
469 RxDataWrap = (MNP_RXDATA_WRAP *) Context;\r
470 NET_CHECK_SIGNATURE (RxDataWrap->Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
471\r
472 ASSERT (RxDataWrap->Nbuf != NULL);\r
473\r
779ae357 474 MnpDeviceData = RxDataWrap->Instance->MnpServiceData->MnpDeviceData;\r
475 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 476\r
477 //\r
478 // Free this Nbuf.\r
479 //\r
779ae357 480 MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);\r
8a67d61d 481 RxDataWrap->Nbuf = NULL;\r
482\r
483 //\r
484 // Close the recycle event.\r
485 //\r
486 gBS->CloseEvent (RxDataWrap->RxData.RecycleEvent);\r
487\r
488 //\r
489 // Remove this Wrap entry from the list.\r
490 //\r
e48e37fc 491 RemoveEntryList (&RxDataWrap->WrapEntry);\r
8a67d61d 492\r
766c7483 493 FreePool (RxDataWrap);\r
8a67d61d 494}\r
495\r
496\r
497/**\r
498 Queue the received packet into instance's receive queue.\r
499\r
6e4bac4d 500 @param[in, out] Instance Pointer to the mnp instance context data.\r
501 @param[in, out] RxDataWrap Pointer to the Wrap structure containing the\r
502 received data and other information.\r
8a67d61d 503**/\r
8a67d61d 504VOID\r
505MnpQueueRcvdPacket (\r
779ae357 506 IN OUT MNP_INSTANCE_DATA *Instance,\r
507 IN OUT MNP_RXDATA_WRAP *RxDataWrap\r
8a67d61d 508 )\r
509{\r
510 MNP_RXDATA_WRAP *OldRxDataWrap;\r
511\r
512 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
513\r
514 //\r
515 // Check the queue size. If it exceeds the limit, drop one packet\r
516 // from the head.\r
517 //\r
518 if (Instance->RcvdPacketQueueSize == MNP_MAX_RCVD_PACKET_QUE_SIZE) {\r
519\r
e48e37fc 520 DEBUG ((EFI_D_WARN, "MnpQueueRcvdPacket: Drop one packet bcz queue size limit reached.\n"));\r
8a67d61d 521\r
522 //\r
523 // Get the oldest packet.\r
524 //\r
525 OldRxDataWrap = NET_LIST_HEAD (\r
526 &Instance->RcvdPacketQueue,\r
527 MNP_RXDATA_WRAP,\r
528 WrapEntry\r
529 );\r
530\r
531 //\r
532 // Recycle this OldRxDataWrap, this entry will be removed by the callee.\r
533 //\r
534 MnpRecycleRxData (NULL, (VOID *) OldRxDataWrap);\r
535 Instance->RcvdPacketQueueSize--;\r
536 }\r
537\r
538 //\r
539 // Update the timeout tick using the configured parameter.\r
540 //\r
541 RxDataWrap->TimeoutTick = Instance->ConfigData.ReceivedQueueTimeoutValue;\r
542\r
543 //\r
544 // Insert this Wrap into the instance queue.\r
545 //\r
e48e37fc 546 InsertTailList (&Instance->RcvdPacketQueue, &RxDataWrap->WrapEntry);\r
8a67d61d 547 Instance->RcvdPacketQueueSize++;\r
548}\r
549\r
550\r
551/**\r
552 Match the received packet with the instance receive filters.\r
553\r
3e8c18da 554 @param[in] Instance Pointer to the mnp instance context data.\r
555 @param[in] RxData Pointer to the EFI_MANAGED_NETWORK_RECEIVE_DATA.\r
556 @param[in] GroupAddress Pointer to the GroupAddress, the GroupAddress is\r
8a67d61d 557 non-NULL and it contains the destination multicast\r
558 mac address of the received packet if the packet\r
559 destinated to a multicast mac address.\r
3e8c18da 560 @param[in] PktAttr The received packets attribute.\r
8a67d61d 561\r
562 @return The received packet matches the instance's receive filters or not.\r
563\r
564**/\r
8a67d61d 565BOOLEAN\r
566MnpMatchPacket (\r
779ae357 567 IN MNP_INSTANCE_DATA *Instance,\r
568 IN EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData,\r
569 IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,\r
570 IN UINT8 PktAttr\r
8a67d61d 571 )\r
572{\r
573 EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData;\r
e48e37fc 574 LIST_ENTRY *Entry;\r
8a67d61d 575 MNP_GROUP_CONTROL_BLOCK *GroupCtrlBlk;\r
576\r
577 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
578\r
579 ConfigData = &Instance->ConfigData;\r
580\r
8a67d61d 581 //\r
582 // Check the protocol type.\r
583 //\r
584 if ((ConfigData->ProtocolTypeFilter != 0) && (ConfigData->ProtocolTypeFilter != RxData->ProtocolType)) {\r
585 return FALSE;\r
586 }\r
587\r
36ee91ca 588 if (ConfigData->EnablePromiscuousReceive) {\r
589 //\r
590 // Always match if this instance is configured to be promiscuous.\r
591 //\r
592 return TRUE;\r
593 }\r
594\r
8a67d61d 595 //\r
596 // The protocol type is matched, check receive filter, include unicast and broadcast.\r
597 //\r
598 if ((Instance->ReceiveFilter & PktAttr) != 0) {\r
599 return TRUE;\r
600 }\r
601\r
602 //\r
603 // Check multicast addresses.\r
604 //\r
605 if (ConfigData->EnableMulticastReceive && RxData->MulticastFlag) {\r
606\r
607 ASSERT (GroupAddress != NULL);\r
608\r
609 NET_LIST_FOR_EACH (Entry, &Instance->GroupCtrlBlkList) {\r
610\r
611 GroupCtrlBlk = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_CONTROL_BLOCK, CtrlBlkEntry);\r
612 if (GroupCtrlBlk->GroupAddress == GroupAddress) {\r
613 //\r
614 // The instance is configured to receiveing packets destinated to this\r
615 // multicast address.\r
616 //\r
617 return TRUE;\r
618 }\r
619 }\r
620 }\r
621\r
622 //\r
623 // No match.\r
624 //\r
625 return FALSE;\r
626}\r
627\r
628\r
629/**\r
630 Analyse the received packets.\r
631\r
6e4bac4d 632 @param[in] MnpServiceData Pointer to the mnp service context data.\r
633 @param[in] Nbuf Pointer to the net buffer holding the received\r
634 packet.\r
635 @param[in, out] RxData Pointer to the buffer used to save the analysed\r
636 result in EFI_MANAGED_NETWORK_RECEIVE_DATA.\r
637 @param[out] GroupAddress Pointer to pointer to a MNP_GROUP_ADDRESS used to\r
638 pass out the address of the multicast address the\r
639 received packet destinated to.\r
640 @param[out] PktAttr Pointer to the buffer used to save the analysed\r
641 packet attribute.\r
8a67d61d 642\r
643**/\r
8a67d61d 644VOID\r
645MnpAnalysePacket (\r
779ae357 646 IN MNP_SERVICE_DATA *MnpServiceData,\r
647 IN NET_BUF *Nbuf,\r
648 IN OUT EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData,\r
649 OUT MNP_GROUP_ADDRESS **GroupAddress,\r
650 OUT UINT8 *PktAttr\r
8a67d61d 651 )\r
652{\r
653 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
779ae357 654 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 655 UINT8 *BufPtr;\r
e48e37fc 656 LIST_ENTRY *Entry;\r
8a67d61d 657\r
779ae357 658 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
659 SnpMode = MnpDeviceData->Snp->Mode;\r
8a67d61d 660\r
661 //\r
662 // Get the packet buffer.\r
663 //\r
664 BufPtr = NetbufGetByte (Nbuf, 0, NULL);\r
665 ASSERT (BufPtr != NULL);\r
666\r
667 //\r
668 // Set the initial values.\r
669 //\r
670 RxData->BroadcastFlag = FALSE;\r
671 RxData->MulticastFlag = FALSE;\r
672 RxData->PromiscuousFlag = FALSE;\r
673 *PktAttr = UNICAST_PACKET;\r
674\r
675 if (!NET_MAC_EQUAL (&SnpMode->CurrentAddress, BufPtr, SnpMode->HwAddressSize)) {\r
676 //\r
677 // This packet isn't destinated to our current mac address, it't not unicast.\r
678 //\r
679 *PktAttr = 0;\r
680\r
681 if (NET_MAC_EQUAL (&SnpMode->BroadcastAddress, BufPtr, SnpMode->HwAddressSize)) {\r
682 //\r
683 // It's broadcast.\r
684 //\r
685 RxData->BroadcastFlag = TRUE;\r
686 *PktAttr = BROADCAST_PACKET;\r
687 } else if ((*BufPtr & 0x01) == 0x1) {\r
688 //\r
689 // It's multicast, try to match the multicast filters.\r
690 //\r
779ae357 691 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
8a67d61d 692\r
693 *GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
694 if (NET_MAC_EQUAL (BufPtr, &((*GroupAddress)->Address), SnpMode->HwAddressSize)) {\r
695 RxData->MulticastFlag = TRUE;\r
696 break;\r
697 }\r
698 }\r
699\r
700 if (!RxData->MulticastFlag) {\r
701 //\r
702 // No match, set GroupAddress to NULL. This multicast packet must\r
703 // be the result of PROMISUCOUS or PROMISUCOUS_MULTICAST flag is on.\r
704 //\r
705 *GroupAddress = NULL;\r
706 RxData->PromiscuousFlag = TRUE;\r
707\r
779ae357 708 if (MnpDeviceData->PromiscuousCount == 0) {\r
8a67d61d 709 //\r
710 // Skip the below code, there is no receiver of this packet.\r
711 //\r
712 return ;\r
713 }\r
714 }\r
715 } else {\r
716 RxData->PromiscuousFlag = TRUE;\r
717 }\r
718 }\r
719\r
e48e37fc 720 ZeroMem (&RxData->Timestamp, sizeof (EFI_TIME));\r
8a67d61d 721\r
722 //\r
723 // Fill the common parts of RxData.\r
724 //\r
725 RxData->PacketLength = Nbuf->TotalSize;\r
726 RxData->HeaderLength = SnpMode->MediaHeaderSize;\r
727 RxData->AddressLength = SnpMode->HwAddressSize;\r
728 RxData->DataLength = RxData->PacketLength - RxData->HeaderLength;\r
729 RxData->ProtocolType = NTOHS (*(UINT16 *) (BufPtr + 2 * SnpMode->HwAddressSize));\r
730}\r
731\r
732\r
733/**\r
734 Wrap the RxData.\r
735\r
6e4bac4d 736 @param[in] Instance Pointer to the mnp instance context data.\r
737 @param[in] RxData Pointer to the receive data to wrap.\r
8a67d61d 738\r
739 @return Pointer to a MNP_RXDATA_WRAP which wraps the RxData.\r
740\r
741**/\r
8a67d61d 742MNP_RXDATA_WRAP *\r
743MnpWrapRxData (\r
779ae357 744 IN MNP_INSTANCE_DATA *Instance,\r
745 IN EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData\r
8a67d61d 746 )\r
747{\r
748 EFI_STATUS Status;\r
749 MNP_RXDATA_WRAP *RxDataWrap;\r
750\r
751 //\r
752 // Allocate memory.\r
753 //\r
e48e37fc 754 RxDataWrap = AllocatePool (sizeof (MNP_RXDATA_WRAP));\r
8a67d61d 755 if (RxDataWrap == NULL) {\r
e48e37fc 756 DEBUG ((EFI_D_ERROR, "MnpDispatchPacket: Failed to allocate a MNP_RXDATA_WRAP.\n"));\r
8a67d61d 757 return NULL;\r
758 }\r
759\r
760 RxDataWrap->Instance = Instance;\r
761\r
762 //\r
763 // Fill the RxData in RxDataWrap,\r
764 //\r
687a2e5f 765 CopyMem (&RxDataWrap->RxData, RxData, sizeof (RxDataWrap->RxData));\r
8a67d61d 766\r
767 //\r
768 // Create the recycle event.\r
769 //\r
770 Status = gBS->CreateEvent (\r
771 EVT_NOTIFY_SIGNAL,\r
e48e37fc 772 TPL_NOTIFY,\r
8a67d61d 773 MnpRecycleRxData,\r
774 RxDataWrap,\r
775 &RxDataWrap->RxData.RecycleEvent\r
776 );\r
777 if (EFI_ERROR (Status)) {\r
e48e37fc 778 DEBUG ((EFI_D_ERROR, "MnpDispatchPacket: gBS->CreateEvent failed, %r.\n", Status));\r
779ae357 779\r
766c7483 780 FreePool (RxDataWrap);\r
8a67d61d 781 return NULL;\r
782 }\r
783\r
784 return RxDataWrap;\r
785}\r
786\r
787\r
788/**\r
789 Enqueue the received the packets to the instances belonging to the\r
790 MnpServiceData.\r
791\r
6e4bac4d 792 @param[in] MnpServiceData Pointer to the mnp service context data.\r
793 @param[in] Nbuf Pointer to the net buffer representing the received\r
794 packet.\r
8a67d61d 795\r
796**/\r
8a67d61d 797VOID\r
798MnpEnqueuePacket (\r
779ae357 799 IN MNP_SERVICE_DATA *MnpServiceData,\r
800 IN NET_BUF *Nbuf\r
8a67d61d 801 )\r
802{\r
e48e37fc 803 LIST_ENTRY *Entry;\r
8a67d61d 804 MNP_INSTANCE_DATA *Instance;\r
805 EFI_MANAGED_NETWORK_RECEIVE_DATA RxData;\r
806 UINT8 PktAttr;\r
807 MNP_GROUP_ADDRESS *GroupAddress;\r
808 MNP_RXDATA_WRAP *RxDataWrap;\r
809\r
67a58d0f 810\r
811 GroupAddress = NULL;\r
8a67d61d 812 //\r
813 // First, analyse the packet header.\r
814 //\r
815 MnpAnalysePacket (MnpServiceData, Nbuf, &RxData, &GroupAddress, &PktAttr);\r
816\r
779ae357 817 if (RxData.PromiscuousFlag && (MnpServiceData->MnpDeviceData->PromiscuousCount == 0)) {\r
8a67d61d 818 //\r
819 // No receivers, no more action need.\r
820 //\r
821 return ;\r
822 }\r
823\r
824 //\r
825 // Iterate the children to find match.\r
826 //\r
827 NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {\r
828\r
829 Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);\r
830 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
831\r
832 if (!Instance->Configured) {\r
833 continue;\r
834 }\r
835\r
836 //\r
837 // Check the packet against the instance receive filters.\r
838 //\r
839 if (MnpMatchPacket (Instance, &RxData, GroupAddress, PktAttr)) {\r
8a67d61d 840 //\r
841 // Wrap the RxData.\r
842 //\r
687a2e5f 843 RxDataWrap = MnpWrapRxData (Instance, &RxData);\r
8a67d61d 844 if (RxDataWrap == NULL) {\r
845 continue;\r
846 }\r
847\r
848 //\r
849 // Associate RxDataWrap with Nbuf and increase the RefCnt.\r
850 //\r
851 RxDataWrap->Nbuf = Nbuf;\r
852 NET_GET_REF (RxDataWrap->Nbuf);\r
853\r
854 //\r
855 // Queue the packet into the instance queue.\r
856 //\r
857 MnpQueueRcvdPacket (Instance, RxDataWrap);\r
858 }\r
859 }\r
860}\r
861\r
862\r
863/**\r
864 Try to receive a packet and deliver it.\r
865\r
779ae357 866 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
8a67d61d 867\r
868 @retval EFI_SUCCESS add return value to function comment\r
869 @retval EFI_NOT_STARTED The simple network protocol is not started.\r
870 @retval EFI_NOT_READY No packet received.\r
871 @retval EFI_DEVICE_ERROR An unexpected error occurs.\r
872\r
873**/\r
874EFI_STATUS\r
875MnpReceivePacket (\r
779ae357 876 IN OUT MNP_DEVICE_DATA *MnpDeviceData\r
8a67d61d 877 )\r
878{\r
879 EFI_STATUS Status;\r
880 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
881 NET_BUF *Nbuf;\r
882 UINT8 *BufPtr;\r
883 UINTN BufLen;\r
884 UINTN HeaderSize;\r
885 UINT32 Trimmed;\r
779ae357 886 MNP_SERVICE_DATA *MnpServiceData;\r
887 UINT16 VlanId;\r
888 BOOLEAN IsVlanPacket;\r
8a67d61d 889\r
779ae357 890 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 891\r
779ae357 892 Snp = MnpDeviceData->Snp;\r
8a67d61d 893 if (Snp->Mode->State != EfiSimpleNetworkInitialized) {\r
894 //\r
895 // The simple network protocol is not started.\r
896 //\r
897 return EFI_NOT_STARTED;\r
898 }\r
899\r
779ae357 900 if (MnpDeviceData->RxNbufCache == NULL) {\r
8a67d61d 901 //\r
902 // Try to get a new buffer as there may be buffers recycled.\r
903 //\r
779ae357 904 MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);\r
8a67d61d 905\r
779ae357 906 if (MnpDeviceData->RxNbufCache == NULL) {\r
8a67d61d 907 //\r
908 // No availabe buffer in the buffer pool.\r
909 //\r
910 return EFI_DEVICE_ERROR;\r
911 }\r
912\r
913 NetbufAllocSpace (\r
779ae357 914 MnpDeviceData->RxNbufCache,\r
915 MnpDeviceData->BufferLength,\r
8a67d61d 916 NET_BUF_TAIL\r
917 );\r
918 }\r
919\r
779ae357 920 Nbuf = MnpDeviceData->RxNbufCache;\r
8a67d61d 921 BufLen = Nbuf->TotalSize;\r
922 BufPtr = NetbufGetByte (Nbuf, 0, NULL);\r
923 ASSERT (BufPtr != NULL);\r
924\r
925 //\r
926 // Receive packet through Snp.\r
927 //\r
928 Status = Snp->Receive (Snp, &HeaderSize, &BufLen, BufPtr, NULL, NULL, NULL);\r
929 if (EFI_ERROR (Status)) {\r
8a67d61d 930 DEBUG_CODE (\r
931 if (Status != EFI_NOT_READY) {\r
982a9eae 932 DEBUG ((EFI_D_WARN, "MnpReceivePacket: Snp->Receive() = %r.\n", Status));\r
933 }\r
8a67d61d 934 );\r
935\r
936 return Status;\r
937 }\r
938\r
939 //\r
940 // Sanity check.\r
941 //\r
942 if ((HeaderSize != Snp->Mode->MediaHeaderSize) || (BufLen < HeaderSize)) {\r
e48e37fc 943 DEBUG (\r
944 (EFI_D_WARN,\r
945 "MnpReceivePacket: Size error, HL:TL = %d:%d.\n",\r
8a67d61d 946 HeaderSize,\r
947 BufLen)\r
948 );\r
949 return EFI_DEVICE_ERROR;\r
950 }\r
951\r
952 Trimmed = 0;\r
953 if (Nbuf->TotalSize != BufLen) {\r
954 //\r
955 // Trim the packet from tail.\r
956 //\r
957 Trimmed = NetbufTrim (Nbuf, Nbuf->TotalSize - (UINT32) BufLen, NET_BUF_TAIL);\r
958 ASSERT (Nbuf->TotalSize == BufLen);\r
959 }\r
960\r
779ae357 961 VlanId = 0;\r
ef89996c 962 if (MnpDeviceData->NumberOfVlan != 0) {\r
963 //\r
964 // VLAN is configured, remove the VLAN tag if any\r
965 //\r
966 IsVlanPacket = MnpRemoveVlanTag (MnpDeviceData, Nbuf, &VlanId);\r
967 } else {\r
968 IsVlanPacket = FALSE;\r
969 }\r
779ae357 970\r
971 MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);\r
972 if (MnpServiceData == NULL) {\r
973 //\r
974 // VLAN is not set for this tagged frame, ignore this packet\r
975 //\r
976 if (Trimmed > 0) {\r
977 NetbufAllocSpace (Nbuf, Trimmed, NET_BUF_TAIL);\r
978 }\r
979\r
980 if (IsVlanPacket) {\r
981 NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);\r
982 }\r
983\r
984 goto EXIT;\r
985 }\r
986\r
8a67d61d 987 //\r
988 // Enqueue the packet to the matched instances.\r
989 //\r
990 MnpEnqueuePacket (MnpServiceData, Nbuf);\r
991\r
992 if (Nbuf->RefCnt > 2) {\r
993 //\r
994 // RefCnt > 2 indicates there is at least one receiver of this packet.\r
995 // Free the current RxNbufCache and allocate a new one.\r
996 //\r
779ae357 997 MnpFreeNbuf (MnpDeviceData, Nbuf);\r
8a67d61d 998\r
779ae357 999 Nbuf = MnpAllocNbuf (MnpDeviceData);\r
1000 MnpDeviceData->RxNbufCache = Nbuf;\r
8a67d61d 1001 if (Nbuf == NULL) {\r
e48e37fc 1002 DEBUG ((EFI_D_ERROR, "MnpReceivePacket: Alloc packet for receiving cache failed.\n"));\r
8a67d61d 1003 return EFI_DEVICE_ERROR;\r
1004 }\r
1005\r
779ae357 1006 NetbufAllocSpace (Nbuf, MnpDeviceData->BufferLength, NET_BUF_TAIL);\r
8a67d61d 1007 } else {\r
1008 //\r
1009 // No receiver for this packet.\r
1010 //\r
772db4bb 1011 if (Trimmed > 0) {\r
1012 NetbufAllocSpace (Nbuf, Trimmed, NET_BUF_TAIL);\r
1013 }\r
779ae357 1014 if (IsVlanPacket) {\r
1015 NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);\r
1016 }\r
772db4bb 1017\r
8a67d61d 1018 goto EXIT;\r
1019 }\r
1020 //\r
1021 // Deliver the queued packets.\r
1022 //\r
1023 MnpDeliverPacket (MnpServiceData);\r
1024\r
1025EXIT:\r
1026\r
779ae357 1027 ASSERT (Nbuf->TotalSize == MnpDeviceData->BufferLength);\r
8a67d61d 1028\r
1029 return Status;\r
1030}\r
1031\r
1032\r
1033/**\r
1034 Remove the received packets if timeout occurs.\r
1035\r
dd29f3ed 1036 @param[in] Event The event this notify function registered to.\r
1037 @param[in] Context Pointer to the context data registered to the event.\r
779ae357 1038\r
8a67d61d 1039**/\r
1040VOID\r
1041EFIAPI\r
1042MnpCheckPacketTimeout (\r
779ae357 1043 IN EFI_EVENT Event,\r
1044 IN VOID *Context\r
8a67d61d 1045 )\r
1046{\r
779ae357 1047 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1048 MNP_SERVICE_DATA *MnpServiceData;\r
e48e37fc 1049 LIST_ENTRY *Entry;\r
779ae357 1050 LIST_ENTRY *ServiceEntry;\r
e48e37fc 1051 LIST_ENTRY *RxEntry;\r
1052 LIST_ENTRY *NextEntry;\r
8a67d61d 1053 MNP_INSTANCE_DATA *Instance;\r
1054 MNP_RXDATA_WRAP *RxDataWrap;\r
1055 EFI_TPL OldTpl;\r
1056\r
779ae357 1057 MnpDeviceData = (MNP_DEVICE_DATA *) Context;\r
1058 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1059\r
779ae357 1060 NET_LIST_FOR_EACH (ServiceEntry, &MnpDeviceData->ServiceList) {\r
1061 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (ServiceEntry);\r
8a67d61d 1062\r
779ae357 1063 NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {\r
8a67d61d 1064\r
779ae357 1065 Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);\r
1066 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
8a67d61d 1067\r
779ae357 1068 if (!Instance->Configured || (Instance->ConfigData.ReceivedQueueTimeoutValue == 0)) {\r
1069 //\r
1070 // This instance is not configured or there is no receive time out,\r
1071 // just skip to the next instance.\r
1072 //\r
1073 continue;\r
1074 }\r
8a67d61d 1075\r
779ae357 1076 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 1077\r
779ae357 1078 NET_LIST_FOR_EACH_SAFE (RxEntry, NextEntry, &Instance->RcvdPacketQueue) {\r
8a67d61d 1079\r
779ae357 1080 RxDataWrap = NET_LIST_USER_STRUCT (RxEntry, MNP_RXDATA_WRAP, WrapEntry);\r
8a67d61d 1081\r
8a67d61d 1082 //\r
779ae357 1083 // TimeoutTick unit is microsecond, MNP_TIMEOUT_CHECK_INTERVAL unit is 100ns.\r
8a67d61d 1084 //\r
779ae357 1085 if (RxDataWrap->TimeoutTick >= (MNP_TIMEOUT_CHECK_INTERVAL / 10)) {\r
1086 RxDataWrap->TimeoutTick -= (MNP_TIMEOUT_CHECK_INTERVAL / 10);\r
1087 } else {\r
1088 //\r
1089 // Drop the timeout packet.\r
1090 //\r
1091 DEBUG ((EFI_D_WARN, "MnpCheckPacketTimeout: Received packet timeout.\n"));\r
1092 MnpRecycleRxData (NULL, RxDataWrap);\r
1093 Instance->RcvdPacketQueueSize--;\r
1094 }\r
8a67d61d 1095 }\r
8a67d61d 1096\r
779ae357 1097 gBS->RestoreTPL (OldTpl);\r
1098 }\r
8a67d61d 1099 }\r
1100}\r
1101\r
dd29f3ed 1102/**\r
1103 Poll to update MediaPresent field in SNP ModeData by Snp->GetStatus().\r
1104\r
1105 @param[in] Event The event this notify function registered to.\r
1106 @param[in] Context Pointer to the context data registered to the event.\r
1107\r
1108**/\r
1109VOID\r
1110EFIAPI\r
1111MnpCheckMediaStatus (\r
1112 IN EFI_EVENT Event,\r
1113 IN VOID *Context\r
1114 )\r
1115{\r
1116 MNP_DEVICE_DATA *MnpDeviceData;\r
1117 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
1118 UINT32 InterruptStatus;\r
1119\r
1120 MnpDeviceData = (MNP_DEVICE_DATA *) Context;\r
1121 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
1122\r
1123 Snp = MnpDeviceData->Snp;\r
1124 if (Snp->Mode->MediaPresentSupported) {\r
1125 //\r
1126 // Upon successful return of GetStatus(), the MediaPresent field of\r
1127 // EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change of media status\r
1128 //\r
1129 Snp->GetStatus (Snp, &InterruptStatus, NULL);\r
1130 }\r
1131}\r
1132\r
8a67d61d 1133/**\r
1134 Poll to receive the packets from Snp. This function is either called by upperlayer\r
1135 protocols/applications or the system poll timer notify mechanism.\r
1136\r
dd29f3ed 1137 @param[in] Event The event this notify function registered to.\r
1138 @param[in] Context Pointer to the context data registered to the event.\r
8a67d61d 1139\r
8a67d61d 1140**/\r
1141VOID\r
1142EFIAPI\r
1143MnpSystemPoll (\r
dd29f3ed 1144 IN EFI_EVENT Event,\r
1145 IN VOID *Context\r
8a67d61d 1146 )\r
1147{\r
779ae357 1148 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 1149\r
779ae357 1150 MnpDeviceData = (MNP_DEVICE_DATA *) Context;\r
1151 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 1152\r
1153 //\r
1154 // Try to receive packets from Snp.\r
1155 //\r
779ae357 1156 MnpReceivePacket (MnpDeviceData);\r
36ee91ca 1157\r
a4df47f1 1158 //\r
1159 // Dispatch the DPC queued by the NotifyFunction of rx token's events.\r
1160 //\r
d8d26fb2 1161 DispatchDpc ();\r
8a67d61d 1162}\r