Beispiel #1
0
bool x86_rtc_set_update(uint32_t msg_content, kernel_pid_t target_pid, bool allow_replace)
{
    if (!valid) {
        return false;
    }

    unsigned old_status = disableIRQ();
    bool result;
    if (target_pid == KERNEL_PID_UNDEF) {
        result = true;
        update_pid = KERNEL_PID_UNDEF;

        x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) & ~RTC_REG_B_INT_UPDATE);
    }
    else {
        result = allow_replace || update_pid == KERNEL_PID_UNDEF;
        if (result) {
            update_msg_content = msg_content;
            update_pid = target_pid;

            x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) | RTC_REG_B_INT_UPDATE);
        }
    }
    rtc_irq_handler(0);
    restoreIRQ(old_status);
    return result;
}
Beispiel #2
0
bool x86_rtc_set_periodic(uint8_t hz, uint32_t msg_content, kernel_pid_t target_pid, bool allow_replace)
{
    if (!valid) {
        return false;
    }

    unsigned old_status = disableIRQ();
    bool result;
    if (target_pid == KERNEL_PID_UNDEF || hz == RTC_REG_A_HZ_OFF) {
        result = true;
        periodic_pid = KERNEL_PID_UNDEF;

        uint8_t old_divider = x86_cmos_read(RTC_REG_A) & ~RTC_REG_A_HZ_MASK;
        x86_cmos_write(RTC_REG_A, old_divider | RTC_REG_A_HZ_OFF);
        x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) & ~RTC_REG_B_INT_PERIODIC);
    }
    else {
        result = allow_replace || periodic_pid == KERNEL_PID_UNDEF;
        if (result) {
            periodic_msg_content = msg_content;
            periodic_pid = target_pid;

            uint8_t old_divider = x86_cmos_read(RTC_REG_A) & ~RTC_REG_A_HZ_MASK;
            x86_cmos_write(RTC_REG_A, old_divider | hz);
            x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) | RTC_REG_B_INT_PERIODIC);
        }
    }
    rtc_irq_handler(0);
    restoreIRQ(old_status);
    return result;
}
Beispiel #3
0
bool x86_rtc_set_alarm(const x86_rtc_data_t *when, uint32_t msg_content, kernel_pid_t target_pid, bool allow_replace)
{
    if (!valid) {
        return false;
    }

    unsigned old_status = irq_disable();
    bool result;
    if (target_pid == KERNEL_PID_UNDEF) {
        result = true;
        alarm_pid = KERNEL_PID_UNDEF;

        uint8_t b = x86_cmos_read(RTC_REG_B);
        x86_cmos_write(RTC_REG_B, b & ~RTC_REG_B_INT_ALARM);
    }
    else {
        result = allow_replace || alarm_pid == KERNEL_PID_UNDEF;
        if (result) {
            alarm_msg_content = msg_content;
            alarm_pid = target_pid;

            uint8_t b = x86_cmos_read(RTC_REG_B);
            if (b & RTC_REG_B_BIN) {
                x86_cmos_write(RTC_REG_ALARM_SECOND, when->second);
                x86_cmos_write(RTC_REG_ALARM_MINUTE, when->minute);
                x86_cmos_write(RTC_REG_ALARM_HOUR, when->hour);
            }
            else {
                x86_cmos_write(RTC_REG_ALARM_SECOND, binary2bcd(when->second));
                x86_cmos_write(RTC_REG_ALARM_MINUTE, binary2bcd(when->minute));
                x86_cmos_write(RTC_REG_ALARM_HOUR, binary2bcd(when->hour));
            }
            x86_cmos_write(RTC_REG_B, b | RTC_REG_B_INT_ALARM);
        }
    }
    rtc_irq_handler(0);
    irq_restore(old_status);
    return result;
}
Beispiel #4
0
void x86_init_rtc(void)
{
    uint8_t d = x86_cmos_read(RTC_REG_D);
    valid = (d & RTC_REG_D_VALID) != 0;
    if (!valid) {
        puts("Warning: RTC does not work.");
        return;
    }

    x86_cmos_write(RTC_REG_B, x86_cmos_read(RTC_REG_B) & ~RTC_REG_B_INT_MASK);
    rtc_irq_handler(0);
    x86_pic_set_handler(PIC_NUM_RTC, &rtc_irq_handler);
    x86_pic_enable_irq(PIC_NUM_RTC);

    x86_rtc_data_t now;
    x86_rtc_read(&now);
    printf("RTC initialized [%02hhu:%02hhu:%02hhu, %04u-%02hhu-%02hhu]\n",
           now.hour, now.minute, now.second,
           now.century * 100 + now.year, now.month, now.day);

    if (x86_cmos_read(RTC_REG_POST) & (RTC_REG_POST_POWER_LOSS | RTC_REG_POST_TIME_INVALID)) {
        puts("Warning: RTC time is invalid (power loss?)");
    }
}