xref: /haiku/src/system/kernel/arch/x86/arch_timer.cpp (revision 99d027cd0238c1d86da86d7c3f4200509ccc61a6)
1 /*
2  * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 
9 
10 #include <boot/stage2.h>
11 #include <kernel.h>
12 
13 #include <arch/int.h>
14 #include <arch/cpu.h>
15 
16 #include <console.h>
17 #include <debug.h>
18 #include <timer.h>
19 #include <int.h>
20 #include <safemode.h>
21 
22 #include <arch/timer.h>
23 
24 #include <arch/x86/smp_priv.h>
25 #include <arch/x86/timer.h>
26 
27 
28 //#define TRACE_TIMER
29 #ifdef TRACE_TIMER
30 #	define TRACE(x) dprintf x
31 #else
32 #	define TRACE(x) ;
33 #endif
34 
35 extern timer_info gPITTimer;
36 extern timer_info gAPICTimer;
37 extern timer_info gHPETTimer;
38 
39 static timer_info *sTimers[] = {
40 	&gHPETTimer,
41 	&gAPICTimer,
42 	&gPITTimer,
43 	NULL
44 };
45 
46 static timer_info *sTimer = NULL;
47 
48 void
49 arch_timer_set_hardware_timer(bigtime_t timeout)
50 {
51 	TRACE(("arch_timer_set_hardware_timer: timeout %lld\n", timeout));
52 	sTimer->set_hardware_timer(timeout);
53 }
54 
55 
56 void
57 arch_timer_clear_hardware_timer(void)
58 {
59 	TRACE(("arch_timer_clear_hardware_timer\n"));
60 	sTimer->clear_hardware_timer();
61 }
62 
63 
64 static void
65 sort_timers(timer_info *timers[], int numTimers)
66 {
67 	timer_info *tempPtr;
68 	int max = 0;
69 	int i = 0;
70 	int j = 0;
71 
72 	for (i = 0; i < numTimers - 1; i++) {
73 		max = i;
74 		for (j = i + 1; j < numTimers; j++) {
75 			if (timers[j]->get_priority() > timers[max]->get_priority())
76 				max = j;
77 		}
78 		if (max != i) {
79 			tempPtr = timers[max];
80 			timers[max] = timers[i];
81 			timers[i] = tempPtr;
82 		}
83 	}
84 
85 #if 0
86 	for (i = 0; i < numTimers; i++)
87 		dprintf(" %s: priority %d\n", timers[i]->name, timers[i]->get_priority());
88 #endif
89 }
90 
91 
92 int
93 arch_init_timer(kernel_args *args)
94 {
95 	// Sort timers by priority
96 	sort_timers(sTimers, (sizeof(sTimers) / sizeof(sTimers[0])) - 1);
97 
98 	timer_info *timer = NULL;
99 	cpu_status state = disable_interrupts();
100 
101 	for (int i = 0; (timer = sTimers[i]) != NULL; i++) {
102 		if (timer->init(args) == B_OK)
103 			break;
104 	}
105 
106 	sTimer = timer;
107 
108 	if (sTimer != NULL) {
109 		dprintf("arch_init_timer: using %s timer.\n", sTimer->name);
110 	} else {
111 		panic("No system timers were found usable.\n");
112 	}
113 
114 	restore_interrupts(state);
115 
116 	return 0;
117 }
118 
119