1 /* 2 * SYS/SYSTIMER.H 3 * 4 * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved. 5 * 6 * This code is derived from software contributed to The DragonFly Project 7 * by Matthew Dillon <dillon@backplane.com> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 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 18 * distribution. 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. 22 * 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 34 * SUCH DAMAGE. 35 * 36 * $DragonFly: src/sys/sys/systimer.h,v 1.13 2007/04/30 06:57:36 dillon Exp $ 37 */ 38 39 #ifndef _SYS_SYSTIMER_H_ 40 #define _SYS_SYSTIMER_H_ 41 42 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES) 43 44 #ifndef _SYS_TYPES_H_ 45 #include <sys/types.h> 46 #endif 47 #ifndef _SYS_QUEUE_H_ 48 #include <sys/queue.h> 49 #endif 50 51 /* XXX fix sys/kinfo.h */ 52 #ifndef __BOOLEAN_T_DEFINED__ 53 #define __BOOLEAN_T_DEFINED__ 54 typedef __boolean_t boolean_t; 55 #endif 56 57 struct intrframe; 58 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 *); 63 64 typedef struct systimer { 65 TAILQ_ENTRY(systimer) node; 66 systimerq_t queue; 67 sysclock_t time; /* absolute time next intr */ 68 sysclock_t periodic; /* if non-zero */ 69 systimer_func_t func; 70 void *data; 71 int flags; 72 int freq; /* frequency if periodic */ 73 struct cputimer *which; /* which timer was used? */ 74 struct globaldata *gd; /* cpu owning structure */ 75 } *systimer_t; 76 77 #define SYSTF_ONQUEUE 0x0001 78 #define SYSTF_IPIRUNNING 0x0002 79 #define SYSTF_NONQUEUED 0x0004 80 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); 89 90 /* 91 * cputimer interface. This provides a free-running (non-interrupt) 92 * timebase for the system. The cputimer 93 * 94 * These variables hold the fixed cputimer frequency, determining the 95 * granularity of cputimer_count(). 96 * 97 * Note that cputimer_count() always returns a full-width wrapping counter. 98 * 99 * The 64 bit versions are used for converting count values into uS or nS 100 * as follows: 101 * 102 * usec = (cputimer_freq64_usec * count) >> 32 103 */ 104 105 struct cputimer { 106 SLIST_ENTRY(cputimer) next; 107 const char *name; 108 int pri; 109 int type; 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) */ 119 }; 120 121 extern struct cputimer *sys_cputimer; 122 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 134 #define CPUTIMER_PRI_DUMMY -10 135 #define CPUTIMER_PRI_8254 0 136 #define CPUTIMER_PRI_ACPI 10 137 #define CPUTIMER_PRI_HPET 20 138 #define CPUTIMER_PRI_CS5536 30 139 #define CPUTIMER_PRI_GEODE 40 140 #define CPUTIMER_PRI_VKERNEL 200 141 #define CPUTIMER_PRI_TSC 250 142 #define CPUTIMER_PRI_VMM 1000 143 144 void cputimer_select(struct cputimer *, int); 145 void cputimer_register(struct cputimer *); 146 void cputimer_deregister(struct cputimer *); 147 void cputimer_set_frequency(struct cputimer *, sysclock_t); 148 sysclock_t cputimer_default_fromhz(int); 149 sysclock_t cputimer_default_fromus(int); 150 void cputimer_default_construct(struct cputimer *, sysclock_t); 151 void cputimer_default_destruct(struct cputimer *); 152 153 /* 154 * Interrupt cputimer interface. 155 * 156 * Interrupt cputimers are normally one shot timers which will 157 * generate interrupt upon expiration. 158 * 159 * initclock -- Called at SI_BOOT2_CLOCKREG, SI_ORDER_SECOND. The 160 * interrupt timer could deregister itself here, if it 161 * is not the selected system interrupt cputimer. Before 162 * this function is called, 'enable' and 'reload' will 163 * not be called. 164 * enable -- Enable interrupt. It is called by each CPU. It is 165 * only called once during boot. Before this function 166 * is called, 'reload' will not be called. 167 * reload -- Called by each CPU when it wants to to reprogram the 168 * one shot timer expiration time. The reload value is 169 * measured in sys_cputimer->freq. 170 * config -- Setup the interrupt cputimer according to the passed 171 * in non-interrupt cputimer. It will be called when 172 * sys_cputimer's frequency is changed or when sys_cputimer 173 * itself is changed. It is also called when this interrupt 174 * cputimer gets registered. 175 * restart -- Start the possibly stalled interrupt cputimer immediately. 176 * Do fixup if necessary. 177 * pmfixup -- Called after ACPI power management is enabled. 178 * pcpuhand -- Per-cpu handler (could be NULL). 179 */ 180 struct cputimer_intr { 181 sysclock_t freq; 182 void (*reload) 183 (struct cputimer_intr *, sysclock_t); 184 void (*enable) 185 (struct cputimer_intr *); 186 void (*config) 187 (struct cputimer_intr *, const struct cputimer *); 188 void (*restart) 189 (struct cputimer_intr *); 190 void (*pmfixup) 191 (struct cputimer_intr *); 192 void (*initclock) 193 (struct cputimer_intr *, boolean_t); 194 void (*pcpuhand) 195 (struct cputimer_intr *); 196 SLIST_ENTRY(cputimer_intr) next; 197 const char *name; 198 int type; /* CPUTIMER_INTR_ */ 199 int prio; /* CPUTIMER_INTR_PRIO_ */ 200 uint32_t caps; /* CPUTIMER_INTR_CAP_ */ 201 void *priv; /* private data */ 202 }; 203 204 #define CPUTIMER_INTR_8254 0 205 #define CPUTIMER_INTR_LAPIC 1 206 #define CPUTIMER_INTR_VKERNEL 2 207 #define CPUTIMER_INTR_VMM 3 208 209 /* NOTE: Keep the new values less than CPUTIMER_INTR_PRIO_MAX */ 210 #define CPUTIMER_INTR_PRIO_8254 0 211 #define CPUTIMER_INTR_PRIO_LAPIC 10 212 #define CPUTIMER_INTR_PRIO_VKERNEL 20 213 #define CPUTIMER_INTR_PRIO_VMM 500 214 #define CPUTIMER_INTR_PRIO_MAX 1000 215 216 #define CPUTIMER_INTR_CAP_NONE 0 217 #define CPUTIMER_INTR_CAP_PS 0x1 /* works during powersaving */ 218 219 /* 220 * Interrupt cputimer implementation interfaces 221 * 222 * NOTE: 223 * cputimer_intr_deregister() is _not_ allowed to be called 224 * with the currently selected interrupt cputimer. 225 */ 226 void cputimer_intr_register(struct cputimer_intr *); 227 void cputimer_intr_deregister(struct cputimer_intr *); 228 int cputimer_intr_select(struct cputimer_intr *, int); 229 230 /* 231 * Interrupt cputimer implementation helper functions 232 * 233 * default_enable -- NOP 234 * default_restart -- reload(0) 235 * default_config -- NOP 236 * default_pmfixup -- NOP 237 * default_initclock -- NOP 238 */ 239 void cputimer_intr_default_enable(struct cputimer_intr *); 240 void cputimer_intr_default_restart(struct cputimer_intr *); 241 void cputimer_intr_default_config(struct cputimer_intr *, 242 const struct cputimer *); 243 void cputimer_intr_default_pmfixup(struct cputimer_intr *); 244 void cputimer_intr_default_initclock(struct cputimer_intr *, boolean_t); 245 246 /* 247 * Interrupt cputimer external interfaces 248 */ 249 void cputimer_intr_enable(void); 250 void cputimer_intr_pmfixup(void); 251 void cputimer_intr_config(const struct cputimer *); 252 void cputimer_intr_reload(sysclock_t); 253 void cputimer_intr_restart(void); 254 int cputimer_intr_select_caps(uint32_t); 255 int cputimer_intr_powersave_addreq(void); 256 void cputimer_intr_powersave_remreq(void); 257 258 #endif /* _KERNEL || _KERNEL_STRUCTURES */ 259 260 #endif /* !_SYS_SYSTIMER_H_ */ 261