2 Implementation of Managed Network Protocol I/O functions.
4 Copyright (c) 2005 - 2010, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The full
8 text of the license may be found at<BR>
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 Validates the Mnp transmit token.
22 @param[in] Instance Pointer to the Mnp instance context data.
23 @param[in] Token Pointer to the transmit token to check.
25 @return The Token is valid or not.
30 IN MNP_INSTANCE_DATA
*Instance
,
31 IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
34 MNP_SERVICE_DATA
*MnpServiceData
;
35 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
38 EFI_MANAGED_NETWORK_FRAGMENT_DATA
*FragmentTable
;
40 MnpServiceData
= Instance
->MnpServiceData
;
41 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
43 TxData
= Token
->Packet
.TxData
;
45 if ((Token
->Event
== NULL
) || (TxData
== NULL
) || (TxData
->FragmentCount
== 0)) {
47 // The token is invalid if the Event is NULL, or the TxData is NULL, or
48 // the fragment count is zero.
50 DEBUG ((EFI_D_WARN
, "MnpIsValidTxToken: Invalid Token.\n"));
54 if ((TxData
->DestinationAddress
!= NULL
) && (TxData
->HeaderLength
!= 0)) {
56 // The token is invalid if the HeaderLength isn't zero while the DestinationAddress
57 // is NULL (The destination address is already put into the packet).
59 DEBUG ((EFI_D_WARN
, "MnpIsValidTxToken: DestinationAddress isn't NULL, HeaderLength must be 0.\n"));
64 FragmentTable
= TxData
->FragmentTable
;
65 for (Index
= 0; Index
< TxData
->FragmentCount
; Index
++) {
67 if ((FragmentTable
[Index
].FragmentLength
== 0) || (FragmentTable
[Index
].FragmentBuffer
== NULL
)) {
69 // The token is invalid if any FragmentLength is zero or any FragmentBuffer is NULL.
71 DEBUG ((EFI_D_WARN
, "MnpIsValidTxToken: Invalid FragmentLength or FragmentBuffer.\n"));
75 TotalLength
+= FragmentTable
[Index
].FragmentLength
;
78 if ((TxData
->DestinationAddress
== NULL
) && (FragmentTable
[0].FragmentLength
< TxData
->HeaderLength
)) {
80 // Media header is split between fragments.
85 if (TotalLength
!= (TxData
->DataLength
+ TxData
->HeaderLength
)) {
87 // The length calculated from the fragment information doesn't equal to the
88 // sum of the DataLength and the HeaderLength.
90 DEBUG ((EFI_D_WARN
, "MnpIsValidTxData: Invalid Datalength compared with the sum of fragment length.\n"));
94 if (TxData
->DataLength
> MnpServiceData
->Mtu
) {
96 // The total length is larger than the MTU.
98 DEBUG ((EFI_D_WARN
, "MnpIsValidTxData: TxData->DataLength exceeds Mtu.\n"));
107 Build the packet to transmit from the TxData passed in.
109 @param[in] MnpServiceData Pointer to the mnp service context data.
110 @param[in] TxData Pointer to the transmit data containing the information
112 @param[out] PktBuf Pointer to record the address of the packet.
113 @param[out] PktLen Pointer to a UINT32 variable used to record the packet's
119 IN MNP_SERVICE_DATA
*MnpServiceData
,
120 IN EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
,
125 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
128 MNP_DEVICE_DATA
*MnpDerviceData
;
130 MnpDerviceData
= MnpServiceData
->MnpDeviceData
;
131 if ((TxData
->DestinationAddress
== NULL
) && (TxData
->FragmentCount
== 1)) {
133 // Media header is in FragmentTable and there is only one fragment,
134 // use fragment buffer directly.
136 *PktBuf
= TxData
->FragmentTable
[0].FragmentBuffer
;
137 *PktLen
= TxData
->FragmentTable
[0].FragmentLength
;
140 // Either media header isn't in FragmentTable or there is more than
141 // one fragment, copy the data into the packet buffer. Reserve the
142 // media header space if necessary.
144 SnpMode
= MnpDerviceData
->Snp
->Mode
;
145 DstPos
= MnpDerviceData
->TxBuf
;
148 if (TxData
->DestinationAddress
!= NULL
) {
150 // If dest address is not NULL, move DstPos to reserve space for the
151 // media header. Add the media header length to buflen.
153 DstPos
+= SnpMode
->MediaHeaderSize
;
154 *PktLen
+= SnpMode
->MediaHeaderSize
;
157 for (Index
= 0; Index
< TxData
->FragmentCount
; Index
++) {
163 TxData
->FragmentTable
[Index
].FragmentBuffer
,
164 TxData
->FragmentTable
[Index
].FragmentLength
166 DstPos
+= TxData
->FragmentTable
[Index
].FragmentLength
;
170 // Set the buffer pointer and the buffer length.
172 *PktBuf
= MnpDerviceData
->TxBuf
;
173 *PktLen
+= TxData
->DataLength
+ TxData
->HeaderLength
;
179 Synchronously send out the packet.
181 @param[in] MnpServiceData Pointer to the mnp service context data.
182 @param[in] Packet Pointer to the pakcet buffer.
183 @param[in] Length The length of the packet.
184 @param[in, out] Token Pointer to the token the packet generated from.
186 @retval EFI_SUCCESS The packet is sent out.
187 @retval EFI_TIMEOUT Time out occurs, the packet isn't sent.
188 @retval EFI_DEVICE_ERROR An unexpected network error occurs.
193 IN MNP_SERVICE_DATA
*MnpServiceData
,
196 IN OUT EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
200 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
201 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
204 MNP_DEVICE_DATA
*MnpDeviceData
;
207 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
208 Snp
= MnpDeviceData
->Snp
;
209 TxData
= Token
->Packet
.TxData
;
211 HeaderSize
= Snp
->Mode
->MediaHeaderSize
- TxData
->HeaderLength
;
214 // Check media status before transmit packet.
215 // Note: media status will be updated by periodic timer MediaDetectTimer.
217 if (!Snp
->Mode
->MediaPresent
) {
219 // Media not present, skip packet transmit and report EFI_NO_MEDIA
221 Status
= EFI_NO_MEDIA
;
226 // Start the timeout event.
228 Status
= gBS
->SetTimer (
229 MnpDeviceData
->TxTimeoutEvent
,
233 if (EFI_ERROR (Status
)) {
240 MnpInsertVlanTag (MnpServiceData
, TxData
, &ProtocolType
, &Packet
, &Length
);
244 // Transmit the packet through SNP.
246 Status
= Snp
->Transmit (
251 TxData
->SourceAddress
,
252 TxData
->DestinationAddress
,
255 if ((Status
!= EFI_SUCCESS
) && (Status
!= EFI_NOT_READY
)) {
256 Status
= EFI_DEVICE_ERROR
;
261 // If Status is EFI_SUCCESS, the packet is put in the transmit queue.
262 // if Status is EFI_NOT_READY, the transmit engine of the network interface is busy.
263 // Both need to sync SNP.
268 // Get the recycled transmit buffer status.
270 Snp
->GetStatus (Snp
, NULL
, (VOID
**) &TxBuf
);
272 if (!EFI_ERROR (gBS
->CheckEvent (MnpDeviceData
->TxTimeoutEvent
))) {
273 Status
= EFI_TIMEOUT
;
276 } while (TxBuf
== NULL
);
278 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_TIMEOUT
)) {
282 // Status is EFI_NOT_READY. Restart the timer event and call Snp->Transmit again.
285 MnpDeviceData
->TxTimeoutEvent
,
293 // Cancel the timer event.
295 gBS
->SetTimer (MnpDeviceData
->TxTimeoutEvent
, TimerCancel
, 0);
299 Token
->Status
= Status
;
300 gBS
->SignalEvent (Token
->Event
);
303 // Dispatch the DPC queued by the NotifyFunction of Token->Event.
312 Try to deliver the received packet to the instance.
314 @param[in, out] Instance Pointer to the mnp instance context data.
316 @retval EFI_SUCCESS The received packet is delivered, or there is no
317 packet to deliver, or there is no available receive
319 @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.
323 MnpInstanceDeliverPacket (
324 IN OUT MNP_INSTANCE_DATA
*Instance
327 MNP_DEVICE_DATA
*MnpDeviceData
;
328 MNP_RXDATA_WRAP
*RxDataWrap
;
330 EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
;
331 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
332 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*RxToken
;
334 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
335 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
337 if (NetMapIsEmpty (&Instance
->RxTokenMap
) || IsListEmpty (&Instance
->RcvdPacketQueue
)) {
339 // No pending received data or no available receive token, return.
344 ASSERT (Instance
->RcvdPacketQueueSize
!= 0);
346 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
347 if (RxDataWrap
->Nbuf
->RefCnt
> 2) {
349 // There are other instances share this Nbuf, duplicate to get a
350 // copy to allow the instance to do R/W operations.
352 DupNbuf
= MnpAllocNbuf (MnpDeviceData
);
353 if (DupNbuf
== NULL
) {
354 DEBUG ((EFI_D_WARN
, "MnpDeliverPacket: Failed to allocate a free Nbuf.\n"));
356 return EFI_OUT_OF_RESOURCES
;
360 // Duplicate the net buffer.
362 NetbufDuplicate (RxDataWrap
->Nbuf
, DupNbuf
, 0);
363 MnpFreeNbuf (MnpDeviceData
, RxDataWrap
->Nbuf
);
364 RxDataWrap
->Nbuf
= DupNbuf
;
368 // All resources are OK, remove the packet from the queue.
370 NetListRemoveHead (&Instance
->RcvdPacketQueue
);
371 Instance
->RcvdPacketQueueSize
--;
373 RxData
= &RxDataWrap
->RxData
;
374 SnpMode
= MnpDeviceData
->Snp
->Mode
;
377 // Set all the buffer pointers.
379 RxData
->MediaHeader
= NetbufGetByte (RxDataWrap
->Nbuf
, 0, NULL
);
380 RxData
->DestinationAddress
= RxData
->MediaHeader
;
381 RxData
->SourceAddress
= (UINT8
*) RxData
->MediaHeader
+ SnpMode
->HwAddressSize
;
382 RxData
->PacketData
= (UINT8
*) RxData
->MediaHeader
+ SnpMode
->MediaHeaderSize
;
385 // Insert this RxDataWrap into the delivered queue.
387 InsertTailList (&Instance
->RxDeliveredPacketQueue
, &RxDataWrap
->WrapEntry
);
390 // Get the receive token from the RxTokenMap.
392 RxToken
= NetMapRemoveHead (&Instance
->RxTokenMap
, NULL
);
395 // Signal this token's event.
397 RxToken
->Packet
.RxData
= &RxDataWrap
->RxData
;
398 RxToken
->Status
= EFI_SUCCESS
;
399 gBS
->SignalEvent (RxToken
->Event
);
406 Deliver the received packet for the instances belonging to the MnpServiceData.
408 @param[in] MnpServiceData Pointer to the mnp service context data.
413 IN MNP_SERVICE_DATA
*MnpServiceData
417 MNP_INSTANCE_DATA
*Instance
;
419 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
421 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->ChildrenList
) {
422 Instance
= NET_LIST_USER_STRUCT (Entry
, MNP_INSTANCE_DATA
, InstEntry
);
423 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
426 // Try to deliver packet for this instance.
428 MnpInstanceDeliverPacket (Instance
);
434 Recycle the RxData and other resources used to hold and deliver the received
437 @param[in] Event The event this notify function registered to.
438 @param[in] Context Pointer to the context data registerd to the Event.
448 MNP_RXDATA_WRAP
*RxDataWrap
;
449 MNP_DEVICE_DATA
*MnpDeviceData
;
451 ASSERT (Context
!= NULL
);
453 RxDataWrap
= (MNP_RXDATA_WRAP
*) Context
;
454 NET_CHECK_SIGNATURE (RxDataWrap
->Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
456 ASSERT (RxDataWrap
->Nbuf
!= NULL
);
458 MnpDeviceData
= RxDataWrap
->Instance
->MnpServiceData
->MnpDeviceData
;
459 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
464 MnpFreeNbuf (MnpDeviceData
, RxDataWrap
->Nbuf
);
465 RxDataWrap
->Nbuf
= NULL
;
468 // Close the recycle event.
470 gBS
->CloseEvent (RxDataWrap
->RxData
.RecycleEvent
);
473 // Remove this Wrap entry from the list.
475 RemoveEntryList (&RxDataWrap
->WrapEntry
);
477 FreePool (RxDataWrap
);
482 Queue the received packet into instance's receive queue.
484 @param[in, out] Instance Pointer to the mnp instance context data.
485 @param[in, out] RxDataWrap Pointer to the Wrap structure containing the
486 received data and other information.
490 IN OUT MNP_INSTANCE_DATA
*Instance
,
491 IN OUT MNP_RXDATA_WRAP
*RxDataWrap
494 MNP_RXDATA_WRAP
*OldRxDataWrap
;
496 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
499 // Check the queue size. If it exceeds the limit, drop one packet
502 if (Instance
->RcvdPacketQueueSize
== MNP_MAX_RCVD_PACKET_QUE_SIZE
) {
504 DEBUG ((EFI_D_WARN
, "MnpQueueRcvdPacket: Drop one packet bcz queue size limit reached.\n"));
507 // Get the oldest packet.
509 OldRxDataWrap
= NET_LIST_HEAD (
510 &Instance
->RcvdPacketQueue
,
516 // Recycle this OldRxDataWrap, this entry will be removed by the callee.
518 MnpRecycleRxData (NULL
, (VOID
*) OldRxDataWrap
);
519 Instance
->RcvdPacketQueueSize
--;
523 // Update the timeout tick using the configured parameter.
525 RxDataWrap
->TimeoutTick
= Instance
->ConfigData
.ReceivedQueueTimeoutValue
;
528 // Insert this Wrap into the instance queue.
530 InsertTailList (&Instance
->RcvdPacketQueue
, &RxDataWrap
->WrapEntry
);
531 Instance
->RcvdPacketQueueSize
++;
536 Match the received packet with the instance receive filters.
538 @param[in] Instance Pointer to the mnp instance context data.
539 @param[in] RxData Pointer to the EFI_MANAGED_NETWORK_RECEIVE_DATA.
540 @param[in] GroupAddress Pointer to the GroupAddress, the GroupAddress is
541 non-NULL and it contains the destination multicast
542 mac address of the received packet if the packet
543 destinated to a multicast mac address.
544 @param[in] PktAttr The received packets attribute.
546 @return The received packet matches the instance's receive filters or not.
551 IN MNP_INSTANCE_DATA
*Instance
,
552 IN EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
,
553 IN MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
557 EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData
;
559 MNP_GROUP_CONTROL_BLOCK
*GroupCtrlBlk
;
561 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
563 ConfigData
= &Instance
->ConfigData
;
566 // Check the protocol type.
568 if ((ConfigData
->ProtocolTypeFilter
!= 0) && (ConfigData
->ProtocolTypeFilter
!= RxData
->ProtocolType
)) {
572 if (ConfigData
->EnablePromiscuousReceive
) {
574 // Always match if this instance is configured to be promiscuous.
580 // The protocol type is matched, check receive filter, include unicast and broadcast.
582 if ((Instance
->ReceiveFilter
& PktAttr
) != 0) {
587 // Check multicast addresses.
589 if (ConfigData
->EnableMulticastReceive
&& RxData
->MulticastFlag
) {
591 ASSERT (GroupAddress
!= NULL
);
593 NET_LIST_FOR_EACH (Entry
, &Instance
->GroupCtrlBlkList
) {
595 GroupCtrlBlk
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_CONTROL_BLOCK
, CtrlBlkEntry
);
596 if (GroupCtrlBlk
->GroupAddress
== GroupAddress
) {
598 // The instance is configured to receiveing packets destinated to this
599 // multicast address.
614 Analyse the received packets.
616 @param[in] MnpServiceData Pointer to the mnp service context data.
617 @param[in] Nbuf Pointer to the net buffer holding the received
619 @param[in, out] RxData Pointer to the buffer used to save the analysed
620 result in EFI_MANAGED_NETWORK_RECEIVE_DATA.
621 @param[out] GroupAddress Pointer to pointer to a MNP_GROUP_ADDRESS used to
622 pass out the address of the multicast address the
623 received packet destinated to.
624 @param[out] PktAttr Pointer to the buffer used to save the analysed
630 IN MNP_SERVICE_DATA
*MnpServiceData
,
632 IN OUT EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
,
633 OUT MNP_GROUP_ADDRESS
**GroupAddress
,
637 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
638 MNP_DEVICE_DATA
*MnpDeviceData
;
642 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
643 SnpMode
= MnpDeviceData
->Snp
->Mode
;
646 // Get the packet buffer.
648 BufPtr
= NetbufGetByte (Nbuf
, 0, NULL
);
649 ASSERT (BufPtr
!= NULL
);
652 // Set the initial values.
654 RxData
->BroadcastFlag
= FALSE
;
655 RxData
->MulticastFlag
= FALSE
;
656 RxData
->PromiscuousFlag
= FALSE
;
657 *PktAttr
= UNICAST_PACKET
;
659 if (!NET_MAC_EQUAL (&SnpMode
->CurrentAddress
, BufPtr
, SnpMode
->HwAddressSize
)) {
661 // This packet isn't destinated to our current mac address, it't not unicast.
665 if (NET_MAC_EQUAL (&SnpMode
->BroadcastAddress
, BufPtr
, SnpMode
->HwAddressSize
)) {
669 RxData
->BroadcastFlag
= TRUE
;
670 *PktAttr
= BROADCAST_PACKET
;
671 } else if ((*BufPtr
& 0x01) == 0x1) {
673 // It's multicast, try to match the multicast filters.
675 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->GroupAddressList
) {
677 *GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
678 if (NET_MAC_EQUAL (BufPtr
, &((*GroupAddress
)->Address
), SnpMode
->HwAddressSize
)) {
679 RxData
->MulticastFlag
= TRUE
;
684 if (!RxData
->MulticastFlag
) {
686 // No match, set GroupAddress to NULL. This multicast packet must
687 // be the result of PROMISUCOUS or PROMISUCOUS_MULTICAST flag is on.
689 *GroupAddress
= NULL
;
690 RxData
->PromiscuousFlag
= TRUE
;
692 if (MnpDeviceData
->PromiscuousCount
== 0) {
694 // Skip the below code, there is no receiver of this packet.
700 RxData
->PromiscuousFlag
= TRUE
;
704 ZeroMem (&RxData
->Timestamp
, sizeof (EFI_TIME
));
707 // Fill the common parts of RxData.
709 RxData
->PacketLength
= Nbuf
->TotalSize
;
710 RxData
->HeaderLength
= SnpMode
->MediaHeaderSize
;
711 RxData
->AddressLength
= SnpMode
->HwAddressSize
;
712 RxData
->DataLength
= RxData
->PacketLength
- RxData
->HeaderLength
;
713 RxData
->ProtocolType
= NTOHS (*(UINT16
*) (BufPtr
+ 2 * SnpMode
->HwAddressSize
));
720 @param[in] Instance Pointer to the mnp instance context data.
721 @param[in] RxData Pointer to the receive data to wrap.
723 @return Pointer to a MNP_RXDATA_WRAP which wraps the RxData.
728 IN MNP_INSTANCE_DATA
*Instance
,
729 IN EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
733 MNP_RXDATA_WRAP
*RxDataWrap
;
738 RxDataWrap
= AllocatePool (sizeof (MNP_RXDATA_WRAP
));
739 if (RxDataWrap
== NULL
) {
740 DEBUG ((EFI_D_ERROR
, "MnpDispatchPacket: Failed to allocate a MNP_RXDATA_WRAP.\n"));
744 RxDataWrap
->Instance
= Instance
;
747 // Fill the RxData in RxDataWrap,
749 CopyMem (&RxDataWrap
->RxData
, RxData
, sizeof (RxDataWrap
->RxData
));
752 // Create the recycle event.
754 Status
= gBS
->CreateEvent (
759 &RxDataWrap
->RxData
.RecycleEvent
761 if (EFI_ERROR (Status
)) {
762 DEBUG ((EFI_D_ERROR
, "MnpDispatchPacket: gBS->CreateEvent failed, %r.\n", Status
));
764 FreePool (RxDataWrap
);
773 Enqueue the received the packets to the instances belonging to the
776 @param[in] MnpServiceData Pointer to the mnp service context data.
777 @param[in] Nbuf Pointer to the net buffer representing the received
783 IN MNP_SERVICE_DATA
*MnpServiceData
,
788 MNP_INSTANCE_DATA
*Instance
;
789 EFI_MANAGED_NETWORK_RECEIVE_DATA RxData
;
791 MNP_GROUP_ADDRESS
*GroupAddress
;
792 MNP_RXDATA_WRAP
*RxDataWrap
;
797 // First, analyse the packet header.
799 MnpAnalysePacket (MnpServiceData
, Nbuf
, &RxData
, &GroupAddress
, &PktAttr
);
801 if (RxData
.PromiscuousFlag
&& (MnpServiceData
->MnpDeviceData
->PromiscuousCount
== 0)) {
803 // No receivers, no more action need.
809 // Iterate the children to find match.
811 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->ChildrenList
) {
813 Instance
= NET_LIST_USER_STRUCT (Entry
, MNP_INSTANCE_DATA
, InstEntry
);
814 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
816 if (!Instance
->Configured
) {
821 // Check the packet against the instance receive filters.
823 if (MnpMatchPacket (Instance
, &RxData
, GroupAddress
, PktAttr
)) {
827 RxDataWrap
= MnpWrapRxData (Instance
, &RxData
);
828 if (RxDataWrap
== NULL
) {
833 // Associate RxDataWrap with Nbuf and increase the RefCnt.
835 RxDataWrap
->Nbuf
= Nbuf
;
836 NET_GET_REF (RxDataWrap
->Nbuf
);
839 // Queue the packet into the instance queue.
841 MnpQueueRcvdPacket (Instance
, RxDataWrap
);
848 Try to receive a packet and deliver it.
850 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
852 @retval EFI_SUCCESS add return value to function comment
853 @retval EFI_NOT_STARTED The simple network protocol is not started.
854 @retval EFI_NOT_READY No packet received.
855 @retval EFI_DEVICE_ERROR An unexpected error occurs.
860 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
864 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
870 MNP_SERVICE_DATA
*MnpServiceData
;
872 BOOLEAN IsVlanPacket
;
874 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
876 Snp
= MnpDeviceData
->Snp
;
877 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
879 // The simple network protocol is not started.
881 return EFI_NOT_STARTED
;
884 if (MnpDeviceData
->RxNbufCache
== NULL
) {
886 // Try to get a new buffer as there may be buffers recycled.
888 MnpDeviceData
->RxNbufCache
= MnpAllocNbuf (MnpDeviceData
);
890 if (MnpDeviceData
->RxNbufCache
== NULL
) {
892 // No availabe buffer in the buffer pool.
894 return EFI_DEVICE_ERROR
;
898 MnpDeviceData
->RxNbufCache
,
899 MnpDeviceData
->BufferLength
,
904 Nbuf
= MnpDeviceData
->RxNbufCache
;
905 BufLen
= Nbuf
->TotalSize
;
906 BufPtr
= NetbufGetByte (Nbuf
, 0, NULL
);
907 ASSERT (BufPtr
!= NULL
);
910 // Receive packet through Snp.
912 Status
= Snp
->Receive (Snp
, &HeaderSize
, &BufLen
, BufPtr
, NULL
, NULL
, NULL
);
913 if (EFI_ERROR (Status
)) {
915 if (Status
!= EFI_NOT_READY
) {
916 DEBUG ((EFI_D_WARN
, "MnpReceivePacket: Snp->Receive() = %r.\n", Status
));
926 if ((HeaderSize
!= Snp
->Mode
->MediaHeaderSize
) || (BufLen
< HeaderSize
)) {
929 "MnpReceivePacket: Size error, HL:TL = %d:%d.\n",
933 return EFI_DEVICE_ERROR
;
937 if (Nbuf
->TotalSize
!= BufLen
) {
939 // Trim the packet from tail.
941 Trimmed
= NetbufTrim (Nbuf
, Nbuf
->TotalSize
- (UINT32
) BufLen
, NET_BUF_TAIL
);
942 ASSERT (Nbuf
->TotalSize
== BufLen
);
946 IsVlanPacket
= MnpRemoveVlanTag (MnpDeviceData
, Nbuf
, &VlanId
);
948 MnpServiceData
= MnpFindServiceData (MnpDeviceData
, VlanId
);
949 if (MnpServiceData
== NULL
) {
951 // VLAN is not set for this tagged frame, ignore this packet
954 NetbufAllocSpace (Nbuf
, Trimmed
, NET_BUF_TAIL
);
958 NetbufAllocSpace (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_HEAD
);
965 // Enqueue the packet to the matched instances.
967 MnpEnqueuePacket (MnpServiceData
, Nbuf
);
969 if (Nbuf
->RefCnt
> 2) {
971 // RefCnt > 2 indicates there is at least one receiver of this packet.
972 // Free the current RxNbufCache and allocate a new one.
974 MnpFreeNbuf (MnpDeviceData
, Nbuf
);
976 Nbuf
= MnpAllocNbuf (MnpDeviceData
);
977 MnpDeviceData
->RxNbufCache
= Nbuf
;
979 DEBUG ((EFI_D_ERROR
, "MnpReceivePacket: Alloc packet for receiving cache failed.\n"));
980 return EFI_DEVICE_ERROR
;
983 NetbufAllocSpace (Nbuf
, MnpDeviceData
->BufferLength
, NET_BUF_TAIL
);
986 // No receiver for this packet.
989 NetbufAllocSpace (Nbuf
, Trimmed
, NET_BUF_TAIL
);
992 NetbufAllocSpace (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_HEAD
);
998 // Deliver the queued packets.
1000 MnpDeliverPacket (MnpServiceData
);
1004 ASSERT (Nbuf
->TotalSize
== MnpDeviceData
->BufferLength
);
1011 Remove the received packets if timeout occurs.
1013 @param[in] Event The event this notify function registered to.
1014 @param[in] Context Pointer to the context data registered to the event.
1019 MnpCheckPacketTimeout (
1024 MNP_DEVICE_DATA
*MnpDeviceData
;
1025 MNP_SERVICE_DATA
*MnpServiceData
;
1027 LIST_ENTRY
*ServiceEntry
;
1028 LIST_ENTRY
*RxEntry
;
1029 LIST_ENTRY
*NextEntry
;
1030 MNP_INSTANCE_DATA
*Instance
;
1031 MNP_RXDATA_WRAP
*RxDataWrap
;
1034 MnpDeviceData
= (MNP_DEVICE_DATA
*) Context
;
1035 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1037 NET_LIST_FOR_EACH (ServiceEntry
, &MnpDeviceData
->ServiceList
) {
1038 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (ServiceEntry
);
1040 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->ChildrenList
) {
1042 Instance
= NET_LIST_USER_STRUCT (Entry
, MNP_INSTANCE_DATA
, InstEntry
);
1043 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1045 if (!Instance
->Configured
|| (Instance
->ConfigData
.ReceivedQueueTimeoutValue
== 0)) {
1047 // This instance is not configured or there is no receive time out,
1048 // just skip to the next instance.
1053 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1055 NET_LIST_FOR_EACH_SAFE (RxEntry
, NextEntry
, &Instance
->RcvdPacketQueue
) {
1057 RxDataWrap
= NET_LIST_USER_STRUCT (RxEntry
, MNP_RXDATA_WRAP
, WrapEntry
);
1060 // TimeoutTick unit is microsecond, MNP_TIMEOUT_CHECK_INTERVAL unit is 100ns.
1062 if (RxDataWrap
->TimeoutTick
>= (MNP_TIMEOUT_CHECK_INTERVAL
/ 10)) {
1063 RxDataWrap
->TimeoutTick
-= (MNP_TIMEOUT_CHECK_INTERVAL
/ 10);
1066 // Drop the timeout packet.
1068 DEBUG ((EFI_D_WARN
, "MnpCheckPacketTimeout: Received packet timeout.\n"));
1069 MnpRecycleRxData (NULL
, RxDataWrap
);
1070 Instance
->RcvdPacketQueueSize
--;
1074 gBS
->RestoreTPL (OldTpl
);
1080 Poll to update MediaPresent field in SNP ModeData by Snp->GetStatus().
1082 @param[in] Event The event this notify function registered to.
1083 @param[in] Context Pointer to the context data registered to the event.
1088 MnpCheckMediaStatus (
1093 MNP_DEVICE_DATA
*MnpDeviceData
;
1094 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1095 UINT32 InterruptStatus
;
1097 MnpDeviceData
= (MNP_DEVICE_DATA
*) Context
;
1098 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1100 Snp
= MnpDeviceData
->Snp
;
1101 if (Snp
->Mode
->MediaPresentSupported
) {
1103 // Upon successful return of GetStatus(), the MediaPresent field of
1104 // EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change of media status
1106 Snp
->GetStatus (Snp
, &InterruptStatus
, NULL
);
1111 Poll to receive the packets from Snp. This function is either called by upperlayer
1112 protocols/applications or the system poll timer notify mechanism.
1114 @param[in] Event The event this notify function registered to.
1115 @param[in] Context Pointer to the context data registered to the event.
1125 MNP_DEVICE_DATA
*MnpDeviceData
;
1127 MnpDeviceData
= (MNP_DEVICE_DATA
*) Context
;
1128 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1131 // Try to receive packets from Snp.
1133 MnpReceivePacket (MnpDeviceData
);
1136 // Dispatch the DPC queued by the NotifyFunction of rx token's events.