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