sync comments, fix function header, rename variable name to follow coding style.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Statistics.c
1 /** @file\r
2     Implementation of collecting the statistics on a network interface.\r
3  \r
4 Copyright (c) 2004 - 2007, Intel Corporation. <BR> \r
5 All rights reserved. This program and the accompanying materials are licensed \r
6 and made available under the terms and conditions of the BSD License which \r
7 accompanies this distribution. The full text of the license may be found at \r
8 http://opensource.org/licenses/bsd-license.php \r
9 \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 **/\r
14 \r
15 \r
16 #include "Snp.h"\r
17 \r
18 \r
19 /**\r
20   Resets or collects the statistics on a network interface.\r
21   \r
22   This function resets or collects the statistics on a network interface. If the\r
23   size of the statistics table specified by StatisticsSize is not big enough for\r
24   all the statistics that are collected by the network interface, then a partial\r
25   buffer of statistics is returned in StatisticsTable, StatisticsSize is set to \r
26   the size required to collect all the available statistics, and \r
27   EFI_BUFFER_TOO_SMALL is returned.\r
28   If StatisticsSize is big enough for all the statistics, then StatisticsTable \r
29   will be filled, StatisticsSize will be set to the size of the returned \r
30   StatisticsTable structure, and EFI_SUCCESS is returned.\r
31   If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.\r
32   If Reset is FALSE, and both StatisticsSize and StatisticsTable are NULL, then\r
33   no operations will be performed, and EFI_SUCCESS will be returned.\r
34   If Reset is TRUE, then all of the supported statistics counters on this network\r
35   interface will be reset to zero.\r
36 \r
37   @param This            A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.\r
38   @param Reset           Set to TRUE to reset the statistics for the network interface.\r
39   @param StatisticsSize  On input the size, in bytes, of StatisticsTable. On output \r
40                          the size, in bytes, of the resulting table of statistics.\r
41   @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that \r
42                          contains the statistics. Type EFI_NETWORK_STATISTICS is \r
43                          defined in "Related Definitions" below. \r
44   \r
45   @retval EFI_SUCCESS           The requested operation succeeded.\r
46   @retval EFI_NOT_STARTED       The Simple Network Protocol interface has not been\r
47                                 started by calling Start().\r
48   @retval EFI_BUFFER_TOO_SMALL  StatisticsSize is not NULL and StatisticsTable is \r
49                                 NULL. The current buffer size that is needed to \r
50                                 hold all the statistics is returned in StatisticsSize.\r
51   @retval EFI_BUFFER_TOO_SMALL  StatisticsSize is not NULL and StatisticsTable is \r
52                                 not NULL. The current buffer size that is needed\r
53                                 to hold all the statistics is returned in \r
54                                 StatisticsSize. A partial set of statistics is \r
55                                 returned in StatisticsTable.\r
56   @retval EFI_INVALID_PARAMETER StatisticsSize is NULL and StatisticsTable is not \r
57                                 NULL.\r
58   @retval EFI_DEVICE_ERROR      The Simple Network Protocol interface has not \r
59                                 been initialized by calling Initialize().\r
60   @retval EFI_DEVICE_ERROR      An error was encountered collecting statistics \r
61                                 from the NIC.\r
62   @retval EFI_UNSUPPORTED       The NIC does not support collecting statistics \r
63                                 from the network interface.\r
64 \r
65 **/\r
66 EFI_STATUS\r
67 EFIAPI\r
68 SnpUndi32Statistics (\r
69   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
70   IN BOOLEAN                     Reset,\r
71   IN OUT UINTN                   *StatisticsSize, OPTIONAL\r
72   IN OUT EFI_NETWORK_STATISTICS  *StatisticsTable OPTIONAL\r
73   )\r
74 {\r
75   SNP_DRIVER        *Snp;\r
76   PXE_DB_STATISTICS *Db;\r
77   UINT64            *Stp;\r
78   UINT64            Mask;\r
79   UINTN             Size;\r
80   UINTN             Index;\r
81   EFI_TPL           OldTpl;\r
82   EFI_STATUS        Status;\r
83 \r
84   //\r
85   // Get pointer to SNP driver instance for *This.\r
86   //\r
87   if (This == NULL) {\r
88     return EFI_INVALID_PARAMETER;\r
89   }\r
90 \r
91   Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
92 \r
93   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
94 \r
95   //\r
96   // Return error if the SNP is not initialized.\r
97   //\r
98   switch (Snp->Mode.State) {\r
99   case EfiSimpleNetworkInitialized:\r
100     break;\r
101 \r
102   case EfiSimpleNetworkStopped:\r
103     Status = EFI_NOT_STARTED;\r
104     goto ON_EXIT;\r
105 \r
106   default:\r
107     Status = EFI_DEVICE_ERROR;\r
108     goto ON_EXIT;\r
109   }\r
110   //\r
111   // if we are not resetting the counters, we have to have a valid stat table\r
112   // with >0 size. if no reset, no table and no size, return success.\r
113   //\r
114   if (!Reset && StatisticsSize == NULL) {\r
115     Status = (StatisticsTable != NULL) ? EFI_INVALID_PARAMETER : EFI_SUCCESS;\r
116     goto ON_EXIT;\r
117   }\r
118   //\r
119   // Initialize UNDI Statistics CDB\r
120   //\r
121   Snp->Cdb.OpCode     = PXE_OPCODE_STATISTICS;\r
122   Snp->Cdb.CPBsize    = PXE_CPBSIZE_NOT_USED;\r
123   Snp->Cdb.CPBaddr    = PXE_CPBADDR_NOT_USED;\r
124   Snp->Cdb.StatCode   = PXE_STATCODE_INITIALIZE;\r
125   Snp->Cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;\r
126   Snp->Cdb.IFnum      = Snp->IfNum;\r
127   Snp->Cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;\r
128 \r
129   if (Reset) {\r
130     Snp->Cdb.OpFlags  = PXE_OPFLAGS_STATISTICS_RESET;\r
131     Snp->Cdb.DBsize   = PXE_DBSIZE_NOT_USED;\r
132     Snp->Cdb.DBaddr   = PXE_DBADDR_NOT_USED;\r
133     Db                = Snp->Db;\r
134   } else {\r
135     Snp->Cdb.OpFlags                = PXE_OPFLAGS_STATISTICS_READ;\r
136     Snp->Cdb.DBsize                 = sizeof (PXE_DB_STATISTICS);\r
137     Snp->Cdb.DBaddr                 = (UINT64)(UINTN) (Db = Snp->Db);\r
138   }\r
139   //\r
140   // Issue UNDI command and check result.\r
141   //\r
142   DEBUG ((EFI_D_NET, "\nsnp->undi.statistics()  "));\r
143 \r
144   (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
145 \r
146   switch (Snp->Cdb.StatCode) {\r
147   case PXE_STATCODE_SUCCESS:\r
148     break;\r
149 \r
150   case PXE_STATCODE_UNSUPPORTED:\r
151     DEBUG (\r
152       (EFI_D_ERROR,\r
153       "\nsnp->undi.statistics()  %xh:%xh\n",\r
154       Snp->Cdb.StatFlags,\r
155       Snp->Cdb.StatCode)\r
156       );\r
157 \r
158     Status = EFI_UNSUPPORTED;\r
159     goto ON_EXIT;\r
160 \r
161   default:\r
162     DEBUG (\r
163       (EFI_D_ERROR,\r
164       "\nsnp->undi.statistics()  %xh:%xh\n",\r
165       Snp->Cdb.StatFlags,\r
166       Snp->Cdb.StatCode)\r
167       );\r
168 \r
169     Status = EFI_DEVICE_ERROR;\r
170     goto ON_EXIT;\r
171   }\r
172 \r
173   if (Reset) {\r
174     Status = EFI_SUCCESS;\r
175     goto ON_EXIT;\r
176   }\r
177 \r
178   if (StatisticsTable == NULL) {\r
179     *StatisticsSize = sizeof (EFI_NETWORK_STATISTICS);\r
180     Status = EFI_BUFFER_TOO_SMALL;\r
181     goto ON_EXIT;\r
182   }\r
183   //\r
184   // Convert the UNDI statistics information to SNP statistics\r
185   // information.\r
186   //\r
187   ZeroMem (StatisticsTable, *StatisticsSize);\r
188   Stp   = (UINT64 *) StatisticsTable;\r
189   Size  = 0;\r
190 \r
191   for (Index = 0, Mask = 1; Index < 64; Index++, Mask = LShiftU64 (Mask, 1), Stp++) {\r
192     //\r
193     // There must be room for a full UINT64.  Partial\r
194     // numbers will not be stored.\r
195     //\r
196     if ((Index + 1) * sizeof (UINT64) > *StatisticsSize) {\r
197       break;\r
198     }\r
199 \r
200     if (Db->Supported & Mask) {\r
201       *Stp  = Db->Data[Index];\r
202       Size  = Index + 1;\r
203     } else {\r
204       SetMem (Stp, sizeof (UINT64), 0xFF);\r
205     }\r
206   }\r
207   //\r
208   // Compute size up to last supported statistic.\r
209   //\r
210   while (++Index < 64) {\r
211     if (Db->Supported & (Mask = LShiftU64 (Mask, 1))) {\r
212       Size = Index;\r
213     }\r
214   }\r
215 \r
216   Size *= sizeof (UINT64);\r
217 \r
218   if (*StatisticsSize >= Size) {\r
219     *StatisticsSize = Size;\r
220     Status = EFI_SUCCESS;\r
221   } else {\r
222     *StatisticsSize = Size;\r
223     Status = EFI_BUFFER_TOO_SMALL;\r
224   }\r
225 \r
226 ON_EXIT:\r
227   gBS->RestoreTPL (OldTpl);\r
228 \r
229   return Status;\r
230 }\r