Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
9.4 KiB

  1. /* Copyright 1999 American Power Conversion, All Rights Reserved
  2. *
  3. * Description:
  4. * Implementation for all RUNNING substates (ON_LINE, ON_BATTERY and NO_COMM)
  5. *
  6. * Revision History:
  7. * dsmith 31Mar1999 Created
  8. * mholly 28Apr1999 call InitUPSStatusBlock & SaveUPSStatusBlock when
  9. * updating the registry in NoComm_Enter/Exit
  10. */
  11. #include <windows.h>
  12. #include "states.h"
  13. #include "events.h"
  14. #include "run_states.h"
  15. #include "statmach.h"
  16. #include "driver.h"
  17. #include "eventlog.h"
  18. #include "notifier.h"
  19. #include "upsmsg.h"
  20. #include "upsreg.h"
  21. // Internal Prototypes
  22. DWORD convert_ups_state_to_run_state(DWORD aUPSstate);
  23. DWORD get_new_state();
  24. DWORD get_transition_event();
  25. // Internal constants
  26. #define WAIT_FOREVER_C INFINITE
  27. #define MILLISECONDS_CONVERSION_C 1000
  28. #define DEFAULT_NOTIFICATION_INTERVAL_C 0 // disable periodic notification
  29. #define DEFAULT_ON_BATTERY_MESSAGE_DELAY_C 5 // in seconds
  30. #define MINUTES_TO_MILLISECONDS_CONVERSION_C 60*MILLISECONDS_CONVERSION_C
  31. /**
  32. * OnLine_Enter
  33. *
  34. * Description:
  35. * Performs the actions necessary when transitioning into the ON_LINE state.
  36. *
  37. * Parameters:
  38. * anEvent The event that caused the transition into this state.
  39. *
  40. * Returns:
  41. * None
  42. */
  43. void OnLine_Enter(DWORD anEvent, int aLogPowerRestoredEvent){
  44. DWORD notification_interval = DEFAULT_NOTIFICATION_INTERVAL_C;
  45. //
  46. // update the registry with status
  47. //
  48. InitUPSStatusBlock();
  49. SetUPSStatusUtilityStatus(UPS_UTILITYPOWER_ON);
  50. SaveUPSStatusBlock(FALSE);
  51. if (aLogPowerRestoredEvent == TRUE){
  52. // Log the power restored event only if appropriate
  53. LogEvent(NELOG_UPS_PowerBack, NULL, ERROR_SUCCESS);
  54. }
  55. /*
  56. * Send the power restored message if notification is enabled.
  57. *
  58. * patrickf: Supress notification message for now
  59. * SendNotification(APE2_UPS_POWER_BACK, notification_interval, 0);
  60. */
  61. CancelNotification();
  62. }
  63. /**
  64. * OnLine_DoWork
  65. *
  66. * Description:
  67. * Wait until the UPS changes state or the state machine exits,
  68. * then leave this state.
  69. *
  70. * Parameters:
  71. * None
  72. *
  73. * Returns:
  74. * The event that caused the transition from the ON_LINE state.
  75. */
  76. DWORD OnLine_DoWork(){
  77. DWORD new_state;
  78. new_state = get_new_state();
  79. while (new_state == ON_LINE && IsStateMachineActive() == TRUE){
  80. // Wait until the UPS state changes. If the state becomes something
  81. // other than ONLINE, then exit the ONLINE state.
  82. UPSWaitForStateChange(UPS_ONLINE, WAIT_FOREVER_C);
  83. new_state = get_new_state();
  84. }
  85. return get_transition_event();
  86. }
  87. /**
  88. * OnLine_Exit
  89. *
  90. * Description:
  91. * Performs the actions necessary when transitioning from the ON_LINE state.
  92. *
  93. * Parameters:
  94. * anEvent The event that caused the transition from the ON_LINE state.
  95. *
  96. * Returns:
  97. * None
  98. */
  99. void OnLine_Exit(DWORD anEvent){
  100. // No work to perform.
  101. }
  102. /**
  103. * OnBattery_Enter
  104. *
  105. * Description:
  106. * Performs the actions necessary when transitioning into the ON_BATTERY state.
  107. *
  108. * Parameters:
  109. * anEvent The event that caused the transition into this state.
  110. *
  111. * Returns:
  112. * None
  113. */
  114. void OnBattery_Enter(DWORD anEvent)
  115. {
  116. BOOL send_power_failed_message = TRUE;
  117. DWORD on_battery_message_delay = DEFAULT_ON_BATTERY_MESSAGE_DELAY_C;
  118. DWORD notification_interval = DEFAULT_NOTIFICATION_INTERVAL_C;
  119. LONG reg_err;
  120. //
  121. // update the registry with the power failed status
  122. //
  123. InitUPSStatusBlock();
  124. SetUPSStatusUtilityStatus(UPS_UTILITYPOWER_OFF);
  125. SaveUPSStatusBlock(FALSE);
  126. //Log the power failed event
  127. LogEvent(NELOG_UPS_PowerOut, NULL, ERROR_SUCCESS);
  128. // Determine if a power failed notification should take place
  129. InitUPSConfigBlock();
  130. reg_err = GetUPSConfigNotifyEnable(&send_power_failed_message);
  131. if (reg_err != ERROR_SUCCESS){
  132. send_power_failed_message = TRUE;
  133. }
  134. if (send_power_failed_message){
  135. // Send the power failed notification after notification delay has expired
  136. reg_err = GetUPSConfigFirstMessageDelay(&on_battery_message_delay);
  137. if (reg_err != ERROR_SUCCESS){
  138. on_battery_message_delay = DEFAULT_ON_BATTERY_MESSAGE_DELAY_C;
  139. }
  140. reg_err = GetUPSConfigMessageInterval(&notification_interval);
  141. if (reg_err != ERROR_SUCCESS) {
  142. notification_interval = DEFAULT_NOTIFICATION_INTERVAL_C;
  143. }
  144. // Send the power failed message
  145. SendNotification(APE2_UPS_POWER_OUT, notification_interval, on_battery_message_delay);
  146. }
  147. }
  148. /**
  149. * OnBattery_DoWork
  150. *
  151. * Description:
  152. * Log on battery event and either wait for a low battery condition or until
  153. * the on battery timer expires. A transition to power restored will also cause
  154. * an exit of this state.
  155. *
  156. * Parameters:
  157. * None
  158. *
  159. * Returns:
  160. * The event that caused the transition from the ON_BATTERY state.
  161. */
  162. DWORD OnBattery_DoWork(){
  163. DWORD wait_before_shutdown = WAIT_FOREVER_C;
  164. DWORD battery_timer_enabled = FALSE;
  165. LONG reg_err;
  166. DWORD transition_event;
  167. DWORD time_to_wait_while_on_battery;
  168. // If the on battery timer is enabled, get the on battery delay. This is the amount
  169. // time to remain on battery before tranisitioning to the shutdown state.
  170. InitUPSConfigBlock();
  171. reg_err = GetUPSConfigShutdownOnBatteryEnable(&battery_timer_enabled);
  172. if (reg_err == ERROR_SUCCESS && battery_timer_enabled == TRUE){
  173. reg_err = GetUPSConfigShutdownOnBatteryWait(&time_to_wait_while_on_battery);
  174. if (reg_err == ERROR_SUCCESS){
  175. wait_before_shutdown = time_to_wait_while_on_battery * MINUTES_TO_MILLISECONDS_CONVERSION_C;
  176. }
  177. }
  178. // Wait until the UPS changes state from ON_BATTERY or the
  179. // ON_BATTERY timer expires
  180. if(get_new_state() == ON_BATTERY && IsStateMachineActive() == TRUE){
  181. UPSWaitForStateChange(UPS_ONBATTERY, wait_before_shutdown );
  182. if (get_new_state() == ON_BATTERY){
  183. // Set the event that caused the state change.
  184. transition_event = ON_BATTERY_TIMER_EXPIRED;
  185. }
  186. else{
  187. // Set the event that caused the state change.
  188. transition_event = get_transition_event();
  189. }
  190. }
  191. else{
  192. // Set the event that caused the state change.
  193. transition_event = get_transition_event();
  194. }
  195. return transition_event;
  196. }
  197. /**
  198. * OnBattery_Exit
  199. *
  200. * Description:
  201. * Performs the actions necessary when transitioning from the ON_BATTERY state.
  202. *
  203. * Parameters:
  204. * anEvent The event that caused the transition from the ON_BATTERY state.
  205. *
  206. * Returns:
  207. * None
  208. */
  209. void OnBattery_Exit(DWORD anEvent){
  210. // Stop sending power failure notifications
  211. CancelNotification();
  212. }
  213. /**
  214. * NoComm_Enter
  215. *
  216. * Description:
  217. * Performs the actions necessary when transitioning into the NO_COMM state.
  218. *
  219. * Parameters:
  220. * anEvent The event that caused the transition into this state.
  221. *
  222. * Returns:
  223. * None
  224. */
  225. void NoComm_Enter(DWORD anEvent){
  226. InitUPSStatusBlock();
  227. SetUPSStatusCommStatus(UPS_COMMSTATUS_LOST);
  228. SaveUPSStatusBlock(FALSE);
  229. }
  230. /**
  231. * NoComm_DoWork
  232. *
  233. * Description:
  234. * Wait until the UPS changes state or the state machine exits.
  235. *
  236. * Parameters:
  237. * None
  238. *
  239. * Returns:
  240. * The event that caused the transition from the NO_COMM state.
  241. */
  242. DWORD NoComm_DoWork(){
  243. // Wait until the UPS state changes, then exit the NO COMM state
  244. while (get_new_state() == NO_COMM && IsStateMachineActive() == TRUE){
  245. UPSWaitForStateChange(UPS_NOCOMM, WAIT_FOREVER_C);
  246. }
  247. return get_transition_event();
  248. }
  249. /**
  250. * NoComm_Exit
  251. *
  252. * Description:
  253. * Performs the actions necessary when transitioning from the NO_COMM state.
  254. *
  255. * Parameters:
  256. * anEvent The event that caused the transition from the NO_COMM state.
  257. *
  258. * Returns:
  259. * None
  260. */
  261. void NoComm_Exit(DWORD anEvent){
  262. // If we leave this state, then some signal has been received from the UPS.
  263. // Set the com status to good
  264. InitUPSStatusBlock();
  265. SetUPSStatusCommStatus(UPS_COMMSTATUS_OK);
  266. SaveUPSStatusBlock(FALSE);
  267. }
  268. /**
  269. * get_new_state
  270. *
  271. * Description:
  272. * Retrieves the UPS status and converts the it into a state.
  273. *
  274. * Parameters:
  275. * None
  276. *
  277. * Returns:
  278. * The new run state.
  279. */
  280. DWORD get_new_state(){
  281. DWORD ups_state;
  282. ups_state = UPSGetState();
  283. return convert_ups_state_to_run_state(ups_state);
  284. }
  285. /**
  286. * convert_ups_state_to_run_state
  287. *
  288. * Description:
  289. * Converts a UPS state into a run state.
  290. *
  291. * Parameters:
  292. * aUPSstate The condition of the UPS.
  293. *
  294. * Returns:
  295. * The new run state.
  296. */
  297. DWORD convert_ups_state_to_run_state(DWORD aUPSstate){
  298. DWORD new_event;
  299. switch (aUPSstate){
  300. case UPS_ONLINE:
  301. new_event = ON_LINE;
  302. break;
  303. case UPS_ONBATTERY:
  304. new_event = ON_BATTERY;
  305. break;
  306. case UPS_LOWBATTERY:
  307. new_event = LOW_BATTERY;
  308. break;
  309. case UPS_NOCOMM:
  310. new_event = NO_COMM;
  311. break;
  312. default:
  313. new_event = EXIT_NOW; //error
  314. }
  315. return new_event;
  316. }
  317. /**
  318. * get_transition_event
  319. *
  320. * Description:
  321. * Returns the event that caused a state transition.
  322. *
  323. * Parameters:
  324. * None
  325. *
  326. * Returns:
  327. * The event that caused a state transition.
  328. */
  329. DWORD get_transition_event(){
  330. DWORD ups_state;
  331. DWORD new_event;
  332. ups_state = UPSGetState();
  333. switch (ups_state){
  334. case UPS_ONLINE:
  335. new_event = POWER_RESTORED;
  336. break;
  337. case UPS_ONBATTERY:
  338. new_event = POWER_FAILED;
  339. break;
  340. case UPS_LOWBATTERY:
  341. new_event = LOW_BATTERY;
  342. break;
  343. case UPS_NOCOMM:
  344. new_event = LOST_COMM;
  345. break;
  346. default:
  347. new_event = NO_EVENT;
  348. }
  349. return new_event;
  350. }