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