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