Applied our style guide.
Commented the debug welcome message in rtc_init(). Moved the seconds per year calculation into a separate function. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5140 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include <arch/real_time_clock.h>
|
#include <arch/real_time_clock.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.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 BASE_YEAR 1970
|
||||||
@@ -29,91 +30,107 @@ uint32 secs_per_month[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, SECONDS_30, SECONDS_31, SECONDS_31, SECONDS_30, SECONDS_31, SECONDS_30,
|
||||||
SECONDS_31};
|
SECONDS_31};
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
bcd_to_int(uint8 bcd) {
|
bcd_to_int(uint8 bcd)
|
||||||
|
{
|
||||||
uint32 numl;
|
uint32 numl;
|
||||||
uint32 numh;
|
uint32 numh;
|
||||||
|
|
||||||
numl = bcd & 0x0f;
|
numl = bcd & 0x0f;
|
||||||
numh = (bcd & 0xf0) >> 4;
|
numh = (bcd & 0xf0) >> 4;
|
||||||
|
|
||||||
return numh * 10 + numl;
|
return numh * 10 + numl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8
|
static uint8
|
||||||
int_to_bcd(uint32 number) {
|
int_to_bcd(uint32 number)
|
||||||
|
{
|
||||||
uint8 low;
|
uint8 low;
|
||||||
uint8 high;
|
uint8 high;
|
||||||
|
|
||||||
if (number > 99)
|
if (number > 99)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
high = number / 10;
|
high = number / 10;
|
||||||
low = number % 10;
|
low = number % 10;
|
||||||
|
|
||||||
return (high << 4) | low;
|
return (high << 4) | low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
leap_year(uint32 year) {
|
leap_year(uint32 year)
|
||||||
|
{
|
||||||
if (year % 400 == 0)
|
if (year % 400 == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (year % 100 == 0)
|
if (year % 100 == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (year % 4 == 0)
|
if (year % 4 == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
same_time(const cmos_time* time1, const cmos_time* time2) {
|
same_time(const cmos_time *time1, const cmos_time *time2)
|
||||||
return (time1->second == time2->second) &&
|
{
|
||||||
(time1->minute == time2->minute) &&
|
return time1->second == time2->second
|
||||||
(time1->hour == time2->hour) &&
|
&& time1->minute == time2->minute
|
||||||
(time1->day == time2->day) &&
|
&& time1->hour == time2->hour
|
||||||
(time1->month == time2->month) &&
|
&& time1->day == time2->day
|
||||||
(time1->year == time2->year) &&
|
&& time1->month == time2->month
|
||||||
(time1->century == time2->century);
|
&& time1->year == time2->year
|
||||||
|
&& time1->century == time2->century;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8
|
static uint8
|
||||||
cmos_read(uint8 addr) {
|
cmos_read(uint8 addr)
|
||||||
|
{
|
||||||
int wait_time;
|
int wait_time;
|
||||||
|
|
||||||
wait_time = 10000;
|
wait_time = 10000;
|
||||||
|
|
||||||
// Wait until bit 7 of Status Register A (indicating whether or not an update is in
|
// Wait until bit 7 of Status Register A (indicating whether or not an update is in
|
||||||
// progress) is clear if we are reading one of the clock data registers...
|
// progress) is clear if we are reading one of the clock data registers...
|
||||||
if (addr < 0x0a) {
|
if (addr < 0x0a) {
|
||||||
out8(0x0a, CMOS_ADDR_PORT);
|
out8(0x0a, CMOS_ADDR_PORT);
|
||||||
while ( (in8(CMOS_DATA_PORT) & 0x80) && --wait_time );
|
while ((in8(CMOS_DATA_PORT) & 0x80) && --wait_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// then read the value.
|
// then read the value.
|
||||||
out8(addr, CMOS_ADDR_PORT);
|
out8(addr, CMOS_ADDR_PORT);
|
||||||
return in8(CMOS_DATA_PORT);
|
return in8(CMOS_DATA_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmos_write(uint8 addr, uint8 data) {
|
cmos_write(uint8 addr, uint8 data)
|
||||||
|
{
|
||||||
out8(addr, CMOS_ADDR_PORT);
|
out8(addr, CMOS_ADDR_PORT);
|
||||||
out8(data, CMOS_DATA_PORT);
|
out8(data, CMOS_DATA_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_24_hour_mode(void) {
|
set_24_hour_mode(void)
|
||||||
|
{
|
||||||
uint8 status_b;
|
uint8 status_b;
|
||||||
|
|
||||||
status_b = cmos_read(0x0b);
|
status_b = cmos_read(0x0b);
|
||||||
status_b |= 0x02;
|
status_b |= 0x02;
|
||||||
cmos_write(0x0b, status_b);
|
cmos_write(0x0b, status_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
read_cmos_clock(cmos_time* cmos) {
|
read_cmos_clock(cmos_time *cmos)
|
||||||
|
{
|
||||||
set_24_hour_mode();
|
set_24_hour_mode();
|
||||||
|
|
||||||
cmos->century = cmos_read(0x32);
|
cmos->century = cmos_read(0x32);
|
||||||
@@ -125,8 +142,10 @@ read_cmos_clock(cmos_time* cmos) {
|
|||||||
cmos->second = cmos_read(0x00);
|
cmos->second = cmos_read(0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_cmos_clock(cmos_time* cmos) {
|
write_cmos_clock(cmos_time *cmos)
|
||||||
|
{
|
||||||
set_24_hour_mode();
|
set_24_hour_mode();
|
||||||
|
|
||||||
cmos_write(0x32, cmos->century);
|
cmos_write(0x32, cmos->century);
|
||||||
@@ -138,32 +157,40 @@ write_cmos_clock(cmos_time* cmos) {
|
|||||||
cmos_write(0x00, cmos->second);
|
cmos_write(0x00, cmos->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 whole_year;
|
{
|
||||||
|
uint32 wholeYear;
|
||||||
uint32 time = 0;
|
uint32 time = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
whole_year = bcd_to_int(cmos->century) * 100 + bcd_to_int(cmos->year);
|
wholeYear = bcd_to_int(cmos->century) * 100 + bcd_to_int(cmos->year);
|
||||||
|
|
||||||
// Add up the seconds from all years since 1970 that have elapsed.
|
// Add up the seconds from all years since 1970 that have elapsed.
|
||||||
for (i = BASE_YEAR; i < whole_year; ++i) {
|
for (i = BASE_YEAR; i < wholeYear; ++i) {
|
||||||
if ( leap_year(i) )
|
time += secs_this_year(i);
|
||||||
time += 31622400;
|
|
||||||
|
|
||||||
else
|
|
||||||
time += 31536000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add up the seconds from all months passed this year.
|
// Add up the seconds from all months passed this year.
|
||||||
for (i = 0; i < bcd_to_int(cmos->month) - 1 && i < 12; ++i)
|
for (i = 0; i < bcd_to_int(cmos->month) - 1 && i < 12; ++i)
|
||||||
time += secs_per_month[i];
|
time += secs_per_month[i];
|
||||||
|
|
||||||
// Add up the seconds from all days passed this month.
|
// Add up the seconds from all days passed this month.
|
||||||
if ( leap_year(whole_year) && bcd_to_int(cmos->month) > 2 )
|
if (leap_year(wholeYear) && bcd_to_int(cmos->month) > 2)
|
||||||
time += SECONDS_DAY;
|
time += SECONDS_DAY;
|
||||||
|
|
||||||
time += ( bcd_to_int(cmos->day) - 1 ) * SECONDS_DAY;
|
time += (bcd_to_int(cmos->day) - 1) * SECONDS_DAY;
|
||||||
time += bcd_to_int(cmos->hour) * 3600;
|
time += bcd_to_int(cmos->hour) * 3600;
|
||||||
time += bcd_to_int(cmos->minute) * 60;
|
time += bcd_to_int(cmos->minute) * 60;
|
||||||
time += bcd_to_int(cmos->second);
|
time += bcd_to_int(cmos->second);
|
||||||
@@ -171,94 +198,93 @@ cmos_to_secs(const cmos_time* cmos) {
|
|||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
secs_to_cmos(uint32 seconds, cmos_time* cmos) {
|
secs_to_cmos(uint32 seconds, cmos_time *cmos)
|
||||||
uint32 whole_year = BASE_YEAR;
|
{
|
||||||
uint32 secs_this_year;
|
uint32 wholeYear = BASE_YEAR;
|
||||||
|
uint32 secsThisYear;
|
||||||
|
bool keepLooping;
|
||||||
|
bool isLeapYear;
|
||||||
int i;
|
int i;
|
||||||
int temp;
|
int temp;
|
||||||
int is_leapyear;
|
|
||||||
int month;
|
int month;
|
||||||
int keep_looping;
|
|
||||||
|
keepLooping = 1;
|
||||||
keep_looping = 1;
|
|
||||||
|
// Determine the current year by starting at 1970 and incrementing whole_year as long as
|
||||||
// Determine the current year by starting at 1970 and incrementing whole_year as long as
|
// we can keep subtracting secs_this_year from seconds.
|
||||||
// we can keep subtracting secs_this_year from seconds.
|
while (keepLooping) {
|
||||||
while (keep_looping) {
|
secsThisYear = secs_this_year(wholeYear);
|
||||||
if ( leap_year(whole_year) )
|
|
||||||
secs_this_year = 31622400;
|
if (seconds >= secsThisYear) {
|
||||||
|
seconds -= secsThisYear;
|
||||||
else
|
++wholeYear;
|
||||||
secs_this_year = 31536000;
|
} else
|
||||||
|
keepLooping = false;
|
||||||
if (seconds >= secs_this_year) {
|
|
||||||
seconds -= secs_this_year;
|
|
||||||
++whole_year;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
keep_looping = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmos->century = int_to_bcd(whole_year / 100);
|
cmos->century = int_to_bcd(wholeYear / 100);
|
||||||
cmos->year = int_to_bcd(whole_year % 100);
|
cmos->year = int_to_bcd(wholeYear % 100);
|
||||||
|
|
||||||
// Determine the current month
|
// Determine the current month
|
||||||
month = 1;
|
month = 1;
|
||||||
is_leapyear = leap_year(whole_year);
|
isLeapYear = leap_year(wholeYear);
|
||||||
do {
|
do {
|
||||||
temp = seconds - secs_per_month[month - 1];
|
temp = seconds - secs_per_month[month - 1];
|
||||||
|
|
||||||
if (is_leapyear && month == 2)
|
if (isLeapYear && month == 2)
|
||||||
temp -= SECONDS_DAY;
|
temp -= SECONDS_DAY;
|
||||||
|
|
||||||
if (temp >= 0) {
|
if (temp >= 0) {
|
||||||
seconds = temp;
|
seconds = temp;
|
||||||
++month;
|
++month;
|
||||||
}
|
}
|
||||||
} while (temp >= 0 && month < 13);
|
} while (temp >= 0 && month < 13);
|
||||||
|
|
||||||
cmos->month = int_to_bcd(month);
|
cmos->month = int_to_bcd(month);
|
||||||
|
|
||||||
cmos->day = int_to_bcd(seconds / SECONDS_DAY + 1);
|
cmos->day = int_to_bcd(seconds / SECONDS_DAY + 1);
|
||||||
seconds = seconds % SECONDS_DAY;
|
seconds = seconds % SECONDS_DAY;
|
||||||
|
|
||||||
cmos->hour = int_to_bcd(seconds / 3600);
|
cmos->hour = int_to_bcd(seconds / 3600);
|
||||||
seconds = seconds % 3600;
|
seconds = seconds % 3600;
|
||||||
|
|
||||||
cmos->minute = int_to_bcd(seconds / 60);
|
cmos->minute = int_to_bcd(seconds / 60);
|
||||||
seconds = seconds % 60;
|
seconds = seconds % 60;
|
||||||
|
|
||||||
cmos->second = int_to_bcd(seconds);
|
cmos->second = int_to_bcd(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
arch_rtc_get_hw_time(void) {
|
arch_rtc_get_hw_time(void)
|
||||||
int wait_time;
|
{
|
||||||
|
int waitTime;
|
||||||
cmos_time cmos1;
|
cmos_time cmos1;
|
||||||
cmos_time cmos2;
|
cmos_time cmos2;
|
||||||
|
|
||||||
wait_time = 1000;
|
waitTime = 1000;
|
||||||
|
|
||||||
// We will read the clock twice and make sure both reads are equal. This will prevent
|
// We will read the clock twice and make sure both reads are equal. This will prevent
|
||||||
// problems that would occur if the clock is read during an update (e.g. if we read the hour
|
// problems that would occur if the clock is read during an update (e.g. if we read the hour
|
||||||
// at 8:59:59, the clock gets changed, and then we read the minute and second, we would
|
// at 8:59:59, the clock gets changed, and then we read the minute and second, we would
|
||||||
// be off by a whole hour)
|
// be off by a whole hour)
|
||||||
do {
|
do {
|
||||||
read_cmos_clock(&cmos1);
|
read_cmos_clock(&cmos1);
|
||||||
read_cmos_clock(&cmos2);
|
read_cmos_clock(&cmos2);
|
||||||
} while ( !same_time(&cmos1, &cmos2) && --wait_time );
|
} while (!same_time(&cmos1, &cmos2) && --waitTime);
|
||||||
|
|
||||||
// Convert the CMOS data to seconds since 1970.
|
// Convert the CMOS data to seconds since 1970.
|
||||||
return cmos_to_secs(&cmos1);
|
return cmos_to_secs(&cmos1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_rtc_set_hw_time(uint32 seconds) {
|
arch_rtc_set_hw_time(uint32 seconds)
|
||||||
|
{
|
||||||
cmos_time cmos;
|
cmos_time cmos;
|
||||||
uint32 read_back;
|
|
||||||
|
|
||||||
secs_to_cmos(seconds, &cmos);
|
secs_to_cmos(seconds, &cmos);
|
||||||
write_cmos_clock(&cmos);
|
write_cmos_clock(&cmos);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,74 +11,86 @@
|
|||||||
#include <arch/real_time_clock.h>
|
#include <arch/real_time_clock.h>
|
||||||
#include <real_time_clock.h>
|
#include <real_time_clock.h>
|
||||||
|
|
||||||
static bigtime_t boot_time;
|
|
||||||
|
static bigtime_t sBootTime;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rtc_print(void) {
|
rtc_print(void)
|
||||||
uint32 current_time;
|
{
|
||||||
|
uint32 currentTime;
|
||||||
current_time = (boot_time + system_time()) / 1000000;
|
|
||||||
|
currentTime = (sBootTime + system_time()) / 1000000;
|
||||||
dprintf("system_time: %u\n", (unsigned)system_time());
|
dprintf("system_time: %u\n", (unsigned)system_time());
|
||||||
dprintf("boot_time: %u\n", (unsigned)boot_time);
|
dprintf("boot_time: %u\n", (unsigned)sBootTime);
|
||||||
dprintf("current_time: %u\n", (unsigned)current_time);
|
dprintf("current_time: %u\n", (unsigned)currentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rtc_debug(int argc, char** argv) {
|
rtc_debug(int argc, char **argv)
|
||||||
// If no arguments were given, output all usefull data.
|
{
|
||||||
if (argc < 2)
|
if (argc < 2) {
|
||||||
|
// If no arguments were given, output all usefull data.
|
||||||
rtc_print();
|
rtc_print();
|
||||||
|
} else {
|
||||||
// If there was an argument, reset the system and hw time.
|
// If there was an argument, reset the system and hw time.
|
||||||
else {
|
rtc_set_system_time(strtoul(argv[1], NULL, 10));
|
||||||
rtc_set_system_time( strtoul(argv[1], NULL, 10) );
|
|
||||||
rtc_system_to_hw();
|
rtc_system_to_hw();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
rtc_init(kernel_args *ka) {
|
status_t
|
||||||
dprintf("rtc_init: entry\n");
|
rtc_init(kernel_args *ka)
|
||||||
|
{
|
||||||
|
//dprintf("rtc_init: entry\n");
|
||||||
add_debugger_command("rtc", &rtc_debug, "Set and test the real-time clock");
|
add_debugger_command("rtc", &rtc_debug, "Set and test the real-time clock");
|
||||||
|
|
||||||
rtc_hw_to_system();
|
rtc_hw_to_system();
|
||||||
|
|
||||||
return 0;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rtc_set_system_time(uint32 current_time) {
|
rtc_set_system_time(uint32 current_time)
|
||||||
|
{
|
||||||
uint64 useconds;
|
uint64 useconds;
|
||||||
|
|
||||||
useconds = (uint64)current_time * 1000000;
|
useconds = (uint64)current_time * 1000000;
|
||||||
boot_time = useconds - system_time();
|
sBootTime = useconds - system_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Write the system time to CMOS. */
|
/** Write the system time to CMOS. */
|
||||||
|
|
||||||
void
|
static void
|
||||||
rtc_system_to_hw(void) {
|
rtc_system_to_hw(void)
|
||||||
|
{
|
||||||
uint32 seconds;
|
uint32 seconds;
|
||||||
|
|
||||||
seconds = (boot_time + system_time()) / 1000000;
|
seconds = (sBootTime + system_time()) / 1000000;
|
||||||
arch_rtc_set_hw_time(seconds);
|
arch_rtc_set_hw_time(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Read the CMOS clock and update the system time accordingly. */
|
/** Read the CMOS clock and update the system time accordingly. */
|
||||||
|
|
||||||
void
|
static void
|
||||||
rtc_hw_to_system(void) {
|
rtc_hw_to_system(void)
|
||||||
|
{
|
||||||
uint32 current_time;
|
uint32 current_time;
|
||||||
|
|
||||||
current_time = arch_rtc_get_hw_time();
|
current_time = arch_rtc_get_hw_time();
|
||||||
rtc_set_system_time(current_time);
|
rtc_set_system_time(current_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bigtime_t
|
bigtime_t
|
||||||
rtc_boot_time(void) {
|
rtc_boot_time(void)
|
||||||
return boot_time;
|
{
|
||||||
|
return sBootTime;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user