]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/SnpDxe/Get_status.c
MdeModulePkg: SNP should check Cdb.StatCode with PXE_STATCODE_SUCCESS.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Get_status.c
index 053297605b78c7b3e31624ed8fd795490ea68dbe..edbc0f2374994c73d3562439b896ee869a6b6178 100644 (file)
@@ -2,7 +2,7 @@
   Implementation of reading the current interrupt status and recycled transmit\r
   buffer status from a network interface.\r
 \r
-Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials are licensed\r
 and made available under the terms and conditions of the BSD License which\r
 accompanies this distribution. The full text of the license may be found at\r
@@ -16,15 +16,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Snp.h"\r
 \r
 /**\r
-  Call undi to get the status of the interrupts, get the list of transmit\r
-  buffers that completed transmitting.\r
+  Call undi to get the status of the interrupts, get the list of recycled transmit\r
+  buffers that completed transmitting. The recycled transmit buffer address will\r
+  be saved into Snp->RecycledTxBuf.\r
 \r
   @param  Snp                     Pointer to snp driver structure.\r
   @param  InterruptStatusPtr      A non null pointer to contain the interrupt\r
                                   status.\r
-  @param  TransmitBufferListPtrs  A non null pointer to contain the list of\r
-                                  pointers of previous transmitted buffers whose\r
-                                  transmission was completed asynchrnously.\r
+  @param  GetTransmittedBuf       Set to TRUE to retrieve the recycled transmit\r
+                                  buffer address.\r
 \r
   @retval EFI_SUCCESS         The status of the network interface was retrieved.\r
   @retval EFI_DEVICE_ERROR    The command could not be sent to the network\r
@@ -35,19 +35,23 @@ EFI_STATUS
 PxeGetStatus (\r
   SNP_DRIVER *Snp,\r
   UINT32     *InterruptStatusPtr,\r
-  VOID       **TransmitBufferListPtr\r
+  BOOLEAN    GetTransmittedBuf\r
   )\r
 {\r
   PXE_DB_GET_STATUS *Db;\r
   UINT16            InterruptFlags;\r
+  UINT32            Index;\r
+  UINT64            *Tmp;\r
 \r
+  Tmp               = NULL;\r
   Db                = Snp->Db;\r
   Snp->Cdb.OpCode   = PXE_OPCODE_GET_STATUS;\r
 \r
   Snp->Cdb.OpFlags  = 0;\r
 \r
-  if (TransmitBufferListPtr != NULL) {\r
+  if (GetTransmittedBuf) {\r
     Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS;\r
+    ZeroMem (Db->TxBuffer, sizeof (Db->TxBuffer));\r
   }\r
 \r
   if (InterruptStatusPtr != NULL) {\r
@@ -61,11 +65,7 @@ PxeGetStatus (
   Snp->Cdb.CPBsize  = PXE_CPBSIZE_NOT_USED;\r
   Snp->Cdb.CPBaddr  = PXE_CPBADDR_NOT_USED;\r
 \r
-  //\r
-  // size DB for return of one buffer\r
-  //\r
-  Snp->Cdb.DBsize     = (UINT16) ((sizeof (PXE_DB_GET_STATUS) - sizeof (Db->TxBuffer)) + sizeof (Db->TxBuffer[0]));\r
-\r
+  Snp->Cdb.DBsize     = (UINT16) sizeof (PXE_DB_GET_STATUS);\r
   Snp->Cdb.DBaddr     = (UINT64)(UINTN) Db;\r
 \r
   Snp->Cdb.StatCode   = PXE_STATCODE_INITIALIZE;\r
@@ -80,12 +80,12 @@ PxeGetStatus (
 \r
   (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
 \r
-  if (Snp->Cdb.StatCode != EFI_SUCCESS) {\r
+  if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
     DEBUG (\r
       (EFI_D_NET,\r
       "\nSnp->undi.get_status()  %xh:%xh\n",\r
       Snp->Cdb.StatFlags,\r
-      Snp->Cdb.StatFlags)\r
+      Snp->Cdb.StatCode)\r
       );\r
 \r
     return EFI_DEVICE_ERROR;\r
@@ -116,13 +116,34 @@ PxeGetStatus (
 \r
   }\r
 \r
-  if (TransmitBufferListPtr != NULL) {\r
-    *TransmitBufferListPtr =\r
-      (\r
-        ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) != 0) ||\r
-        ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY) != 0)\r
-      ) ? 0 : (VOID *) (UINTN) Db->TxBuffer[0];\r
-\r
+  if (GetTransmittedBuf) {\r
+    if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) == 0) {\r
+      //\r
+      // UNDI has written some transmitted buffer addresses into the DB. Store them into Snp->RecycledTxBuf.\r
+      //\r
+      for (Index = 0; Index < MAX_XMIT_BUFFERS; Index++) {\r
+        if (Db->TxBuffer[Index] != 0) {\r
+          if (Snp->RecycledTxBufCount == Snp->MaxRecycledTxBuf) {\r
+            //\r
+            // Snp->RecycledTxBuf is full, reallocate a new one.\r
+            //\r
+            if ((Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >= SNP_MAX_TX_BUFFER_NUM) {\r
+              return EFI_DEVICE_ERROR;\r
+            }\r
+            Tmp = AllocatePool (sizeof (UINT64) * (Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT));\r
+            if (Tmp == NULL) {\r
+              return EFI_DEVICE_ERROR;\r
+            }\r
+            CopyMem (Tmp, Snp->RecycledTxBuf, sizeof (UINT64) * Snp->RecycledTxBufCount);\r
+            FreePool (Snp->RecycledTxBuf);\r
+            Snp->RecycledTxBuf    =  Tmp;\r
+            Snp->MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT;\r
+          }\r
+          Snp->RecycledTxBuf[Snp->RecycledTxBufCount] = Db->TxBuffer[Index];\r
+          Snp->RecycledTxBufCount++;\r
+        }\r
+      }\r
+    }\r
   }\r
 \r
   //\r
@@ -216,7 +237,23 @@ SnpUndi32GetStatus (
     goto ON_EXIT;\r
   }\r
 \r
-  Status = PxeGetStatus (Snp, InterruptStatus, TxBuf);\r
+  if (Snp->RecycledTxBufCount == 0 && TxBuf != NULL) {\r
+    Status = PxeGetStatus (Snp, InterruptStatus, TRUE);\r
+  } else {\r
+    Status = PxeGetStatus (Snp, InterruptStatus, FALSE);\r
+  }\r
+\r
+  if (TxBuf != NULL) {\r
+    //\r
+    // Get a recycled buf from Snp->RecycledTxBuf\r
+    //\r
+    if (Snp->RecycledTxBufCount == 0) {\r
+      *TxBuf = NULL;\r
+    } else {\r
+      Snp->RecycledTxBufCount--;\r
+      *TxBuf = (VOID *) (UINTN) Snp->RecycledTxBuf[Snp->RecycledTxBufCount];\r
+    }\r
+  }\r
 \r
 ON_EXIT:\r
   gBS->RestoreTPL (OldTpl);\r