# HG changeset patch # User John Tsiombikas # Date 1307673218 -10800 # Node ID e70b1ab9613e461734aa51bb3c2547a775b7f169 # Parent 06172322fb76d319b4b5307b27cdb5b5d803df97 - added cmos rtc code - added time/date functions in klibc - implemented an iowait macro with output to 0x80 diff -r 06172322fb76 -r e70b1ab9613e src/asmops.h --- a/src/asmops.h Thu Jun 09 05:09:49 2011 +0300 +++ b/src/asmops.h Fri Jun 10 05:33:38 2011 +0300 @@ -32,4 +32,6 @@ "outl %0, %1\n\t" \ :: "a" ((unsigned long)(src)), "dN" ((unsigned short)(port))) +#define iodelay() outb(0, 0x80) + #endif /* ASMOPS_H_ */ diff -r 06172322fb76 -r e70b1ab9613e src/klibc/time.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/klibc/time.c Fri Jun 10 05:33:38 2011 +0300 @@ -0,0 +1,70 @@ +#include +#include "time.h" + +#define MINSEC 60 +#define HOURSEC (60 * MINSEC) +#define DAYSEC (24 * HOURSEC) + +static int is_leap_year(int yr); + + +static char *wday[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; +static char *mon[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + + +char *asctime(struct tm *tm) +{ + static char buf[64]; + + sprintf(buf, "%s %s %d %02d:%02d:%02d %d\n", wday[tm->tm_wday], + mon[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec, tm->tm_year + 1900); + return buf; +} + +time_t mktime(struct tm *tm) +{ + int i, num_years = tm->tm_year - 70; + int year = 1970; + int days = day_of_year(tm->tm_year + 1900, tm->tm_mon, tm->tm_mday - 1); + + for(i=0; itm_hour * HOURSEC + + tm->tm_min * MINSEC + tm->tm_sec; +} + +int day_of_year(int year, int mon, int day) +{ + static int commdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + static int leapdays[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + int *mdays, i, yday; + + mdays = is_leap_year(year) ? leapdays : commdays; + + yday = day; + for(i=0; i +#include +#include + +/* CMOS I/O ports */ +#define PORT_CTL 0x70 +#define PORT_DATA 0x71 + +/* CMOS RTC registers */ +#define REG_SEC 0 +#define REG_ALARM_SEC 1 +#define REG_MIN 2 +#define REG_ALARM_MIN 3 +#define REG_HOUR 4 +#define REG_ALARM_HOUR 5 +#define REG_WEEKDAY 6 +#define REG_DAY 7 +#define REG_MONTH 8 +#define REG_YEAR 9 +#define REG_STATA 10 +#define REG_STATB 11 +#define REG_STATC 12 +#define REG_STATD 13 + +#define STATA_BUSY (1 << 7) +#define STATB_24HR (1 << 1) +#define STATB_BIN (1 << 2) + +#define HOUR_PM_BIT (1 << 7) + +#define BCD_TO_BIN(x) ((((x) >> 4) & 0xf) * 10 + ((x) & 0xf)) + +static void read_rtc(struct tm *tm); +static int read_reg(int reg); + +static unsigned long start_time; + + +void init_rtc(void) +{ + struct tm tm; + + read_rtc(&tm); + printf("System real-time clock: %s", asctime(&tm)); + printf("time_t: %ld\n", mktime(&tm)); +} + +static void read_rtc(struct tm *tm) +{ + int statb, pm; + + /* wait for any clock updates to finish */ + while(read_reg(REG_STATA) & STATA_BUSY); + + tm->tm_sec = read_reg(REG_SEC); + tm->tm_min = read_reg(REG_MIN); + tm->tm_hour = read_reg(REG_HOUR); + tm->tm_mday = read_reg(REG_DAY); + tm->tm_mon = read_reg(REG_MONTH); + tm->tm_year = read_reg(REG_YEAR); + tm->tm_wday = read_reg(REG_WEEKDAY); + + /* in 12hour mode, bit 7 means post-meridiem */ + pm = tm->tm_hour & HOUR_PM_BIT; + tm->tm_hour &= ~HOUR_PM_BIT; + + /* convert to binary if needed */ + statb = read_reg(REG_STATB); + if(!(statb & STATB_BIN)) { + tm->tm_sec = BCD_TO_BIN(tm->tm_sec); + tm->tm_min = BCD_TO_BIN(tm->tm_min); + tm->tm_hour = BCD_TO_BIN(tm->tm_hour); + tm->tm_mday = BCD_TO_BIN(tm->tm_mday); + tm->tm_mon = BCD_TO_BIN(tm->tm_mon); + tm->tm_year = BCD_TO_BIN(tm->tm_year); + tm->tm_wday = BCD_TO_BIN(tm->tm_wday); + } + + /* make the year an offset from 1900 */ + if(tm->tm_year < 100) { + tm->tm_year += 100; + } else { + tm->tm_year -= 1900; + } + + /* if tm_hour is in 12h mode, convert to 24h */ + if(!(statb & STATB_24HR)) { + if(tm->tm_hour == 12) { + tm->tm_hour = 0; + } + if(pm) { + tm->tm_hour += 12; + } + } + + tm->tm_mon -= 1; /* we want months to start from 0 */ + tm->tm_wday -= 1; /* we want weekdays to start from 0 */ + tm->tm_yday = day_of_year(tm->tm_year + 1900, tm->tm_mon, tm->tm_mday - 1); +} + +static int read_reg(int reg) +{ + unsigned char val; + outb(reg, PORT_CTL); + iodelay(); + inb(val, PORT_DATA); + iodelay(); + return val; +} diff -r 06172322fb76 -r e70b1ab9613e src/rtc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/rtc.h Fri Jun 10 05:33:38 2011 +0300 @@ -0,0 +1,7 @@ +#ifndef _RTC_H_ +#define _RTC_H_ + +void init_rtc(void); + + +#endif /* _RTC_H_ */