Deleted Added
full compact
clock.c (209927) clock.c (209979)
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 *

--- 20 unchanged lines hidden (view full) ---

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 *

--- 20 unchanged lines hidden (view full) ---

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 209927 2010-07-12 06:46:17Z mav $");
37__FBSDID("$FreeBSD: head/sys/x86/isa/clock.c 209979 2010-07-13 06:57:27Z mav $");
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"

--- 15 unchanged lines hidden (view full) ---

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
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"

--- 15 unchanged lines hidden (view full) ---

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
69#include <isa/rtc.h>
72#include <isa/rtc.h>
73#endif
70#ifdef DEV_ISA
74#ifdef DEV_ISA
75#ifdef PC98
76#include <pc98/cbus/cbus.h>
77#else
71#include <isa/isareg.h>
78#include <isa/isareg.h>
79#endif
72#include <isa/isavar.h>
73#endif
74
75#ifdef DEV_MCA
76#include <i386/bios/mca_machdep.h>
77#endif
78
79int clkintr_pending;
80#ifndef TIMER_FREQ
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
81#define TIMER_FREQ 1193182
82#endif
92#define TIMER_FREQ 1193182
93#endif
94#endif
83u_int i8254_freq = TIMER_FREQ;
84TUNABLE_INT("hw.i8254.freq", &i8254_freq);
85int i8254_max_count;
86static int i8254_real_max_count;
87
88struct mtx clock_lock;
89static struct intsrc *i8254_intsrc;
90static uint16_t i8254_lastcount;
91static uint16_t i8254_offset;
92static int (*i8254_pending)(struct intsrc *);
93static int i8254_ticked;
94
95struct attimer_softc {
96 int intr_en;
97 int port_rid, intr_rid;
98 struct resource *port_res;
99 struct resource *intr_res;
95u_int i8254_freq = TIMER_FREQ;
96TUNABLE_INT("hw.i8254.freq", &i8254_freq);
97int i8254_max_count;
98static int i8254_real_max_count;
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
100 void *intr_handler;
101 struct timecounter tc;
102 struct eventtimer et;
103 uint32_t intr_period;
104};
105static struct attimer_softc *attimer_sc = NULL;
106
107/* Values for timerX_state: */

--- 37 unchanged lines hidden (view full) ---

145 return (FILTER_HANDLED);
146}
147
148int
149timer_spkr_acquire(void)
150{
151 int mode;
152
116 void *intr_handler;
117 struct timecounter tc;
118 struct eventtimer et;
119 uint32_t intr_period;
120};
121static struct attimer_softc *attimer_sc = NULL;
122
123/* Values for timerX_state: */

--- 37 unchanged lines hidden (view full) ---

161 return (FILTER_HANDLED);
162}
163
164int
165timer_spkr_acquire(void)
166{
167 int mode;
168
169#ifdef PC98
170 mode = TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT;
171#else
153 mode = TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT;
172 mode = TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT;
173#endif
154
155 if (timer2_state != RELEASED)
156 return (-1);
157 timer2_state = ACQUIRED;
158
159 /*
160 * This access to the timer registers is as atomic as possible
161 * because it is a single instruction. We could do better if we
162 * knew the rate. Use of splclock() limits glitches to 10-100us,
163 * and this is probably good enough for timer2, so we aren't as
164 * careful with it as with timer0.
165 */
174
175 if (timer2_state != RELEASED)
176 return (-1);
177 timer2_state = ACQUIRED;
178
179 /*
180 * This access to the timer registers is as atomic as possible
181 * because it is a single instruction. We could do better if we
182 * knew the rate. Use of splclock() limits glitches to 10-100us,
183 * and this is probably good enough for timer2, so we aren't as
184 * careful with it as with timer0.
185 */
186#ifdef PC98
187 outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f));
188#else
166 outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
189 outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
190#endif
167 ppi_spkr_on(); /* enable counter2 output to speaker */
168 return (0);
169}
170
171int
172timer_spkr_release(void)
173{
174
175 if (timer2_state != ACQUIRED)
176 return (-1);
177 timer2_state = RELEASED;
191 ppi_spkr_on(); /* enable counter2 output to speaker */
192 return (0);
193}
194
195int
196timer_spkr_release(void)
197{
198
199 if (timer2_state != ACQUIRED)
200 return (-1);
201 timer2_state = RELEASED;
202#ifdef PC98
203 outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT);
204#else
178 outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
205 outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
206#endif
179 ppi_spkr_off(); /* disable counter2 output to speaker */
180 return (0);
181}
182
183void
184timer_spkr_setfreq(int freq)
185{
186
187 freq = i8254_freq / freq;
188 mtx_lock_spin(&clock_lock);
207 ppi_spkr_off(); /* disable counter2 output to speaker */
208 return (0);
209}
210
211void
212timer_spkr_setfreq(int freq)
213{
214
215 freq = i8254_freq / freq;
216 mtx_lock_spin(&clock_lock);
217#ifdef PC98
218 outb(TIMER_CNTR1, freq & 0xff);
219 outb(TIMER_CNTR1, freq >> 8);
220#else
189 outb(TIMER_CNTR2, freq & 0xff);
190 outb(TIMER_CNTR2, freq >> 8);
221 outb(TIMER_CNTR2, freq & 0xff);
222 outb(TIMER_CNTR2, freq >> 8);
223#endif
191 mtx_unlock_spin(&clock_lock);
192}
193
194static int
195getit(void)
196{
197 int high, low;
198

--- 89 unchanged lines hidden (view full) ---

288 * before the delay is up (unless we're interrupted).
289 */
290 ticks_left = ((u_int)n * (long long)i8254_freq + 999999)
291 / 1000000;
292
293 while (ticks_left > 0) {
294#ifdef KDB
295 if (kdb_active) {
224 mtx_unlock_spin(&clock_lock);
225}
226
227static int
228getit(void)
229{
230 int high, low;
231

--- 89 unchanged lines hidden (view full) ---

321 * before the delay is up (unless we're interrupted).
322 */
323 ticks_left = ((u_int)n * (long long)i8254_freq + 999999)
324 / 1000000;
325
326 while (ticks_left > 0) {
327#ifdef KDB
328 if (kdb_active) {
329#ifdef PC98
330 outb(0x5f, 0);
331#else
296 inb(0x84);
332 inb(0x84);
333#endif
297 tick = prev_tick - 1;
298 if (tick <= 0)
299 tick = i8254_max_count;
300 } else
301#endif
302 tick = getit();
303#ifdef DELAYDEBUG
304 ++getit_calls;

--- 67 unchanged lines hidden (view full) ---

372 * As long as pmtimer is not part of amd64 suport, skip this for the amd64
373 * case.
374 */
375void
376timer_restore(void)
377{
378
379 i8254_restore(); /* restore i8254_freq and hz */
334 tick = prev_tick - 1;
335 if (tick <= 0)
336 tick = i8254_max_count;
337 } else
338#endif
339 tick = getit();
340#ifdef DELAYDEBUG
341 ++getit_calls;

--- 67 unchanged lines hidden (view full) ---

409 * As long as pmtimer is not part of amd64 suport, skip this for the amd64
410 * case.
411 */
412void
413timer_restore(void)
414{
415
416 i8254_restore(); /* restore i8254_freq and hz */
417#ifndef PC98
380 atrtc_restore(); /* reenable RTC interrupts */
418 atrtc_restore(); /* reenable RTC interrupts */
419#endif
381}
382#endif
383
384/* This is separate from startrtclock() so that it can be called early. */
385void
386i8254_init(void)
387{
388
389 mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
420}
421#endif
422
423/* This is separate from startrtclock() so that it can be called early. */
424void
425i8254_init(void)
426{
427
428 mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE);
429#ifdef PC98
430 if (pc98_machine_type & M_8M)
431 i8254_freq = 1996800L; /* 1.9968 MHz */
432#endif
390 set_i8254_freq(i8254_freq, 0);
391}
392
393void
394startrtclock()
395{
396
397 init_TSC();

--- 103 unchanged lines hidden (view full) ---

501/*
502 * Attach to the ISA PnP descriptors for the timer
503 */
504static struct isa_pnp_id attimer_ids[] = {
505 { 0x0001d041 /* PNP0100 */, "AT timer" },
506 { 0 }
507};
508
433 set_i8254_freq(i8254_freq, 0);
434}
435
436void
437startrtclock()
438{
439
440 init_TSC();

--- 103 unchanged lines hidden (view full) ---

544/*
545 * Attach to the ISA PnP descriptors for the timer
546 */
547static struct isa_pnp_id attimer_ids[] = {
548 { 0x0001d041 /* PNP0100 */, "AT timer" },
549 { 0 }
550};
551
552#ifdef PC98
553static void
554pc98_alloc_resource(device_t dev)
555{
556 static bus_addr_t iat1[] = {0, 2, 4, 6};
557 static bus_addr_t iat2[] = {0, 4};
558 struct attimer_softc *sc;
559
560 sc = device_get_softc(dev);
561
562 sc->port_rid = 0;
563 bus_set_resource(dev, SYS_RES_IOPORT, sc->port_rid, IO_TIMER1, 1);
564 sc->port_res = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
565 &sc->port_rid, iat1, 4, RF_ACTIVE);
566 if (sc->port_res == NULL)
567 device_printf(dev, "Warning: Couldn't map I/O.\n");
568 else
569 isa_load_resourcev(sc->port_res, iat1, 4);
570
571 sc->port_rid2 = 4;
572 bus_set_resource(dev, SYS_RES_IOPORT, sc->port_rid2, TIMER_CNTR1, 1);
573 sc->port_res2 = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
574 &sc->port_rid2, iat2, 2, RF_ACTIVE);
575 if (sc->port_res2 == NULL)
576 device_printf(dev, "Warning: Couldn't map I/O.\n");
577 else
578 isa_load_resourcev(sc->port_res2, iat2, 2);
579}
580
581static void
582pc98_release_resource(device_t dev)
583{
584 struct attimer_softc *sc;
585
586 sc = device_get_softc(dev);
587
588 if (sc->port_res)
589 bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
590 sc->port_res);
591 if (sc->port_res2)
592 bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid2,
593 sc->port_res2);
594}
595#endif
596
509static int
510attimer_probe(device_t dev)
511{
512 int result;
513
514 result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids);
515 /* ENOENT means no PnP-ID, device is hinted. */
516 if (result == ENOENT) {
517 device_set_desc(dev, "AT timer");
597static int
598attimer_probe(device_t dev)
599{
600 int result;
601
602 result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids);
603 /* ENOENT means no PnP-ID, device is hinted. */
604 if (result == ENOENT) {
605 device_set_desc(dev, "AT timer");
606#ifdef PC98
607 /* To print resources correctly. */
608 pc98_alloc_resource(dev);
609 pc98_release_resource(dev);
610#endif
518 return (BUS_PROBE_LOW_PRIORITY);
519 }
520 return (result);
521}
522
523static int
524attimer_attach(device_t dev)
525{
526 struct attimer_softc *sc;
527 u_long s;
528 int i;
529
530 attimer_sc = sc = device_get_softc(dev);
531 bzero(sc, sizeof(struct attimer_softc));
611 return (BUS_PROBE_LOW_PRIORITY);
612 }
613 return (result);
614}
615
616static int
617attimer_attach(device_t dev)
618{
619 struct attimer_softc *sc;
620 u_long s;
621 int i;
622
623 attimer_sc = sc = device_get_softc(dev);
624 bzero(sc, sizeof(struct attimer_softc));
625#ifdef PC98
626 pc98_alloc_resource(dev);
627#else
532 if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
533 &sc->port_rid, IO_TIMER1, IO_TIMER1 + 3, 4, RF_ACTIVE)))
534 device_printf(dev,"Warning: Couldn't map I/O.\n");
628 if (!(sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
629 &sc->port_rid, IO_TIMER1, IO_TIMER1 + 3, 4, RF_ACTIVE)))
630 device_printf(dev,"Warning: Couldn't map I/O.\n");
631#endif
535 i8254_intsrc = intr_lookup_source(0);
536 if (i8254_intsrc != NULL)
537 i8254_pending = i8254_intsrc->is_pic->pic_source_pending;
538 set_i8254_freq(i8254_freq, 0);
539 sc->tc.tc_get_timecount = i8254_get_timecount;
540 sc->tc.tc_counter_mask = 0xffff;
541 sc->tc.tc_frequency = i8254_freq;
542 sc->tc.tc_name = "i8254";

--- 69 unchanged lines hidden ---
632 i8254_intsrc = intr_lookup_source(0);
633 if (i8254_intsrc != NULL)
634 i8254_pending = i8254_intsrc->is_pic->pic_source_pending;
635 set_i8254_freq(i8254_freq, 0);
636 sc->tc.tc_get_timecount = i8254_get_timecount;
637 sc->tc.tc_counter_mask = 0xffff;
638 sc->tc.tc_frequency = i8254_freq;
639 sc->tc.tc_name = "i8254";

--- 69 unchanged lines hidden ---