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