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