Deleted Added
full compact
clock.c (212812) clock.c (218965)
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * William Jolitz and Don Ahn.
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 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * from: @(#)clock.c 7.2 (Berkeley) 5/12/91
34 */
35
36#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * William Jolitz and Don Ahn.
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 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * from: @(#)clock.c 7.2 (Berkeley) 5/12/91
34 */
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: head/sys/x86/isa/clock.c 212812 2010-09-18 07:36:43Z mav $");
37__FBSDID("$FreeBSD: head/sys/x86/isa/clock.c 218965 2011-02-23 09:22:33Z brucec $");
38
39/*
40 * Routines to handle clock hardware.
41 */
42
43#include "opt_clock.h"
44#include "opt_isa.h"
45#include "opt_mca.h"
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/bus.h>
50#include <sys/lock.h>
51#include <sys/kdb.h>
52#include <sys/mutex.h>
53#include <sys/proc.h>
54#include <sys/kernel.h>
55#include <sys/module.h>
56#include <sys/rman.h>
57#include <sys/sched.h>
58#include <sys/smp.h>
59#include <sys/sysctl.h>
60#include <sys/timeet.h>
61#include <sys/timetc.h>
62
63#include <machine/clock.h>
64#include <machine/cpu.h>
65#include <machine/intr_machdep.h>
66#include <machine/ppireg.h>
67#include <machine/timerreg.h>
68
69#ifdef PC98
70#include <pc98/pc98/pc98_machdep.h>
71#else
72#include <isa/rtc.h>
73#endif
74#ifdef DEV_ISA
75#ifdef PC98
76#include <pc98/cbus/cbus.h>
77#else
78#include <isa/isareg.h>
79#endif
80#include <isa/isavar.h>
81#endif
82
83#ifdef DEV_MCA
84#include <i386/bios/mca_machdep.h>
85#endif
86
87int clkintr_pending;
88#ifndef TIMER_FREQ
89#ifdef PC98
90#define TIMER_FREQ 2457600
91#else
92#define TIMER_FREQ 1193182
93#endif
94#endif
95u_int i8254_freq = TIMER_FREQ;
96TUNABLE_INT("hw.i8254.freq", &i8254_freq);
97int i8254_max_count;
98static int i8254_timecounter = 1;
99
100struct mtx clock_lock;
101static struct intsrc *i8254_intsrc;
102static uint16_t i8254_lastcount;
103static uint16_t i8254_offset;
104static int (*i8254_pending)(struct intsrc *);
105static int i8254_ticked;
106
107struct attimer_softc {
108 int intr_en;
109 int port_rid, intr_rid;
110 struct resource *port_res;
111 struct resource *intr_res;
112#ifdef PC98
113 int port_rid2;
114 struct resource *port_res2;
115#endif
116 void *intr_handler;
117 struct timecounter tc;
118 struct eventtimer et;
119 int mode;
120#define MODE_STOP 0
121#define MODE_PERIODIC 1
122#define MODE_ONESHOT 2
123 uint32_t period;
124};
125static struct attimer_softc *attimer_sc = NULL;
126
127static int timer0_period = -2;
128
129/* Values for timerX_state: */
130#define RELEASED 0
131#define RELEASE_PENDING 1
132#define ACQUIRED 2
133#define ACQUIRE_PENDING 3
134
135static u_char timer2_state;
136
137static unsigned i8254_get_timecount(struct timecounter *tc);
138static void set_i8254_freq(int mode, uint32_t period);
139
140static int
141clkintr(void *arg)
142{
143 struct attimer_softc *sc = (struct attimer_softc *)arg;
144
145 if (i8254_timecounter && sc->period != 0) {
146 mtx_lock_spin(&clock_lock);
147 if (i8254_ticked)
148 i8254_ticked = 0;
149 else {
150 i8254_offset += i8254_max_count;
151 i8254_lastcount = 0;
152 }
153 clkintr_pending = 0;
154 mtx_unlock_spin(&clock_lock);
155 }
156
157 if (sc && sc->et.et_active && sc->mode != MODE_STOP)
158 sc->et.et_event_cb(&sc->et, sc->et.et_arg);
159
160#ifdef DEV_MCA
161 /* Reset clock interrupt by asserting bit 7 of port 0x61 */
162 if (MCA_system)
163 outb(0x61, inb(0x61) | 0x80);
164#endif
165 return (FILTER_HANDLED);
166}
167
168int
169timer_spkr_acquire(void)
170{
171 int mode;
172
173#ifdef PC98
174 mode = TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT;
175#else
176 mode = TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT;
177#endif
178
179 if (timer2_state != RELEASED)
180 return (-1);
181 timer2_state = ACQUIRED;
182
183 /*
184 * This access to the timer registers is as atomic as possible
185 * because it is a single instruction. We could do better if we
186 * knew the rate. Use of splclock() limits glitches to 10-100us,
187 * and this is probably good enough for timer2, so we aren't as
188 * careful with it as with timer0.
189 */
190#ifdef PC98
191 outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f));
192#else
193 outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
194#endif
195 ppi_spkr_on(); /* enable counter2 output to speaker */
196 return (0);
197}
198
199int
200timer_spkr_release(void)
201{
202
203 if (timer2_state != ACQUIRED)
204 return (-1);
205 timer2_state = RELEASED;
206#ifdef PC98
207 outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT);
208#else
209 outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
210#endif
211 ppi_spkr_off(); /* disable counter2 output to speaker */
212 return (0);
213}
214
215void
216timer_spkr_setfreq(int freq)
217{
218
219 freq = i8254_freq / freq;
220 mtx_lock_spin(&clock_lock);
221#ifdef PC98
222 outb(TIMER_CNTR1, freq & 0xff);
223 outb(TIMER_CNTR1, freq >> 8);
224#else
225 outb(TIMER_CNTR2, freq & 0xff);
226 outb(TIMER_CNTR2, freq >> 8);
227#endif
228 mtx_unlock_spin(&clock_lock);
229}
230
231static int
232getit(void)
233{
234 int high, low;
235
236 mtx_lock_spin(&clock_lock);
237
238 /* Select timer0 and latch counter value. */
239 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
240
241 low = inb(TIMER_CNTR0);
242 high = inb(TIMER_CNTR0);
243
244 mtx_unlock_spin(&clock_lock);
245 return ((high << 8) | low);
246}
247
248/*
249 * Wait "n" microseconds.
250 * Relies on timer 1 counting down from (i8254_freq / hz)
251 * Note: timer had better have been programmed before this is first used!
252 */
253void
254DELAY(int n)
255{
256 int delta, prev_tick, tick, ticks_left;
257
258#ifdef DELAYDEBUG
259 int getit_calls = 1;
260 int n1;
261 static int state = 0;
262#endif
263
264 if (tsc_freq != 0 && !tsc_is_broken) {
265 uint64_t start, end, now;
266
267 sched_pin();
268 start = rdtsc();
269 end = start + (tsc_freq * n) / 1000000;
270 do {
271 cpu_spinwait();
272 now = rdtsc();
273 } while (now < end || (now > start && end < start));
274 sched_unpin();
275 return;
276 }
277#ifdef DELAYDEBUG
278 if (state == 0) {
279 state = 1;
280 for (n1 = 1; n1 <= 10000000; n1 *= 10)
281 DELAY(n1);
282 state = 2;
283 }
284 if (state == 1)
285 printf("DELAY(%d)...", n);
286#endif
287 /*
288 * Read the counter first, so that the rest of the setup overhead is
289 * counted. Guess the initial overhead is 20 usec (on most systems it
290 * takes about 1.5 usec for each of the i/o's in getit(). The loop
291 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The
292 * multiplications and divisions to scale the count take a while).
293 *
294 * However, if ddb is active then use a fake counter since reading
295 * the i8254 counter involves acquiring a lock. ddb must not do
296 * locking for many reasons, but it calls here for at least atkbd
297 * input.
298 */
299#ifdef KDB
300 if (kdb_active)
301 prev_tick = 1;
302 else
303#endif
304 prev_tick = getit();
305 n -= 0; /* XXX actually guess no initial overhead */
306 /*
307 * Calculate (n * (i8254_freq / 1e6)) without using floating point
308 * and without any avoidable overflows.
309 */
310 if (n <= 0)
311 ticks_left = 0;
312 else if (n < 256)
313 /*
314 * Use fixed point to avoid a slow division by 1000000.
315 * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
316 * 2^15 is the first power of 2 that gives exact results
317 * for n between 0 and 256.
318 */
319 ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
320 else
321 /*
322 * Don't bother using fixed point, although gcc-2.7.2
323 * generates particularly poor code for the long long
324 * division, since even the slow way will complete long
325 * before the delay is up (unless we're interrupted).
326 */
327 ticks_left = ((u_int)n * (long long)i8254_freq + 999999)
328 / 1000000;
329
330 while (ticks_left > 0) {
331#ifdef KDB
332 if (kdb_active) {
333#ifdef PC98
334 outb(0x5f, 0);
335#else
336 inb(0x84);
337#endif
338 tick = prev_tick - 1;
339 if (tick <= 0)
340 tick = i8254_max_count;
341 } else
342#endif
343 tick = getit();
344#ifdef DELAYDEBUG
345 ++getit_calls;
346#endif
347 delta = prev_tick - tick;
348 prev_tick = tick;
349 if (delta < 0) {
350 delta += i8254_max_count;
351 /*
352 * Guard against i8254_max_count being wrong.
353 * This shouldn't happen in normal operation,
354 * but it may happen if set_i8254_freq() is
355 * traced.
356 */
357 if (delta < 0)
358 delta = 0;
359 }
360 ticks_left -= delta;
361 }
362#ifdef DELAYDEBUG
363 if (state == 1)
364 printf(" %d calls to getit() at %d usec each\n",
365 getit_calls, (n + 5) / getit_calls);
366#endif
367}
368
369static void
370set_i8254_freq(int mode, uint32_t period)
371{
372 int new_count;
373
374 mtx_lock_spin(&clock_lock);
375 if (mode == MODE_STOP) {
376 if (i8254_timecounter) {
377 mode = MODE_PERIODIC;
378 new_count = 0x10000;
379 } else
380 new_count = -1;
381 } else {
382 new_count = min(((uint64_t)i8254_freq * period +
383 0x80000000LLU) >> 32, 0x10000);
384 }
385 if (new_count == timer0_period)
386 goto out;
387 i8254_max_count = ((new_count & ~0xffff) != 0) ? 0xffff : new_count;
388 timer0_period = (mode == MODE_PERIODIC) ? new_count : -1;
389 switch (mode) {
390 case MODE_STOP:
391 outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT);
392 outb(TIMER_CNTR0, 0);
393 outb(TIMER_CNTR0, 0);
394 break;
395 case MODE_PERIODIC:
396 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
397 outb(TIMER_CNTR0, new_count & 0xff);
398 outb(TIMER_CNTR0, new_count >> 8);
399 break;
400 case MODE_ONESHOT:
401 outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT);
402 outb(TIMER_CNTR0, new_count & 0xff);
403 outb(TIMER_CNTR0, new_count >> 8);
404 break;
405 }
406out:
407 mtx_unlock_spin(&clock_lock);
408}
409
410static void
411i8254_restore(void)
412{
413
414 timer0_period = -2;
415 if (attimer_sc != NULL)
416 set_i8254_freq(attimer_sc->mode, attimer_sc->period);
417 else
418 set_i8254_freq(0, 0);
419}
420
421#ifndef __amd64__
422/*
423 * Restore all the timers non-atomically (XXX: should be atomically).
424 *
425 * This function is called from pmtimer_resume() to restore all the timers.
426 * This should not be necessary, but there are broken laptops that do not
427 * restore all the timers on resume.
428 * As long as pmtimer is not part of amd64 suport, skip this for the amd64
429 * case.
430 */
431void
432timer_restore(void)
433{
434
435 i8254_restore(); /* restore i8254_freq and hz */
436#ifndef PC98
437 atrtc_restore(); /* reenable RTC interrupts */
438#endif
439}
440#endif
441
442/* This is separate from startrtclock() so that it can be called early. */
443void
444i8254_init(void)
445{
446
447 mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
448#ifdef PC98
449 if (pc98_machine_type & M_8M)
450 i8254_freq = 1996800L; /* 1.9968 MHz */
451#endif
452 set_i8254_freq(0, 0);
453}
454
455void
456startrtclock()
457{
458
459 init_TSC();
460}
461
462void
463cpu_initclocks(void)
464{
465
466 init_TSC_tc();
467 cpu_initclocks_bsp();
468}
469
470static int
471sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
472{
473 int error;
474 u_int freq;
475
476 /*
477 * Use `i8254' instead of `timer' in external names because `timer'
38
39/*
40 * Routines to handle clock hardware.
41 */
42
43#include "opt_clock.h"
44#include "opt_isa.h"
45#include "opt_mca.h"
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/bus.h>
50#include <sys/lock.h>
51#include <sys/kdb.h>
52#include <sys/mutex.h>
53#include <sys/proc.h>
54#include <sys/kernel.h>
55#include <sys/module.h>
56#include <sys/rman.h>
57#include <sys/sched.h>
58#include <sys/smp.h>
59#include <sys/sysctl.h>
60#include <sys/timeet.h>
61#include <sys/timetc.h>
62
63#include <machine/clock.h>
64#include <machine/cpu.h>
65#include <machine/intr_machdep.h>
66#include <machine/ppireg.h>
67#include <machine/timerreg.h>
68
69#ifdef PC98
70#include <pc98/pc98/pc98_machdep.h>
71#else
72#include <isa/rtc.h>
73#endif
74#ifdef DEV_ISA
75#ifdef PC98
76#include <pc98/cbus/cbus.h>
77#else
78#include <isa/isareg.h>
79#endif
80#include <isa/isavar.h>
81#endif
82
83#ifdef DEV_MCA
84#include <i386/bios/mca_machdep.h>
85#endif
86
87int clkintr_pending;
88#ifndef TIMER_FREQ
89#ifdef PC98
90#define TIMER_FREQ 2457600
91#else
92#define TIMER_FREQ 1193182
93#endif
94#endif
95u_int i8254_freq = TIMER_FREQ;
96TUNABLE_INT("hw.i8254.freq", &i8254_freq);
97int i8254_max_count;
98static int i8254_timecounter = 1;
99
100struct mtx clock_lock;
101static struct intsrc *i8254_intsrc;
102static uint16_t i8254_lastcount;
103static uint16_t i8254_offset;
104static int (*i8254_pending)(struct intsrc *);
105static int i8254_ticked;
106
107struct attimer_softc {
108 int intr_en;
109 int port_rid, intr_rid;
110 struct resource *port_res;
111 struct resource *intr_res;
112#ifdef PC98
113 int port_rid2;
114 struct resource *port_res2;
115#endif
116 void *intr_handler;
117 struct timecounter tc;
118 struct eventtimer et;
119 int mode;
120#define MODE_STOP 0
121#define MODE_PERIODIC 1
122#define MODE_ONESHOT 2
123 uint32_t period;
124};
125static struct attimer_softc *attimer_sc = NULL;
126
127static int timer0_period = -2;
128
129/* Values for timerX_state: */
130#define RELEASED 0
131#define RELEASE_PENDING 1
132#define ACQUIRED 2
133#define ACQUIRE_PENDING 3
134
135static u_char timer2_state;
136
137static unsigned i8254_get_timecount(struct timecounter *tc);
138static void set_i8254_freq(int mode, uint32_t period);
139
140static int
141clkintr(void *arg)
142{
143 struct attimer_softc *sc = (struct attimer_softc *)arg;
144
145 if (i8254_timecounter && sc->period != 0) {
146 mtx_lock_spin(&clock_lock);
147 if (i8254_ticked)
148 i8254_ticked = 0;
149 else {
150 i8254_offset += i8254_max_count;
151 i8254_lastcount = 0;
152 }
153 clkintr_pending = 0;
154 mtx_unlock_spin(&clock_lock);
155 }
156
157 if (sc && sc->et.et_active && sc->mode != MODE_STOP)
158 sc->et.et_event_cb(&sc->et, sc->et.et_arg);
159
160#ifdef DEV_MCA
161 /* Reset clock interrupt by asserting bit 7 of port 0x61 */
162 if (MCA_system)
163 outb(0x61, inb(0x61) | 0x80);
164#endif
165 return (FILTER_HANDLED);
166}
167
168int
169timer_spkr_acquire(void)
170{
171 int mode;
172
173#ifdef PC98
174 mode = TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT;
175#else
176 mode = TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT;
177#endif
178
179 if (timer2_state != RELEASED)
180 return (-1);
181 timer2_state = ACQUIRED;
182
183 /*
184 * This access to the timer registers is as atomic as possible
185 * because it is a single instruction. We could do better if we
186 * knew the rate. Use of splclock() limits glitches to 10-100us,
187 * and this is probably good enough for timer2, so we aren't as
188 * careful with it as with timer0.
189 */
190#ifdef PC98
191 outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f));
192#else
193 outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
194#endif
195 ppi_spkr_on(); /* enable counter2 output to speaker */
196 return (0);
197}
198
199int
200timer_spkr_release(void)
201{
202
203 if (timer2_state != ACQUIRED)
204 return (-1);
205 timer2_state = RELEASED;
206#ifdef PC98
207 outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT);
208#else
209 outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
210#endif
211 ppi_spkr_off(); /* disable counter2 output to speaker */
212 return (0);
213}
214
215void
216timer_spkr_setfreq(int freq)
217{
218
219 freq = i8254_freq / freq;
220 mtx_lock_spin(&clock_lock);
221#ifdef PC98
222 outb(TIMER_CNTR1, freq & 0xff);
223 outb(TIMER_CNTR1, freq >> 8);
224#else
225 outb(TIMER_CNTR2, freq & 0xff);
226 outb(TIMER_CNTR2, freq >> 8);
227#endif
228 mtx_unlock_spin(&clock_lock);
229}
230
231static int
232getit(void)
233{
234 int high, low;
235
236 mtx_lock_spin(&clock_lock);
237
238 /* Select timer0 and latch counter value. */
239 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
240
241 low = inb(TIMER_CNTR0);
242 high = inb(TIMER_CNTR0);
243
244 mtx_unlock_spin(&clock_lock);
245 return ((high << 8) | low);
246}
247
248/*
249 * Wait "n" microseconds.
250 * Relies on timer 1 counting down from (i8254_freq / hz)
251 * Note: timer had better have been programmed before this is first used!
252 */
253void
254DELAY(int n)
255{
256 int delta, prev_tick, tick, ticks_left;
257
258#ifdef DELAYDEBUG
259 int getit_calls = 1;
260 int n1;
261 static int state = 0;
262#endif
263
264 if (tsc_freq != 0 && !tsc_is_broken) {
265 uint64_t start, end, now;
266
267 sched_pin();
268 start = rdtsc();
269 end = start + (tsc_freq * n) / 1000000;
270 do {
271 cpu_spinwait();
272 now = rdtsc();
273 } while (now < end || (now > start && end < start));
274 sched_unpin();
275 return;
276 }
277#ifdef DELAYDEBUG
278 if (state == 0) {
279 state = 1;
280 for (n1 = 1; n1 <= 10000000; n1 *= 10)
281 DELAY(n1);
282 state = 2;
283 }
284 if (state == 1)
285 printf("DELAY(%d)...", n);
286#endif
287 /*
288 * Read the counter first, so that the rest of the setup overhead is
289 * counted. Guess the initial overhead is 20 usec (on most systems it
290 * takes about 1.5 usec for each of the i/o's in getit(). The loop
291 * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The
292 * multiplications and divisions to scale the count take a while).
293 *
294 * However, if ddb is active then use a fake counter since reading
295 * the i8254 counter involves acquiring a lock. ddb must not do
296 * locking for many reasons, but it calls here for at least atkbd
297 * input.
298 */
299#ifdef KDB
300 if (kdb_active)
301 prev_tick = 1;
302 else
303#endif
304 prev_tick = getit();
305 n -= 0; /* XXX actually guess no initial overhead */
306 /*
307 * Calculate (n * (i8254_freq / 1e6)) without using floating point
308 * and without any avoidable overflows.
309 */
310 if (n <= 0)
311 ticks_left = 0;
312 else if (n < 256)
313 /*
314 * Use fixed point to avoid a slow division by 1000000.
315 * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
316 * 2^15 is the first power of 2 that gives exact results
317 * for n between 0 and 256.
318 */
319 ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
320 else
321 /*
322 * Don't bother using fixed point, although gcc-2.7.2
323 * generates particularly poor code for the long long
324 * division, since even the slow way will complete long
325 * before the delay is up (unless we're interrupted).
326 */
327 ticks_left = ((u_int)n * (long long)i8254_freq + 999999)
328 / 1000000;
329
330 while (ticks_left > 0) {
331#ifdef KDB
332 if (kdb_active) {
333#ifdef PC98
334 outb(0x5f, 0);
335#else
336 inb(0x84);
337#endif
338 tick = prev_tick - 1;
339 if (tick <= 0)
340 tick = i8254_max_count;
341 } else
342#endif
343 tick = getit();
344#ifdef DELAYDEBUG
345 ++getit_calls;
346#endif
347 delta = prev_tick - tick;
348 prev_tick = tick;
349 if (delta < 0) {
350 delta += i8254_max_count;
351 /*
352 * Guard against i8254_max_count being wrong.
353 * This shouldn't happen in normal operation,
354 * but it may happen if set_i8254_freq() is
355 * traced.
356 */
357 if (delta < 0)
358 delta = 0;
359 }
360 ticks_left -= delta;
361 }
362#ifdef DELAYDEBUG
363 if (state == 1)
364 printf(" %d calls to getit() at %d usec each\n",
365 getit_calls, (n + 5) / getit_calls);
366#endif
367}
368
369static void
370set_i8254_freq(int mode, uint32_t period)
371{
372 int new_count;
373
374 mtx_lock_spin(&clock_lock);
375 if (mode == MODE_STOP) {
376 if (i8254_timecounter) {
377 mode = MODE_PERIODIC;
378 new_count = 0x10000;
379 } else
380 new_count = -1;
381 } else {
382 new_count = min(((uint64_t)i8254_freq * period +
383 0x80000000LLU) >> 32, 0x10000);
384 }
385 if (new_count == timer0_period)
386 goto out;
387 i8254_max_count = ((new_count & ~0xffff) != 0) ? 0xffff : new_count;
388 timer0_period = (mode == MODE_PERIODIC) ? new_count : -1;
389 switch (mode) {
390 case MODE_STOP:
391 outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT);
392 outb(TIMER_CNTR0, 0);
393 outb(TIMER_CNTR0, 0);
394 break;
395 case MODE_PERIODIC:
396 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
397 outb(TIMER_CNTR0, new_count & 0xff);
398 outb(TIMER_CNTR0, new_count >> 8);
399 break;
400 case MODE_ONESHOT:
401 outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT);
402 outb(TIMER_CNTR0, new_count & 0xff);
403 outb(TIMER_CNTR0, new_count >> 8);
404 break;
405 }
406out:
407 mtx_unlock_spin(&clock_lock);
408}
409
410static void
411i8254_restore(void)
412{
413
414 timer0_period = -2;
415 if (attimer_sc != NULL)
416 set_i8254_freq(attimer_sc->mode, attimer_sc->period);
417 else
418 set_i8254_freq(0, 0);
419}
420
421#ifndef __amd64__
422/*
423 * Restore all the timers non-atomically (XXX: should be atomically).
424 *
425 * This function is called from pmtimer_resume() to restore all the timers.
426 * This should not be necessary, but there are broken laptops that do not
427 * restore all the timers on resume.
428 * As long as pmtimer is not part of amd64 suport, skip this for the amd64
429 * case.
430 */
431void
432timer_restore(void)
433{
434
435 i8254_restore(); /* restore i8254_freq and hz */
436#ifndef PC98
437 atrtc_restore(); /* reenable RTC interrupts */
438#endif
439}
440#endif
441
442/* This is separate from startrtclock() so that it can be called early. */
443void
444i8254_init(void)
445{
446
447 mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
448#ifdef PC98
449 if (pc98_machine_type & M_8M)
450 i8254_freq = 1996800L; /* 1.9968 MHz */
451#endif
452 set_i8254_freq(0, 0);
453}
454
455void
456startrtclock()
457{
458
459 init_TSC();
460}
461
462void
463cpu_initclocks(void)
464{
465
466 init_TSC_tc();
467 cpu_initclocks_bsp();
468}
469
470static int
471sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
472{
473 int error;
474 u_int freq;
475
476 /*
477 * Use `i8254' instead of `timer' in external names because `timer'
478 * is is too generic. Should use it everywhere.
478 * is too generic. Should use it everywhere.
479 */
480 freq = i8254_freq;
481 error = sysctl_handle_int(oidp, &freq, 0, req);
482 if (error == 0 && req->newptr != NULL) {
483 i8254_freq = freq;
484 if (attimer_sc != NULL) {
485 set_i8254_freq(attimer_sc->mode, attimer_sc->period);
486 attimer_sc->tc.tc_frequency = freq;
487 } else {
488 set_i8254_freq(0, 0);
489 }
490 }
491 return (error);
492}
493
494SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
495 0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
496
497static unsigned
498i8254_get_timecount(struct timecounter *tc)
499{
500 device_t dev = (device_t)tc->tc_priv;
501 struct attimer_softc *sc = device_get_softc(dev);
502 register_t flags;
503 uint16_t count;
504 u_int high, low;
505
506 if (sc->period == 0)
507 return (i8254_max_count - getit());
508
509#ifdef __amd64__
510 flags = read_rflags();
511#else
512 flags = read_eflags();
513#endif
514 mtx_lock_spin(&clock_lock);
515
516 /* Select timer0 and latch counter value. */
517 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
518
519 low = inb(TIMER_CNTR0);
520 high = inb(TIMER_CNTR0);
521 count = i8254_max_count - ((high << 8) | low);
522 if (count < i8254_lastcount ||
523 (!i8254_ticked && (clkintr_pending ||
524 ((count < 20 || (!(flags & PSL_I) &&
525 count < i8254_max_count / 2u)) &&
526 i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
527 i8254_ticked = 1;
528 i8254_offset += i8254_max_count;
529 }
530 i8254_lastcount = count;
531 count += i8254_offset;
532 mtx_unlock_spin(&clock_lock);
533 return (count);
534}
535
536static int
537attimer_start(struct eventtimer *et,
538 struct bintime *first, struct bintime *period)
539{
540 device_t dev = (device_t)et->et_priv;
541 struct attimer_softc *sc = device_get_softc(dev);
542
543 if (period != NULL) {
544 sc->mode = MODE_PERIODIC;
545 sc->period = period->frac >> 32;
546 } else {
547 sc->mode = MODE_ONESHOT;
548 sc->period = first->frac >> 32;
549 }
550 if (!sc->intr_en) {
551 i8254_intsrc->is_pic->pic_enable_source(i8254_intsrc);
552 sc->intr_en = 1;
553 }
554 set_i8254_freq(sc->mode, sc->period);
555 return (0);
556}
557
558static int
559attimer_stop(struct eventtimer *et)
560{
561 device_t dev = (device_t)et->et_priv;
562 struct attimer_softc *sc = device_get_softc(dev);
563
564 sc->mode = MODE_STOP;
565 sc->period = 0;
566 set_i8254_freq(sc->mode, sc->period);
567 return (0);
568}
569
570#ifdef DEV_ISA
571/*
572 * Attach to the ISA PnP descriptors for the timer
573 */
574static struct isa_pnp_id attimer_ids[] = {
575 { 0x0001d041 /* PNP0100 */, "AT timer" },
576 { 0 }
577};
578
579#ifdef PC98
580static void
581pc98_alloc_resource(device_t dev)
582{
583 static bus_addr_t iat1[] = {0, 2, 4, 6};
584 static bus_addr_t iat2[] = {0, 4};
585 struct attimer_softc *sc;
586
587 sc = device_get_softc(dev);
588
589 sc->port_rid = 0;
590 bus_set_resource(dev, SYS_RES_IOPORT, sc->port_rid, IO_TIMER1, 1);
591 sc->port_res = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
592 &sc->port_rid, iat1, 4, RF_ACTIVE);
593 if (sc->port_res == NULL)
594 device_printf(dev, "Warning: Couldn't map I/O.\n");
595 else
596 isa_load_resourcev(sc->port_res, iat1, 4);
597
598 sc->port_rid2 = 4;
599 bus_set_resource(dev, SYS_RES_IOPORT, sc->port_rid2, TIMER_CNTR1, 1);
600 sc->port_res2 = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
601 &sc->port_rid2, iat2, 2, RF_ACTIVE);
602 if (sc->port_res2 == NULL)
603 device_printf(dev, "Warning: Couldn't map I/O.\n");
604 else
605 isa_load_resourcev(sc->port_res2, iat2, 2);
606}
607
608static void
609pc98_release_resource(device_t dev)
610{
611 struct attimer_softc *sc;
612
613 sc = device_get_softc(dev);
614
615 if (sc->port_res)
616 bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
617 sc->port_res);
618 if (sc->port_res2)
619 bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid2,
620 sc->port_res2);
621}
622#endif
623
624static int
625attimer_probe(device_t dev)
626{
627 int result;
628
629 result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids);
630 /* ENOENT means no PnP-ID, device is hinted. */
631 if (result == ENOENT) {
632 device_set_desc(dev, "AT timer");
633#ifdef PC98
634 /* To print resources correctly. */
635 pc98_alloc_resource(dev);
636 pc98_release_resource(dev);
637#endif
638 return (BUS_PROBE_LOW_PRIORITY);
639 }
640 return (result);
641}
642
643static int
644attimer_attach(device_t dev)
645{
646 struct attimer_softc *sc;
647 u_long s;
648 int i;
649
650 attimer_sc = sc = device_get_softc(dev);
651 bzero(sc, sizeof(struct attimer_softc));
652#ifdef PC98
653 pc98_alloc_resource(dev);
654#else
655 if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
656 &sc->port_rid, IO_TIMER1, IO_TIMER1 + 3, 4, RF_ACTIVE)))
657 device_printf(dev,"Warning: Couldn't map I/O.\n");
658#endif
659 i8254_intsrc = intr_lookup_source(0);
660 if (i8254_intsrc != NULL)
661 i8254_pending = i8254_intsrc->is_pic->pic_source_pending;
662 resource_int_value(device_get_name(dev), device_get_unit(dev),
663 "timecounter", &i8254_timecounter);
664 set_i8254_freq(0, 0);
665 if (i8254_timecounter) {
666 sc->tc.tc_get_timecount = i8254_get_timecount;
667 sc->tc.tc_counter_mask = 0xffff;
668 sc->tc.tc_frequency = i8254_freq;
669 sc->tc.tc_name = "i8254";
670 sc->tc.tc_quality = 0;
671 sc->tc.tc_priv = dev;
672 tc_init(&sc->tc);
673 }
674 if (resource_int_value(device_get_name(dev), device_get_unit(dev),
675 "clock", &i) != 0 || i != 0) {
676 sc->intr_rid = 0;
677 while (bus_get_resource(dev, SYS_RES_IRQ, sc->intr_rid,
678 &s, NULL) == 0 && s != 0)
679 sc->intr_rid++;
680 if (!(sc->intr_res = bus_alloc_resource(dev, SYS_RES_IRQ,
681 &sc->intr_rid, 0, 0, 1, RF_ACTIVE))) {
682 device_printf(dev,"Can't map interrupt.\n");
683 return (0);
684 }
685 /* Dirty hack, to make bus_setup_intr to not enable source. */
686 i8254_intsrc->is_handlers++;
687 if ((bus_setup_intr(dev, sc->intr_res,
688 INTR_MPSAFE | INTR_TYPE_CLK,
689 (driver_filter_t *)clkintr, NULL,
690 sc, &sc->intr_handler))) {
691 device_printf(dev, "Can't setup interrupt.\n");
692 i8254_intsrc->is_handlers--;
693 return (0);
694 }
695 i8254_intsrc->is_handlers--;
696 i8254_intsrc->is_pic->pic_enable_intr(i8254_intsrc);
697 sc->et.et_name = "i8254";
698 sc->et.et_flags = ET_FLAGS_PERIODIC;
699 if (!i8254_timecounter)
700 sc->et.et_flags |= ET_FLAGS_ONESHOT;
701 sc->et.et_quality = 100;
702 sc->et.et_frequency = i8254_freq;
703 sc->et.et_min_period.sec = 0;
704 sc->et.et_min_period.frac =
705 ((0x0002LLU << 48) / i8254_freq) << 16;
706 sc->et.et_max_period.sec = 0xffff / i8254_freq;
707 sc->et.et_max_period.frac =
708 ((0xfffeLLU << 48) / i8254_freq) << 16;
709 sc->et.et_start = attimer_start;
710 sc->et.et_stop = attimer_stop;
711 sc->et.et_priv = dev;
712 et_register(&sc->et);
713 }
714 return(0);
715}
716
717static int
718attimer_resume(device_t dev)
719{
720
721 i8254_restore();
722 return (0);
723}
724
725static device_method_t attimer_methods[] = {
726 /* Device interface */
727 DEVMETHOD(device_probe, attimer_probe),
728 DEVMETHOD(device_attach, attimer_attach),
729 DEVMETHOD(device_detach, bus_generic_detach),
730 DEVMETHOD(device_shutdown, bus_generic_shutdown),
731 DEVMETHOD(device_suspend, bus_generic_suspend),
732 DEVMETHOD(device_resume, attimer_resume),
733 { 0, 0 }
734};
735
736static driver_t attimer_driver = {
737 "attimer",
738 attimer_methods,
739 sizeof(struct attimer_softc),
740};
741
742static devclass_t attimer_devclass;
743
744DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
745DRIVER_MODULE(attimer, acpi, attimer_driver, attimer_devclass, 0, 0);
746
747#endif /* DEV_ISA */
479 */
480 freq = i8254_freq;
481 error = sysctl_handle_int(oidp, &freq, 0, req);
482 if (error == 0 && req->newptr != NULL) {
483 i8254_freq = freq;
484 if (attimer_sc != NULL) {
485 set_i8254_freq(attimer_sc->mode, attimer_sc->period);
486 attimer_sc->tc.tc_frequency = freq;
487 } else {
488 set_i8254_freq(0, 0);
489 }
490 }
491 return (error);
492}
493
494SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
495 0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
496
497static unsigned
498i8254_get_timecount(struct timecounter *tc)
499{
500 device_t dev = (device_t)tc->tc_priv;
501 struct attimer_softc *sc = device_get_softc(dev);
502 register_t flags;
503 uint16_t count;
504 u_int high, low;
505
506 if (sc->period == 0)
507 return (i8254_max_count - getit());
508
509#ifdef __amd64__
510 flags = read_rflags();
511#else
512 flags = read_eflags();
513#endif
514 mtx_lock_spin(&clock_lock);
515
516 /* Select timer0 and latch counter value. */
517 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
518
519 low = inb(TIMER_CNTR0);
520 high = inb(TIMER_CNTR0);
521 count = i8254_max_count - ((high << 8) | low);
522 if (count < i8254_lastcount ||
523 (!i8254_ticked && (clkintr_pending ||
524 ((count < 20 || (!(flags & PSL_I) &&
525 count < i8254_max_count / 2u)) &&
526 i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
527 i8254_ticked = 1;
528 i8254_offset += i8254_max_count;
529 }
530 i8254_lastcount = count;
531 count += i8254_offset;
532 mtx_unlock_spin(&clock_lock);
533 return (count);
534}
535
536static int
537attimer_start(struct eventtimer *et,
538 struct bintime *first, struct bintime *period)
539{
540 device_t dev = (device_t)et->et_priv;
541 struct attimer_softc *sc = device_get_softc(dev);
542
543 if (period != NULL) {
544 sc->mode = MODE_PERIODIC;
545 sc->period = period->frac >> 32;
546 } else {
547 sc->mode = MODE_ONESHOT;
548 sc->period = first->frac >> 32;
549 }
550 if (!sc->intr_en) {
551 i8254_intsrc->is_pic->pic_enable_source(i8254_intsrc);
552 sc->intr_en = 1;
553 }
554 set_i8254_freq(sc->mode, sc->period);
555 return (0);
556}
557
558static int
559attimer_stop(struct eventtimer *et)
560{
561 device_t dev = (device_t)et->et_priv;
562 struct attimer_softc *sc = device_get_softc(dev);
563
564 sc->mode = MODE_STOP;
565 sc->period = 0;
566 set_i8254_freq(sc->mode, sc->period);
567 return (0);
568}
569
570#ifdef DEV_ISA
571/*
572 * Attach to the ISA PnP descriptors for the timer
573 */
574static struct isa_pnp_id attimer_ids[] = {
575 { 0x0001d041 /* PNP0100 */, "AT timer" },
576 { 0 }
577};
578
579#ifdef PC98
580static void
581pc98_alloc_resource(device_t dev)
582{
583 static bus_addr_t iat1[] = {0, 2, 4, 6};
584 static bus_addr_t iat2[] = {0, 4};
585 struct attimer_softc *sc;
586
587 sc = device_get_softc(dev);
588
589 sc->port_rid = 0;
590 bus_set_resource(dev, SYS_RES_IOPORT, sc->port_rid, IO_TIMER1, 1);
591 sc->port_res = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
592 &sc->port_rid, iat1, 4, RF_ACTIVE);
593 if (sc->port_res == NULL)
594 device_printf(dev, "Warning: Couldn't map I/O.\n");
595 else
596 isa_load_resourcev(sc->port_res, iat1, 4);
597
598 sc->port_rid2 = 4;
599 bus_set_resource(dev, SYS_RES_IOPORT, sc->port_rid2, TIMER_CNTR1, 1);
600 sc->port_res2 = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
601 &sc->port_rid2, iat2, 2, RF_ACTIVE);
602 if (sc->port_res2 == NULL)
603 device_printf(dev, "Warning: Couldn't map I/O.\n");
604 else
605 isa_load_resourcev(sc->port_res2, iat2, 2);
606}
607
608static void
609pc98_release_resource(device_t dev)
610{
611 struct attimer_softc *sc;
612
613 sc = device_get_softc(dev);
614
615 if (sc->port_res)
616 bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
617 sc->port_res);
618 if (sc->port_res2)
619 bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid2,
620 sc->port_res2);
621}
622#endif
623
624static int
625attimer_probe(device_t dev)
626{
627 int result;
628
629 result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids);
630 /* ENOENT means no PnP-ID, device is hinted. */
631 if (result == ENOENT) {
632 device_set_desc(dev, "AT timer");
633#ifdef PC98
634 /* To print resources correctly. */
635 pc98_alloc_resource(dev);
636 pc98_release_resource(dev);
637#endif
638 return (BUS_PROBE_LOW_PRIORITY);
639 }
640 return (result);
641}
642
643static int
644attimer_attach(device_t dev)
645{
646 struct attimer_softc *sc;
647 u_long s;
648 int i;
649
650 attimer_sc = sc = device_get_softc(dev);
651 bzero(sc, sizeof(struct attimer_softc));
652#ifdef PC98
653 pc98_alloc_resource(dev);
654#else
655 if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
656 &sc->port_rid, IO_TIMER1, IO_TIMER1 + 3, 4, RF_ACTIVE)))
657 device_printf(dev,"Warning: Couldn't map I/O.\n");
658#endif
659 i8254_intsrc = intr_lookup_source(0);
660 if (i8254_intsrc != NULL)
661 i8254_pending = i8254_intsrc->is_pic->pic_source_pending;
662 resource_int_value(device_get_name(dev), device_get_unit(dev),
663 "timecounter", &i8254_timecounter);
664 set_i8254_freq(0, 0);
665 if (i8254_timecounter) {
666 sc->tc.tc_get_timecount = i8254_get_timecount;
667 sc->tc.tc_counter_mask = 0xffff;
668 sc->tc.tc_frequency = i8254_freq;
669 sc->tc.tc_name = "i8254";
670 sc->tc.tc_quality = 0;
671 sc->tc.tc_priv = dev;
672 tc_init(&sc->tc);
673 }
674 if (resource_int_value(device_get_name(dev), device_get_unit(dev),
675 "clock", &i) != 0 || i != 0) {
676 sc->intr_rid = 0;
677 while (bus_get_resource(dev, SYS_RES_IRQ, sc->intr_rid,
678 &s, NULL) == 0 && s != 0)
679 sc->intr_rid++;
680 if (!(sc->intr_res = bus_alloc_resource(dev, SYS_RES_IRQ,
681 &sc->intr_rid, 0, 0, 1, RF_ACTIVE))) {
682 device_printf(dev,"Can't map interrupt.\n");
683 return (0);
684 }
685 /* Dirty hack, to make bus_setup_intr to not enable source. */
686 i8254_intsrc->is_handlers++;
687 if ((bus_setup_intr(dev, sc->intr_res,
688 INTR_MPSAFE | INTR_TYPE_CLK,
689 (driver_filter_t *)clkintr, NULL,
690 sc, &sc->intr_handler))) {
691 device_printf(dev, "Can't setup interrupt.\n");
692 i8254_intsrc->is_handlers--;
693 return (0);
694 }
695 i8254_intsrc->is_handlers--;
696 i8254_intsrc->is_pic->pic_enable_intr(i8254_intsrc);
697 sc->et.et_name = "i8254";
698 sc->et.et_flags = ET_FLAGS_PERIODIC;
699 if (!i8254_timecounter)
700 sc->et.et_flags |= ET_FLAGS_ONESHOT;
701 sc->et.et_quality = 100;
702 sc->et.et_frequency = i8254_freq;
703 sc->et.et_min_period.sec = 0;
704 sc->et.et_min_period.frac =
705 ((0x0002LLU << 48) / i8254_freq) << 16;
706 sc->et.et_max_period.sec = 0xffff / i8254_freq;
707 sc->et.et_max_period.frac =
708 ((0xfffeLLU << 48) / i8254_freq) << 16;
709 sc->et.et_start = attimer_start;
710 sc->et.et_stop = attimer_stop;
711 sc->et.et_priv = dev;
712 et_register(&sc->et);
713 }
714 return(0);
715}
716
717static int
718attimer_resume(device_t dev)
719{
720
721 i8254_restore();
722 return (0);
723}
724
725static device_method_t attimer_methods[] = {
726 /* Device interface */
727 DEVMETHOD(device_probe, attimer_probe),
728 DEVMETHOD(device_attach, attimer_attach),
729 DEVMETHOD(device_detach, bus_generic_detach),
730 DEVMETHOD(device_shutdown, bus_generic_shutdown),
731 DEVMETHOD(device_suspend, bus_generic_suspend),
732 DEVMETHOD(device_resume, attimer_resume),
733 { 0, 0 }
734};
735
736static driver_t attimer_driver = {
737 "attimer",
738 attimer_methods,
739 sizeof(struct attimer_softc),
740};
741
742static devclass_t attimer_devclass;
743
744DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
745DRIVER_MODULE(attimer, acpi, attimer_driver, attimer_devclass, 0, 0);
746
747#endif /* DEV_ISA */