Expand USB OHCI support.
[seabios.git] / src / clock.c
1 // 16bit code to handle system clocks.
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002  MandrakeSoft S.A.
5 //
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
7
8 #include "biosvar.h" // SET_BDA
9 #include "util.h" // debug_enter
10 #include "disk.h" // floppy_tick
11 #include "cmos.h" // inb_cmos
12 #include "pic.h" // eoi_pic1
13 #include "bregs.h" // struct bregs
14 #include "biosvar.h" // GET_GLOBAL
15 #include "usb-hid.h" // usb_check_key
16
17 // RTC register flags
18 #define RTC_A_UIP 0x80
19
20 #define RTC_B_SET  0x80
21 #define RTC_B_PIE  0x40
22 #define RTC_B_AIE  0x20
23 #define RTC_B_UIE  0x10
24 #define RTC_B_BIN  0x04
25 #define RTC_B_24HR 0x02
26 #define RTC_B_DSE  0x01
27
28
29 // Bits for PORT_PS2_CTRLB
30 #define PPCB_T2GATE (1<<0)
31 #define PPCB_SPKR   (1<<1)
32 #define PPCB_T2OUT  (1<<5)
33
34 // Bits for PORT_PIT_MODE
35 #define PM_SEL_TIMER0   (0<<6)
36 #define PM_SEL_TIMER1   (1<<6)
37 #define PM_SEL_TIMER2   (2<<6)
38 #define PM_SEL_READBACK (3<<6)
39 #define PM_ACCESS_LATCH  (0<<4)
40 #define PM_ACCESS_LOBYTE (1<<4)
41 #define PM_ACCESS_HIBYTE (2<<4)
42 #define PM_ACCESS_WORD   (3<<4)
43 #define PM_MODE0 (0<<1)
44 #define PM_MODE1 (1<<1)
45 #define PM_MODE2 (2<<1)
46 #define PM_MODE3 (3<<1)
47 #define PM_MODE4 (4<<1)
48 #define PM_MODE5 (5<<1)
49 #define PM_CNT_BINARY (0<<0)
50 #define PM_CNT_BCD    (1<<0)
51
52
53 /****************************************************************
54  * TSC timer
55  ****************************************************************/
56
57 #define PIT_TICK_RATE 1193180   // Underlying HZ of PIT
58 #define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer
59 #define TICKS_PER_DAY (u32)((u64)60*60*24*PIT_TICK_RATE / PIT_TICK_INTERVAL)
60 #define CALIBRATE_COUNT 0x800   // Approx 1.7ms
61
62 u32 cpu_khz VAR16VISIBLE;
63
64 static void
65 calibrate_tsc()
66 {
67     // Setup "timer2"
68     u8 orig = inb(PORT_PS2_CTRLB);
69     outb((orig & ~PPCB_SPKR) | PPCB_T2GATE, PORT_PS2_CTRLB);
70     /* binary, mode 0, LSB/MSB, Ch 2 */
71     outb(PM_SEL_TIMER2|PM_ACCESS_WORD|PM_MODE0|PM_CNT_BINARY, PORT_PIT_MODE);
72     /* LSB of ticks */
73     outb(CALIBRATE_COUNT & 0xFF, PORT_PIT_COUNTER2);
74     /* MSB of ticks */
75     outb(CALIBRATE_COUNT >> 8, PORT_PIT_COUNTER2);
76
77     u64 start = rdtscll();
78     while ((inb(PORT_PS2_CTRLB) & PPCB_T2OUT) == 0)
79         ;
80     u64 end = rdtscll();
81
82     // Restore PORT_PS2_CTRLB
83     outb(orig, PORT_PS2_CTRLB);
84
85     // Store calibrated cpu khz.
86     u64 diff = end - start;
87     dprintf(6, "tsc calibrate start=%u end=%u diff=%u\n"
88             , (u32)start, (u32)end, (u32)diff);
89     u32 hz = diff * PIT_TICK_RATE / CALIBRATE_COUNT;
90     SET_GLOBAL(cpu_khz, hz / 1000);
91
92     dprintf(1, "CPU Mhz=%u\n", hz / 1000000);
93 }
94
95 static void
96 tscsleep(u64 diff)
97 {
98     u64 start = rdtscll();
99     u64 end = start + diff;
100     while (rdtscll() <= end)
101         cpu_relax();
102 }
103
104 void
105 ndelay(u32 count)
106 {
107     u32 khz = GET_GLOBAL(cpu_khz);
108     tscsleep(count * khz / 1000000);
109 }
110 void
111 udelay(u32 count)
112 {
113     u32 khz = GET_GLOBAL(cpu_khz);
114     tscsleep(count * khz / 1000);
115 }
116 void
117 mdelay(u32 count)
118 {
119     u32 khz = GET_GLOBAL(cpu_khz);
120     tscsleep(count * khz);
121 }
122
123 // Return the TSC value that is 'msecs' time in the future.
124 u64
125 calc_future_tsc(u32 msecs)
126 {
127     u32 khz = GET_GLOBAL(cpu_khz);
128     return rdtscll() + ((u64)khz * msecs);
129 }
130 u64
131 calc_future_tsc_usec(u32 usecs)
132 {
133     u32 khz = GET_GLOBAL(cpu_khz);
134     return rdtscll() + ((u64)(khz/1000) * usecs);
135 }
136
137
138 /****************************************************************
139  * Init
140  ****************************************************************/
141
142 static int
143 rtc_updating()
144 {
145     // This function checks to see if the update-in-progress bit
146     // is set in CMOS Status Register A.  If not, it returns 0.
147     // If it is set, it tries to wait until there is a transition
148     // to 0, and will return 0 if such a transition occurs.  A -1
149     // is returned only after timing out.  The maximum period
150     // that this bit should be set is constrained to (1984+244)
151     // useconds, so we wait for 3 msec max.
152
153     if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
154         return 0;
155     u64 end = calc_future_tsc(3);
156     do {
157         if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
158             return 0;
159     } while (rdtscll() <= end);
160
161     // update-in-progress never transitioned to 0
162     return -1;
163 }
164
165 static void
166 pit_setup()
167 {
168     // timer0: binary count, 16bit count, mode 2
169     outb(PM_SEL_TIMER0|PM_ACCESS_WORD|PM_MODE2|PM_CNT_BINARY, PORT_PIT_MODE);
170     // maximum count of 0000H = 18.2Hz
171     outb(0x0, PORT_PIT_COUNTER0);
172     outb(0x0, PORT_PIT_COUNTER0);
173 }
174
175 static void
176 init_rtc()
177 {
178     outb_cmos(0x26, CMOS_STATUS_A);    // 32,768Khz src, 976.5625us updates
179     u8 regB = inb_cmos(CMOS_STATUS_B);
180     outb_cmos((regB & RTC_B_DSE) | RTC_B_24HR, CMOS_STATUS_B);
181     inb_cmos(CMOS_STATUS_C);
182     inb_cmos(CMOS_STATUS_D);
183 }
184
185 static u32
186 bcd2bin(u8 val)
187 {
188     return (val & 0xf) + ((val >> 4) * 10);
189 }
190
191 void
192 timer_setup()
193 {
194     dprintf(3, "init timer\n");
195     calibrate_tsc();
196     pit_setup();
197
198     init_rtc();
199     rtc_updating();
200     u32 seconds = bcd2bin(inb_cmos(CMOS_RTC_SECONDS));
201     u32 minutes = bcd2bin(inb_cmos(CMOS_RTC_MINUTES));
202     u32 hours = bcd2bin(inb_cmos(CMOS_RTC_HOURS));
203     u32 ticks = (hours * 60 + minutes) * 60 + seconds;
204     ticks = ((u64)ticks * PIT_TICK_RATE) / PIT_TICK_INTERVAL;
205     SET_BDA(timer_counter, ticks);
206     SET_BDA(timer_rollover, 0);
207
208     enable_hwirq(0, entry_08);
209     enable_hwirq(8, entry_70);
210 }
211
212
213 /****************************************************************
214  * Standard clock functions
215  ****************************************************************/
216
217 // get current clock count
218 static void
219 handle_1a00(struct bregs *regs)
220 {
221     u32 ticks = GET_BDA(timer_counter);
222     regs->cx = ticks >> 16;
223     regs->dx = ticks;
224     regs->al = GET_BDA(timer_rollover);
225     SET_BDA(timer_rollover, 0); // reset flag
226     set_success(regs);
227 }
228
229 // Set Current Clock Count
230 static void
231 handle_1a01(struct bregs *regs)
232 {
233     u32 ticks = (regs->cx << 16) | regs->dx;
234     SET_BDA(timer_counter, ticks);
235     SET_BDA(timer_rollover, 0); // reset flag
236     // XXX - should use set_code_success()?
237     regs->ah = 0;
238     set_success(regs);
239 }
240
241 // Read CMOS Time
242 static void
243 handle_1a02(struct bregs *regs)
244 {
245     if (rtc_updating()) {
246         set_fail(regs);
247         return;
248     }
249
250     regs->dh = inb_cmos(CMOS_RTC_SECONDS);
251     regs->cl = inb_cmos(CMOS_RTC_MINUTES);
252     regs->ch = inb_cmos(CMOS_RTC_HOURS);
253     regs->dl = inb_cmos(CMOS_STATUS_B) & RTC_B_DSE;
254     regs->ah = 0;
255     regs->al = regs->ch;
256     set_success(regs);
257 }
258
259 // Set CMOS Time
260 static void
261 handle_1a03(struct bregs *regs)
262 {
263     // Using a debugger, I notice the following masking/setting
264     // of bits in Status Register B, by setting Reg B to
265     // a few values and getting its value after INT 1A was called.
266     //
267     //        try#1       try#2       try#3
268     // before 1111 1101   0111 1101   0000 0000
269     // after  0110 0010   0110 0010   0000 0010
270     //
271     // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
272     // My assumption: RegB = ((RegB & 01100000b) | 00000010b)
273     if (rtc_updating()) {
274         init_rtc();
275         // fall through as if an update were not in progress
276     }
277     outb_cmos(regs->dh, CMOS_RTC_SECONDS);
278     outb_cmos(regs->cl, CMOS_RTC_MINUTES);
279     outb_cmos(regs->ch, CMOS_RTC_HOURS);
280     // Set Daylight Savings time enabled bit to requested value
281     u8 val8 = ((inb_cmos(CMOS_STATUS_B) & (RTC_B_PIE|RTC_B_AIE))
282                | RTC_B_24HR | (regs->dl & RTC_B_DSE));
283     outb_cmos(val8, CMOS_STATUS_B);
284     regs->ah = 0;
285     regs->al = val8; // val last written to Reg B
286     set_success(regs);
287 }
288
289 // Read CMOS Date
290 static void
291 handle_1a04(struct bregs *regs)
292 {
293     regs->ah = 0;
294     if (rtc_updating()) {
295         set_fail(regs);
296         return;
297     }
298     regs->cl = inb_cmos(CMOS_RTC_YEAR);
299     regs->dh = inb_cmos(CMOS_RTC_MONTH);
300     regs->dl = inb_cmos(CMOS_RTC_DAY_MONTH);
301     if (CONFIG_COREBOOT) {
302         if (regs->cl > 0x80)
303             regs->ch = 0x19;
304         else
305             regs->ch = 0x20;
306     } else {
307         regs->ch = inb_cmos(CMOS_CENTURY);
308     }
309     regs->al = regs->ch;
310     set_success(regs);
311 }
312
313 // Set CMOS Date
314 static void
315 handle_1a05(struct bregs *regs)
316 {
317     // Using a debugger, I notice the following masking/setting
318     // of bits in Status Register B, by setting Reg B to
319     // a few values and getting its value after INT 1A was called.
320     //
321     //        try#1       try#2       try#3       try#4
322     // before 1111 1101   0111 1101   0000 0010   0000 0000
323     // after  0110 1101   0111 1101   0000 0010   0000 0000
324     //
325     // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
326     // My assumption: RegB = (RegB & 01111111b)
327     if (rtc_updating()) {
328         init_rtc();
329         set_fail(regs);
330         return;
331     }
332     outb_cmos(regs->cl, CMOS_RTC_YEAR);
333     outb_cmos(regs->dh, CMOS_RTC_MONTH);
334     outb_cmos(regs->dl, CMOS_RTC_DAY_MONTH);
335     if (!CONFIG_COREBOOT)
336         outb_cmos(regs->ch, CMOS_CENTURY);
337     // clear halt-clock bit
338     u8 val8 = inb_cmos(CMOS_STATUS_B) & ~RTC_B_SET;
339     outb_cmos(val8, CMOS_STATUS_B);
340     regs->ah = 0;
341     regs->al = val8; // AL = val last written to Reg B
342     set_success(regs);
343 }
344
345 // Set Alarm Time in CMOS
346 static void
347 handle_1a06(struct bregs *regs)
348 {
349     // Using a debugger, I notice the following masking/setting
350     // of bits in Status Register B, by setting Reg B to
351     // a few values and getting its value after INT 1A was called.
352     //
353     //        try#1       try#2       try#3
354     // before 1101 1111   0101 1111   0000 0000
355     // after  0110 1111   0111 1111   0010 0000
356     //
357     // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
358     // My assumption: RegB = ((RegB & 01111111b) | 00100000b)
359     u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B
360     regs->ax = 0;
361     if (val8 & RTC_B_AIE) {
362         // Alarm interrupt enabled already
363         set_fail(regs);
364         return;
365     }
366     if (rtc_updating()) {
367         init_rtc();
368         // fall through as if an update were not in progress
369     }
370     outb_cmos(regs->dh, CMOS_RTC_SECONDS_ALARM);
371     outb_cmos(regs->cl, CMOS_RTC_MINUTES_ALARM);
372     outb_cmos(regs->ch, CMOS_RTC_HOURS_ALARM);
373     // enable Status Reg B alarm bit, clear halt clock bit
374     outb_cmos((val8 & ~RTC_B_SET) | RTC_B_AIE, CMOS_STATUS_B);
375     set_success(regs);
376 }
377
378 // Turn off Alarm
379 static void
380 handle_1a07(struct bregs *regs)
381 {
382     // Using a debugger, I notice the following masking/setting
383     // of bits in Status Register B, by setting Reg B to
384     // a few values and getting its value after INT 1A was called.
385     //
386     //        try#1       try#2       try#3       try#4
387     // before 1111 1101   0111 1101   0010 0000   0010 0010
388     // after  0100 0101   0101 0101   0000 0000   0000 0010
389     //
390     // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
391     // My assumption: RegB = (RegB & 01010111b)
392     u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B
393     // clear clock-halt bit, disable alarm bit
394     outb_cmos(val8 & ~(RTC_B_SET|RTC_B_AIE), CMOS_STATUS_B);
395     regs->ah = 0;
396     regs->al = val8; // val last written to Reg B
397     set_success(regs);
398 }
399
400 // Unsupported
401 static void
402 handle_1aXX(struct bregs *regs)
403 {
404     set_fail(regs);
405 }
406
407 // INT 1Ah Time-of-day Service Entry Point
408 void VISIBLE16
409 handle_1a(struct bregs *regs)
410 {
411     debug_enter(regs, DEBUG_HDL_1a);
412     switch (regs->ah) {
413     case 0x00: handle_1a00(regs); break;
414     case 0x01: handle_1a01(regs); break;
415     case 0x02: handle_1a02(regs); break;
416     case 0x03: handle_1a03(regs); break;
417     case 0x04: handle_1a04(regs); break;
418     case 0x05: handle_1a05(regs); break;
419     case 0x06: handle_1a06(regs); break;
420     case 0x07: handle_1a07(regs); break;
421     case 0xb1: handle_1ab1(regs); break;
422     default:   handle_1aXX(regs); break;
423     }
424 }
425
426 // INT 08h System Timer ISR Entry Point
427 void VISIBLE16
428 handle_08()
429 {
430     debug_isr(DEBUG_ISR_08);
431
432     floppy_tick();
433
434     u32 counter = GET_BDA(timer_counter);
435     counter++;
436     // compare to one days worth of timer ticks at 18.2 hz
437     if (counter >= TICKS_PER_DAY) {
438         // there has been a midnight rollover at this point
439         counter = 0;
440         SET_BDA(timer_rollover, GET_BDA(timer_rollover) + 1);
441     }
442
443     SET_BDA(timer_counter, counter);
444
445     usb_check_key();
446
447     // chain to user timer tick INT #0x1c
448     u32 eax=0, flags;
449     call16_simpint(0x1c, &eax, &flags);
450
451     eoi_pic1();
452 }
453
454
455 /****************************************************************
456  * Periodic timer
457  ****************************************************************/
458
459 static int
460 set_usertimer(u32 usecs, u16 seg, u16 offset)
461 {
462     if (GET_BDA(rtc_wait_flag) & RWS_WAIT_PENDING)
463         return -1;
464
465     // Interval not already set.
466     SET_BDA(rtc_wait_flag, RWS_WAIT_PENDING);  // Set status byte.
467     SET_BDA(user_wait_complete_flag, SEGOFF(seg, offset));
468     SET_BDA(user_wait_timeout, usecs);
469
470     // Turn on the Periodic Interrupt timer
471     u8 bRegister = inb_cmos(CMOS_STATUS_B);
472     outb_cmos(bRegister | RTC_B_PIE, CMOS_STATUS_B);
473
474     return 0;
475 }
476
477 static void
478 clear_usertimer()
479 {
480     // Turn off status byte.
481     SET_BDA(rtc_wait_flag, 0);
482     // Clear the Periodic Interrupt.
483     u8 bRegister = inb_cmos(CMOS_STATUS_B);
484     outb_cmos(bRegister & ~RTC_B_PIE, CMOS_STATUS_B);
485 }
486
487 #define RET_ECLOCKINUSE  0x83
488
489 // Wait for CX:DX microseconds
490 void
491 handle_1586(struct bregs *regs)
492 {
493     // Use the rtc to wait for the specified time.
494     u8 statusflag = 0;
495     u32 count = (regs->cx << 16) | regs->dx;
496     int ret = set_usertimer(count, GET_SEG(SS), (u32)&statusflag);
497     if (ret) {
498         set_code_fail(regs, RET_ECLOCKINUSE);
499         return;
500     }
501     while (!statusflag)
502         wait_irq();
503     set_success(regs);
504 }
505
506 // Set Interval requested.
507 static void
508 handle_158300(struct bregs *regs)
509 {
510     int ret = set_usertimer((regs->cx << 16) | regs->dx, regs->es, regs->bx);
511     if (ret)
512         // Interval already set.
513         set_code_fail(regs, RET_EUNSUPPORTED);
514     else
515         set_success(regs);
516 }
517
518 // Clear interval requested
519 static void
520 handle_158301(struct bregs *regs)
521 {
522     clear_usertimer();
523     set_success(regs);
524 }
525
526 static void
527 handle_1583XX(struct bregs *regs)
528 {
529     set_code_fail(regs, RET_EUNSUPPORTED);
530     regs->al--;
531 }
532
533 void
534 handle_1583(struct bregs *regs)
535 {
536     switch (regs->al) {
537     case 0x00: handle_158300(regs); break;
538     case 0x01: handle_158301(regs); break;
539     default:   handle_1583XX(regs); break;
540     }
541 }
542
543 #define USEC_PER_RTC DIV_ROUND_CLOSEST(1000000, 1024)
544
545 // int70h: IRQ8 - CMOS RTC
546 void VISIBLE16
547 handle_70()
548 {
549     debug_isr(DEBUG_ISR_70);
550
551     // Check which modes are enabled and have occurred.
552     u8 registerB = inb_cmos(CMOS_STATUS_B);
553     u8 registerC = inb_cmos(CMOS_STATUS_C);
554
555     if (!(registerB & (RTC_B_PIE|RTC_B_AIE)))
556         goto done;
557     if (registerC & RTC_B_AIE) {
558         // Handle Alarm Interrupt.
559         u32 eax=0, flags;
560         call16_simpint(0x4a, &eax, &flags);
561     }
562     if (!(registerC & RTC_B_PIE))
563         goto done;
564
565     // Handle Periodic Interrupt.
566
567     if (!GET_BDA(rtc_wait_flag))
568         goto done;
569
570     // Wait Interval (Int 15, AH=83) active.
571     u32 time = GET_BDA(user_wait_timeout);  // Time left in microseconds.
572     if (time < USEC_PER_RTC) {
573         // Done waiting - write to specified flag byte.
574         struct segoff_s segoff = GET_BDA(user_wait_complete_flag);
575         u16 ptr_seg = segoff.seg;
576         u8 *ptr_far = (u8*)(segoff.offset+0);
577         u8 oldval = GET_FARVAR(ptr_seg, *ptr_far);
578         SET_FARVAR(ptr_seg, *ptr_far, oldval | 0x80);
579
580         clear_usertimer();
581     } else {
582         // Continue waiting.
583         time -= USEC_PER_RTC;
584         SET_BDA(user_wait_timeout, time);
585     }
586
587 done:
588     eoi_pic2();
589 }