4 * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
6 * This code is derived from software contributed to The DragonFly Project
7 * by Matthew Dillon <dillon@backplane.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
19 * 3. Neither the name of The DragonFly Project nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific, prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * $DragonFly: src/sys/sys/systimer.h,v 1.13 2007/04/30 06:57:36 dillon Exp $
39 #ifndef _SYS_SYSTIMER_H_
40 #define _SYS_SYSTIMER_H_
42 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
45 #include <sys/types.h>
48 #include <sys/queue.h>
51 /* XXX fix sys/kinfo.h */
52 #ifndef __BOOLEAN_T_DEFINED__
53 #define __BOOLEAN_T_DEFINED__
54 typedef __boolean_t boolean_t
;
59 typedef __uint32_t sysclock_t
;
60 typedef int32_t ssysclock_t
;
61 typedef TAILQ_HEAD(systimerq
, systimer
) *systimerq_t
;
62 typedef void (*systimer_func_t
)(struct systimer
*, int, struct intrframe
*);
64 typedef struct systimer
{
65 TAILQ_ENTRY(systimer
) node
;
67 sysclock_t time
; /* absolute time next intr */
68 sysclock_t periodic
; /* if non-zero */
72 int freq
; /* frequency if periodic */
73 struct cputimer
*which
; /* which timer was used? */
74 struct globaldata
*gd
; /* cpu owning structure */
77 #define SYSTF_ONQUEUE 0x0001
78 #define SYSTF_IPIRUNNING 0x0002
79 #define SYSTF_NONQUEUED 0x0004
81 void systimer_intr_enable(void);
82 void systimer_intr(sysclock_t
*, int, struct intrframe
*);
83 void systimer_add(systimer_t
);
84 void systimer_del(systimer_t
);
85 void systimer_init_periodic(systimer_t
, systimer_func_t
, void *, int);
86 void systimer_init_periodic_nq(systimer_t
, systimer_func_t
, void *, int);
87 void systimer_adjust_periodic(systimer_t
, int);
88 void systimer_init_oneshot(systimer_t
, systimer_func_t
, void *, int);
91 * cputimer interface. This provides a free-running (non-interrupt)
92 * timebase for the system. The cputimer
94 * These variables hold the fixed cputimer frequency, determining the
95 * granularity of cputimer_count().
97 * Note that cputimer_count() always returns a full-width wrapping counter.
99 * The 64 bit versions are used for converting count values into uS or nS
102 * usec = (cputimer_freq64_usec * count) >> 32
106 SLIST_ENTRY(cputimer
) next
;
110 sysclock_t (*count
)(void);
111 sysclock_t (*fromhz
)(int freq
);
112 sysclock_t (*fromus
)(int us
);
113 void (*construct
)(struct cputimer
*, sysclock_t
);
114 void (*destruct
)(struct cputimer
*);
115 sysclock_t freq
; /* in Hz */
116 int64_t freq64_usec
; /* in (1e6 << 32) / timer_freq */
117 int64_t freq64_nsec
; /* in (1e9 << 32) / timer_freq */
118 sysclock_t base
; /* (implementation dependant) */
121 extern struct cputimer
*sys_cputimer
;
123 #define CPUTIMER_DUMMY 0
124 #define CPUTIMER_8254_SEL1 1
125 #define CPUTIMER_8254_SEL2 2
126 #define CPUTIMER_ACPI 3
127 #define CPUTIMER_VKERNEL 4
128 #define CPUTIMER_HPET 5
129 #define CPUTIMER_GEODE 6
130 #define CPUTIMER_CS5536 7
131 #define CPUTIMER_TSC 8
132 #define CPUTIMER_VMM 9
133 #define CPUTIMER_VMM1 10
134 #define CPUTIMER_VMM2 11
136 #define CPUTIMER_PRI_DUMMY -10
137 #define CPUTIMER_PRI_8254 0
138 #define CPUTIMER_PRI_ACPI 10
139 #define CPUTIMER_PRI_HPET 20
140 #define CPUTIMER_PRI_CS5536 30
141 #define CPUTIMER_PRI_GEODE 40
142 #define CPUTIMER_PRI_VKERNEL 200
143 #define CPUTIMER_PRI_TSC 250
144 #define CPUTIMER_PRI_VMM 1000
145 #define CPUTIMER_PRI_VMM_HI 2000
147 void cputimer_select(struct cputimer
*, int);
148 void cputimer_register(struct cputimer
*);
149 void cputimer_deregister(struct cputimer
*);
150 void cputimer_set_frequency(struct cputimer
*, sysclock_t
);
151 sysclock_t
cputimer_default_fromhz(int);
152 sysclock_t
cputimer_default_fromus(int);
153 void cputimer_default_construct(struct cputimer
*, sysclock_t
);
154 void cputimer_default_destruct(struct cputimer
*);
157 * Interrupt cputimer interface.
159 * Interrupt cputimers are normally one shot timers which will
160 * generate interrupt upon expiration.
162 * initclock -- Called at SI_BOOT2_CLOCKREG, SI_ORDER_SECOND. The
163 * interrupt timer could deregister itself here, if it
164 * is not the selected system interrupt cputimer. Before
165 * this function is called, 'enable' and 'reload' will
167 * enable -- Enable interrupt. It is called by each CPU. It is
168 * only called once during boot. Before this function
169 * is called, 'reload' will not be called.
170 * reload -- Called by each CPU when it wants to to reprogram the
171 * one shot timer expiration time. The reload value is
172 * measured in sys_cputimer->freq.
173 * config -- Setup the interrupt cputimer according to the passed
174 * in non-interrupt cputimer. It will be called when
175 * sys_cputimer's frequency is changed or when sys_cputimer
176 * itself is changed. It is also called when this interrupt
177 * cputimer gets registered.
178 * restart -- Start the possibly stalled interrupt cputimer immediately.
179 * Do fixup if necessary.
180 * pmfixup -- Called after ACPI power management is enabled.
181 * pcpuhand -- Per-cpu handler (could be NULL).
183 struct cputimer_intr
{
186 (struct cputimer_intr
*, sysclock_t
);
188 (struct cputimer_intr
*);
190 (struct cputimer_intr
*, const struct cputimer
*);
192 (struct cputimer_intr
*);
194 (struct cputimer_intr
*);
196 (struct cputimer_intr
*, boolean_t
);
198 (struct cputimer_intr
*);
199 SLIST_ENTRY(cputimer_intr
) next
;
201 int type
; /* CPUTIMER_INTR_ */
202 int prio
; /* CPUTIMER_INTR_PRIO_ */
203 uint32_t caps
; /* CPUTIMER_INTR_CAP_ */
204 void *priv
; /* private data */
207 #define CPUTIMER_INTR_8254 0
208 #define CPUTIMER_INTR_LAPIC 1
209 #define CPUTIMER_INTR_VKERNEL 2
210 #define CPUTIMER_INTR_VMM 3
212 /* NOTE: Keep the new values less than CPUTIMER_INTR_PRIO_MAX */
213 #define CPUTIMER_INTR_PRIO_8254 0
214 #define CPUTIMER_INTR_PRIO_LAPIC 10
215 #define CPUTIMER_INTR_PRIO_VKERNEL 20
216 #define CPUTIMER_INTR_PRIO_VMM 500
217 #define CPUTIMER_INTR_PRIO_MAX 1000
219 #define CPUTIMER_INTR_CAP_NONE 0
220 #define CPUTIMER_INTR_CAP_PS 0x1 /* works during powersaving */
223 * Interrupt cputimer implementation interfaces
226 * cputimer_intr_deregister() is _not_ allowed to be called
227 * with the currently selected interrupt cputimer.
229 void cputimer_intr_register(struct cputimer_intr
*);
230 void cputimer_intr_deregister(struct cputimer_intr
*);
231 int cputimer_intr_select(struct cputimer_intr
*, int);
234 * Interrupt cputimer implementation helper functions
236 * default_enable -- NOP
237 * default_restart -- reload(0)
238 * default_config -- NOP
239 * default_pmfixup -- NOP
240 * default_initclock -- NOP
242 void cputimer_intr_default_enable(struct cputimer_intr
*);
243 void cputimer_intr_default_restart(struct cputimer_intr
*);
244 void cputimer_intr_default_config(struct cputimer_intr
*,
245 const struct cputimer
*);
246 void cputimer_intr_default_pmfixup(struct cputimer_intr
*);
247 void cputimer_intr_default_initclock(struct cputimer_intr
*, boolean_t
);
250 * Interrupt cputimer external interfaces
252 void cputimer_intr_enable(void);
253 void cputimer_intr_pmfixup(void);
254 void cputimer_intr_config(const struct cputimer
*);
255 void cputimer_intr_reload(sysclock_t
);
256 void cputimer_intr_restart(void);
257 int cputimer_intr_select_caps(uint32_t);
258 int cputimer_intr_powersave_addreq(void);
259 void cputimer_intr_powersave_remreq(void);
261 #endif /* _KERNEL || _KERNEL_STRUCTURES */
263 #endif /* !_SYS_SYSTIMER_H_ */