Pulled the conversion between seconds since the epoche and the split up
(year, month,...) representation out of the x86 specific code and put respective support functions into real_time_clock.c. We'll need those for the PPC specific part too. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15827 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
b41356006a
commit
d9a5e6050f
@ -8,6 +8,10 @@
|
|||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define RTC_EPOCHE_BASE_YEAR 1970
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -26,6 +30,11 @@ typedef struct rtc_info {
|
|||||||
|
|
||||||
status_t get_rtc_info(rtc_info *info);
|
status_t get_rtc_info(rtc_info *info);
|
||||||
|
|
||||||
|
// Both functions use the passed struct tm only partially
|
||||||
|
// (no tm_wday, tm_yday, tm_isdst).
|
||||||
|
uint32 rtc_tm_to_secs(const struct tm *t);
|
||||||
|
void rtc_secs_to_tm(uint32 seconds, struct tm *t);
|
||||||
|
|
||||||
bigtime_t _user_system_time(void);
|
bigtime_t _user_system_time(void);
|
||||||
status_t _user_set_real_time_clock(uint32 time);
|
status_t _user_set_real_time_clock(uint32 time);
|
||||||
status_t _user_set_timezone(int32 timezoneOffset, bool daylightSavingTime);
|
status_t _user_set_timezone(int32 timezoneOffset, bool daylightSavingTime);
|
||||||
|
@ -9,16 +9,12 @@
|
|||||||
#include <arch/real_time_clock.h>
|
#include <arch/real_time_clock.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
|
#include <real_time_clock.h>
|
||||||
#include <real_time_data.h>
|
#include <real_time_data.h>
|
||||||
|
|
||||||
|
|
||||||
#define CMOS_ADDR_PORT 0x70
|
#define CMOS_ADDR_PORT 0x70
|
||||||
#define CMOS_DATA_PORT 0x71
|
#define CMOS_DATA_PORT 0x71
|
||||||
#define BASE_YEAR 1970
|
|
||||||
#define SECONDS_31 2678400
|
|
||||||
#define SECONDS_30 2592000
|
|
||||||
#define SECONDS_28 2419200
|
|
||||||
#define SECONDS_DAY 86400
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8 second;
|
uint8 second;
|
||||||
@ -30,10 +26,6 @@ typedef struct {
|
|||||||
uint8 century;
|
uint8 century;
|
||||||
} cmos_time;
|
} cmos_time;
|
||||||
|
|
||||||
static uint32 sSecsPerMonth[12] = {SECONDS_31, SECONDS_28, SECONDS_31, SECONDS_30,
|
|
||||||
SECONDS_31, SECONDS_30, SECONDS_31, SECONDS_31, SECONDS_30, SECONDS_31, SECONDS_30,
|
|
||||||
SECONDS_31};
|
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
bcd_to_int(uint8 bcd)
|
bcd_to_int(uint8 bcd)
|
||||||
@ -64,22 +56,6 @@ int_to_bcd(uint32 number)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
leap_year(uint32 year)
|
|
||||||
{
|
|
||||||
if (year % 400 == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (year % 100 == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (year % 4 == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
same_time(const cmos_time *time1, const cmos_time *time2)
|
same_time(const cmos_time *time1, const cmos_time *time2)
|
||||||
{
|
{
|
||||||
@ -160,105 +136,39 @@ write_cmos_clock(cmos_time *cmos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline uint32
|
|
||||||
secs_this_year(uint32 year)
|
|
||||||
{
|
|
||||||
if (leap_year(year))
|
|
||||||
return 31622400;
|
|
||||||
|
|
||||||
return 31536000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
cmos_to_secs(const cmos_time *cmos)
|
cmos_to_secs(const cmos_time *cmos)
|
||||||
{
|
{
|
||||||
uint32 wholeYear;
|
struct tm t;
|
||||||
uint32 time = 0;
|
t.tm_year = bcd_to_int(cmos->century) * 100 + bcd_to_int(cmos->year)
|
||||||
uint32 i;
|
- RTC_EPOCHE_BASE_YEAR;
|
||||||
|
t.tm_mon = bcd_to_int(cmos->month) - 1;
|
||||||
|
t.tm_mday = bcd_to_int(cmos->day);
|
||||||
|
t.tm_hour = bcd_to_int(cmos->hour);
|
||||||
|
t.tm_min = bcd_to_int(cmos->minute);
|
||||||
|
t.tm_sec = bcd_to_int(cmos->second);
|
||||||
|
|
||||||
wholeYear = bcd_to_int(cmos->century) * 100 + bcd_to_int(cmos->year);
|
return rtc_tm_to_secs(&t);
|
||||||
|
|
||||||
// ToDo: get rid of these loops and compute the correct value
|
|
||||||
// i.e. days = (long)(year > 0) + year*365 + --year/4 - year/100 + year/400;
|
|
||||||
// let sSecsPerMonth[] have the values already added up
|
|
||||||
|
|
||||||
// Add up the seconds from all years since 1970 that have elapsed.
|
|
||||||
for (i = BASE_YEAR; i < wholeYear; ++i) {
|
|
||||||
time += secs_this_year(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add up the seconds from all months passed this year.
|
|
||||||
for (i = 0; i < bcd_to_int(cmos->month) - 1 && i < 12; ++i)
|
|
||||||
time += sSecsPerMonth[i];
|
|
||||||
|
|
||||||
// Add up the seconds from all days passed this month.
|
|
||||||
if (leap_year(wholeYear) && bcd_to_int(cmos->month) > 2)
|
|
||||||
time += SECONDS_DAY;
|
|
||||||
|
|
||||||
time += (bcd_to_int(cmos->day) - 1) * SECONDS_DAY;
|
|
||||||
time += bcd_to_int(cmos->hour) * 3600;
|
|
||||||
time += bcd_to_int(cmos->minute) * 60;
|
|
||||||
time += bcd_to_int(cmos->second);
|
|
||||||
|
|
||||||
return time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
secs_to_cmos(uint32 seconds, cmos_time *cmos)
|
secs_to_cmos(uint32 seconds, cmos_time *cmos)
|
||||||
{
|
{
|
||||||
uint32 wholeYear = BASE_YEAR;
|
int wholeYear;
|
||||||
uint32 secsThisYear;
|
|
||||||
bool keepLooping;
|
|
||||||
bool isLeapYear;
|
|
||||||
int temp;
|
|
||||||
int month;
|
|
||||||
|
|
||||||
keepLooping = 1;
|
struct tm t;
|
||||||
|
rtc_secs_to_tm(seconds, &t);
|
||||||
|
|
||||||
// Determine the current year by starting at 1970 and incrementing whole_year as long as
|
wholeYear = t.tm_year + RTC_EPOCHE_BASE_YEAR;
|
||||||
// we can keep subtracting secs_this_year from seconds.
|
|
||||||
while (keepLooping) {
|
|
||||||
secsThisYear = secs_this_year(wholeYear);
|
|
||||||
|
|
||||||
if (seconds >= secsThisYear) {
|
|
||||||
seconds -= secsThisYear;
|
|
||||||
++wholeYear;
|
|
||||||
} else
|
|
||||||
keepLooping = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmos->century = int_to_bcd(wholeYear / 100);
|
cmos->century = int_to_bcd(wholeYear / 100);
|
||||||
cmos->year = int_to_bcd(wholeYear % 100);
|
cmos->year = int_to_bcd(wholeYear % 100);
|
||||||
|
cmos->month = int_to_bcd(t.tm_mon + 1);
|
||||||
// Determine the current month
|
cmos->day = int_to_bcd(t.tm_mday);
|
||||||
month = 1;
|
cmos->hour = int_to_bcd(t.tm_hour);
|
||||||
isLeapYear = leap_year(wholeYear);
|
cmos->minute = int_to_bcd(t.tm_min);
|
||||||
do {
|
cmos->second = int_to_bcd(t.tm_sec);
|
||||||
temp = seconds - sSecsPerMonth[month - 1];
|
|
||||||
|
|
||||||
if (isLeapYear && month == 2)
|
|
||||||
temp -= SECONDS_DAY;
|
|
||||||
|
|
||||||
if (temp >= 0) {
|
|
||||||
seconds = temp;
|
|
||||||
++month;
|
|
||||||
}
|
|
||||||
} while (temp >= 0 && month < 13);
|
|
||||||
|
|
||||||
cmos->month = int_to_bcd(month);
|
|
||||||
|
|
||||||
cmos->day = int_to_bcd(seconds / SECONDS_DAY + 1);
|
|
||||||
seconds = seconds % SECONDS_DAY;
|
|
||||||
|
|
||||||
cmos->hour = int_to_bcd(seconds / 3600);
|
|
||||||
seconds = seconds % 3600;
|
|
||||||
|
|
||||||
cmos->minute = int_to_bcd(seconds / 60);
|
|
||||||
seconds = seconds % 60;
|
|
||||||
|
|
||||||
cmos->second = int_to_bcd(seconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,6 +155,136 @@ get_rtc_info(rtc_info *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
#define SECONDS_31 2678400
|
||||||
|
#define SECONDS_30 2592000
|
||||||
|
#define SECONDS_28 2419200
|
||||||
|
#define SECONDS_DAY 86400
|
||||||
|
|
||||||
|
static uint32 sSecsPerMonth[12] = {SECONDS_31, SECONDS_28, SECONDS_31, SECONDS_30,
|
||||||
|
SECONDS_31, SECONDS_30, SECONDS_31, SECONDS_31, SECONDS_30, SECONDS_31, SECONDS_30,
|
||||||
|
SECONDS_31};
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
leap_year(uint32 year)
|
||||||
|
{
|
||||||
|
if (year % 400 == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (year % 100 == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (year % 4 == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint32
|
||||||
|
secs_this_year(uint32 year)
|
||||||
|
{
|
||||||
|
if (leap_year(year))
|
||||||
|
return 31622400;
|
||||||
|
|
||||||
|
return 31536000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
rtc_tm_to_secs(const struct tm *t)
|
||||||
|
{
|
||||||
|
uint32 wholeYear;
|
||||||
|
uint32 time = 0;
|
||||||
|
uint32 i;
|
||||||
|
|
||||||
|
wholeYear = 1900 + t->tm_year;
|
||||||
|
|
||||||
|
// ToDo: get rid of these loops and compute the correct value
|
||||||
|
// i.e. days = (long)(year > 0) + year*365 + --year/4 - year/100 + year/400;
|
||||||
|
// let sSecsPerMonth[] have the values already added up
|
||||||
|
|
||||||
|
// Add up the seconds from all years since 1970 that have elapsed.
|
||||||
|
for (i = RTC_EPOCHE_BASE_YEAR; i < wholeYear; ++i) {
|
||||||
|
time += secs_this_year(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add up the seconds from all months passed this year.
|
||||||
|
for (i = 0; i < t->tm_mon && i < 12; ++i)
|
||||||
|
time += sSecsPerMonth[i];
|
||||||
|
|
||||||
|
// Add up the seconds from all days passed this month.
|
||||||
|
if (leap_year(wholeYear) && t->tm_mon >= 2)
|
||||||
|
time += SECONDS_DAY;
|
||||||
|
|
||||||
|
time += (t->tm_mday - 1) * SECONDS_DAY;
|
||||||
|
time += t->tm_hour * 3600;
|
||||||
|
time += t->tm_min * 60;
|
||||||
|
time += t->tm_sec;
|
||||||
|
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
rtc_secs_to_tm(uint32 seconds, struct tm *t)
|
||||||
|
{
|
||||||
|
uint32 wholeYear = RTC_EPOCHE_BASE_YEAR;
|
||||||
|
uint32 secsThisYear;
|
||||||
|
bool keepLooping;
|
||||||
|
bool isLeapYear;
|
||||||
|
int temp;
|
||||||
|
int month;
|
||||||
|
|
||||||
|
keepLooping = 1;
|
||||||
|
|
||||||
|
// Determine the current year by starting at 1970 and incrementing whole_year as long as
|
||||||
|
// we can keep subtracting secs_this_year from seconds.
|
||||||
|
while (keepLooping) {
|
||||||
|
secsThisYear = secs_this_year(wholeYear);
|
||||||
|
|
||||||
|
if (seconds >= secsThisYear) {
|
||||||
|
seconds -= secsThisYear;
|
||||||
|
++wholeYear;
|
||||||
|
} else
|
||||||
|
keepLooping = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->tm_year = wholeYear - RTC_EPOCHE_BASE_YEAR;
|
||||||
|
|
||||||
|
// Determine the current month
|
||||||
|
month = 0;
|
||||||
|
isLeapYear = leap_year(wholeYear);
|
||||||
|
do {
|
||||||
|
temp = seconds - sSecsPerMonth[month];
|
||||||
|
|
||||||
|
if (isLeapYear && month == 1)
|
||||||
|
temp -= SECONDS_DAY;
|
||||||
|
|
||||||
|
if (temp >= 0) {
|
||||||
|
seconds = temp;
|
||||||
|
++month;
|
||||||
|
}
|
||||||
|
} while (temp >= 0 && month < 12);
|
||||||
|
|
||||||
|
t->tm_mon = month;
|
||||||
|
|
||||||
|
t->tm_mday = seconds / SECONDS_DAY + 1;
|
||||||
|
seconds = seconds % SECONDS_DAY;
|
||||||
|
|
||||||
|
t->tm_hour = seconds / 3600;
|
||||||
|
seconds = seconds % 3600;
|
||||||
|
|
||||||
|
t->tm_min = seconds / 60;
|
||||||
|
seconds = seconds % 60;
|
||||||
|
|
||||||
|
t->tm_sec = seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
// public userland API
|
// public userland API
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user