xref: /haiku/src/system/kernel/arch/x86/timers/x86_pit.cpp (revision 46b7da1f4f40f7157d74fc7fb26ff9ec7f2416f2)
1 /*
2  * Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
3  * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  *
6  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
7  * Distributed under the terms of the NewOS License.
8  */
9 
10 #include <timer.h>
11 #include <arch/x86/timer.h>
12 
13 #include <arch/int.h>
14 #include <arch/cpu.h>
15 
16 #include "pit.h"
17 
18 
19 //#define TRACE_PIT
20 #ifdef TRACE_PIT
21 #	define TRACE(x...) dprintf("pit: " x)
22 #else
23 #	define TRACE(x...) ;
24 #endif
25 
26 
27 static bool sPITTimerInitialized = false;
28 
29 struct timer_info gPITTimer = {
30 	"PIT",
31 	&pit_get_prio,
32 	&pit_set_hardware_timer,
33 	&pit_clear_hardware_timer,
34 	&pit_init
35 };
36 
37 
38 static int
pit_get_prio(void)39 pit_get_prio(void)
40 {
41 	return 1;
42 }
43 
44 
45 static int32
pit_timer_interrupt(void * data)46 pit_timer_interrupt(void *data)
47 {
48 	return timer_interrupt();
49 }
50 
51 
52 static status_t
pit_set_hardware_timer(bigtime_t relativeTimeout)53 pit_set_hardware_timer(bigtime_t relativeTimeout)
54 {
55 	uint16 nextEventClocks;
56 
57 	if (relativeTimeout <= 0)
58 		nextEventClocks = 2;
59 	else if (relativeTimeout < PIT_MAX_TIMER_INTERVAL)
60 		nextEventClocks = relativeTimeout * PIT_CLOCK_RATE / 1000000;
61 	else
62 		nextEventClocks = 0xffff;
63 
64 	out8(PIT_SELCH0 | PIT_RWBOTH | PIT_MD_INTON0, PIT_CTRL);
65 	out8(nextEventClocks & 0xff, PIT_CNT0);
66 	out8((nextEventClocks >> 8) & 0xff, PIT_CNT0);
67 
68 	arch_int_enable_io_interrupt(0);
69 	return B_OK;
70 }
71 
72 
73 static status_t
pit_clear_hardware_timer(void)74 pit_clear_hardware_timer(void)
75 {
76 	arch_int_disable_io_interrupt(0);
77 	return B_OK;
78 }
79 
80 
81 static status_t
pit_init(struct kernel_args * args)82 pit_init(struct kernel_args *args)
83 {
84 	if (sPITTimerInitialized) {
85 		TRACE("timer is already initialized");
86 		return B_OK;
87 	}
88 
89 	install_io_interrupt_handler(0, &pit_timer_interrupt, NULL, 0);
90 	pit_clear_hardware_timer();
91 
92 	sPITTimerInitialized = true;
93 	TRACE("timer initialized");
94 
95 	return B_OK;
96 }
97