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