+ if (!acAdaptorConnected) {
+ DLOG("full wake check: no AC\n");
+ return false;
+ }
+ }
+#endif
+ return true;
+}
+
+//******************************************************************************
+// mustHibernate
+//******************************************************************************
+
+#if HIBERNATION
+
+bool
+IOPMrootDomain::mustHibernate( void )
+{
+ return lowBatteryCondition || thermalWarningState;
+}
+
+#endif /* HIBERNATION */
+
+//******************************************************************************
+// AOT
+//******************************************************************************
+
+// Tables for accumulated days in year by month, latter used for leap years
+
+static const int daysbymonth[] =
+{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+
+static const int lydaysbymonth[] =
+{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
+
+static int __unused
+IOPMConvertSecondsToCalendar(long secs, IOPMCalendarStruct * dt)
+{
+ const int * dbm = daysbymonth;
+ long n, x, y, z;
+
+ if (secs < 0) {
+ return 0;
+ }
+
+ // Calculate seconds, minutes and hours
+
+ n = secs % (24 * 3600);
+ dt->second = n % 60;
+ n /= 60;
+ dt->minute = n % 60;
+ dt->hour = n / 60;
+
+ // Calculate day of week
+
+ n = secs / (24 * 3600);
+// dt->dayWeek = (n + 4) % 7;
+
+ // Calculate year
+ // Rebase from days since Unix epoch (1/1/1970) store in 'n',
+ // to days since 1/1/1968 to start on 4 year cycle, beginning
+ // on a leap year.
+
+ n += (366 + 365);
+
+ // Every 4 year cycle will be exactly (366 + 365 * 3) = 1461 days.
+ // Valid before 2100, since 2100 is not a leap year.
+
+ x = n / 1461; // number of 4 year cycles
+ y = n % 1461; // days into current 4 year cycle
+ z = 1968 + (4 * x);
+
+ // Add in years in the current 4 year cycle
+
+ if (y >= 366) {
+ y -= 366; // days after the leap year
+ n = y % 365; // days into the current year
+ z += (1 + y / 365); // years after the past 4-yr cycle
+ } else {
+ n = y;
+ dbm = lydaysbymonth;
+ }
+ if (z > 2099) {
+ return 0;
+ }
+
+ dt->year = z;
+
+ // Adjust remaining days value to start at 1
+
+ n += 1;
+
+ // Calculate month
+
+ for (x = 1; n > dbm[x]; x++) {
+ continue;
+ }
+ dt->month = x;
+
+ // Calculate day of month
+
+ dt->day = n - dbm[x - 1];
+
+ return 1;
+}
+
+static long
+IOPMConvertCalendarToSeconds(const IOPMCalendarStruct * dt)
+{
+ const int * dbm = daysbymonth;
+ long y, secs, days;
+
+ if (dt->year < 1970) {
+ return 0;
+ }
+
+ // Seconds elapsed in the current day
+
+ secs = dt->second + 60 * dt->minute + 3600 * dt->hour;
+
+ // Number of days from 1/1/70 to beginning of current year
+ // Account for extra day every 4 years starting at 1973
+
+ y = dt->year - 1970;
+ days = (y * 365) + ((y + 1) / 4);
+
+ // Change table if current year is a leap year
+
+ if ((dt->year % 4) == 0) {
+ dbm = lydaysbymonth;
+ }
+
+ // Add in days elapsed in the current year
+
+ days += (dt->day - 1) + dbm[dt->month - 1];
+
+ // Add accumulated days to accumulated seconds
+
+ secs += 24 * 3600 * days;
+
+ return secs;
+}
+
+#if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
+
+unsigned long
+IOPMrootDomain::getRUN_STATE(void)
+{
+ return _aotNow ? AOT_STATE : ON_STATE;
+}
+
+bool
+IOPMrootDomain::isAOTMode()
+{
+ return _aotNow;
+}
+
+IOReturn
+IOPMrootDomain::setWakeTime(uint64_t wakeContinuousTime)
+{
+ clock_sec_t nowsecs, wakesecs;
+ clock_usec_t nowmicrosecs, wakemicrosecs;
+ uint64_t nowAbs, wakeAbs;
+
+ clock_gettimeofday_and_absolute_time(&nowsecs, &nowmicrosecs, &nowAbs);
+ wakeAbs = continuoustime_to_absolutetime(wakeContinuousTime);
+ if (wakeAbs < nowAbs) {
+ printf(LOG_PREFIX "wakeAbs %qd < nowAbs %qd\n", wakeAbs, nowAbs);
+ wakeAbs = nowAbs;
+ }
+ wakeAbs -= nowAbs;
+ absolutetime_to_microtime(wakeAbs, &wakesecs, &wakemicrosecs);
+
+ wakesecs += nowsecs;
+ wakemicrosecs += nowmicrosecs;
+ if (wakemicrosecs >= USEC_PER_SEC) {
+ wakesecs++;
+ wakemicrosecs -= USEC_PER_SEC;
+ }
+ if (wakemicrosecs >= (USEC_PER_SEC / 10)) {
+ wakesecs++;
+ }
+
+ IOPMConvertSecondsToCalendar(wakesecs, &_aotWakeTimeCalendar);
+
+ if (_aotWakeTimeContinuous != wakeContinuousTime) {
+ _aotWakeTimeContinuous = wakeContinuousTime;
+ IOLog(LOG_PREFIX "setWakeTime: " YMDTF "\n", YMDT(&_aotWakeTimeCalendar));
+ }
+ _aotWakeTimeCalendar.selector = kPMCalendarTypeMaintenance;
+ _aotWakeTimeUTC = wakesecs;
+
+ return kIOReturnSuccess;
+}
+
+// assumes WAKEEVENT_LOCK
+bool
+IOPMrootDomain::aotShouldExit(bool checkTimeSet, bool software)
+{
+ bool exitNow;
+ const char * reason = "";
+
+ if (software) {
+ _aotExit = true;
+ _aotMetrics->softwareRequestCount++;
+ reason = "software request";
+ } else if (kIOPMWakeEventAOTExitFlags & _aotPendingFlags) {
+ _aotExit = true;
+ reason = gWakeReasonString;
+ } else if (checkTimeSet && (kPMCalendarTypeInvalid == _aotWakeTimeCalendar.selector)) {
+ _aotExit = true;
+ _aotMetrics->noTimeSetCount++;
+ reason = "flipbook expired";
+ } else if ((kIOPMAOTModeRespectTimers & _aotMode) && _scheduledAlarmUTC) {
+ clock_sec_t sec;
+ clock_usec_t usec;
+ clock_get_calendar_microtime(&sec, &usec);
+ if (_scheduledAlarmUTC <= sec) {
+ _aotExit = true;
+ _aotMetrics->rtcAlarmsCount++;
+ reason = "user alarm";
+ }
+ }
+ exitNow = (_aotNow && _aotExit);
+ if (exitNow) {
+ _aotNow = false;
+ IOLog(LOG_PREFIX "AOT exit for %s, sc %d po %d, cp %d, rj %d, ex %d, nt %d, rt %d\n",
+ reason,
+ _aotMetrics->sleepCount,
+ _aotMetrics->possibleCount,
+ _aotMetrics->confirmedPossibleCount,
+ _aotMetrics->rejectedPossibleCount,
+ _aotMetrics->expiredPossibleCount,
+ _aotMetrics->noTimeSetCount,
+ _aotMetrics->rtcAlarmsCount);
+ }
+ return exitNow;
+}
+
+void
+IOPMrootDomain::aotExit(bool cps)
+{
+ _aotTasksSuspended = false;
+ _aotReadyToFullWake = false;
+ if (_aotTimerScheduled) {
+ _aotTimerES->cancelTimeout();
+ _aotTimerScheduled = false;
+ }
+ updateTasksSuspend();
+
+ _aotMetrics->totalTime += mach_absolute_time() - _aotLastWakeTime;
+ _aotLastWakeTime = 0;
+ if (_aotMetrics->sleepCount && (_aotMetrics->sleepCount <= kIOPMAOTMetricsKernelWakeCountMax)) {
+ strlcpy(&_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount - 1][0],
+ gWakeReasonString,
+ sizeof(_aotMetrics->kernelWakeReason[_aotMetrics->sleepCount]));
+ }
+
+ _aotWakeTimeCalendar.selector = kPMCalendarTypeInvalid;
+
+ _systemMessageClientMask = kSystemMessageClientLegacyApp;
+ tellClients(kIOMessageSystemWillPowerOn);
+
+ if (cps) {
+ changePowerStateToPriv(getRUN_STATE());
+ }
+}
+
+void
+IOPMrootDomain::aotEvaluate(IOTimerEventSource * timer)
+{
+ bool exitNow;
+
+ IOLog("aotEvaluate(%d) 0x%x\n", (timer != NULL), _aotPendingFlags);
+
+ WAKEEVENT_LOCK();
+ exitNow = aotShouldExit(false, false);
+ if (timer != NULL) {
+ _aotTimerScheduled = false;