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
36extern timer_info gPITTimer;
37extern timer_info gAPICTimer;
38extern timer_info gHPETTimer;
39
40static timer_info *sTimers[] = {
41	&gHPETTimer,
42	&gAPICTimer,
43	&gPITTimer,
44	NULL
45};
46
47static timer_info *sTimer = NULL;
48
49void
50arch_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
57void
58arch_timer_clear_hardware_timer(void)
59{
60	TRACE("arch_timer_clear_hardware_timer\n");
61	sTimer->clear_hardware_timer();
62}
63
64
65static void
66sort_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
93int
94arch_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