19f28239a5e0a5df3cf88c2ae80d04ca019213ec
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Statistics.c
1 /** @file\r
2 Copyright (c) 2004 - 2007, Intel Corporation\r
3 All rights reserved. This program and the accompanying materials\r
4 are licensed and made available under the terms and conditions of the BSD License\r
5 which accompanies this distribution.  The full text of the license may be found at\r
6 http://opensource.org/licenses/bsd-license.php\r
7 \r
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10 \r
11 Module name:\r
12   statistics.c\r
13 \r
14 Abstract:\r
15 \r
16 Revision history:\r
17   2000-Feb-17 M(f)J   Genesis.\r
18 \r
19 **/\r
20 \r
21 \r
22 #include "Snp.h"\r
23 \r
24 \r
25 /**\r
26   This is the SNP interface routine for getting the NIC's statistics.\r
27   This routine basically retrieves snp structure, checks the SNP state and\r
28   calls the pxe_ routine to actually do the\r
29 \r
30   @param  this              context pointer\r
31   @param  ResetFlag         true to reset the NIC's statistics counters to zero.\r
32   @param  StatTableSizePtr  pointer to the statistics table size\r
33   @param  StatTablePtr      pointer to the statistics table\r
34 \r
35 \r
36 **/\r
37 EFI_STATUS\r
38 EFIAPI\r
39 snp_undi32_statistics (\r
40   IN EFI_SIMPLE_NETWORK_PROTOCOL * this,\r
41   IN BOOLEAN                     ResetFlag,\r
42   IN OUT UINTN                   *StatTableSizePtr OPTIONAL,\r
43   IN OUT EFI_NETWORK_STATISTICS  * StatTablePtr OPTIONAL\r
44   )\r
45 {\r
46   SNP_DRIVER        *snp;\r
47   PXE_DB_STATISTICS *db;\r
48   UINT64            *stp;\r
49   UINT64            mask;\r
50   UINTN             size;\r
51   UINTN             n;\r
52   EFI_TPL           OldTpl;\r
53   EFI_STATUS        Status;\r
54 \r
55   //\r
56   // Get pointer to SNP driver instance for *this.\r
57   //\r
58   if (this == NULL) {\r
59     return EFI_INVALID_PARAMETER;\r
60   }\r
61 \r
62   snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);\r
63 \r
64   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
65 \r
66   //\r
67   // Return error if the SNP is not initialized.\r
68   //\r
69   switch (snp->mode.State) {\r
70   case EfiSimpleNetworkInitialized:\r
71     break;\r
72 \r
73   case EfiSimpleNetworkStopped:\r
74     Status = EFI_NOT_STARTED;\r
75     goto ON_EXIT;\r
76 \r
77   default:\r
78     Status = EFI_DEVICE_ERROR;\r
79     goto ON_EXIT;\r
80   }\r
81   //\r
82   // if we are not resetting the counters, we have to have a valid stat table\r
83   // with >0 size. if no reset, no table and no size, return success.\r
84   //\r
85   if (!ResetFlag && StatTableSizePtr == NULL) {\r
86     Status = StatTablePtr ? EFI_INVALID_PARAMETER : EFI_SUCCESS;\r
87     goto ON_EXIT;\r
88   }\r
89   //\r
90   // Initialize UNDI Statistics CDB\r
91   //\r
92   snp->cdb.OpCode     = PXE_OPCODE_STATISTICS;\r
93   snp->cdb.CPBsize    = PXE_CPBSIZE_NOT_USED;\r
94   snp->cdb.CPBaddr    = PXE_CPBADDR_NOT_USED;\r
95   snp->cdb.StatCode   = PXE_STATCODE_INITIALIZE;\r
96   snp->cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;\r
97   snp->cdb.IFnum      = snp->if_num;\r
98   snp->cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;\r
99 \r
100   if (ResetFlag) {\r
101     snp->cdb.OpFlags  = PXE_OPFLAGS_STATISTICS_RESET;\r
102     snp->cdb.DBsize   = PXE_DBSIZE_NOT_USED;\r
103     snp->cdb.DBaddr   = PXE_DBADDR_NOT_USED;\r
104     db                = snp->db;\r
105   } else {\r
106     snp->cdb.OpFlags                = PXE_OPFLAGS_STATISTICS_READ;\r
107     snp->cdb.DBsize                 = sizeof (PXE_DB_STATISTICS);\r
108     snp->cdb.DBaddr                 = (UINT64)(UINTN) (db = snp->db);\r
109   }\r
110   //\r
111   // Issue UNDI command and check result.\r
112   //\r
113   DEBUG ((EFI_D_NET, "\nsnp->undi.statistics()  "));\r
114 \r
115   (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);\r
116 \r
117   switch (snp->cdb.StatCode) {\r
118   case PXE_STATCODE_SUCCESS:\r
119     break;\r
120 \r
121   case PXE_STATCODE_UNSUPPORTED:\r
122     DEBUG (\r
123       (EFI_D_ERROR,\r
124       "\nsnp->undi.statistics()  %xh:%xh\n",\r
125       snp->cdb.StatFlags,\r
126       snp->cdb.StatCode)\r
127       );\r
128 \r
129     Status = EFI_UNSUPPORTED;\r
130     goto ON_EXIT;\r
131 \r
132   default:\r
133     DEBUG (\r
134       (EFI_D_ERROR,\r
135       "\nsnp->undi.statistics()  %xh:%xh\n",\r
136       snp->cdb.StatFlags,\r
137       snp->cdb.StatCode)\r
138       );\r
139 \r
140     Status = EFI_DEVICE_ERROR;\r
141     goto ON_EXIT;\r
142   }\r
143 \r
144   if (ResetFlag) {\r
145     Status = EFI_SUCCESS;\r
146     goto ON_EXIT;\r
147   }\r
148 \r
149   if (StatTablePtr == NULL) {\r
150     *StatTableSizePtr = sizeof (EFI_NETWORK_STATISTICS);\r
151     Status = EFI_BUFFER_TOO_SMALL;\r
152     goto ON_EXIT;\r
153   }\r
154   //\r
155   // Convert the UNDI statistics information to SNP statistics\r
156   // information.\r
157   //\r
158   ZeroMem (StatTablePtr, *StatTableSizePtr);\r
159   stp   = (UINT64 *) StatTablePtr;\r
160   size  = 0;\r
161 \r
162   for (n = 0, mask = 1; n < 64; n++, mask = LShiftU64 (mask, 1), stp++) {\r
163     //\r
164     // There must be room for a full UINT64.  Partial\r
165     // numbers will not be stored.\r
166     //\r
167     if ((n + 1) * sizeof (UINT64) > *StatTableSizePtr) {\r
168       break;\r
169     }\r
170 \r
171     if (db->Supported & mask) {\r
172       *stp  = db->Data[n];\r
173       size  = n + 1;\r
174     } else {\r
175       SetMem (stp, sizeof (UINT64), 0xFF);\r
176     }\r
177   }\r
178   //\r
179   // Compute size up to last supported statistic.\r
180   //\r
181   while (++n < 64) {\r
182     if (db->Supported & (mask = LShiftU64 (mask, 1))) {\r
183       size = n;\r
184     }\r
185   }\r
186 \r
187   size *= sizeof (UINT64);\r
188 \r
189   if (*StatTableSizePtr >= size) {\r
190     *StatTableSizePtr = size;\r
191     Status = EFI_SUCCESS;\r
192   } else {\r
193     *StatTableSizePtr = size;\r
194     Status = EFI_BUFFER_TOO_SMALL;\r
195   }\r
196 \r
197 ON_EXIT:\r
198   gBS->RestoreTPL (OldTpl);\r
199 \r
200   return Status;\r
201 }\r