kern

view src/rtc.c @ 80:4db99a52863e

fixed the "endianess" of the text messages in the ATA identify info block. this is the first time I've seen wrong byteorder in ascii text, the ATA committee should be commended.
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 06 Dec 2011 13:35:39 +0200
parents 2c401f69128e
children
line source
1 #include <stdio.h>
2 #include <time.h>
3 #include <asmops.h>
4 #include "rtc.h"
6 /* CMOS I/O ports */
7 #define PORT_CTL 0x70
8 #define PORT_DATA 0x71
10 /* CMOS RTC registers */
11 #define REG_SEC 0
12 #define REG_ALARM_SEC 1
13 #define REG_MIN 2
14 #define REG_ALARM_MIN 3
15 #define REG_HOUR 4
16 #define REG_ALARM_HOUR 5
17 #define REG_WEEKDAY 6
18 #define REG_DAY 7
19 #define REG_MONTH 8
20 #define REG_YEAR 9
21 #define REG_STATA 10
22 #define REG_STATB 11
23 #define REG_STATC 12
24 #define REG_STATD 13
26 #define STATA_BUSY (1 << 7)
27 #define STATB_24HR (1 << 1)
28 #define STATB_BIN (1 << 2)
30 #define HOUR_PM_BIT (1 << 7)
32 #define BCD_TO_BIN(x) ((((x) >> 4) & 0xf) * 10 + ((x) & 0xf))
34 static void read_rtc(struct tm *tm);
35 static int read_reg(int reg);
38 void init_rtc(void)
39 {
40 struct tm tm;
42 read_rtc(&tm);
43 start_time = mktime(&tm);
45 printf("System real-time clock: %s", asctime(&tm));
46 }
49 static void read_rtc(struct tm *tm)
50 {
51 int statb, pm;
53 /* wait for any clock updates to finish */
54 while(read_reg(REG_STATA) & STATA_BUSY);
56 tm->tm_sec = read_reg(REG_SEC);
57 tm->tm_min = read_reg(REG_MIN);
58 tm->tm_hour = read_reg(REG_HOUR);
59 tm->tm_mday = read_reg(REG_DAY);
60 tm->tm_mon = read_reg(REG_MONTH);
61 tm->tm_year = read_reg(REG_YEAR);
63 /* in 12hour mode, bit 7 means post-meridiem */
64 pm = tm->tm_hour & HOUR_PM_BIT;
65 tm->tm_hour &= ~HOUR_PM_BIT;
67 /* convert to binary if needed */
68 statb = read_reg(REG_STATB);
69 if(!(statb & STATB_BIN)) {
70 tm->tm_sec = BCD_TO_BIN(tm->tm_sec);
71 tm->tm_min = BCD_TO_BIN(tm->tm_min);
72 tm->tm_hour = BCD_TO_BIN(tm->tm_hour);
73 tm->tm_mday = BCD_TO_BIN(tm->tm_mday);
74 tm->tm_mon = BCD_TO_BIN(tm->tm_mon);
75 tm->tm_year = BCD_TO_BIN(tm->tm_year);
76 }
78 /* make the year an offset from 1900 */
79 if(tm->tm_year < 100) {
80 tm->tm_year += 100;
81 } else {
82 tm->tm_year -= 1900;
83 }
85 /* if tm_hour is in 12h mode, convert to 24h */
86 if(!(statb & STATB_24HR)) {
87 if(tm->tm_hour == 12) {
88 tm->tm_hour = 0;
89 }
90 if(pm) {
91 tm->tm_hour += 12;
92 }
93 }
95 tm->tm_mon -= 1; /* we want months to start from 0 */
96 }
98 static int read_reg(int reg)
99 {
100 unsigned char val;
101 outb(reg, PORT_CTL);
102 iodelay();
103 inb(val, PORT_DATA);
104 iodelay();
105 return val;
106 }