]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/pc98/cbus/clock.c
Now that all platforms use genclock, shuffle things around slightly
[FreeBSD/FreeBSD.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_isa.h"
49 #include "opt_mca.h"
50
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/bus.h>
54 #include <sys/lock.h>
55 #include <sys/kdb.h>
56 #include <sys/mutex.h>
57 #include <sys/proc.h>
58 #include <sys/timetc.h>
59 #include <sys/kernel.h>
60 #include <sys/module.h>
61 #include <sys/sysctl.h>
62
63 #include <machine/clock.h>
64 #include <machine/cpu.h>
65 #include <machine/frame.h>
66 #include <machine/intr_machdep.h>
67 #include <machine/md_var.h>
68 #ifdef DEV_APIC
69 #include <machine/apicvar.h>
70 #endif
71 #include <machine/ppireg.h>
72 #include <machine/timerreg.h>
73
74 #include <pc98/pc98/pc98_machdep.h>
75 #ifdef DEV_ISA
76 #include <pc98/cbus/cbus.h>
77 #include <isa/isavar.h>
78 #endif
79
80 #define TIMER_DIV(x) ((i8254_freq + (x) / 2) / (x))
81
82 int     clkintr_pending;
83 int     statclock_disable;
84 #ifndef TIMER_FREQ
85 #define TIMER_FREQ   2457600
86 #endif
87 u_int   i8254_freq = TIMER_FREQ;
88 TUNABLE_INT("hw.i8254.freq", &i8254_freq);
89 int     i8254_max_count;
90 static int i8254_real_max_count;
91
92 static  struct mtx clock_lock;
93 static  struct intsrc *i8254_intsrc;
94 static  u_int32_t i8254_lastcount;
95 static  u_int32_t i8254_offset;
96 static  int     (*i8254_pending)(struct intsrc *);
97 static  int     i8254_ticked;
98 static  int     using_lapic_timer;
99
100 /* Values for timerX_state: */
101 #define RELEASED        0
102 #define RELEASE_PENDING 1
103 #define ACQUIRED        2
104 #define ACQUIRE_PENDING 3
105
106 static  u_char  timer1_state;
107
108 static  unsigned i8254_get_timecount(struct timecounter *tc);
109 static  unsigned i8254_simple_get_timecount(struct timecounter *tc);
110 static  void    set_i8254_freq(u_int freq, int intr_freq);
111
112 static struct timecounter i8254_timecounter = {
113         i8254_get_timecount,    /* get_timecount */
114         0,                      /* no poll_pps */
115         ~0u,                    /* counter_mask */
116         0,                      /* frequency */
117         "i8254",                /* name */
118         0                       /* quality */
119 };
120
121 static int
122 clkintr(struct trapframe *frame)
123 {
124
125         if (timecounter->tc_get_timecount == i8254_get_timecount) {
126                 mtx_lock_spin(&clock_lock);
127                 if (i8254_ticked)
128                         i8254_ticked = 0;
129                 else {
130                         i8254_offset += i8254_max_count;
131                         i8254_lastcount = 0;
132                 }
133                 clkintr_pending = 0;
134                 mtx_unlock_spin(&clock_lock);
135         }
136         KASSERT(!using_lapic_timer, ("clk interrupt enabled with lapic timer"));
137         hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
138         return (FILTER_HANDLED);
139 }
140
141 int
142 timer_spkr_acquire(void)
143 {
144         int mode;
145
146         mode = TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT;
147
148         if (timer1_state != RELEASED)
149                 return (-1);
150         timer1_state = ACQUIRED;
151
152         /*
153          * This access to the timer registers is as atomic as possible
154          * because it is a single instruction.  We could do better if we
155          * knew the rate.  Use of splclock() limits glitches to 10-100us,
156          * and this is probably good enough for timer2, so we aren't as
157          * careful with it as with timer0.
158          */
159         outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f));
160         ppi_spkr_on();          /* enable counter1 output to speaker */
161
162         return (0);
163 }
164
165 int
166 timer_spkr_release(void)
167 {
168
169         if (timer1_state != ACQUIRED)
170                 return (-1);
171         timer1_state = RELEASED;
172         outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT);
173         ppi_spkr_off();         /* disable counter1 output to speaker */
174         return (0);
175 }
176
177 void
178 timer_spkr_setfreq(int freq)
179 {
180
181         freq = i8254_freq / freq;
182         mtx_lock_spin(&clock_lock);
183         outb(TIMER_CNTR1, (freq) & 0xff);
184         outb(TIMER_CNTR1, (freq) >> 8);
185         mtx_unlock_spin(&clock_lock);
186 }
187
188
189 static int
190 getit(void)
191 {
192         int high, low;
193
194         mtx_lock_spin(&clock_lock);
195
196         /* Select timer0 and latch counter value. */
197         outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
198
199         low = inb(TIMER_CNTR0);
200         high = inb(TIMER_CNTR0);
201
202         mtx_unlock_spin(&clock_lock);
203         return ((high << 8) | low);
204 }
205
206 /*
207  * Wait "n" microseconds.
208  * Relies on timer 1 counting down from (i8254_freq / hz)
209  * Note: timer had better have been programmed before this is first used!
210  */
211 void
212 DELAY(int n)
213 {
214         int delta, prev_tick, tick, ticks_left;
215
216 #ifdef DELAYDEBUG
217         int getit_calls = 1;
218         int n1;
219         static int state = 0;
220
221         if (state == 0) {
222                 state = 1;
223                 for (n1 = 1; n1 <= 10000000; n1 *= 10)
224                         DELAY(n1);
225                 state = 2;
226         }
227         if (state == 1)
228                 printf("DELAY(%d)...", n);
229 #endif
230         /*
231          * Read the counter first, so that the rest of the setup overhead is
232          * counted.  Guess the initial overhead is 20 usec (on most systems it
233          * takes about 1.5 usec for each of the i/o's in getit().  The loop
234          * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
235          * multiplications and divisions to scale the count take a while).
236          *
237          * However, if ddb is active then use a fake counter since reading
238          * the i8254 counter involves acquiring a lock.  ddb must not do
239          * locking for many reasons, but it calls here for at least atkbd
240          * input.
241          */
242 #ifdef KDB
243         if (kdb_active)
244                 prev_tick = 1;
245         else
246 #endif
247                 prev_tick = getit();
248         n -= 0;                 /* XXX actually guess no initial overhead */
249         /*
250          * Calculate (n * (i8254_freq / 1e6)) without using floating point
251          * and without any avoidable overflows.
252          */
253         if (n <= 0)
254                 ticks_left = 0;
255         else if (n < 256)
256                 /*
257                  * Use fixed point to avoid a slow division by 1000000.
258                  * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
259                  * 2^15 is the first power of 2 that gives exact results
260                  * for n between 0 and 256.
261                  */
262                 ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
263         else
264                 /*
265                  * Don't bother using fixed point, although gcc-2.7.2
266                  * generates particularly poor code for the long long
267                  * division, since even the slow way will complete long
268                  * before the delay is up (unless we're interrupted).
269                  */
270                 ticks_left = ((u_int)n * (long long)i8254_freq + 999999)
271                              / 1000000;
272
273         while (ticks_left > 0) {
274 #ifdef KDB
275                 if (kdb_active) {
276                         outb(0x5f, 0);
277                         tick = prev_tick - 1;
278                         if (tick <= 0)
279                                 tick = i8254_max_count;
280                 } else
281 #endif
282                         tick = getit();
283 #ifdef DELAYDEBUG
284                 ++getit_calls;
285 #endif
286                 delta = prev_tick - tick;
287                 prev_tick = tick;
288                 if (delta < 0) {
289                         delta += i8254_max_count;
290                         /*
291                          * Guard against i8254_max_count being wrong.
292                          * This shouldn't happen in normal operation,
293                          * but it may happen if set_i8254_freq() is
294                          * traced.
295                          */
296                         if (delta < 0)
297                                 delta = 0;
298                 }
299                 ticks_left -= delta;
300         }
301 #ifdef DELAYDEBUG
302         if (state == 1)
303                 printf(" %d calls to getit() at %d usec each\n",
304                        getit_calls, (n + 5) / getit_calls);
305 #endif
306 }
307
308 static void
309 set_i8254_freq(u_int freq, int intr_freq)
310 {
311         int new_i8254_real_max_count;
312
313         i8254_timecounter.tc_frequency = freq;
314         mtx_lock_spin(&clock_lock);
315         i8254_freq = freq;
316         if (using_lapic_timer)
317                 new_i8254_real_max_count = 0x10000;
318         else
319                 new_i8254_real_max_count = TIMER_DIV(intr_freq);
320         if (new_i8254_real_max_count != i8254_real_max_count) {
321                 i8254_real_max_count = new_i8254_real_max_count;
322                 if (i8254_real_max_count == 0x10000)
323                         i8254_max_count = 0xffff;
324                 else
325                         i8254_max_count = i8254_real_max_count;
326                 outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
327                 outb(TIMER_CNTR0, i8254_real_max_count & 0xff);
328                 outb(TIMER_CNTR0, i8254_real_max_count >> 8);
329         }
330         mtx_unlock_spin(&clock_lock);
331 }
332
333 static void
334 i8254_restore(void)
335 {
336
337         mtx_lock_spin(&clock_lock);
338         outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
339         outb(TIMER_CNTR0, i8254_real_max_count & 0xff);
340         outb(TIMER_CNTR0, i8254_real_max_count >> 8);
341         mtx_unlock_spin(&clock_lock);
342 }
343
344 /*
345  * Restore all the timers non-atomically (XXX: should be atomically).
346  *
347  * This function is called from pmtimer_resume() to restore all the timers.
348  * This should not be necessary, but there are broken laptops that do not
349  * restore all the timers on resume.
350  */
351 void
352 timer_restore(void)
353 {
354
355         i8254_restore();                /* restore i8254_freq and hz */
356 }
357
358 /* This is separate from startrtclock() so that it can be called early. */
359 void
360 i8254_init(void)
361 {
362
363         mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
364
365         if (pc98_machine_type & M_8M)
366                 i8254_freq = 1996800L; /* 1.9968 MHz */
367         else
368                 i8254_freq = 2457600L; /* 2.4576 MHz */
369
370         set_i8254_freq(i8254_freq, hz);
371 }
372
373 void
374 startrtclock()
375 {
376
377         set_i8254_freq(i8254_freq, hz);
378         tc_init(&i8254_timecounter);
379
380         init_TSC();
381 }
382
383 /*
384  * Start both clocks running.
385  */
386 void
387 cpu_initclocks()
388 {
389
390 #ifdef DEV_APIC
391         using_lapic_timer = lapic_setup_clock();
392 #endif
393         /*
394          * If we aren't using the local APIC timer to drive the kernel
395          * clocks, setup the interrupt handler for the 8254 timer 0 so
396          * that it can drive hardclock().  Otherwise, change the 8254
397          * timecounter to user a simpler algorithm.
398          */
399         if (!using_lapic_timer) {
400                 intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL,
401                     NULL, INTR_TYPE_CLK, NULL);
402                 i8254_intsrc = intr_lookup_source(0);
403                 if (i8254_intsrc != NULL)
404                         i8254_pending =
405                             i8254_intsrc->is_pic->pic_source_pending;
406         } else {
407                 i8254_timecounter.tc_get_timecount =
408                     i8254_simple_get_timecount;
409                 i8254_timecounter.tc_counter_mask = 0xffff;
410                 set_i8254_freq(i8254_freq, hz);
411         }
412
413         init_TSC_tc();
414 }
415
416 void
417 cpu_startprofclock(void)
418 {
419 }
420
421 void
422 cpu_stopprofclock(void)
423 {
424 }
425
426 static int
427 sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
428 {
429         int error;
430         u_int freq;
431
432         /*
433          * Use `i8254' instead of `timer' in external names because `timer'
434          * is is too generic.  Should use it everywhere.
435          */
436         freq = i8254_freq;
437         error = sysctl_handle_int(oidp, &freq, 0, req);
438         if (error == 0 && req->newptr != NULL)
439                 set_i8254_freq(freq, hz);
440         return (error);
441 }
442
443 SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
444     0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
445
446 static unsigned
447 i8254_simple_get_timecount(struct timecounter *tc)
448 {
449
450         return (i8254_max_count - getit());
451 }
452
453 static unsigned
454 i8254_get_timecount(struct timecounter *tc)
455 {
456         u_int count;
457         u_int high, low;
458         u_int eflags;
459
460         eflags = read_eflags();
461         mtx_lock_spin(&clock_lock);
462
463         /* Select timer0 and latch counter value. */
464         outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
465
466         low = inb(TIMER_CNTR0);
467         high = inb(TIMER_CNTR0);
468         count = i8254_max_count - ((high << 8) | low);
469         if (count < i8254_lastcount ||
470             (!i8254_ticked && (clkintr_pending ||
471             ((count < 20 || (!(eflags & PSL_I) &&
472             count < i8254_max_count / 2u)) &&
473             i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
474                 i8254_ticked = 1;
475                 i8254_offset += i8254_max_count;
476         }
477         i8254_lastcount = count;
478         count += i8254_offset;
479         mtx_unlock_spin(&clock_lock);
480         return (count);
481 }
482
483 #ifdef DEV_ISA
484 /*
485  * Attach to the ISA PnP descriptors for the timer
486  */
487 static struct isa_pnp_id attimer_ids[] = {
488         { 0x0001d041 /* PNP0100 */, "AT timer" },
489         { 0 }
490 };
491
492 static int
493 attimer_probe(device_t dev)
494 {
495         int result;
496         
497         result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids);
498         if (result <= 0)
499                 device_quiet(dev);
500         return(result);
501 }
502
503 static int
504 attimer_attach(device_t dev)
505 {
506         return(0);
507 }
508
509 static device_method_t attimer_methods[] = {
510         /* Device interface */
511         DEVMETHOD(device_probe,         attimer_probe),
512         DEVMETHOD(device_attach,        attimer_attach),
513         DEVMETHOD(device_detach,        bus_generic_detach),
514         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
515         DEVMETHOD(device_suspend,       bus_generic_suspend),
516         DEVMETHOD(device_resume,        bus_generic_resume),
517         { 0, 0 }
518 };
519
520 static driver_t attimer_driver = {
521         "attimer",
522         attimer_methods,
523         1,              /* no softc */
524 };
525
526 static devclass_t attimer_devclass;
527
528 DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
529
530 #endif /* DEV_ISA */