📄 time.c
字号:
static unsigned long __initrpcc_after_update_in_progress(void){ do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); return rpcc();}void __inittime_init(void){ unsigned int year, mon, day, hour, min, sec, cc1, cc2, epoch; unsigned long cycle_freq, one_percent; long diff; /* Calibrate CPU clock -- attempt #1. */ if (!est_cycle_freq) est_cycle_freq = validate_cc_value(calibrate_cc_with_pic()); cc1 = rpcc_after_update_in_progress(); /* Calibrate CPU clock -- attempt #2. */ if (!est_cycle_freq) { cc2 = rpcc_after_update_in_progress(); est_cycle_freq = validate_cc_value(cc2 - cc1); cc1 = cc2; } cycle_freq = hwrpb->cycle_freq; if (est_cycle_freq) { /* If the given value is within 1% of what we calculated, accept it. Otherwise, use what we found. */ one_percent = cycle_freq / 100; diff = cycle_freq - est_cycle_freq; if (diff < 0) diff = -diff; if (diff > one_percent) { cycle_freq = est_cycle_freq; printk("HWRPB cycle frequency bogus. " "Estimated %lu Hz\n", cycle_freq); } else { est_cycle_freq = 0; } } else if (! validate_cc_value (cycle_freq)) { printk("HWRPB cycle frequency bogus, " "and unable to estimate a proper value!\n"); } /* From John Bowman <bowman@math.ualberta.ca>: allow the values to settle, as the Update-In-Progress bit going low isn't good enough on some hardware. 2ms is our guess; we havn't found bogomips yet, but this is close on a 500Mhz box. */ __delay(1000000); sec = CMOS_READ(RTC_SECONDS); min = CMOS_READ(RTC_MINUTES); hour = CMOS_READ(RTC_HOURS); day = CMOS_READ(RTC_DAY_OF_MONTH); mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(sec); BCD_TO_BIN(min); BCD_TO_BIN(hour); BCD_TO_BIN(day); BCD_TO_BIN(mon); BCD_TO_BIN(year); } /* PC-like is standard; used for year < 20 || year >= 70 */ epoch = 1900; if (year < 20) epoch = 2000; else if (year >= 20 && year < 48) /* NT epoch */ epoch = 1980; else if (year >= 48 && year < 70) /* Digital UNIX epoch */ epoch = 1952; printk(KERN_INFO "Using epoch = %d\n", epoch); if ((year += epoch) < 1970) year += 100; xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_usec = 0; if (HZ > (1<<16)) { extern void __you_loose (void); __you_loose(); } state.last_time = cc1; state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / cycle_freq; state.last_rtc_update = 0; state.partial_tick = 0L; /* Startup the timer source. */ alpha_mv.init_rtc();}/* * Use the cycle counter to estimate an displacement from the last time * tick. Unfortunately the Alpha designers made only the low 32-bits of * the cycle counter active, so we overflow on 8.2 seconds on a 500MHz * part. So we can't do the "find absolute time in terms of cycles" thing * that the other ports do. */voiddo_gettimeofday(struct timeval *tv){ unsigned long sec, usec, lost, flags; unsigned long delta_cycles, delta_usec, partial_tick; read_lock_irqsave(&xtime_lock, flags); delta_cycles = rpcc() - state.last_time; sec = xtime.tv_sec; usec = xtime.tv_usec; partial_tick = state.partial_tick; lost = jiffies - wall_jiffies; read_unlock_irqrestore(&xtime_lock, flags);#ifdef CONFIG_SMP /* Until and unless we figure out how to get cpu cycle counters in sync and keep them there, we can't use the rpcc tricks. */ delta_usec = lost * (1000000 / HZ);#else /* * usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks) * = cycles * (s_t_p_c) * 1e6 / (2**48 * ticks) * = cycles * (s_t_p_c) * 15625 / (2**42 * ticks) * * which, given a 600MHz cycle and a 1024Hz tick, has a * dynamic range of about 1.7e17, which is less than the * 1.8e19 in an unsigned long, so we are safe from overflow. * * Round, but with .5 up always, since .5 to even is harder * with no clear gain. */ delta_usec = (delta_cycles * state.scaled_ticks_per_cycle + partial_tick + (lost << FIX_SHIFT)) * 15625; delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;#endif usec += delta_usec; if (usec >= 1000000) { sec += 1; usec -= 1000000; } tv->tv_sec = sec; tv->tv_usec = usec;}voiddo_settimeofday(struct timeval *tv){ unsigned long delta_usec; long sec, usec; write_lock_irq(&xtime_lock); /* The offset that is added into time in do_gettimeofday above must be subtracted out here to keep a coherent view of the time. Without this, a full-tick error is possible. */#ifdef CONFIG_SMP delta_usec = (jiffies - wall_jiffies) * (1000000 / HZ);#else delta_usec = rpcc() - state.last_time; delta_usec = (delta_usec * state.scaled_ticks_per_cycle + state.partial_tick + ((jiffies - wall_jiffies) << FIX_SHIFT)) * 15625; delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;#endif sec = tv->tv_sec; usec = tv->tv_usec; usec -= delta_usec; if (usec < 0) { usec += 1000000; sec -= 1; } xtime.tv_sec = sec; xtime.tv_usec = usec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_unlock_irq(&xtime_lock);}/* * In order to set the CMOS clock precisely, set_rtc_mmss has to be * called 500 ms after the second nowtime has started, because when * nowtime is written into the registers of the CMOS clock, it will * jump to the next second precisely 500 ms later. Check the Motorola * MC146818A or Dallas DS12887 data sheet for details. * * BUG: This routine does not handle hour overflow properly; it just * sets the minutes. Usually you won't notice until after reboot! */extern int abs(int);static intset_rtc_mmss(unsigned long nowtime){ int retval = 0; int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; /* irq are locally disabled here */ spin_lock(&rtc_lock); /* Tell the clock it's being set */ save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); /* Stop and reset prescaler */ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); cmos_minutes = CMOS_READ(RTC_MINUTES); if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) BCD_TO_BIN(cmos_minutes); /* * since we're only adjusting minutes and seconds, * don't interfere with hour overflow. This avoids * messing with unknown time zones but requires your * RTC not to be off by more than 15 minutes */ real_seconds = nowtime % 60; real_minutes = nowtime / 60; if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) { /* correct for half hour time zone */ real_minutes += 30; } real_minutes %= 60; if (abs(real_minutes - cmos_minutes) < 30) { if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BIN_TO_BCD(real_seconds); BIN_TO_BCD(real_minutes); } CMOS_WRITE(real_seconds,RTC_SECONDS); CMOS_WRITE(real_minutes,RTC_MINUTES); } else { printk(KERN_WARNING "set_rtc_mmss: can't update from %d to %d\n", cmos_minutes, real_minutes); retval = -1; } /* The following flags have to be released exactly in this order, * otherwise the DS12887 (popular MC146818A clone with integrated * battery and quartz) will not reset the oscillator and will not * update precisely 500 ms later. You won't find this mentioned in * the Dallas Semiconductor data sheets, but who believes data * sheets anyway ... -- Markus Kuhn */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); spin_unlock(&rtc_lock); return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -