/** @file\r
Implementation of Managed Network Protocol I/O functions.\r
\r
-Copyright (c) 2005 - 2009, Intel Corporation.<BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
of the BSD License which accompanies this distribution. The full\r
text of the license may be found at<BR>\r
return TRUE;\r
}\r
\r
-\r
/**\r
Build the packet to transmit from the TxData passed in.\r
\r
@param[out] PktLen Pointer to a UINT32 variable used to record the packet's\r
length.\r
\r
+ @retval EFI_SUCCESS TxPackage is built.\r
+ @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.\r
+\r
**/\r
-VOID\r
+EFI_STATUS\r
MnpBuildTxPacket (\r
IN MNP_SERVICE_DATA *MnpServiceData,\r
IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData,\r
EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
UINT8 *DstPos;\r
UINT16 Index;\r
- MNP_DEVICE_DATA *MnpDerviceData;\r
-\r
- MnpDerviceData = MnpServiceData->MnpDeviceData;\r
+ MNP_DEVICE_DATA *MnpDeviceData;\r
+ UINT8 *TxBuf;\r
+ \r
+ MnpDeviceData = MnpServiceData->MnpDeviceData;\r
+ \r
+ TxBuf = MnpAllocTxBuf (MnpDeviceData);\r
+ if (TxBuf == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ //\r
+ // Reserve space for vlan tag if needed.\r
+ //\r
+ if (MnpServiceData->VlanId != 0) {\r
+ *PktBuf = TxBuf + NET_VLAN_TAG_LEN;\r
+ } else {\r
+ *PktBuf = TxBuf;\r
+ }\r
+ \r
if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {\r
- //\r
- // Media header is in FragmentTable and there is only one fragment,\r
- // use fragment buffer directly.\r
- //\r
- *PktBuf = TxData->FragmentTable[0].FragmentBuffer;\r
+ CopyMem (\r
+ *PktBuf,\r
+ TxData->FragmentTable[0].FragmentBuffer,\r
+ TxData->FragmentTable[0].FragmentLength\r
+ );\r
+ \r
*PktLen = TxData->FragmentTable[0].FragmentLength;\r
} else {\r
//\r
// one fragment, copy the data into the packet buffer. Reserve the\r
// media header space if necessary.\r
//\r
- SnpMode = MnpDerviceData->Snp->Mode;\r
- DstPos = MnpDerviceData->TxBuf;\r
-\r
+ SnpMode = MnpDeviceData->Snp->Mode; \r
+ DstPos = *PktBuf;\r
*PktLen = 0;\r
if (TxData->DestinationAddress != NULL) {\r
//\r
}\r
\r
//\r
- // Set the buffer pointer and the buffer length.\r
+ // Set the buffer length.\r
//\r
- *PktBuf = MnpDerviceData->TxBuf;\r
*PktLen += TxData->DataLength + TxData->HeaderLength;\r
}\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
\r
/**\r
- Synchronously send out the packet.\r
+ Synchronously send out the packet. \r
+\r
+ This functon places the packet buffer to SNP driver's tansmit queue. The packet\r
+ can be considered successfully sent out once SNP acccetp the packet, while the\r
+ packet buffer recycle is deferred for better performance.\r
\r
@param[in] MnpServiceData Pointer to the mnp service context data.\r
@param[in] Packet Pointer to the pakcet buffer.\r
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;\r
UINT32 HeaderSize;\r
- UINT8 *TxBuf;\r
MNP_DEVICE_DATA *MnpDeviceData;\r
UINT16 ProtocolType;\r
\r
MnpDeviceData = MnpServiceData->MnpDeviceData;\r
Snp = MnpDeviceData->Snp;\r
TxData = Token->Packet.TxData;\r
-\r
+ Token->Status = EFI_SUCCESS;\r
HeaderSize = Snp->Mode->MediaHeaderSize - TxData->HeaderLength;\r
\r
//\r
- // Start the timeout event.\r
+ // Check media status before transmit packet.\r
+ // Note: media status will be updated by periodic timer MediaDetectTimer.\r
//\r
- Status = gBS->SetTimer (\r
- MnpDeviceData->TxTimeoutEvent,\r
- TimerRelative,\r
- MNP_TX_TIMEOUT_TIME\r
- );\r
- if (EFI_ERROR (Status)) {\r
+ if (Snp->Mode->MediaPresentSupported && !Snp->Mode->MediaPresent) {\r
+ //\r
+ // Media not present, skip packet transmit and report EFI_NO_MEDIA\r
+ //\r
+ DEBUG ((EFI_D_WARN, "MnpSyncSendPacket: No network cable detected.\n"));\r
+ Token->Status = EFI_NO_MEDIA;\r
goto SIGNAL_TOKEN;\r
}\r
\r
+ \r
+ if (MnpServiceData->VlanId != 0) {\r
+ //\r
+ // Insert VLAN tag\r
+ //\r
+ MnpInsertVlanTag (MnpServiceData, TxData, &ProtocolType, &Packet, &Length);\r
+ } else {\r
+ ProtocolType = TxData->ProtocolType;\r
+ }\r
+\r
//\r
- // Insert VLAN tag\r
+ // Transmit the packet through SNP.\r
//\r
- MnpInsertVlanTag (MnpServiceData, TxData, &ProtocolType, &Packet, &Length);\r
+ Status = Snp->Transmit (\r
+ Snp,\r
+ HeaderSize,\r
+ Length,\r
+ Packet,\r
+ TxData->SourceAddress,\r
+ TxData->DestinationAddress,\r
+ &ProtocolType\r
+ );\r
+ if (Status == EFI_NOT_READY) {\r
+ Status = MnpRecycleTxBuf (MnpDeviceData);\r
+ if (EFI_ERROR (Status)) {\r
+ Token->Status = EFI_DEVICE_ERROR;\r
+ goto SIGNAL_TOKEN;\r
+ }\r
\r
- for (;;) {\r
- //\r
- // Transmit the packet through SNP.\r
- //\r
Status = Snp->Transmit (\r
Snp,\r
HeaderSize,\r
TxData->SourceAddress,\r
TxData->DestinationAddress,\r
&ProtocolType\r
- );\r
- if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {\r
- Status = EFI_DEVICE_ERROR;\r
- break;\r
- }\r
-\r
- //\r
- // If Status is EFI_SUCCESS, the packet is put in the transmit queue.\r
- // if Status is EFI_NOT_READY, the transmit engine of the network interface is busy.\r
- // Both need to sync SNP.\r
- //\r
- TxBuf = NULL;\r
- do {\r
- //\r
- // Get the recycled transmit buffer status.\r
- //\r
- Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);\r
-\r
- if (!EFI_ERROR (gBS->CheckEvent (MnpDeviceData->TxTimeoutEvent))) {\r
- Status = EFI_TIMEOUT;\r
- break;\r
- }\r
- } while (TxBuf == NULL);\r
-\r
- if ((Status == EFI_SUCCESS) || (Status == EFI_TIMEOUT)) {\r
- break;\r
- } else {\r
- //\r
- // Status is EFI_NOT_READY. Restart the timer event and call Snp->Transmit again.\r
- //\r
- gBS->SetTimer (\r
- MnpDeviceData->TxTimeoutEvent,\r
- TimerRelative,\r
- MNP_TX_TIMEOUT_TIME\r
- );\r
- }\r
+ ); \r
+ }\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ Token->Status = EFI_DEVICE_ERROR;\r
}\r
-\r
- //\r
- // Cancel the timer event.\r
- //\r
- gBS->SetTimer (MnpDeviceData->TxTimeoutEvent, TimerCancel, 0);\r
\r
SIGNAL_TOKEN:\r
\r
- Token->Status = Status;\r
gBS->SignalEvent (Token->Event);\r
\r
//\r
}\r
\r
VlanId = 0;\r
- IsVlanPacket = MnpRemoveVlanTag (MnpDeviceData, Nbuf, &VlanId);\r
+ if (MnpDeviceData->NumberOfVlan != 0) {\r
+ //\r
+ // VLAN is configured, remove the VLAN tag if any\r
+ //\r
+ IsVlanPacket = MnpRemoveVlanTag (MnpDeviceData, Nbuf, &VlanId);\r
+ } else {\r
+ IsVlanPacket = FALSE;\r
+ }\r
\r
MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);\r
if (MnpServiceData == NULL) {\r
/**\r
Remove the received packets if timeout occurs.\r
\r
- @param[in] Event The event this notify function registered to.\r
- @param[in] Context Pointer to the context data registered to the\r
- event.\r
+ @param[in] Event The event this notify function registered to.\r
+ @param[in] Context Pointer to the context data registered to the event.\r
\r
**/\r
VOID\r
}\r
}\r
\r
+/**\r
+ Poll to update MediaPresent field in SNP ModeData by Snp->GetStatus().\r
+\r
+ @param[in] Event The event this notify function registered to.\r
+ @param[in] Context Pointer to the context data registered to the event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+MnpCheckMediaStatus (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ MNP_DEVICE_DATA *MnpDeviceData;\r
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
+ UINT32 InterruptStatus;\r
+\r
+ MnpDeviceData = (MNP_DEVICE_DATA *) Context;\r
+ NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
+\r
+ Snp = MnpDeviceData->Snp;\r
+ if (Snp->Mode->MediaPresentSupported) {\r
+ //\r
+ // Upon successful return of GetStatus(), the MediaPresent field of\r
+ // EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change of media status\r
+ //\r
+ Snp->GetStatus (Snp, &InterruptStatus, NULL);\r
+ }\r
+}\r
+\r
/**\r
Poll to receive the packets from Snp. This function is either called by upperlayer\r
protocols/applications or the system poll timer notify mechanism.\r
\r
- @param[in] Event The event this notify function registered to.\r
- @param[in, out] Context Pointer to the context data registered to the event.\r
+ @param[in] Event The event this notify function registered to.\r
+ @param[in] Context Pointer to the context data registered to the event.\r
\r
**/\r
VOID\r
EFIAPI\r
MnpSystemPoll (\r
- IN EFI_EVENT Event,\r
- IN OUT VOID *Context\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
)\r
{\r
MNP_DEVICE_DATA *MnpDeviceData;\r