]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/pc98/cbus/clock.c
MFC r199852, r202387, r202441, r202534:
[FreeBSD/stable/8.git] / sys / pc98 / cbus / clock.c
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * William Jolitz and Don Ahn.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *      from: @(#)clock.c       7.2 (Berkeley) 5/12/91
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 /*
39  * Routines to handle clock hardware.
40  */
41
42 /*
43  * modified for PC98 by Kakefuda
44  */
45
46 #include "opt_apic.h"
47 #include "opt_clock.h"
48 #include "opt_kdtrace.h"
49 #include "opt_isa.h"
50 #include "opt_mca.h"
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/bus.h>
55 #include <sys/lock.h>
56 #include <sys/kdb.h>
57 #include <sys/mutex.h>
58 #include <sys/proc.h>
59 #include <sys/timetc.h>
60 #include <sys/kernel.h>
61 #include <sys/module.h>
62 #include <sys/smp.h>
63 #include <sys/sysctl.h>
64
65 #include <machine/clock.h>
66 #include <machine/cpu.h>
67 #include <machine/frame.h>
68 #include <machine/intr_machdep.h>
69 #include <machine/md_var.h>
70 #include <machine/apicvar.h>
71 #include <machine/ppireg.h>
72 #include <machine/timerreg.h>
73 #include <machine/smp.h>
74
75 #include <pc98/pc98/pc98_machdep.h>
76 #ifdef DEV_ISA
77 #include <pc98/cbus/cbus.h>
78 #include <isa/isavar.h>
79 #endif
80
81 #ifdef KDTRACE_HOOKS
82 #include <sys/dtrace_bsd.h>
83 #endif
84
85 #define TIMER_DIV(x) ((i8254_freq + (x) / 2) / (x))
86
87 int     clkintr_pending;
88 #ifndef TIMER_FREQ
89 #define TIMER_FREQ   2457600
90 #endif
91 u_int   i8254_freq = TIMER_FREQ;
92 TUNABLE_INT("hw.i8254.freq", &i8254_freq);
93 int     i8254_max_count;
94 static int i8254_real_max_count;
95
96 static  struct mtx clock_lock;
97 static  struct intsrc *i8254_intsrc;
98 static  u_int32_t i8254_lastcount;
99 static  u_int32_t i8254_offset;
100 static  int     (*i8254_pending)(struct intsrc *);
101 static  int     i8254_ticked;
102 static  enum lapic_clock using_lapic_timer = LAPIC_CLOCK_NONE;
103
104 /* Values for timerX_state: */
105 #define RELEASED        0
106 #define RELEASE_PENDING 1
107 #define ACQUIRED        2
108 #define ACQUIRE_PENDING 3
109
110 static  u_char  timer1_state;
111
112 static  unsigned i8254_get_timecount(struct timecounter *tc);
113 static  unsigned i8254_simple_get_timecount(struct timecounter *tc);
114 static  void    set_i8254_freq(u_int freq, int intr_freq);
115
116 static struct timecounter i8254_timecounter = {
117         i8254_get_timecount,    /* get_timecount */
118         0,                      /* no poll_pps */
119         ~0u,                    /* counter_mask */
120         0,                      /* frequency */
121         "i8254",                /* name */
122         0                       /* quality */
123 };
124
125 int
126 hardclockintr(struct trapframe *frame)
127 {
128
129         if (PCPU_GET(cpuid) == 0)
130                 hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
131         else
132                 hardclock_cpu(TRAPF_USERMODE(frame));
133         return (FILTER_HANDLED);
134 }
135
136 int
137 statclockintr(struct trapframe *frame)
138 {
139
140         return (FILTER_HANDLED);
141 }
142
143 int
144 profclockintr(struct trapframe *frame)
145 {
146
147         return (FILTER_HANDLED);
148 }
149
150 static int
151 clkintr(struct trapframe *frame)
152 {
153
154         if (timecounter->tc_get_timecount == i8254_get_timecount) {
155                 mtx_lock_spin(&clock_lock);
156                 if (i8254_ticked)
157                         i8254_ticked = 0;
158                 else {
159                         i8254_offset += i8254_max_count;
160                         i8254_lastcount = 0;
161                 }
162                 clkintr_pending = 0;
163                 mtx_unlock_spin(&clock_lock);
164         }
165         KASSERT(using_lapic_timer == LAPIC_CLOCK_NONE,
166             ("clk interrupt enabled with lapic timer"));
167
168 #ifdef KDTRACE_HOOKS
169         /*
170          * If the DTrace hooks are configured and a callback function
171          * has been registered, then call it to process the high speed
172          * timers.
173          */
174         int cpu = PCPU_GET(cpuid);
175         if (lapic_cyclic_clock_func[cpu] != NULL)
176                 (*lapic_cyclic_clock_func[cpu])(frame);
177 #endif
178
179 #ifdef SMP
180         if (smp_started)
181                 ipi_all_but_self(IPI_HARDCLOCK);
182 #endif 
183         hardclockintr(frame);
184         return (FILTER_HANDLED);
185 }
186
187 int
188 timer_spkr_acquire(void)
189 {
190         int mode;
191
192         mode = TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT;
193
194         if (timer1_state != RELEASED)
195                 return (-1);
196         timer1_state = ACQUIRED;
197
198         /*
199          * This access to the timer registers is as atomic as possible
200          * because it is a single instruction.  We could do better if we
201          * knew the rate.  Use of splclock() limits glitches to 10-100us,
202          * and this is probably good enough for timer2, so we aren't as
203          * careful with it as with timer0.
204          */
205         outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f));
206         ppi_spkr_on();          /* enable counter1 output to speaker */
207
208         return (0);
209 }
210
211 int
212 timer_spkr_release(void)
213 {
214
215         if (timer1_state != ACQUIRED)
216                 return (-1);
217         timer1_state = RELEASED;
218         outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT);
219         ppi_spkr_off();         /* disable counter1 output to speaker */
220         return (0);
221 }
222
223 void
224 timer_spkr_setfreq(int freq)
225 {
226
227         freq = i8254_freq / freq;
228         mtx_lock_spin(&clock_lock);
229         outb(TIMER_CNTR1, (freq) & 0xff);
230         outb(TIMER_CNTR1, (freq) >> 8);
231         mtx_unlock_spin(&clock_lock);
232 }
233
234
235 static int
236 getit(void)
237 {
238         int high, low;
239
240         mtx_lock_spin(&clock_lock);
241
242         /* Select timer0 and latch counter value. */
243         outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
244
245         low = inb(TIMER_CNTR0);
246         high = inb(TIMER_CNTR0);
247
248         mtx_unlock_spin(&clock_lock);
249         return ((high << 8) | low);
250 }
251
252 /*
253  * Wait "n" microseconds.
254  * Relies on timer 1 counting down from (i8254_freq / hz)
255  * Note: timer had better have been programmed before this is first used!
256  */
257 void
258 DELAY(int n)
259 {
260         int delta, prev_tick, tick, ticks_left;
261
262 #ifdef DELAYDEBUG
263         int getit_calls = 1;
264         int n1;
265         static int state = 0;
266
267         if (state == 0) {
268                 state = 1;
269                 for (n1 = 1; n1 <= 10000000; n1 *= 10)
270                         DELAY(n1);
271                 state = 2;
272         }
273         if (state == 1)
274                 printf("DELAY(%d)...", n);
275 #endif
276         /*
277          * Read the counter first, so that the rest of the setup overhead is
278          * counted.  Guess the initial overhead is 20 usec (on most systems it
279          * takes about 1.5 usec for each of the i/o's in getit().  The loop
280          * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
281          * multiplications and divisions to scale the count take a while).
282          *
283          * However, if ddb is active then use a fake counter since reading
284          * the i8254 counter involves acquiring a lock.  ddb must not do
285          * locking for many reasons, but it calls here for at least atkbd
286          * input.
287          */
288 #ifdef KDB
289         if (kdb_active)
290                 prev_tick = 1;
291         else
292 #endif
293                 prev_tick = getit();
294         n -= 0;                 /* XXX actually guess no initial overhead */
295         /*
296          * Calculate (n * (i8254_freq / 1e6)) without using floating point
297          * and without any avoidable overflows.
298          */
299         if (n <= 0)
300                 ticks_left = 0;
301         else if (n < 256)
302                 /*
303                  * Use fixed point to avoid a slow division by 1000000.
304                  * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
305                  * 2^15 is the first power of 2 that gives exact results
306                  * for n between 0 and 256.
307                  */
308                 ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
309         else
310                 /*
311                  * Don't bother using fixed point, although gcc-2.7.2
312                  * generates particularly poor code for the long long
313                  * division, since even the slow way will complete long
314                  * before the delay is up (unless we're interrupted).
315                  */
316                 ticks_left = ((u_int)n * (long long)i8254_freq + 999999)
317                              / 1000000;
318
319         while (ticks_left > 0) {
320 #ifdef KDB
321                 if (kdb_active) {
322                         outb(0x5f, 0);
323                         tick = prev_tick - 1;
324                         if (tick <= 0)
325                                 tick = i8254_max_count;
326                 } else
327 #endif
328                         tick = getit();
329 #ifdef DELAYDEBUG
330                 ++getit_calls;
331 #endif
332                 delta = prev_tick - tick;
333                 prev_tick = tick;
334                 if (delta < 0) {
335                         delta += i8254_max_count;
336                         /*
337                          * Guard against i8254_max_count being wrong.
338                          * This shouldn't happen in normal operation,
339                          * but it may happen if set_i8254_freq() is
340                          * traced.
341                          */
342                         if (delta < 0)
343                                 delta = 0;
344                 }
345                 ticks_left -= delta;
346         }
347 #ifdef DELAYDEBUG
348         if (state == 1)
349                 printf(" %d calls to getit() at %d usec each\n",
350                        getit_calls, (n + 5) / getit_calls);
351 #endif
352 }
353
354 static void
355 set_i8254_freq(u_int freq, int intr_freq)
356 {
357         int new_i8254_real_max_count;
358
359         i8254_timecounter.tc_frequency = freq;
360         mtx_lock_spin(&clock_lock);
361         i8254_freq = freq;
362         if (using_lapic_timer != LAPIC_CLOCK_NONE)
363                 new_i8254_real_max_count = 0x10000;
364         else
365                 new_i8254_real_max_count = TIMER_DIV(intr_freq);
366         if (new_i8254_real_max_count != i8254_real_max_count) {
367                 i8254_real_max_count = new_i8254_real_max_count;
368                 if (i8254_real_max_count == 0x10000)
369                         i8254_max_count = 0xffff;
370                 else
371                         i8254_max_count = i8254_real_max_count;
372                 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
373                 outb(TIMER_CNTR0, i8254_real_max_count & 0xff);
374                 outb(TIMER_CNTR0, i8254_real_max_count >> 8);
375         }
376         mtx_unlock_spin(&clock_lock);
377 }
378
379 static void
380 i8254_restore(void)
381 {
382
383         mtx_lock_spin(&clock_lock);
384         outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
385         outb(TIMER_CNTR0, i8254_real_max_count & 0xff);
386         outb(TIMER_CNTR0, i8254_real_max_count >> 8);
387         mtx_unlock_spin(&clock_lock);
388 }
389
390 /*
391  * Restore all the timers non-atomically (XXX: should be atomically).
392  *
393  * This function is called from pmtimer_resume() to restore all the timers.
394  * This should not be necessary, but there are broken laptops that do not
395  * restore all the timers on resume.
396  */
397 void
398 timer_restore(void)
399 {
400
401         i8254_restore();                /* restore i8254_freq and hz */
402 }
403
404 /* This is separate from startrtclock() so that it can be called early. */
405 void
406 i8254_init(void)
407 {
408
409         mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
410
411         if (pc98_machine_type & M_8M)
412                 i8254_freq = 1996800L; /* 1.9968 MHz */
413         else
414                 i8254_freq = 2457600L; /* 2.4576 MHz */
415
416         set_i8254_freq(i8254_freq, hz);
417 }
418
419 void
420 startrtclock()
421 {
422
423         set_i8254_freq(i8254_freq, hz);
424         tc_init(&i8254_timecounter);
425
426         init_TSC();
427 }
428
429 /*
430  * Start both clocks running.
431  */
432 void
433 cpu_initclocks()
434 {
435
436 #ifdef DEV_APIC
437         using_lapic_timer = lapic_setup_clock();
438 #endif
439         /*
440          * If we aren't using the local APIC timer to drive the kernel
441          * clocks, setup the interrupt handler for the 8254 timer 0 so
442          * that it can drive hardclock().  Otherwise, change the 8254
443          * timecounter to user a simpler algorithm.
444          */
445         if (using_lapic_timer == LAPIC_CLOCK_NONE) {
446                 intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL,
447                     NULL, INTR_TYPE_CLK, NULL);
448                 i8254_intsrc = intr_lookup_source(0);
449                 if (i8254_intsrc != NULL)
450                         i8254_pending =
451                             i8254_intsrc->is_pic->pic_source_pending;
452         } else {
453                 i8254_timecounter.tc_get_timecount =
454                     i8254_simple_get_timecount;
455                 i8254_timecounter.tc_counter_mask = 0xffff;
456                 set_i8254_freq(i8254_freq, hz);
457         }
458
459         init_TSC_tc();
460 }
461
462 void
463 cpu_startprofclock(void)
464 {
465 }
466
467 void
468 cpu_stopprofclock(void)
469 {
470 }
471
472 static int
473 sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
474 {
475         int error;
476         u_int freq;
477
478         /*
479          * Use `i8254' instead of `timer' in external names because `timer'
480          * is is too generic.  Should use it everywhere.
481          */
482         freq = i8254_freq;
483         error = sysctl_handle_int(oidp, &freq, 0, req);
484         if (error == 0 && req->newptr != NULL)
485                 set_i8254_freq(freq, hz);
486         return (error);
487 }
488
489 SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
490     0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
491
492 static unsigned
493 i8254_simple_get_timecount(struct timecounter *tc)
494 {
495
496         return (i8254_max_count - getit());
497 }
498
499 static unsigned
500 i8254_get_timecount(struct timecounter *tc)
501 {
502         u_int count;
503         u_int high, low;
504         u_int eflags;
505
506         eflags = read_eflags();
507         mtx_lock_spin(&clock_lock);
508
509         /* Select timer0 and latch counter value. */
510         outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
511
512         low = inb(TIMER_CNTR0);
513         high = inb(TIMER_CNTR0);
514         count = i8254_max_count - ((high << 8) | low);
515         if (count < i8254_lastcount ||
516             (!i8254_ticked && (clkintr_pending ||
517             ((count < 20 || (!(eflags & PSL_I) &&
518             count < i8254_max_count / 2u)) &&
519             i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
520                 i8254_ticked = 1;
521                 i8254_offset += i8254_max_count;
522         }
523         i8254_lastcount = count;
524         count += i8254_offset;
525         mtx_unlock_spin(&clock_lock);
526         return (count);
527 }
528
529 #ifdef DEV_ISA
530 /*
531  * Attach to the ISA PnP descriptors for the timer
532  */
533 static struct isa_pnp_id attimer_ids[] = {
534         { 0x0001d041 /* PNP0100 */, "AT timer" },
535         { 0 }
536 };
537
538 static int
539 attimer_probe(device_t dev)
540 {
541         int result;
542         
543         result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids);
544         if (result <= 0)
545                 device_quiet(dev);
546         return(result);
547 }
548
549 static int
550 attimer_attach(device_t dev)
551 {
552         return(0);
553 }
554
555 static device_method_t attimer_methods[] = {
556         /* Device interface */
557         DEVMETHOD(device_probe,         attimer_probe),
558         DEVMETHOD(device_attach,        attimer_attach),
559         DEVMETHOD(device_detach,        bus_generic_detach),
560         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
561         DEVMETHOD(device_suspend,       bus_generic_suspend),
562         DEVMETHOD(device_resume,        bus_generic_resume),
563         { 0, 0 }
564 };
565
566 static driver_t attimer_driver = {
567         "attimer",
568         attimer_methods,
569         1,              /* no softc */
570 };
571
572 static devclass_t attimer_devclass;
573
574 DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
575
576 #endif /* DEV_ISA */