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:
Axel Dörfler
2003-10-24 12:01:25 +00:00
parent a34e8cc39f
commit f328aeecb6
2 changed files with 177 additions and 139 deletions
+132 -106
View File
@@ -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);
} }
+45 -33
View File
@@ -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;
} }