This source file includes following definitions.
- lapicw
- lapicinit
- lapicid
- lapiceoi
- microdelay
- lapicstartap
- cmos_read
- fill_rtcdate
- cmostime
1
2
3
4 #include "param.h"
5 #include "types.h"
6 #include "defs.h"
7 #include "date.h"
8 #include "memlayout.h"
9 #include "traps.h"
10 #include "mmu.h"
11 #include "x86.h"
12
13
14 #define ID (0x0020/4)
15 #define VER (0x0030/4)
16 #define TPR (0x0080/4)
17 #define EOI (0x00B0/4)
18 #define SVR (0x00F0/4)
19 #define ENABLE 0x00000100
20 #define ESR (0x0280/4)
21 #define ICRLO (0x0300/4)
22 #define INIT 0x00000500
23 #define STARTUP 0x00000600
24 #define DELIVS 0x00001000
25 #define ASSERT 0x00004000
26 #define DEASSERT 0x00000000
27 #define LEVEL 0x00008000
28 #define BCAST 0x00080000
29 #define BUSY 0x00001000
30 #define FIXED 0x00000000
31 #define ICRHI (0x0310/4)
32 #define TIMER (0x0320/4)
33 #define X1 0x0000000B
34 #define PERIODIC 0x00020000
35 #define PCINT (0x0340/4)
36 #define LINT0 (0x0350/4)
37 #define LINT1 (0x0360/4)
38 #define ERROR (0x0370/4)
39 #define MASKED 0x00010000
40 #define TICR (0x0380/4)
41 #define TCCR (0x0390/4)
42 #define TDCR (0x03E0/4)
43
44 volatile uint *lapic;
45
46
47 static void
48 lapicw(int index, int value)
49 {
50 lapic[index] = value;
51 lapic[ID];
52 }
53
54 void
55 lapicinit(void)
56 {
57 if(!lapic)
58 return;
59
60
61 lapicw(SVR, ENABLE | (T_IRQ0 + IRQ_SPURIOUS));
62
63
64
65
66
67 lapicw(TDCR, X1);
68 lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));
69 lapicw(TICR, 10000000);
70
71
72 lapicw(LINT0, MASKED);
73 lapicw(LINT1, MASKED);
74
75
76
77 if(((lapic[VER]>>16) & 0xFF) >= 4)
78 lapicw(PCINT, MASKED);
79
80
81 lapicw(ERROR, T_IRQ0 + IRQ_ERROR);
82
83
84 lapicw(ESR, 0);
85 lapicw(ESR, 0);
86
87
88 lapicw(EOI, 0);
89
90
91 lapicw(ICRHI, 0);
92 lapicw(ICRLO, BCAST | INIT | LEVEL);
93 while(lapic[ICRLO] & DELIVS)
94 ;
95
96
97 lapicw(TPR, 0);
98 }
99
100 int
101 lapicid(void)
102 {
103 if (!lapic)
104 return 0;
105 return lapic[ID] >> 24;
106 }
107
108
109 void
110 lapiceoi(void)
111 {
112 if(lapic)
113 lapicw(EOI, 0);
114 }
115
116
117
118 void
119 microdelay(int us)
120 {
121 }
122
123 #define CMOS_PORT 0x70
124 #define CMOS_RETURN 0x71
125
126
127
128 void
129 lapicstartap(uchar apicid, uint addr)
130 {
131 int i;
132 ushort *wrv;
133
134
135
136
137 outb(CMOS_PORT, 0xF);
138 outb(CMOS_PORT+1, 0x0A);
139 wrv = (ushort*)P2V((0x40<<4 | 0x67));
140 wrv[0] = 0;
141 wrv[1] = addr >> 4;
142
143
144
145 lapicw(ICRHI, apicid<<24);
146 lapicw(ICRLO, INIT | LEVEL | ASSERT);
147 microdelay(200);
148 lapicw(ICRLO, INIT | LEVEL);
149 microdelay(100);
150
151
152
153
154
155
156 for(i = 0; i < 2; i++){
157 lapicw(ICRHI, apicid<<24);
158 lapicw(ICRLO, STARTUP | (addr>>12));
159 microdelay(200);
160 }
161 }
162
163 #define CMOS_STATA 0x0a
164 #define CMOS_STATB 0x0b
165 #define CMOS_UIP (1 << 7)
166
167 #define SECS 0x00
168 #define MINS 0x02
169 #define HOURS 0x04
170 #define DAY 0x07
171 #define MONTH 0x08
172 #define YEAR 0x09
173
174 static uint
175 cmos_read(uint reg)
176 {
177 outb(CMOS_PORT, reg);
178 microdelay(200);
179
180 return inb(CMOS_RETURN);
181 }
182
183 static void
184 fill_rtcdate(struct rtcdate *r)
185 {
186 r->second = cmos_read(SECS);
187 r->minute = cmos_read(MINS);
188 r->hour = cmos_read(HOURS);
189 r->day = cmos_read(DAY);
190 r->month = cmos_read(MONTH);
191 r->year = cmos_read(YEAR);
192 }
193
194
195 void
196 cmostime(struct rtcdate *r)
197 {
198 struct rtcdate t1, t2;
199 int sb, bcd;
200
201 sb = cmos_read(CMOS_STATB);
202
203 bcd = (sb & (1 << 2)) == 0;
204
205
206 for(;;) {
207 fill_rtcdate(&t1);
208 if(cmos_read(CMOS_STATA) & CMOS_UIP)
209 continue;
210 fill_rtcdate(&t2);
211 if(memcmp(&t1, &t2, sizeof(t1)) == 0)
212 break;
213 }
214
215
216 if(bcd) {
217 #define CONV(x) (t1.x = ((t1.x >> 4) * 10) + (t1.x & 0xf))
218 CONV(second);
219 CONV(minute);
220 CONV(hour );
221 CONV(day );
222 CONV(month );
223 CONV(year );
224 #undef CONV
225 }
226
227 *r = t1;
228 r->year += 2000;
229 }