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