]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ia32/rtc-ia32.cpp
Update
[l4.git] / kernel / fiasco / src / kern / ia32 / rtc-ia32.cpp
1 INTERFACE[ia32,amd64]:
2
3 class Rtc
4 {
5 private:
6   Rtc();
7   Rtc(const Rtc&);
8 };
9
10 IMPLEMENTATION[ia32,amd64]:
11
12 #include "io.h"
13 #include "globalconfig.h"
14
15 #define RTC_STATUSA      0x0a   /* status register A */
16 #define  RTCSA_TUP       0x80   /* time update, don't look now */
17 #define  RTCSA_DIVIDER   0x20   /* divider correct for 32768 Hz */
18 #define  RTCSA_8192      0x03
19 #define  RTCSA_4096      0x04
20 #define  RTCSA_2048      0x05
21 #define  RTCSA_1024      0x06
22 #define  RTCSA_512       0x07
23 #define  RTCSA_256       0x08
24 #define  RTCSA_128       0x09
25 #define  RTCSA_64        0x0a
26 #define  RTCSA_32        0x0b
27
28 #define RTC_STATUSB     0x0b    /* status register B */
29 #define  RTCSB_DST       0x01   /* Daylight Savings Time enable */
30 #define  RTCSB_24HR      0x02   /* 0 = 12 hours, 1 = 24 hours */
31 #define  RTCSB_BCD       0x04   /* 0 = BCD, 1 = Binary coded time */
32 #define  RTCSB_SQWE      0x08   /* 1 = output sqare wave at SQW pin */
33 #define  RTCSB_UINTR     0x10   /* 1 = enable update-ended interrupt */
34 #define  RTCSB_AINTR     0x20   /* 1 = enable alarm interrupt */
35 #define  RTCSB_PINTR     0x40   /* 1 = enable periodic clock interrupt */
36 #define  RTCSB_HALT      0x80   /* stop clock updates */
37
38 #define RTC_INTR        0x0c    /* status register C (R) interrupt source */
39 #define  RTCIR_UPDATE    0x10   /* update intr */
40 #define  RTCIR_ALARM     0x20   /* alarm intr */
41 #define  RTCIR_PERIOD    0x40   /* periodic intr */
42 #define  RTCIR_INT       0x80   /* interrupt output signal */
43
44
45 static inline
46 unsigned char
47 Rtc::reg_read(unsigned char reg)
48 {
49   Io::out8_p(reg, 0x70);
50   return Io::in8_p(0x71);
51 }
52
53 static inline
54 void
55 Rtc::reg_write(unsigned char reg, unsigned char val)
56 {
57   Io::out8_p(reg,0x70);
58   Io::out8_p(val,0x71);
59 }
60
61 // set up timer interrupt (~ 1ms)
62 PUBLIC static
63 void
64 Rtc::init()
65 {
66   while (reg_read(RTC_STATUSA) & RTCSA_TUP) 
67     ; // wait till RTC ready
68
69 #ifdef CONFIG_SLOW_RTC
70   // set divider to 64 Hz
71   reg_write(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_64);
72 #else
73   // set divider to 1024 Hz
74   reg_write(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_1024);
75 #endif
76
77   // set up interrupt
78   reg_write(RTC_STATUSB, reg_read(RTC_STATUSB) | RTCSB_PINTR | RTCSB_SQWE); 
79
80   // reset
81   reg_read(RTC_INTR);
82 }
83
84 PUBLIC static
85 void
86 Rtc::done()
87 {
88   // disable all potential interrupt sources
89   reg_write(RTC_STATUSB,
90          reg_read(RTC_STATUSB) & ~(RTCSB_PINTR | RTCSB_AINTR | RTCSB_UINTR));
91
92   // reset
93   reg_read(RTC_INTR);
94 }
95
96 PUBLIC static
97 void
98 Rtc::set_freq_slow()
99 {
100   // set divider to 32 Hz
101   reg_write(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_32);
102 }
103
104 PUBLIC static
105 void
106 Rtc::set_freq_normal()
107 {
108   // set divider to 1024 Hz
109   reg_write(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_1024);
110 }
111
112 // acknowledge RTC interrupt
113 PUBLIC static inline
114 void
115 Rtc::reset()
116 {
117   // reset irq by reading the cmos port
118   // do it fast because we are cli'd
119   asm volatile ("movb $0xc, %%al\n\t"
120                 "outb %%al,$0x70\n\t"
121                 "outb %%al,$0x80\n\t"
122                 "inb  $0x71,%%al\n\t" : : : "eax");
123 }
124