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