+/** @file \r
+\r
+ Task priority (TPL) function \r
+\r
+Copyright (c) 2006 - 2008, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+**/\r
+\r
+#include <DxeMain.h>\r
+\r
+\r
+/**\r
+ Set Interrupt State.\r
+\r
+ @param Enable The state of enable or disable interrupt\r
+\r
+**/\r
+STATIC\r
+VOID\r
+CoreSetInterruptState (\r
+ IN BOOLEAN Enable\r
+ )\r
+{\r
+ if (gCpu != NULL) {\r
+ if (Enable) {\r
+ gCpu->EnableInterrupt(gCpu);\r
+ } else {\r
+ gCpu->DisableInterrupt(gCpu);\r
+ }\r
+ }\r
+}\r
+\r
+//\r
+// Return the highest set bit\r
+//\r
+\r
+/**\r
+ Return the highest set bit.\r
+\r
+ @param Number The value to check \r
+\r
+ @return Bit position of the highest set bit\r
+\r
+**/\r
+UINTN\r
+CoreHighestSetBit (\r
+ IN UINTN Number\r
+ )\r
+{\r
+ UINTN msb;\r
+ \r
+ msb = 31;\r
+ while ((msb > 0) && ((Number & (UINTN)(1 << msb)) == 0)) {\r
+ msb--;\r
+ }\r
+\r
+ return msb;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+ Raise the task priority level to the new level.\r
+ High level is implemented by disabling processor interrupts.\r
+\r
+ @param NewTpl New task priority level \r
+\r
+ @return The previous task priority level\r
+\r
+**/\r
+EFI_TPL\r
+EFIAPI\r
+CoreRaiseTpl (\r
+ IN EFI_TPL NewTpl\r
+ )\r
+{\r
+ EFI_TPL OldTpl;\r
+\r
+ OldTpl = gEfiCurrentTpl;\r
+ ASSERT (OldTpl <= NewTpl);\r
+ ASSERT (VALID_TPL (NewTpl));\r
+\r
+ //\r
+ // If raising to high level, disable interrupts\r
+ //\r
+ if (NewTpl >= TPL_HIGH_LEVEL && OldTpl < TPL_HIGH_LEVEL) {\r
+ CoreSetInterruptState (FALSE);\r
+ }\r
+\r
+ //\r
+ // Set the new value\r
+ //\r
+ gEfiCurrentTpl = NewTpl;\r
+\r
+ return OldTpl;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+ Lowers the task priority to the previous value. If the new\r
+ priority unmasks events at a higher priority, they are dispatched.\r
+\r
+ @param NewTpl New, lower, task priority\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+CoreRestoreTpl (\r
+ IN EFI_TPL NewTpl\r
+ )\r
+{\r
+ EFI_TPL OldTpl;\r
+\r
+ OldTpl = gEfiCurrentTpl;\r
+ ASSERT (NewTpl <= OldTpl);\r
+ ASSERT (VALID_TPL (NewTpl));\r
+\r
+ //\r
+ // If lowering below HIGH_LEVEL, make sure\r
+ // interrupts are enabled\r
+ //\r
+\r
+ if (OldTpl >= TPL_HIGH_LEVEL && NewTpl < TPL_HIGH_LEVEL) {\r
+ gEfiCurrentTpl = TPL_HIGH_LEVEL; \r
+ }\r
+\r
+ //\r
+ // Dispatch any pending events\r
+ //\r
+\r
+ while ((-2 << NewTpl) & gEventPending) {\r
+ gEfiCurrentTpl = CoreHighestSetBit (gEventPending);\r
+ if (gEfiCurrentTpl < TPL_HIGH_LEVEL) {\r
+ CoreSetInterruptState (TRUE);\r
+ }\r
+ CoreDispatchEventNotifies (gEfiCurrentTpl);\r
+ }\r
+\r
+ //\r
+ // Set the new value\r
+ //\r
+\r
+ gEfiCurrentTpl = NewTpl;\r
+\r
+ //\r
+ // If lowering below HIGH_LEVEL, make sure\r
+ // interrupts are enabled\r
+ //\r
+ if (gEfiCurrentTpl < TPL_HIGH_LEVEL) {\r
+ CoreSetInterruptState (TRUE);\r
+ }\r
+\r
+}\r