]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c
MdeModulePkg: Update MNP driver to recycle TX buffer asynchronously.
[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
05074499 4Copyright (c) 2005 - 2016, 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
8a67d61d 105/**\r
106 Build the packet to transmit from the TxData passed in.\r
107\r
6e4bac4d 108 @param[in] MnpServiceData Pointer to the mnp service context data.\r
779ae357 109 @param[in] TxData Pointer to the transmit data containing the information\r
6e4bac4d 110 to build the packet.\r
111 @param[out] PktBuf Pointer to record the address of the packet.\r
779ae357 112 @param[out] PktLen Pointer to a UINT32 variable used to record the packet's\r
6e4bac4d 113 length.\r
114\r
05074499
FS
115 @retval EFI_SUCCESS TxPackage is built.\r
116 @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.\r
117\r
8a67d61d 118**/\r
05074499 119EFI_STATUS\r
8a67d61d 120MnpBuildTxPacket (\r
779ae357 121 IN MNP_SERVICE_DATA *MnpServiceData,\r
122 IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData,\r
123 OUT UINT8 **PktBuf,\r
124 OUT UINT32 *PktLen\r
8a67d61d 125 )\r
126{\r
127 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
128 UINT8 *DstPos;\r
129 UINT16 Index;\r
05074499
FS
130 MNP_DEVICE_DATA *MnpDeviceData;\r
131 UINT8 *TxBuf;\r
132 \r
133 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
134 \r
135 TxBuf = MnpAllocTxBuf (MnpDeviceData);\r
136 if (TxBuf == NULL) {\r
137 return EFI_OUT_OF_RESOURCES;\r
138 }\r
139 \r
8ff272ee 140 //\r
05074499 141 // Reserve space for vlan tag if needed.\r
8ff272ee 142 //\r
05074499
FS
143 if (MnpServiceData->VlanId != 0) {\r
144 *PktBuf = TxBuf + NET_VLAN_TAG_LEN;\r
145 } else {\r
146 *PktBuf = TxBuf;\r
147 }\r
8ff272ee 148 \r
8a67d61d 149 if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {\r
bdebd2ce
WJ
150 CopyMem (\r
151 *PktBuf,\r
152 TxData->FragmentTable[0].FragmentBuffer,\r
153 TxData->FragmentTable[0].FragmentLength\r
154 );\r
155 \r
8a67d61d 156 *PktLen = TxData->FragmentTable[0].FragmentLength;\r
157 } else {\r
158 //\r
159 // Either media header isn't in FragmentTable or there is more than\r
160 // one fragment, copy the data into the packet buffer. Reserve the\r
161 // media header space if necessary.\r
162 //\r
05074499 163 SnpMode = MnpDeviceData->Snp->Mode; \r
8ff272ee 164 DstPos = *PktBuf;\r
8a67d61d 165 *PktLen = 0;\r
166 if (TxData->DestinationAddress != NULL) {\r
167 //\r
168 // If dest address is not NULL, move DstPos to reserve space for the\r
169 // media header. Add the media header length to buflen.\r
170 //\r
171 DstPos += SnpMode->MediaHeaderSize;\r
172 *PktLen += SnpMode->MediaHeaderSize;\r
173 }\r
174\r
175 for (Index = 0; Index < TxData->FragmentCount; Index++) {\r
176 //\r
177 // Copy the data.\r
178 //\r
e48e37fc 179 CopyMem (\r
8a67d61d 180 DstPos,\r
181 TxData->FragmentTable[Index].FragmentBuffer,\r
182 TxData->FragmentTable[Index].FragmentLength\r
183 );\r
184 DstPos += TxData->FragmentTable[Index].FragmentLength;\r
185 }\r
186\r
187 //\r
8ff272ee 188 // Set the buffer length.\r
8a67d61d 189 //\r
8a67d61d 190 *PktLen += TxData->DataLength + TxData->HeaderLength;\r
191 }\r
05074499
FS
192\r
193 return EFI_SUCCESS;\r
8a67d61d 194}\r
195\r
196\r
197/**\r
05074499
FS
198 Synchronously send out the packet. \r
199\r
200 This functon places the packet buffer to SNP driver's tansmit queue. The packet\r
201 can be considered successfully sent out once SNP acccetp the packet, while the\r
202 packet buffer recycle is deferred for better performance.\r
8a67d61d 203\r
6e4bac4d 204 @param[in] MnpServiceData Pointer to the mnp service context data.\r
205 @param[in] Packet Pointer to the pakcet buffer.\r
206 @param[in] Length The length of the packet.\r
207 @param[in, out] Token Pointer to the token the packet generated from.\r
8a67d61d 208\r
6e4bac4d 209 @retval EFI_SUCCESS The packet is sent out.\r
210 @retval EFI_TIMEOUT Time out occurs, the packet isn't sent.\r
211 @retval EFI_DEVICE_ERROR An unexpected network error occurs.\r
8a67d61d 212\r
213**/\r
214EFI_STATUS\r
215MnpSyncSendPacket (\r
779ae357 216 IN MNP_SERVICE_DATA *MnpServiceData,\r
217 IN UINT8 *Packet,\r
218 IN UINT32 Length,\r
219 IN OUT EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token\r
8a67d61d 220 )\r
221{\r
222 EFI_STATUS Status;\r
223 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
224 EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;\r
225 UINT32 HeaderSize;\r
779ae357 226 MNP_DEVICE_DATA *MnpDeviceData;\r
227 UINT16 ProtocolType;\r
8a67d61d 228\r
779ae357 229 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
230 Snp = MnpDeviceData->Snp;\r
231 TxData = Token->Packet.TxData;\r
05074499 232 Token->Status = EFI_SUCCESS;\r
779ae357 233 HeaderSize = Snp->Mode->MediaHeaderSize - TxData->HeaderLength;\r
8a67d61d 234\r
dd29f3ed 235 //\r
236 // Check media status before transmit packet.\r
237 // Note: media status will be updated by periodic timer MediaDetectTimer.\r
238 //\r
412d1ed9 239 if (Snp->Mode->MediaPresentSupported && !Snp->Mode->MediaPresent) {\r
dd29f3ed 240 //\r
241 // Media not present, skip packet transmit and report EFI_NO_MEDIA\r
242 //\r
412d1ed9 243 DEBUG ((EFI_D_WARN, "MnpSyncSendPacket: No network cable detected.\n"));\r
05074499 244 Token->Status = EFI_NO_MEDIA;\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
05074499
FS
258 //\r
259 // Transmit the packet through SNP.\r
260 //\r
261 Status = Snp->Transmit (\r
262 Snp,\r
263 HeaderSize,\r
264 Length,\r
265 Packet,\r
266 TxData->SourceAddress,\r
267 TxData->DestinationAddress,\r
268 &ProtocolType\r
269 );\r
270 if (Status == EFI_NOT_READY) {\r
271 Status = MnpRecycleTxBuf (MnpDeviceData);\r
272 if (EFI_ERROR (Status)) {\r
273 Token->Status = EFI_DEVICE_ERROR;\r
274 goto SIGNAL_TOKEN;\r
275 }\r
276\r
8a67d61d 277 Status = Snp->Transmit (\r
278 Snp,\r
279 HeaderSize,\r
280 Length,\r
281 Packet,\r
282 TxData->SourceAddress,\r
283 TxData->DestinationAddress,\r
779ae357 284 &ProtocolType\r
05074499
FS
285 ); \r
286 }\r
287 \r
288 if (EFI_ERROR (Status)) {\r
289 Token->Status = EFI_DEVICE_ERROR;\r
8a67d61d 290 }\r
8a67d61d 291\r
292SIGNAL_TOKEN:\r
293\r
8a67d61d 294 gBS->SignalEvent (Token->Event);\r
295\r
36ee91ca 296 //\r
297 // Dispatch the DPC queued by the NotifyFunction of Token->Event.\r
298 //\r
d8d26fb2 299 DispatchDpc ();\r
36ee91ca 300\r
8a67d61d 301 return EFI_SUCCESS;\r
302}\r
303\r
304\r
305/**\r
306 Try to deliver the received packet to the instance.\r
307\r
6e4bac4d 308 @param[in, out] Instance Pointer to the mnp instance context data.\r
8a67d61d 309\r
310 @retval EFI_SUCCESS The received packet is delivered, or there is no\r
311 packet to deliver, or there is no available receive\r
312 token.\r
313 @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.\r
314\r
315**/\r
316EFI_STATUS\r
317MnpInstanceDeliverPacket (\r
779ae357 318 IN OUT MNP_INSTANCE_DATA *Instance\r
8a67d61d 319 )\r
320{\r
779ae357 321 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 322 MNP_RXDATA_WRAP *RxDataWrap;\r
323 NET_BUF *DupNbuf;\r
324 EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;\r
325 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
326 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *RxToken;\r
327\r
779ae357 328 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;\r
329 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 330\r
e48e37fc 331 if (NetMapIsEmpty (&Instance->RxTokenMap) || IsListEmpty (&Instance->RcvdPacketQueue)) {\r
8a67d61d 332 //\r
333 // No pending received data or no available receive token, return.\r
334 //\r
335 return EFI_SUCCESS;\r
336 }\r
337\r
338 ASSERT (Instance->RcvdPacketQueueSize != 0);\r
339\r
340 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);\r
341 if (RxDataWrap->Nbuf->RefCnt > 2) {\r
342 //\r
343 // There are other instances share this Nbuf, duplicate to get a\r
344 // copy to allow the instance to do R/W operations.\r
345 //\r
779ae357 346 DupNbuf = MnpAllocNbuf (MnpDeviceData);\r
8a67d61d 347 if (DupNbuf == NULL) {\r
e48e37fc 348 DEBUG ((EFI_D_WARN, "MnpDeliverPacket: Failed to allocate a free Nbuf.\n"));\r
8a67d61d 349\r
350 return EFI_OUT_OF_RESOURCES;\r
351 }\r
352\r
353 //\r
354 // Duplicate the net buffer.\r
355 //\r
356 NetbufDuplicate (RxDataWrap->Nbuf, DupNbuf, 0);\r
779ae357 357 MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);\r
8a67d61d 358 RxDataWrap->Nbuf = DupNbuf;\r
359 }\r
360\r
361 //\r
362 // All resources are OK, remove the packet from the queue.\r
363 //\r
364 NetListRemoveHead (&Instance->RcvdPacketQueue);\r
365 Instance->RcvdPacketQueueSize--;\r
366\r
367 RxData = &RxDataWrap->RxData;\r
779ae357 368 SnpMode = MnpDeviceData->Snp->Mode;\r
8a67d61d 369\r
370 //\r
371 // Set all the buffer pointers.\r
372 //\r
373 RxData->MediaHeader = NetbufGetByte (RxDataWrap->Nbuf, 0, NULL);\r
374 RxData->DestinationAddress = RxData->MediaHeader;\r
375 RxData->SourceAddress = (UINT8 *) RxData->MediaHeader + SnpMode->HwAddressSize;\r
376 RxData->PacketData = (UINT8 *) RxData->MediaHeader + SnpMode->MediaHeaderSize;\r
377\r
378 //\r
379 // Insert this RxDataWrap into the delivered queue.\r
380 //\r
e48e37fc 381 InsertTailList (&Instance->RxDeliveredPacketQueue, &RxDataWrap->WrapEntry);\r
8a67d61d 382\r
383 //\r
384 // Get the receive token from the RxTokenMap.\r
385 //\r
386 RxToken = NetMapRemoveHead (&Instance->RxTokenMap, NULL);\r
387\r
388 //\r
389 // Signal this token's event.\r
390 //\r
391 RxToken->Packet.RxData = &RxDataWrap->RxData;\r
392 RxToken->Status = EFI_SUCCESS;\r
393 gBS->SignalEvent (RxToken->Event);\r
394\r
395 return EFI_SUCCESS;\r
396}\r
397\r
398\r
399/**\r
400 Deliver the received packet for the instances belonging to the MnpServiceData.\r
401\r
6e4bac4d 402 @param[in] MnpServiceData Pointer to the mnp service context data.\r
8a67d61d 403\r
8a67d61d 404**/\r
8a67d61d 405VOID\r
406MnpDeliverPacket (\r
779ae357 407 IN MNP_SERVICE_DATA *MnpServiceData\r
8a67d61d 408 )\r
409{\r
e48e37fc 410 LIST_ENTRY *Entry;\r
8a67d61d 411 MNP_INSTANCE_DATA *Instance;\r
412\r
413 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
414\r
415 NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {\r
416 Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);\r
417 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
418\r
419 //\r
420 // Try to deliver packet for this instance.\r
421 //\r
422 MnpInstanceDeliverPacket (Instance);\r
423 }\r
424}\r
425\r
426\r
427/**\r
428 Recycle the RxData and other resources used to hold and deliver the received\r
429 packet.\r
430\r
6e4bac4d 431 @param[in] Event The event this notify function registered to.\r
432 @param[in] Context Pointer to the context data registerd to the Event.\r
433\r
8a67d61d 434**/\r
435VOID\r
436EFIAPI\r
437MnpRecycleRxData (\r
779ae357 438 IN EFI_EVENT Event,\r
439 IN VOID *Context\r
8a67d61d 440 )\r
441{\r
779ae357 442 MNP_RXDATA_WRAP *RxDataWrap;\r
443 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 444\r
445 ASSERT (Context != NULL);\r
446\r
447 RxDataWrap = (MNP_RXDATA_WRAP *) Context;\r
448 NET_CHECK_SIGNATURE (RxDataWrap->Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
449\r
450 ASSERT (RxDataWrap->Nbuf != NULL);\r
451\r
779ae357 452 MnpDeviceData = RxDataWrap->Instance->MnpServiceData->MnpDeviceData;\r
453 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 454\r
455 //\r
456 // Free this Nbuf.\r
457 //\r
779ae357 458 MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);\r
8a67d61d 459 RxDataWrap->Nbuf = NULL;\r
460\r
461 //\r
462 // Close the recycle event.\r
463 //\r
464 gBS->CloseEvent (RxDataWrap->RxData.RecycleEvent);\r
465\r
466 //\r
467 // Remove this Wrap entry from the list.\r
468 //\r
e48e37fc 469 RemoveEntryList (&RxDataWrap->WrapEntry);\r
8a67d61d 470\r
766c7483 471 FreePool (RxDataWrap);\r
8a67d61d 472}\r
473\r
474\r
475/**\r
476 Queue the received packet into instance's receive queue.\r
477\r
6e4bac4d 478 @param[in, out] Instance Pointer to the mnp instance context data.\r
479 @param[in, out] RxDataWrap Pointer to the Wrap structure containing the\r
480 received data and other information.\r
8a67d61d 481**/\r
8a67d61d 482VOID\r
483MnpQueueRcvdPacket (\r
779ae357 484 IN OUT MNP_INSTANCE_DATA *Instance,\r
485 IN OUT MNP_RXDATA_WRAP *RxDataWrap\r
8a67d61d 486 )\r
487{\r
488 MNP_RXDATA_WRAP *OldRxDataWrap;\r
489\r
490 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
491\r
492 //\r
493 // Check the queue size. If it exceeds the limit, drop one packet\r
494 // from the head.\r
495 //\r
496 if (Instance->RcvdPacketQueueSize == MNP_MAX_RCVD_PACKET_QUE_SIZE) {\r
497\r
e48e37fc 498 DEBUG ((EFI_D_WARN, "MnpQueueRcvdPacket: Drop one packet bcz queue size limit reached.\n"));\r
8a67d61d 499\r
500 //\r
501 // Get the oldest packet.\r
502 //\r
503 OldRxDataWrap = NET_LIST_HEAD (\r
504 &Instance->RcvdPacketQueue,\r
505 MNP_RXDATA_WRAP,\r
506 WrapEntry\r
507 );\r
508\r
509 //\r
510 // Recycle this OldRxDataWrap, this entry will be removed by the callee.\r
511 //\r
512 MnpRecycleRxData (NULL, (VOID *) OldRxDataWrap);\r
513 Instance->RcvdPacketQueueSize--;\r
514 }\r
515\r
516 //\r
517 // Update the timeout tick using the configured parameter.\r
518 //\r
519 RxDataWrap->TimeoutTick = Instance->ConfigData.ReceivedQueueTimeoutValue;\r
520\r
521 //\r
522 // Insert this Wrap into the instance queue.\r
523 //\r
e48e37fc 524 InsertTailList (&Instance->RcvdPacketQueue, &RxDataWrap->WrapEntry);\r
8a67d61d 525 Instance->RcvdPacketQueueSize++;\r
526}\r
527\r
528\r
529/**\r
530 Match the received packet with the instance receive filters.\r
531\r
3e8c18da 532 @param[in] Instance Pointer to the mnp instance context data.\r
533 @param[in] RxData Pointer to the EFI_MANAGED_NETWORK_RECEIVE_DATA.\r
534 @param[in] GroupAddress Pointer to the GroupAddress, the GroupAddress is\r
8a67d61d 535 non-NULL and it contains the destination multicast\r
536 mac address of the received packet if the packet\r
537 destinated to a multicast mac address.\r
3e8c18da 538 @param[in] PktAttr The received packets attribute.\r
8a67d61d 539\r
540 @return The received packet matches the instance's receive filters or not.\r
541\r
542**/\r
8a67d61d 543BOOLEAN\r
544MnpMatchPacket (\r
779ae357 545 IN MNP_INSTANCE_DATA *Instance,\r
546 IN EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData,\r
547 IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,\r
548 IN UINT8 PktAttr\r
8a67d61d 549 )\r
550{\r
551 EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData;\r
e48e37fc 552 LIST_ENTRY *Entry;\r
8a67d61d 553 MNP_GROUP_CONTROL_BLOCK *GroupCtrlBlk;\r
554\r
555 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
556\r
557 ConfigData = &Instance->ConfigData;\r
558\r
8a67d61d 559 //\r
560 // Check the protocol type.\r
561 //\r
562 if ((ConfigData->ProtocolTypeFilter != 0) && (ConfigData->ProtocolTypeFilter != RxData->ProtocolType)) {\r
563 return FALSE;\r
564 }\r
565\r
36ee91ca 566 if (ConfigData->EnablePromiscuousReceive) {\r
567 //\r
568 // Always match if this instance is configured to be promiscuous.\r
569 //\r
570 return TRUE;\r
571 }\r
572\r
8a67d61d 573 //\r
574 // The protocol type is matched, check receive filter, include unicast and broadcast.\r
575 //\r
576 if ((Instance->ReceiveFilter & PktAttr) != 0) {\r
577 return TRUE;\r
578 }\r
579\r
580 //\r
581 // Check multicast addresses.\r
582 //\r
583 if (ConfigData->EnableMulticastReceive && RxData->MulticastFlag) {\r
584\r
585 ASSERT (GroupAddress != NULL);\r
586\r
587 NET_LIST_FOR_EACH (Entry, &Instance->GroupCtrlBlkList) {\r
588\r
589 GroupCtrlBlk = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_CONTROL_BLOCK, CtrlBlkEntry);\r
590 if (GroupCtrlBlk->GroupAddress == GroupAddress) {\r
591 //\r
592 // The instance is configured to receiveing packets destinated to this\r
593 // multicast address.\r
594 //\r
595 return TRUE;\r
596 }\r
597 }\r
598 }\r
599\r
600 //\r
601 // No match.\r
602 //\r
603 return FALSE;\r
604}\r
605\r
606\r
607/**\r
608 Analyse the received packets.\r
609\r
6e4bac4d 610 @param[in] MnpServiceData Pointer to the mnp service context data.\r
611 @param[in] Nbuf Pointer to the net buffer holding the received\r
612 packet.\r
613 @param[in, out] RxData Pointer to the buffer used to save the analysed\r
614 result in EFI_MANAGED_NETWORK_RECEIVE_DATA.\r
615 @param[out] GroupAddress Pointer to pointer to a MNP_GROUP_ADDRESS used to\r
616 pass out the address of the multicast address the\r
617 received packet destinated to.\r
618 @param[out] PktAttr Pointer to the buffer used to save the analysed\r
619 packet attribute.\r
8a67d61d 620\r
621**/\r
8a67d61d 622VOID\r
623MnpAnalysePacket (\r
779ae357 624 IN MNP_SERVICE_DATA *MnpServiceData,\r
625 IN NET_BUF *Nbuf,\r
626 IN OUT EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData,\r
627 OUT MNP_GROUP_ADDRESS **GroupAddress,\r
628 OUT UINT8 *PktAttr\r
8a67d61d 629 )\r
630{\r
631 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
779ae357 632 MNP_DEVICE_DATA *MnpDeviceData;\r
8a67d61d 633 UINT8 *BufPtr;\r
e48e37fc 634 LIST_ENTRY *Entry;\r
8a67d61d 635\r
779ae357 636 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
637 SnpMode = MnpDeviceData->Snp->Mode;\r
8a67d61d 638\r
639 //\r
640 // Get the packet buffer.\r
641 //\r
642 BufPtr = NetbufGetByte (Nbuf, 0, NULL);\r
643 ASSERT (BufPtr != NULL);\r
644\r
645 //\r
646 // Set the initial values.\r
647 //\r
648 RxData->BroadcastFlag = FALSE;\r
649 RxData->MulticastFlag = FALSE;\r
650 RxData->PromiscuousFlag = FALSE;\r
651 *PktAttr = UNICAST_PACKET;\r
652\r
653 if (!NET_MAC_EQUAL (&SnpMode->CurrentAddress, BufPtr, SnpMode->HwAddressSize)) {\r
654 //\r
655 // This packet isn't destinated to our current mac address, it't not unicast.\r
656 //\r
657 *PktAttr = 0;\r
658\r
659 if (NET_MAC_EQUAL (&SnpMode->BroadcastAddress, BufPtr, SnpMode->HwAddressSize)) {\r
660 //\r
661 // It's broadcast.\r
662 //\r
663 RxData->BroadcastFlag = TRUE;\r
664 *PktAttr = BROADCAST_PACKET;\r
665 } else if ((*BufPtr & 0x01) == 0x1) {\r
666 //\r
667 // It's multicast, try to match the multicast filters.\r
668 //\r
779ae357 669 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {\r
8a67d61d 670\r
671 *GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
672 if (NET_MAC_EQUAL (BufPtr, &((*GroupAddress)->Address), SnpMode->HwAddressSize)) {\r
673 RxData->MulticastFlag = TRUE;\r
674 break;\r
675 }\r
676 }\r
677\r
678 if (!RxData->MulticastFlag) {\r
679 //\r
680 // No match, set GroupAddress to NULL. This multicast packet must\r
681 // be the result of PROMISUCOUS or PROMISUCOUS_MULTICAST flag is on.\r
682 //\r
683 *GroupAddress = NULL;\r
684 RxData->PromiscuousFlag = TRUE;\r
685\r
779ae357 686 if (MnpDeviceData->PromiscuousCount == 0) {\r
8a67d61d 687 //\r
688 // Skip the below code, there is no receiver of this packet.\r
689 //\r
690 return ;\r
691 }\r
692 }\r
693 } else {\r
694 RxData->PromiscuousFlag = TRUE;\r
695 }\r
696 }\r
697\r
e48e37fc 698 ZeroMem (&RxData->Timestamp, sizeof (EFI_TIME));\r
8a67d61d 699\r
700 //\r
701 // Fill the common parts of RxData.\r
702 //\r
703 RxData->PacketLength = Nbuf->TotalSize;\r
704 RxData->HeaderLength = SnpMode->MediaHeaderSize;\r
705 RxData->AddressLength = SnpMode->HwAddressSize;\r
706 RxData->DataLength = RxData->PacketLength - RxData->HeaderLength;\r
707 RxData->ProtocolType = NTOHS (*(UINT16 *) (BufPtr + 2 * SnpMode->HwAddressSize));\r
708}\r
709\r
710\r
711/**\r
712 Wrap the RxData.\r
713\r
6e4bac4d 714 @param[in] Instance Pointer to the mnp instance context data.\r
715 @param[in] RxData Pointer to the receive data to wrap.\r
8a67d61d 716\r
717 @return Pointer to a MNP_RXDATA_WRAP which wraps the RxData.\r
718\r
719**/\r
8a67d61d 720MNP_RXDATA_WRAP *\r
721MnpWrapRxData (\r
779ae357 722 IN MNP_INSTANCE_DATA *Instance,\r
723 IN EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData\r
8a67d61d 724 )\r
725{\r
726 EFI_STATUS Status;\r
727 MNP_RXDATA_WRAP *RxDataWrap;\r
728\r
729 //\r
730 // Allocate memory.\r
731 //\r
e48e37fc 732 RxDataWrap = AllocatePool (sizeof (MNP_RXDATA_WRAP));\r
8a67d61d 733 if (RxDataWrap == NULL) {\r
e48e37fc 734 DEBUG ((EFI_D_ERROR, "MnpDispatchPacket: Failed to allocate a MNP_RXDATA_WRAP.\n"));\r
8a67d61d 735 return NULL;\r
736 }\r
737\r
738 RxDataWrap->Instance = Instance;\r
739\r
740 //\r
741 // Fill the RxData in RxDataWrap,\r
742 //\r
687a2e5f 743 CopyMem (&RxDataWrap->RxData, RxData, sizeof (RxDataWrap->RxData));\r
8a67d61d 744\r
745 //\r
746 // Create the recycle event.\r
747 //\r
748 Status = gBS->CreateEvent (\r
749 EVT_NOTIFY_SIGNAL,\r
e48e37fc 750 TPL_NOTIFY,\r
8a67d61d 751 MnpRecycleRxData,\r
752 RxDataWrap,\r
753 &RxDataWrap->RxData.RecycleEvent\r
754 );\r
755 if (EFI_ERROR (Status)) {\r
e48e37fc 756 DEBUG ((EFI_D_ERROR, "MnpDispatchPacket: gBS->CreateEvent failed, %r.\n", Status));\r
779ae357 757\r
766c7483 758 FreePool (RxDataWrap);\r
8a67d61d 759 return NULL;\r
760 }\r
761\r
762 return RxDataWrap;\r
763}\r
764\r
765\r
766/**\r
767 Enqueue the received the packets to the instances belonging to the\r
768 MnpServiceData.\r
769\r
6e4bac4d 770 @param[in] MnpServiceData Pointer to the mnp service context data.\r
771 @param[in] Nbuf Pointer to the net buffer representing the received\r
772 packet.\r
8a67d61d 773\r
774**/\r
8a67d61d 775VOID\r
776MnpEnqueuePacket (\r
779ae357 777 IN MNP_SERVICE_DATA *MnpServiceData,\r
778 IN NET_BUF *Nbuf\r
8a67d61d 779 )\r
780{\r
e48e37fc 781 LIST_ENTRY *Entry;\r
8a67d61d 782 MNP_INSTANCE_DATA *Instance;\r
783 EFI_MANAGED_NETWORK_RECEIVE_DATA RxData;\r
784 UINT8 PktAttr;\r
785 MNP_GROUP_ADDRESS *GroupAddress;\r
786 MNP_RXDATA_WRAP *RxDataWrap;\r
787\r
67a58d0f 788\r
789 GroupAddress = NULL;\r
8a67d61d 790 //\r
791 // First, analyse the packet header.\r
792 //\r
793 MnpAnalysePacket (MnpServiceData, Nbuf, &RxData, &GroupAddress, &PktAttr);\r
794\r
779ae357 795 if (RxData.PromiscuousFlag && (MnpServiceData->MnpDeviceData->PromiscuousCount == 0)) {\r
8a67d61d 796 //\r
797 // No receivers, no more action need.\r
798 //\r
799 return ;\r
800 }\r
801\r
802 //\r
803 // Iterate the children to find match.\r
804 //\r
805 NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {\r
806\r
807 Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);\r
808 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
809\r
810 if (!Instance->Configured) {\r
811 continue;\r
812 }\r
813\r
814 //\r
815 // Check the packet against the instance receive filters.\r
816 //\r
817 if (MnpMatchPacket (Instance, &RxData, GroupAddress, PktAttr)) {\r
8a67d61d 818 //\r
819 // Wrap the RxData.\r
820 //\r
687a2e5f 821 RxDataWrap = MnpWrapRxData (Instance, &RxData);\r
8a67d61d 822 if (RxDataWrap == NULL) {\r
823 continue;\r
824 }\r
825\r
826 //\r
827 // Associate RxDataWrap with Nbuf and increase the RefCnt.\r
828 //\r
829 RxDataWrap->Nbuf = Nbuf;\r
830 NET_GET_REF (RxDataWrap->Nbuf);\r
831\r
832 //\r
833 // Queue the packet into the instance queue.\r
834 //\r
835 MnpQueueRcvdPacket (Instance, RxDataWrap);\r
836 }\r
837 }\r
838}\r
839\r
840\r
841/**\r
842 Try to receive a packet and deliver it.\r
843\r
779ae357 844 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
8a67d61d 845\r
846 @retval EFI_SUCCESS add return value to function comment\r
847 @retval EFI_NOT_STARTED The simple network protocol is not started.\r
848 @retval EFI_NOT_READY No packet received.\r
849 @retval EFI_DEVICE_ERROR An unexpected error occurs.\r
850\r
851**/\r
852EFI_STATUS\r
853MnpReceivePacket (\r
779ae357 854 IN OUT MNP_DEVICE_DATA *MnpDeviceData\r
8a67d61d 855 )\r
856{\r
857 EFI_STATUS Status;\r
858 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
859 NET_BUF *Nbuf;\r
860 UINT8 *BufPtr;\r
861 UINTN BufLen;\r
862 UINTN HeaderSize;\r
863 UINT32 Trimmed;\r
779ae357 864 MNP_SERVICE_DATA *MnpServiceData;\r
865 UINT16 VlanId;\r
866 BOOLEAN IsVlanPacket;\r
8a67d61d 867\r
779ae357 868 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
8a67d61d 869\r
779ae357 870 Snp = MnpDeviceData->Snp;\r
8a67d61d 871 if (Snp->Mode->State != EfiSimpleNetworkInitialized) {\r
872 //\r
873 // The simple network protocol is not started.\r
874 //\r
875 return EFI_NOT_STARTED;\r
876 }\r
877\r
779ae357 878 if (MnpDeviceData->RxNbufCache == NULL) {\r
8a67d61d 879 //\r
880 // Try to get a new buffer as there may be buffers recycled.\r
881 //\r
779ae357 882 MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);\r
8a67d61d 883\r
779ae357 884 if (MnpDeviceData->RxNbufCache == NULL) {\r
8a67d61d 885 //\r
886 // No availabe buffer in the buffer pool.\r
887 //\r
888 return EFI_DEVICE_ERROR;\r
889 }\r
890\r
891 NetbufAllocSpace (\r
779ae357 892 MnpDeviceData->RxNbufCache,\r
893 MnpDeviceData->BufferLength,\r
8a67d61d 894 NET_BUF_TAIL\r
895 );\r
896 }\r
897\r
779ae357 898 Nbuf = MnpDeviceData->RxNbufCache;\r
8a67d61d 899 BufLen = Nbuf->TotalSize;\r
900 BufPtr = NetbufGetByte (Nbuf, 0, NULL);\r
901 ASSERT (BufPtr != NULL);\r
902\r
903 //\r
904 // Receive packet through Snp.\r
905 //\r
906 Status = Snp->Receive (Snp, &HeaderSize, &BufLen, BufPtr, NULL, NULL, NULL);\r
907 if (EFI_ERROR (Status)) {\r
8a67d61d 908 DEBUG_CODE (\r
909 if (Status != EFI_NOT_READY) {\r
982a9eae 910 DEBUG ((EFI_D_WARN, "MnpReceivePacket: Snp->Receive() = %r.\n", Status));\r
911 }\r
8a67d61d 912 );\r
913\r
914 return Status;\r
915 }\r
916\r
917 //\r
918 // Sanity check.\r
919 //\r
920 if ((HeaderSize != Snp->Mode->MediaHeaderSize) || (BufLen < HeaderSize)) {\r
e48e37fc 921 DEBUG (\r
922 (EFI_D_WARN,\r
923 "MnpReceivePacket: Size error, HL:TL = %d:%d.\n",\r
8a67d61d 924 HeaderSize,\r
925 BufLen)\r
926 );\r
927 return EFI_DEVICE_ERROR;\r
928 }\r
929\r
930 Trimmed = 0;\r
931 if (Nbuf->TotalSize != BufLen) {\r
932 //\r
933 // Trim the packet from tail.\r
934 //\r
935 Trimmed = NetbufTrim (Nbuf, Nbuf->TotalSize - (UINT32) BufLen, NET_BUF_TAIL);\r
936 ASSERT (Nbuf->TotalSize == BufLen);\r
937 }\r
938\r
779ae357 939 VlanId = 0;\r
ef89996c 940 if (MnpDeviceData->NumberOfVlan != 0) {\r
941 //\r
942 // VLAN is configured, remove the VLAN tag if any\r
943 //\r
944 IsVlanPacket = MnpRemoveVlanTag (MnpDeviceData, Nbuf, &VlanId);\r
945 } else {\r
946 IsVlanPacket = FALSE;\r
947 }\r
779ae357 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