1 /** @file
2 
3 Copyright (c) 2013-2015 Intel Corporation.
4 
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 
8 **/
9 
10 //
11 // Include common header file for this module.
12 //
13 #include "CommonHeader.h"
14 
15 #include "QNCSmm.h"
16 #include "QNCSmmHelpers.h"
17 
18 //
19 // #define BIT_ZERO 0x00000001
20 //
21 CONST UINT32  BIT_ZERO = 0x00000001;
22 
23 //
24 // /////////////////////////////////////////////////////////////////////////////
25 // SUPPORT / HELPER FUNCTIONS (QNC version-independent)
26 //
27 BOOLEAN
28 CompareEnables (
29   CONST IN QNC_SMM_SOURCE_DESC *Src1,
30   CONST IN QNC_SMM_SOURCE_DESC *Src2
31   )
32 /*++
33 
34 Routine Description:
35 
36   GC_TODO: Add function description
37 
38 Arguments:
39 
40   Src1  - GC_TODO: add argument description
41   Src2  - GC_TODO: add argument description
42 
43 Returns:
44 
45   GC_TODO: add return values
46 
47 --*/
48 {
49   BOOLEAN IsEqual;
50   UINTN   loopvar;
51 
52   IsEqual = TRUE;
53   for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
54     //
55     // It's okay to compare a NULL bit description to a non-NULL bit description.
56     // They are unequal and these tests will generate the correct result.
57     //
58     if (Src1->En[loopvar].Bit != Src2->En[loopvar].Bit ||
59         Src1->En[loopvar].Reg.Type != Src2->En[loopvar].Reg.Type ||
60         Src1->En[loopvar].Reg.Data.raw != Src2->En[loopvar].Reg.Data.raw
61         ) {
62       IsEqual = FALSE;
63       break;
64       //
65       // out of for loop
66       //
67     }
68   }
69 
70   return IsEqual;
71 }
72 
73 BOOLEAN
74 CompareStatuses (
75   CONST IN QNC_SMM_SOURCE_DESC *Src1,
76   CONST IN QNC_SMM_SOURCE_DESC *Src2
77   )
78 /*++
79 
80 Routine Description:
81 
82   GC_TODO: Add function description
83 
84 Arguments:
85 
86   Src1  - GC_TODO: add argument description
87   Src2  - GC_TODO: add argument description
88 
89 Returns:
90 
91   GC_TODO: add return values
92 
93 --*/
94 {
95   BOOLEAN IsEqual;
96   UINTN   loopvar;
97 
98   IsEqual = TRUE;
99 
100   for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
101     //
102     // It's okay to compare a NULL bit description to a non-NULL bit description.
103     // They are unequal and these tests will generate the correct result.
104     //
105     if (Src1->Sts[loopvar].Bit != Src2->Sts[loopvar].Bit ||
106         Src1->Sts[loopvar].Reg.Type != Src2->Sts[loopvar].Reg.Type ||
107         Src1->Sts[loopvar].Reg.Data.raw != Src2->Sts[loopvar].Reg.Data.raw
108         ) {
109       IsEqual = FALSE;
110       break;
111       //
112       // out of for loop
113       //
114     }
115   }
116 
117   return IsEqual;
118 }
119 
120 BOOLEAN
121 CompareSources (
122   CONST IN QNC_SMM_SOURCE_DESC *Src1,
123   CONST IN QNC_SMM_SOURCE_DESC *Src2
124   )
125 /*++
126 
127 Routine Description:
128 
129   GC_TODO: Add function description
130 
131 Arguments:
132 
133   Src1  - GC_TODO: add argument description
134   Src2  - GC_TODO: add argument description
135 
136 Returns:
137 
138   GC_TODO: add return values
139 
140 --*/
141 {
142   return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2));
143 }
144 
145 BOOLEAN
146 SourceIsActive (
147   CONST IN QNC_SMM_SOURCE_DESC *Src
148   )
149 /*++
150 
151 Routine Description:
152 
153   GC_TODO: Add function description
154 
155 Arguments:
156 
157   Src - GC_TODO: add argument description
158 
159 Returns:
160 
161   GC_TODO: add return values
162 
163 --*/
164 {
165   BOOLEAN IsActive;
166   UINTN   loopvar;
167 
168   BOOLEAN SciEn;
169 
170   IsActive  = TRUE;
171 
172   SciEn     = QNCSmmGetSciEn ();
173 
174   if ((Src->Flags & QNC_SMM_SCI_EN_DEPENDENT) && (SciEn)) {
175     //
176     // This source is dependent on SciEn, and SciEn == 1.  An ACPI OS is present,
177     // so we shouldn't do anything w/ this source until SciEn == 0.
178     //
179     IsActive = FALSE;
180 
181   } else {
182     //
183     // Read each bit desc from hardware and make sure it's a one
184     //
185     for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
186 
187       if (!IS_BIT_DESC_NULL (Src->En[loopvar])) {
188 
189         if (ReadBitDesc (&Src->En[loopvar]) == 0) {
190           IsActive = FALSE;
191           break;
192           //
193           // out of for loop
194           //
195         }
196 
197       }
198     }
199 
200     if (IsActive) {
201       //
202       // Read each bit desc from hardware and make sure it's a one
203       //
204       for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
205 
206         if (!IS_BIT_DESC_NULL (Src->Sts[loopvar])) {
207 
208           if (ReadBitDesc (&Src->Sts[loopvar]) == 0) {
209             IsActive = FALSE;
210             break;
211             //
212             // out of for loop
213             //
214           }
215 
216         }
217       }
218     }
219   }
220 
221   return IsActive;
222 }
223 
224 VOID
225 QNCSmmEnableSource (
226   CONST QNC_SMM_SOURCE_DESC *SrcDesc
227   )
228 /*++
229 
230 Routine Description:
231 
232   GC_TODO: Add function description
233 
234 Arguments:
235 
236   SrcDesc - GC_TODO: add argument description
237 
238 Returns:
239 
240   GC_TODO: add return values
241 
242 --*/
243 {
244   UINTN loopvar;
245 
246   //
247   // Set enables to 1 by writing a 1
248   //
249   for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
250     if (!IS_BIT_DESC_NULL (SrcDesc->En[loopvar])) {
251       WriteBitDesc (&SrcDesc->En[loopvar], 1);
252     }
253   }
254 
255   QNCSmmClearSource (SrcDesc);
256 
257 }
258 
259 VOID
260 QNCSmmDisableSource (
261   CONST QNC_SMM_SOURCE_DESC *SrcDesc
262   )
263 /*++
264 
265 Routine Description:
266 
267   GC_TODO: Add function description
268 
269 Arguments:
270 
271   SrcDesc - GC_TODO: add argument description
272 
273 Returns:
274 
275   GC_TODO: add return values
276 
277 --*/
278 {
279   UINTN loopvar;
280 
281   for (loopvar = 0; loopvar < NUM_EN_BITS; loopvar++) {
282     if (!IS_BIT_DESC_NULL (SrcDesc->En[loopvar])) {
283       WriteBitDesc (&SrcDesc->En[loopvar], 0);
284     }
285   }
286 }
287 
288 VOID
289 QNCSmmClearSource (
290   CONST QNC_SMM_SOURCE_DESC *SrcDesc
291   )
292 /*++
293 
294 Routine Description:
295 
296   GC_TODO: Add function description
297 
298 Arguments:
299 
300   SrcDesc - GC_TODO: add argument description
301 
302 Returns:
303 
304   GC_TODO: add return values
305 
306 --*/
307 {
308   UINTN loopvar;
309   BOOLEAN ValueToWrite;
310 
311   ValueToWrite =
312     ((SrcDesc->Flags & QNC_SMM_CLEAR_WITH_ZERO) == 0) ? TRUE : FALSE;
313 
314   for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
315     if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) {
316       WriteBitDesc (&SrcDesc->Sts[loopvar], ValueToWrite);
317     }
318   }
319 }
320 
321 VOID
322 QNCSmmClearSourceAndBlock (
323   CONST QNC_SMM_SOURCE_DESC *SrcDesc
324   )
325 // GC_TODO: function comment should start with '/*++'
326 /*
327   Sets the source to a 1 or 0 and then waits for it to clear.
328   Be very careful when calling this function -- it will not
329   ASSERT.  An acceptable case to call the function is when
330   waiting for the NEWCENTURY_STS bit to clear (which takes
331   3 RTCCLKs).
332 */
333 // GC_TODO: function comment should end with '--*/'
334 // GC_TODO: function comment is missing 'Routine Description:'
335 // GC_TODO: function comment is missing 'Arguments:'
336 // GC_TODO: function comment is missing 'Returns:'
337 // GC_TODO:    SrcDesc - add argument and description to function comment
338 {
339   UINTN   loopvar;
340   BOOLEAN IsSet;
341   BOOLEAN ValueToWrite;
342 
343   ValueToWrite =
344     ((SrcDesc->Flags & QNC_SMM_CLEAR_WITH_ZERO) == 0) ? TRUE : FALSE;
345 
346   for (loopvar = 0; loopvar < NUM_STS_BITS; loopvar++) {
347 
348     if (!IS_BIT_DESC_NULL (SrcDesc->Sts[loopvar])) {
349       //
350       // Write the bit
351       //
352       WriteBitDesc (&SrcDesc->Sts[loopvar], ValueToWrite);
353 
354       //
355       // Don't return until the bit actually clears.
356       //
357       IsSet = TRUE;
358       while (IsSet) {
359         IsSet = ReadBitDesc (&SrcDesc->Sts[loopvar]);
360         //
361         // IsSet will eventually clear -- or else we'll have
362         // an infinite loop.
363         //
364       }
365     }
366   }
367 }
368