1
// 16bit code to handle system clocks.
3
// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4
// Copyright (C) 2002 MandrakeSoft S.A.
6
// This file may be distributed under the terms of the GNU LGPLv3 license.
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_event
18
#define RTC_A_UIP 0x80
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
29
// Bits for PORT_PS2_CTRLB
30
#define PPCB_T2GATE (1<<0)
31
#define PPCB_SPKR (1<<1)
32
#define PPCB_T2OUT (1<<5)
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)
53
/****************************************************************
55
****************************************************************/
57
#define CALIBRATE_COUNT 0x800 // Approx 1.7ms
59
u32 cpu_khz VAR16VISIBLE;
65
u8 orig = inb(PORT_PS2_CTRLB);
66
outb((orig & ~PPCB_SPKR) | PPCB_T2GATE, PORT_PS2_CTRLB);
67
/* binary, mode 0, LSB/MSB, Ch 2 */
68
outb(PM_SEL_TIMER2|PM_ACCESS_WORD|PM_MODE0|PM_CNT_BINARY, PORT_PIT_MODE);
70
outb(CALIBRATE_COUNT & 0xFF, PORT_PIT_COUNTER2);
72
outb(CALIBRATE_COUNT >> 8, PORT_PIT_COUNTER2);
74
u64 start = rdtscll();
75
while ((inb(PORT_PS2_CTRLB) & PPCB_T2OUT) == 0)
79
// Restore PORT_PS2_CTRLB
80
outb(orig, PORT_PS2_CTRLB);
82
// Store calibrated cpu khz.
83
u64 diff = end - start;
84
dprintf(6, "tsc calibrate start=%u end=%u diff=%u\n"
85
, (u32)start, (u32)end, (u32)diff);
86
u32 hz = diff * PIT_TICK_RATE / CALIBRATE_COUNT;
87
SET_GLOBAL(cpu_khz, hz / 1000);
89
dprintf(1, "CPU Mhz=%u\n", hz / 1000000);
95
u64 start = rdtscll();
96
u64 end = start + diff;
97
while (!check_tsc(end))
104
u64 start = rdtscll();
105
u64 end = start + diff;
106
while (!check_tsc(end))
110
void ndelay(u32 count) {
111
tscdelay(count * GET_GLOBAL(cpu_khz) / 1000000);
113
void udelay(u32 count) {
114
tscdelay(count * GET_GLOBAL(cpu_khz) / 1000);
116
void mdelay(u32 count) {
117
tscdelay(count * GET_GLOBAL(cpu_khz));
120
void nsleep(u32 count) {
121
tscsleep(count * GET_GLOBAL(cpu_khz) / 1000000);
123
void usleep(u32 count) {
124
tscsleep(count * GET_GLOBAL(cpu_khz) / 1000);
126
void msleep(u32 count) {
127
tscsleep(count * GET_GLOBAL(cpu_khz));
130
// Return the TSC value that is 'msecs' time in the future.
132
calc_future_tsc(u32 msecs)
134
u32 khz = GET_GLOBAL(cpu_khz);
135
return rdtscll() + ((u64)khz * msecs);
138
calc_future_tsc_usec(u32 usecs)
140
u32 khz = GET_GLOBAL(cpu_khz);
141
return rdtscll() + ((u64)(khz/1000) * usecs);
145
/****************************************************************
147
****************************************************************/
152
// This function checks to see if the update-in-progress bit
153
// is set in CMOS Status Register A. If not, it returns 0.
154
// If it is set, it tries to wait until there is a transition
155
// to 0, and will return 0 if such a transition occurs. A -1
156
// is returned only after timing out. The maximum period
157
// that this bit should be set is constrained to (1984+244)
158
// useconds, but we wait for longer just to be sure.
160
if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
162
u64 end = calc_future_tsc(15);
164
if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
167
// update-in-progress never transitioned to 0
176
// timer0: binary count, 16bit count, mode 2
177
outb(PM_SEL_TIMER0|PM_ACCESS_WORD|PM_MODE2|PM_CNT_BINARY, PORT_PIT_MODE);
178
// maximum count of 0000H = 18.2Hz
179
outb(0x0, PORT_PIT_COUNTER0);
180
outb(0x0, PORT_PIT_COUNTER0);
186
outb_cmos(0x26, CMOS_STATUS_A); // 32,768Khz src, 976.5625us updates
187
u8 regB = inb_cmos(CMOS_STATUS_B);
188
outb_cmos((regB & RTC_B_DSE) | RTC_B_24HR, CMOS_STATUS_B);
189
inb_cmos(CMOS_STATUS_C);
190
inb_cmos(CMOS_STATUS_D);
196
return (val & 0xf) + ((val >> 4) * 10);
202
dprintf(3, "init timer\n");
208
u32 seconds = bcd2bin(inb_cmos(CMOS_RTC_SECONDS));
209
u32 minutes = bcd2bin(inb_cmos(CMOS_RTC_MINUTES));
210
u32 hours = bcd2bin(inb_cmos(CMOS_RTC_HOURS));
211
u32 ticks = (hours * 60 + minutes) * 60 + seconds;
212
ticks = ((u64)ticks * PIT_TICK_RATE) / PIT_TICK_INTERVAL;
213
SET_BDA(timer_counter, ticks);
214
SET_BDA(timer_rollover, 0);
216
enable_hwirq(0, entry_08);
217
enable_hwirq(8, entry_70);
221
/****************************************************************
222
* Standard clock functions
223
****************************************************************/
225
#define TICKS_PER_DAY (u32)((u64)60*60*24*PIT_TICK_RATE / PIT_TICK_INTERVAL)
227
// Calculate the timer value at 'count' number of full timer ticks in
230
calc_future_timer_ticks(u32 count)
232
return (GET_BDA(timer_counter) + count + 1) % TICKS_PER_DAY;
234
// Return the timer value that is 'msecs' time in the future.
236
calc_future_timer(u32 msecs)
238
u32 kticks = DIV_ROUND_UP((u64)(msecs * PIT_TICK_RATE), PIT_TICK_INTERVAL);
239
u32 ticks = DIV_ROUND_UP(kticks, 1000);
240
return calc_future_timer_ticks(ticks);
242
// Check if the given timer value has passed.
246
return (((GET_BDA(timer_counter) + TICKS_PER_DAY - end) % TICKS_PER_DAY)
247
< (TICKS_PER_DAY/2));
250
// get current clock count
252
handle_1a00(struct bregs *regs)
255
u32 ticks = GET_BDA(timer_counter);
256
regs->cx = ticks >> 16;
258
regs->al = GET_BDA(timer_rollover);
259
SET_BDA(timer_rollover, 0); // reset flag
263
// Set Current Clock Count
265
handle_1a01(struct bregs *regs)
267
u32 ticks = (regs->cx << 16) | regs->dx;
268
SET_BDA(timer_counter, ticks);
269
SET_BDA(timer_rollover, 0); // reset flag
270
// XXX - should use set_code_success()?
277
handle_1a02(struct bregs *regs)
279
if (rtc_updating()) {
284
regs->dh = inb_cmos(CMOS_RTC_SECONDS);
285
regs->cl = inb_cmos(CMOS_RTC_MINUTES);
286
regs->ch = inb_cmos(CMOS_RTC_HOURS);
287
regs->dl = inb_cmos(CMOS_STATUS_B) & RTC_B_DSE;
295
handle_1a03(struct bregs *regs)
297
// Using a debugger, I notice the following masking/setting
298
// of bits in Status Register B, by setting Reg B to
299
// a few values and getting its value after INT 1A was called.
302
// before 1111 1101 0111 1101 0000 0000
303
// after 0110 0010 0110 0010 0000 0010
305
// Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
306
// My assumption: RegB = ((RegB & 01100000b) | 00000010b)
307
if (rtc_updating()) {
309
// fall through as if an update were not in progress
311
outb_cmos(regs->dh, CMOS_RTC_SECONDS);
312
outb_cmos(regs->cl, CMOS_RTC_MINUTES);
313
outb_cmos(regs->ch, CMOS_RTC_HOURS);
314
// Set Daylight Savings time enabled bit to requested value
315
u8 val8 = ((inb_cmos(CMOS_STATUS_B) & (RTC_B_PIE|RTC_B_AIE))
316
| RTC_B_24HR | (regs->dl & RTC_B_DSE));
317
outb_cmos(val8, CMOS_STATUS_B);
319
regs->al = val8; // val last written to Reg B
325
handle_1a04(struct bregs *regs)
328
if (rtc_updating()) {
332
regs->cl = inb_cmos(CMOS_RTC_YEAR);
333
regs->dh = inb_cmos(CMOS_RTC_MONTH);
334
regs->dl = inb_cmos(CMOS_RTC_DAY_MONTH);
335
if (CONFIG_COREBOOT) {
341
regs->ch = inb_cmos(CMOS_CENTURY);
349
handle_1a05(struct bregs *regs)
351
// Using a debugger, I notice the following masking/setting
352
// of bits in Status Register B, by setting Reg B to
353
// a few values and getting its value after INT 1A was called.
355
// try#1 try#2 try#3 try#4
356
// before 1111 1101 0111 1101 0000 0010 0000 0000
357
// after 0110 1101 0111 1101 0000 0010 0000 0000
359
// Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
360
// My assumption: RegB = (RegB & 01111111b)
361
if (rtc_updating()) {
366
outb_cmos(regs->cl, CMOS_RTC_YEAR);
367
outb_cmos(regs->dh, CMOS_RTC_MONTH);
368
outb_cmos(regs->dl, CMOS_RTC_DAY_MONTH);
369
if (!CONFIG_COREBOOT)
370
outb_cmos(regs->ch, CMOS_CENTURY);
371
// clear halt-clock bit
372
u8 val8 = inb_cmos(CMOS_STATUS_B) & ~RTC_B_SET;
373
outb_cmos(val8, CMOS_STATUS_B);
375
regs->al = val8; // AL = val last written to Reg B
379
// Set Alarm Time in CMOS
381
handle_1a06(struct bregs *regs)
383
// Using a debugger, I notice the following masking/setting
384
// of bits in Status Register B, by setting Reg B to
385
// a few values and getting its value after INT 1A was called.
388
// before 1101 1111 0101 1111 0000 0000
389
// after 0110 1111 0111 1111 0010 0000
391
// Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
392
// My assumption: RegB = ((RegB & 01111111b) | 00100000b)
393
u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B
395
if (val8 & RTC_B_AIE) {
396
// Alarm interrupt enabled already
400
if (rtc_updating()) {
402
// fall through as if an update were not in progress
404
outb_cmos(regs->dh, CMOS_RTC_SECONDS_ALARM);
405
outb_cmos(regs->cl, CMOS_RTC_MINUTES_ALARM);
406
outb_cmos(regs->ch, CMOS_RTC_HOURS_ALARM);
407
// enable Status Reg B alarm bit, clear halt clock bit
408
outb_cmos((val8 & ~RTC_B_SET) | RTC_B_AIE, CMOS_STATUS_B);
414
handle_1a07(struct bregs *regs)
416
// Using a debugger, I notice the following masking/setting
417
// of bits in Status Register B, by setting Reg B to
418
// a few values and getting its value after INT 1A was called.
420
// try#1 try#2 try#3 try#4
421
// before 1111 1101 0111 1101 0010 0000 0010 0010
422
// after 0100 0101 0101 0101 0000 0000 0000 0010
424
// Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
425
// My assumption: RegB = (RegB & 01010111b)
426
u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B
427
// clear clock-halt bit, disable alarm bit
428
outb_cmos(val8 & ~(RTC_B_SET|RTC_B_AIE), CMOS_STATUS_B);
430
regs->al = val8; // val last written to Reg B
436
handle_1aXX(struct bregs *regs)
438
set_unimplemented(regs);
441
// INT 1Ah Time-of-day Service Entry Point
443
handle_1a(struct bregs *regs)
445
debug_enter(regs, DEBUG_HDL_1a);
447
case 0x00: handle_1a00(regs); break;
448
case 0x01: handle_1a01(regs); break;
449
case 0x02: handle_1a02(regs); break;
450
case 0x03: handle_1a03(regs); break;
451
case 0x04: handle_1a04(regs); break;
452
case 0x05: handle_1a05(regs); break;
453
case 0x06: handle_1a06(regs); break;
454
case 0x07: handle_1a07(regs); break;
455
case 0xb1: handle_1ab1(regs); break;
456
default: handle_1aXX(regs); break;
460
// INT 08h System Timer ISR Entry Point
464
debug_isr(DEBUG_ISR_08);
468
u32 counter = GET_BDA(timer_counter);
470
// compare to one days worth of timer ticks at 18.2 hz
471
if (counter >= TICKS_PER_DAY) {
472
// there has been a midnight rollover at this point
474
SET_BDA(timer_rollover, GET_BDA(timer_rollover) + 1);
477
SET_BDA(timer_counter, counter);
481
// chain to user timer tick INT #0x1c
483
call16_simpint(0x1c, &eax, &flags);
489
/****************************************************************
491
****************************************************************/
496
u16 ebda_seg = get_ebda_seg();
497
int count = GET_EBDA2(ebda_seg, RTCusers);
498
SET_EBDA2(ebda_seg, RTCusers, count+1);
501
// Turn on the Periodic Interrupt timer
502
u8 bRegister = inb_cmos(CMOS_STATUS_B);
503
outb_cmos(bRegister | RTC_B_PIE, CMOS_STATUS_B);
509
u16 ebda_seg = get_ebda_seg();
510
int count = GET_EBDA2(ebda_seg, RTCusers);
511
SET_EBDA2(ebda_seg, RTCusers, count-1);
514
// Clear the Periodic Interrupt.
515
u8 bRegister = inb_cmos(CMOS_STATUS_B);
516
outb_cmos(bRegister & ~RTC_B_PIE, CMOS_STATUS_B);
520
set_usertimer(u32 usecs, u16 seg, u16 offset)
522
if (GET_BDA(rtc_wait_flag) & RWS_WAIT_PENDING)
525
// Interval not already set.
526
SET_BDA(rtc_wait_flag, RWS_WAIT_PENDING); // Set status byte.
527
SET_BDA(user_wait_complete_flag, SEGOFF(seg, offset));
528
SET_BDA(user_wait_timeout, usecs);
534
clear_usertimer(void)
536
if (!(GET_BDA(rtc_wait_flag) & RWS_WAIT_PENDING))
538
// Turn off status byte.
539
SET_BDA(rtc_wait_flag, 0);
543
#define RET_ECLOCKINUSE 0x83
545
// Wait for CX:DX microseconds
547
handle_1586(struct bregs *regs)
549
// Use the rtc to wait for the specified time.
551
u32 count = (regs->cx << 16) | regs->dx;
552
int ret = set_usertimer(count, GET_SEG(SS), (u32)&statusflag);
554
set_code_invalid(regs, RET_ECLOCKINUSE);
562
// Set Interval requested.
564
handle_158300(struct bregs *regs)
566
int ret = set_usertimer((regs->cx << 16) | regs->dx, regs->es, regs->bx);
568
// Interval already set.
569
set_code_invalid(regs, RET_EUNSUPPORTED);
574
// Clear interval requested
576
handle_158301(struct bregs *regs)
583
handle_1583XX(struct bregs *regs)
585
set_code_unimplemented(regs, RET_EUNSUPPORTED);
590
handle_1583(struct bregs *regs)
593
case 0x00: handle_158300(regs); break;
594
case 0x01: handle_158301(regs); break;
595
default: handle_1583XX(regs); break;
599
#define USEC_PER_RTC DIV_ROUND_CLOSEST(1000000, 1024)
601
// int70h: IRQ8 - CMOS RTC
605
debug_isr(DEBUG_ISR_70);
607
// Check which modes are enabled and have occurred.
608
u8 registerB = inb_cmos(CMOS_STATUS_B);
609
u8 registerC = inb_cmos(CMOS_STATUS_C);
611
if (!(registerB & (RTC_B_PIE|RTC_B_AIE)))
613
if (registerC & RTC_B_AIE) {
614
// Handle Alarm Interrupt.
616
call16_simpint(0x4a, &eax, &flags);
618
if (!(registerC & RTC_B_PIE))
621
// Handle Periodic Interrupt.
625
if (!GET_BDA(rtc_wait_flag))
628
// Wait Interval (Int 15, AH=83) active.
629
u32 time = GET_BDA(user_wait_timeout); // Time left in microseconds.
630
if (time < USEC_PER_RTC) {
631
// Done waiting - write to specified flag byte.
632
struct segoff_s segoff = GET_BDA(user_wait_complete_flag);
633
u16 ptr_seg = segoff.seg;
634
u8 *ptr_far = (u8*)(segoff.offset+0);
635
u8 oldval = GET_FARVAR(ptr_seg, *ptr_far);
636
SET_FARVAR(ptr_seg, *ptr_far, oldval | 0x80);
641
time -= USEC_PER_RTC;
642
SET_BDA(user_wait_timeout, time);