xref: /haiku/src/system/kernel/arch/x86/arch_timer.cpp (revision 52f7c9389475e19fc21487b38064b4390eeb6fea)
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("arch_timer: " x)
31 #else
32 #	define TRACE(x...) ;
33 #endif
34 
35 
36 extern timer_info gPITTimer;
37 extern timer_info gAPICTimer;
38 extern timer_info gHPETTimer;
39 
40 static timer_info *sTimers[] = {
41 	&gHPETTimer,
42 	&gAPICTimer,
43 	&gPITTimer,
44 	NULL
45 };
46 
47 static timer_info *sTimer = NULL;
48 
49 void
50 arch_timer_set_hardware_timer(bigtime_t timeout)
51 {
52 	TRACE("arch_timer_set_hardware_timer: timeout %" B_PRIdBIGTIME "\n", timeout);
53 	sTimer->set_hardware_timer(timeout);
54 }
55 
56 
57 void
58 arch_timer_clear_hardware_timer(void)
59 {
60 	TRACE("arch_timer_clear_hardware_timer\n");
61 	sTimer->clear_hardware_timer();
62 }
63 
64 
65 static void
66 sort_timers(timer_info *timers[], int numTimers)
67 {
68 	timer_info *tempPtr;
69 	int max = 0;
70 	int i = 0;
71 	int j = 0;
72 
73 	for (i = 0; i < numTimers - 1; i++) {
74 		max = i;
75 		for (j = i + 1; j < numTimers; j++) {
76 			if (timers[j]->get_priority() > timers[max]->get_priority())
77 				max = j;
78 		}
79 		if (max != i) {
80 			tempPtr = timers[max];
81 			timers[max] = timers[i];
82 			timers[i] = tempPtr;
83 		}
84 	}
85 
86 #if 0
87 	for (i = 0; i < numTimers; i++)
88 		dprintf(" %s: priority %d\n", timers[i]->name, timers[i]->get_priority());
89 #endif
90 }
91 
92 
93 int
94 arch_init_timer(kernel_args *args)
95 {
96 	// Sort timers by priority
97 	sort_timers(sTimers, (sizeof(sTimers) / sizeof(sTimers[0])) - 1);
98 
99 	timer_info *timer = NULL;
100 	cpu_status state = disable_interrupts();
101 
102 	for (int i = 0; (timer = sTimers[i]) != NULL; i++) {
103 		if (timer->init(args) == B_OK)
104 			break;
105 	}
106 
107 	sTimer = timer;
108 
109 	if (sTimer != NULL) {
110 		dprintf("arch_init_timer: using %s timer.\n", sTimer->name);
111 	} else {
112 		panic("No system timers were found usable.\n");
113 	}
114 
115 	restore_interrupts(state);
116 
117 	return 0;
118 }
119 
120