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