static void rtc_update_timer(void *opaque) { RTCState *s = opaque; int32_t irqs = REG_C_UF; int32_t new_irqs; assert((s->cmos_data[RTC_REG_A] & 0x60) != 0x60); /* UIP might have been latched, update time and clear it. */ rtc_update_time(s); s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; if (qemu_clock_get_ns(rtc_clock) >= s->next_alarm_time) { irqs |= REG_C_AF; if (s->cmos_data[RTC_REG_B] & REG_B_AIE) { qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC); } } new_irqs = irqs & ~s->cmos_data[RTC_REG_C]; s->cmos_data[RTC_REG_C] |= irqs; if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) { s->cmos_data[RTC_REG_C] |= REG_C_IRQF; qemu_irq_raise(s->irq); } check_update_timer(s); }
static void rtc_get_date(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { RTCState *s = MC146818_RTC(obj); struct tm current_tm; rtc_update_time(s); rtc_get_time(s, ¤t_tm); visit_start_struct(v, NULL, "struct tm", name, 0, errp); visit_type_int32(v, ¤t_tm.tm_year, "tm_year", errp); visit_type_int32(v, ¤t_tm.tm_mon, "tm_mon", errp); visit_type_int32(v, ¤t_tm.tm_mday, "tm_mday", errp); visit_type_int32(v, ¤t_tm.tm_hour, "tm_hour", errp); visit_type_int32(v, ¤t_tm.tm_min, "tm_min", errp); visit_type_int32(v, ¤t_tm.tm_sec, "tm_sec", errp); visit_end_struct(v, errp); }
static void rtc_get_date(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { ISADevice *isa = ISA_DEVICE(obj); RTCState *s = DO_UPCAST(RTCState, dev, isa); struct tm current_tm; rtc_update_time(s); rtc_get_time(s, ¤t_tm); visit_start_struct(v, NULL, "struct tm", name, 0, errp); visit_type_int32(v, ¤t_tm.tm_year, "tm_year", errp); visit_type_int32(v, ¤t_tm.tm_mon, "tm_mon", errp); visit_type_int32(v, ¤t_tm.tm_mday, "tm_mday", errp); visit_type_int32(v, ¤t_tm.tm_hour, "tm_hour", errp); visit_type_int32(v, ¤t_tm.tm_min, "tm_min", errp); visit_type_int32(v, ¤t_tm.tm_sec, "tm_sec", errp); visit_end_struct(v, errp); }
static void rtc_get_date(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { Error *err = NULL; RTCState *s = MC146818_RTC(obj); struct tm current_tm; rtc_update_time(s); rtc_get_time(s, ¤t_tm); visit_start_struct(v, NULL, "struct tm", name, 0, &err); if (err) { goto out; } visit_type_int32(v, ¤t_tm.tm_year, "tm_year", &err); if (err) { goto out_end; } visit_type_int32(v, ¤t_tm.tm_mon, "tm_mon", &err); if (err) { goto out_end; } visit_type_int32(v, ¤t_tm.tm_mday, "tm_mday", &err); if (err) { goto out_end; } visit_type_int32(v, ¤t_tm.tm_hour, "tm_hour", &err); if (err) { goto out_end; } visit_type_int32(v, ¤t_tm.tm_min, "tm_min", &err); if (err) { goto out_end; } visit_type_int32(v, ¤t_tm.tm_sec, "tm_sec", &err); if (err) { goto out_end; } out_end: error_propagate(errp, err); err = NULL; visit_end_struct(v, errp); out: error_propagate(errp, err); }
// Send back data after an SMS request void sms_send_data_request(char *number) { uint32_t iOffset; char *data = getSMSBufferHelper(); if (number == NULL || strlen(number) == 0) return; //get temperature values rtc_update_time(); strcat(data, get_simplified_date_string(&g_tmCurrTime)); strcat(data, " "); for (iOffset = 0; iOffset < SYSTEM_NUM_SENSORS; iOffset++) { strcat(data, SensorName[iOffset]); strcat(data, ":"); strcat(data, temperature_getString(iOffset)); strcat(data, "C, "); } // added for show msg// strcat(data, "BATTERY:"); strcat(data, itoa_nopadding(batt_getlevel())); strcat(data, "%, "); if (P4IN & BIT4) //power not plugged { strcat(data, "POWER OUT"); } else if (((P4IN & BIT6)) && (batt_getlevel() == 100)) { strcat(data, "FULL CHARGE"); } else { strcat(data, "CHARGING"); } #ifdef _DEBUG strcat(data, ",UPTIME:"); strcat(data, itoa_nopadding(iMinuteTick)); strcat(data, ",STACK:"); strcat(data, itoa_nopadding(g_pSysCfg->stackLeft)); #endif iOffset = strlen(data); sms_send_message_number(number, data); }
static uint64_t cmos_ioport_read(void *opaque, hwaddr addr, unsigned size) { RTCState *s = opaque; int ret; if ((addr & 1) == 0) { return 0xff; } else { switch(s->cmos_index) { case RTC_IBM_PS2_CENTURY_BYTE: s->cmos_index = RTC_CENTURY; /* fall through */ case RTC_CENTURY: case RTC_SECONDS: case RTC_MINUTES: case RTC_HOURS: case RTC_DAY_OF_WEEK: case RTC_DAY_OF_MONTH: case RTC_MONTH: case RTC_YEAR: /* if not in set mode, calibrate cmos before * reading*/ if (rtc_running(s)) { rtc_update_time(s); } ret = s->cmos_data[s->cmos_index]; break; case RTC_REG_A: if (update_in_progress(s)) { s->cmos_data[s->cmos_index] |= REG_A_UIP; } else { s->cmos_data[s->cmos_index] &= ~REG_A_UIP; } ret = s->cmos_data[s->cmos_index]; break; case RTC_REG_C: ret = s->cmos_data[s->cmos_index]; qemu_irq_lower(s->irq); s->cmos_data[RTC_REG_C] = 0x00; if (ret & (REG_C_UF | REG_C_AF)) { check_update_timer(s); } #ifdef TARGET_I386 if(s->irq_coalesced && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) { s->irq_reinject_on_ack_count++; s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF; apic_reset_irq_delivered(); DPRINTF_C("cmos: injecting on ack\n"); qemu_irq_raise(s->irq); if (apic_get_irq_delivered()) { s->irq_coalesced--; DPRINTF_C("cmos: coalesced irqs decreased to %d\n", s->irq_coalesced); } } #endif break; default: ret = s->cmos_data[s->cmos_index]; break; } CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n", s->cmos_index, ret); return ret; } }
static void cmos_ioport_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { RTCState *s = opaque; if ((addr & 1) == 0) { s->cmos_index = data & 0x7f; } else { CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02x\n", s->cmos_index, data); switch(s->cmos_index) { case RTC_SECONDS_ALARM: case RTC_MINUTES_ALARM: case RTC_HOURS_ALARM: s->cmos_data[s->cmos_index] = data; check_update_timer(s); break; case RTC_IBM_PS2_CENTURY_BYTE: s->cmos_index = RTC_CENTURY; /* fall through */ case RTC_CENTURY: case RTC_SECONDS: case RTC_MINUTES: case RTC_HOURS: case RTC_DAY_OF_WEEK: case RTC_DAY_OF_MONTH: case RTC_MONTH: case RTC_YEAR: s->cmos_data[s->cmos_index] = data; /* if in set mode, do not update the time */ if (rtc_running(s)) { rtc_set_time(s); check_update_timer(s); } break; case RTC_REG_A: if ((data & 0x60) == 0x60) { if (rtc_running(s)) { rtc_update_time(s); } /* What happens to UIP when divider reset is enabled is * unclear from the datasheet. Shouldn't matter much * though. */ s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; } else if (((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) && (data & 0x70) <= 0x20) { /* when the divider reset is removed, the first update cycle * begins one-half second later*/ if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { s->offset = 500000000; rtc_set_time(s); } s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; } /* UIP bit is read only */ s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) | (s->cmos_data[RTC_REG_A] & REG_A_UIP); periodic_timer_update(s, qemu_get_clock_ns(rtc_clock)); check_update_timer(s); break; case RTC_REG_B: if (data & REG_B_SET) { /* update cmos to when the rtc was stopping */ if (rtc_running(s)) { rtc_update_time(s); } /* set mode: reset UIP mode */ s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; data &= ~REG_B_UIE; } else { /* if disabling set mode, update the time */ if ((s->cmos_data[RTC_REG_B] & REG_B_SET) && (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20) { s->offset = get_guest_rtc_ns(s) % NSEC_PER_SEC; rtc_set_time(s); } } /* if an interrupt flag is already set when the interrupt * becomes enabled, raise an interrupt immediately. */ if (data & s->cmos_data[RTC_REG_C] & REG_C_MASK) { s->cmos_data[RTC_REG_C] |= REG_C_IRQF; qemu_irq_raise(s->irq); } else { s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF; qemu_irq_lower(s->irq); } s->cmos_data[RTC_REG_B] = data; periodic_timer_update(s, qemu_get_clock_ns(rtc_clock)); check_update_timer(s); break; case RTC_REG_C: case RTC_REG_D: /* cannot write to them */ break; default: s->cmos_data[s->cmos_index] = data; break; } } }
static uint64_t get_next_alarm(RTCState *s) { int32_t alarm_sec, alarm_min, alarm_hour, cur_hour, cur_min, cur_sec; int32_t hour, min, sec; rtc_update_time(s); alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]); alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]); alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]); alarm_hour = alarm_hour == -1 ? -1 : convert_hour(s, alarm_hour); cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]); cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]); cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]); cur_hour = convert_hour(s, cur_hour); if (alarm_hour == -1) { alarm_hour = cur_hour; if (alarm_min == -1) { alarm_min = cur_min; if (alarm_sec == -1) { alarm_sec = cur_sec + 1; } else if (cur_sec > alarm_sec) { alarm_min++; } } else if (cur_min == alarm_min) { if (alarm_sec == -1) { alarm_sec = cur_sec + 1; } else { if (cur_sec > alarm_sec) { alarm_hour++; } } if (alarm_sec == SEC_PER_MIN) { /* wrap to next hour, minutes is not in don't care mode */ alarm_sec = 0; alarm_hour++; } } else if (cur_min > alarm_min) { alarm_hour++; } } else if (cur_hour == alarm_hour) { if (alarm_min == -1) { alarm_min = cur_min; if (alarm_sec == -1) { alarm_sec = cur_sec + 1; } else if (cur_sec > alarm_sec) { alarm_min++; } if (alarm_sec == SEC_PER_MIN) { alarm_sec = 0; alarm_min++; } /* wrap to next day, hour is not in don't care mode */ alarm_min %= MIN_PER_HOUR; } else if (cur_min == alarm_min) { if (alarm_sec == -1) { alarm_sec = cur_sec + 1; } /* wrap to next day, hours+minutes not in don't care mode */ alarm_sec %= SEC_PER_MIN; } } /* values that are still don't care fire at the next min/sec */ if (alarm_min == -1) { alarm_min = 0; } if (alarm_sec == -1) { alarm_sec = 0; } /* keep values in range */ if (alarm_sec == SEC_PER_MIN) { alarm_sec = 0; alarm_min++; } if (alarm_min == MIN_PER_HOUR) { alarm_min = 0; alarm_hour++; } alarm_hour %= HOUR_PER_DAY; hour = alarm_hour - cur_hour; min = hour * MIN_PER_HOUR + alarm_min - cur_min; sec = min * SEC_PER_MIN + alarm_sec - cur_sec; return sec <= 0 ? sec + SEC_PER_DAY : sec; }