Deleted Added
full compact
pcrtc.c (177651) pcrtc.c (178169)
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

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

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

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

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: head/sys/pc98/cbus/pcrtc.c 177651 2008-03-26 22:12:00Z phk $");
36__FBSDID("$FreeBSD: head/sys/pc98/cbus/pcrtc.c 178169 2008-04-13 06:18:34Z nyan $");
37
38/*
39 * Routines to handle clock hardware.
40 */
41
42/*
43 * inittodr, settodr and support routines written
44 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>

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

114
115/* Values for timerX_state: */
116#define RELEASED 0
117#define RELEASE_PENDING 1
118#define ACQUIRED 2
119#define ACQUIRE_PENDING 3
120
121static u_char timer1_state;
37
38/*
39 * Routines to handle clock hardware.
40 */
41
42/*
43 * inittodr, settodr and support routines written
44 * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>

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

114
115/* Values for timerX_state: */
116#define RELEASED 0
117#define RELEASE_PENDING 1
118#define ACQUIRED 2
119#define ACQUIRE_PENDING 3
120
121static u_char timer1_state;
122static void rtc_serialcombit(int);
123static void rtc_serialcom(int);
124static int rtc_inb(void);
125static void rtc_outb(int);
126
127static unsigned i8254_get_timecount(struct timecounter *tc);
128static unsigned i8254_simple_get_timecount(struct timecounter *tc);
129static void set_i8254_freq(u_int freq, int intr_freq);
130
131static struct timecounter i8254_timecounter = {
132 i8254_get_timecount, /* get_timecount */
133 0, /* no poll_pps */

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

395{
396
397 set_i8254_freq(i8254_freq, hz);
398 tc_init(&i8254_timecounter);
399
400 init_TSC();
401}
402
122
123static unsigned i8254_get_timecount(struct timecounter *tc);
124static unsigned i8254_simple_get_timecount(struct timecounter *tc);
125static void set_i8254_freq(u_int freq, int intr_freq);
126
127static struct timecounter i8254_timecounter = {
128 i8254_get_timecount, /* get_timecount */
129 0, /* no poll_pps */

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

391{
392
393 set_i8254_freq(i8254_freq, hz);
394 tc_init(&i8254_timecounter);
395
396 init_TSC();
397}
398
403static void
404rtc_serialcombit(int i)
405{
406 outb(IO_RTC, ((i&0x01)<<5)|0x07);
407 DELAY(1);
408 outb(IO_RTC, ((i&0x01)<<5)|0x17);
409 DELAY(1);
410 outb(IO_RTC, ((i&0x01)<<5)|0x07);
411 DELAY(1);
412}
413
414static void
415rtc_serialcom(int i)
416{
417 rtc_serialcombit(i&0x01);
418 rtc_serialcombit((i&0x02)>>1);
419 rtc_serialcombit((i&0x04)>>2);
420 rtc_serialcombit((i&0x08)>>3);
421 outb(IO_RTC, 0x07);
422 DELAY(1);
423 outb(IO_RTC, 0x0f);
424 DELAY(1);
425 outb(IO_RTC, 0x07);
426 DELAY(1);
427}
428
429static void
430rtc_outb(int val)
431{
432 int s;
433 int sa = 0;
434
435 for (s=0;s<8;s++) {
436 sa = ((val >> s) & 0x01) ? 0x27 : 0x07;
437 outb(IO_RTC, sa); /* set DI & CLK 0 */
438 DELAY(1);
439 outb(IO_RTC, sa | 0x10); /* CLK 1 */
440 DELAY(1);
441 }
442 outb(IO_RTC, sa & 0xef); /* CLK 0 */
443}
444
445static int
446rtc_inb(void)
447{
448 int s;
449 int sa = 0;
450
451 for (s=0;s<8;s++) {
452 sa |= ((inb(0x33) & 0x01) << s);
453 outb(IO_RTC, 0x17); /* CLK 1 */
454 DELAY(1);
455 outb(IO_RTC, 0x07); /* CLK 0 */
456 DELAY(2);
457 }
458 return sa;
459}
460
461/*
399/*
462 * Initialize the time of day register, based on the time base which is, e.g.
463 * from a filesystem.
464 */
465void
466inittodr(time_t base)
467{
468 struct timespec ts;
469 struct clocktime ct;
470 int i;
471
472 if (base) {
473 ts.tv_sec = base;
474 ts.tv_nsec = 0;
475 tc_setclock(&ts);
476 }
477
478 rtc_serialcom(0x03); /* Time Read */
479 rtc_serialcom(0x01); /* Register shift command. */
480 DELAY(20);
481
482 ct.nsec = 0;
483 ct.sec = bcd2bin(rtc_inb() & 0xff); /* sec */
484 ct.min = bcd2bin(rtc_inb() & 0xff); /* min */
485 ct.hour = bcd2bin(rtc_inb() & 0xff); /* hour */
486 ct.day = bcd2bin(rtc_inb() & 0xff); /* date */
487 i = rtc_inb();
488 ct.dow = i & 0x0f; /* dow */
489 ct.mon = (i >> 4) & 0x0f; /* month */
490 ct.year = bcd2bin(rtc_inb() & 0xff) + 1900; /* year */
491 if (ct.year < 1995)
492 ct.year += 100;
493 /* Set dow = -1 because some clocks don't set it correctly. */
494 ct.dow = -1;
495 if (clock_ct_to_ts(&ct, &ts)) {
496 printf("Invalid time in clock: check and reset the date!\n");
497 return;
498 }
499 ts.tv_sec += utc_offset();
500 tc_setclock(&ts);
501}
502
503/*
504 * Write system time back to RTC
505 */
506void
507resettodr()
508{
509 struct timespec ts;
510 struct clocktime ct;
511
512 if (disable_rtc_set)
513 return;
514
515 getnanotime(&ts);
516 ts.tv_sec -= utc_offset();
517 clock_ts_to_ct(&ts, &ct);
518
519 rtc_serialcom(0x01); /* Register shift command. */
520
521 rtc_outb(bin2bcd(ct.sec)); /* Write back Seconds */
522 rtc_outb(bin2bcd(ct.min)); /* Write back Minutes */
523 rtc_outb(bin2bcd(ct.hour)); /* Write back Hours */
524
525 rtc_outb(bin2bcd(ct.day)); /* Write back Day */
526 rtc_outb((ct.mon << 4) | ct.dow); /* Write back Month and DOW */
527 rtc_outb(bin2bcd(ct.year % 100)); /* Write back Year */
528
529 rtc_serialcom(0x02); /* Time set & Counter hold command. */
530 rtc_serialcom(0x00); /* Register hold command. */
531}
532
533
534/*
535 * Start both clocks running.
536 */
537void
538cpu_initclocks()
539{
540
541#ifdef DEV_APIC
542 using_lapic_timer = lapic_setup_clock();

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

614 /* Select timer0 and latch counter value. */
615 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
616
617 low = inb(TIMER_CNTR0);
618 high = inb(TIMER_CNTR0);
619 count = i8254_max_count - ((high << 8) | low);
620 if (count < i8254_lastcount ||
621 (!i8254_ticked && (clkintr_pending ||
400 * Start both clocks running.
401 */
402void
403cpu_initclocks()
404{
405
406#ifdef DEV_APIC
407 using_lapic_timer = lapic_setup_clock();

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

479 /* Select timer0 and latch counter value. */
480 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
481
482 low = inb(TIMER_CNTR0);
483 high = inb(TIMER_CNTR0);
484 count = i8254_max_count - ((high << 8) | low);
485 if (count < i8254_lastcount ||
486 (!i8254_ticked && (clkintr_pending ||
622 ((count < 20 || (!(eflags & PSL_I) && count < i8254_max_count / 2u)) &&
487 ((count < 20 || (!(eflags & PSL_I) &&
488 count < i8254_max_count / 2u)) &&
623 i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
624 i8254_ticked = 1;
625 i8254_offset += i8254_max_count;
626 }
627 i8254_lastcount = count;
628 count += i8254_offset;
629 mtx_unlock_spin(&clock_lock);
630 return (count);
631}
632
633#ifdef DEV_ISA
634/*
489 i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
490 i8254_ticked = 1;
491 i8254_offset += i8254_max_count;
492 }
493 i8254_lastcount = count;
494 count += i8254_offset;
495 mtx_unlock_spin(&clock_lock);
496 return (count);
497}
498
499#ifdef DEV_ISA
500/*
635 * Attach to the ISA PnP descriptors for the timer and realtime clock.
501 * Attach to the ISA PnP descriptors for the timer
636 */
637static struct isa_pnp_id attimer_ids[] = {
638 { 0x0001d041 /* PNP0100 */, "AT timer" },
502 */
503static struct isa_pnp_id attimer_ids[] = {
504 { 0x0001d041 /* PNP0100 */, "AT timer" },
639 { 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
640 { 0 }
641};
642
643static int
644attimer_probe(device_t dev)
645{
646 int result;
647
505 { 0 }
506};
507
508static int
509attimer_probe(device_t dev)
510{
511 int result;
512
648 if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0)
513 result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids);
514 if (result <= 0)
649 device_quiet(dev);
650 return(result);
651}
652
653static int
654attimer_attach(device_t dev)
655{
656 return(0);
657}
658
659static device_method_t attimer_methods[] = {
660 /* Device interface */
661 DEVMETHOD(device_probe, attimer_probe),
662 DEVMETHOD(device_attach, attimer_attach),
663 DEVMETHOD(device_detach, bus_generic_detach),
664 DEVMETHOD(device_shutdown, bus_generic_shutdown),
515 device_quiet(dev);
516 return(result);
517}
518
519static int
520attimer_attach(device_t dev)
521{
522 return(0);
523}
524
525static device_method_t attimer_methods[] = {
526 /* Device interface */
527 DEVMETHOD(device_probe, attimer_probe),
528 DEVMETHOD(device_attach, attimer_attach),
529 DEVMETHOD(device_detach, bus_generic_detach),
530 DEVMETHOD(device_shutdown, bus_generic_shutdown),
665 DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX stop statclock? */
666 DEVMETHOD(device_resume, bus_generic_resume), /* XXX restart statclock? */
531 DEVMETHOD(device_suspend, bus_generic_suspend),
532 DEVMETHOD(device_resume, bus_generic_resume),
667 { 0, 0 }
668};
669
670static driver_t attimer_driver = {
671 "attimer",
672 attimer_methods,
673 1, /* no softc */
674};
675
676static devclass_t attimer_devclass;
677
678DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
533 { 0, 0 }
534};
535
536static driver_t attimer_driver = {
537 "attimer",
538 attimer_methods,
539 1, /* no softc */
540};
541
542static devclass_t attimer_devclass;
543
544DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
545
679#endif /* DEV_ISA */
546#endif /* DEV_ISA */
547
548#ifdef DEV_ISA
549
550/**********************************************************************
551 * RTC driver for subr_rtc
552 */
553
554#include "clock_if.h"
555
556#include <sys/rman.h>
557
558static void rtc_serialcombit(int);
559static void rtc_serialcom(int);
560static int rtc_inb(void);
561static void rtc_outb(int);
562
563static void
564rtc_serialcombit(int i)
565{
566 outb(IO_RTC, ((i&0x01)<<5)|0x07);
567 DELAY(1);
568 outb(IO_RTC, ((i&0x01)<<5)|0x17);
569 DELAY(1);
570 outb(IO_RTC, ((i&0x01)<<5)|0x07);
571 DELAY(1);
572}
573
574static void
575rtc_serialcom(int i)
576{
577 rtc_serialcombit(i&0x01);
578 rtc_serialcombit((i&0x02)>>1);
579 rtc_serialcombit((i&0x04)>>2);
580 rtc_serialcombit((i&0x08)>>3);
581 outb(IO_RTC, 0x07);
582 DELAY(1);
583 outb(IO_RTC, 0x0f);
584 DELAY(1);
585 outb(IO_RTC, 0x07);
586 DELAY(1);
587}
588
589static void
590rtc_outb(int val)
591{
592 int s;
593 int sa = 0;
594
595 for (s=0;s<8;s++) {
596 sa = ((val >> s) & 0x01) ? 0x27 : 0x07;
597 outb(IO_RTC, sa); /* set DI & CLK 0 */
598 DELAY(1);
599 outb(IO_RTC, sa | 0x10); /* CLK 1 */
600 DELAY(1);
601 }
602 outb(IO_RTC, sa & 0xef); /* CLK 0 */
603}
604
605static int
606rtc_inb(void)
607{
608 int s;
609 int sa = 0;
610
611 for (s=0;s<8;s++) {
612 sa |= ((inb(0x33) & 0x01) << s);
613 outb(IO_RTC, 0x17); /* CLK 1 */
614 DELAY(1);
615 outb(IO_RTC, 0x07); /* CLK 0 */
616 DELAY(2);
617 }
618 return sa;
619}
620
621struct pcrtc_softc {
622 int port_rid1, port_rid2;
623 struct resource *port_res1, *port_res2;
624};
625
626/*
627 * Attach to the ISA PnP descriptors for the timer and realtime clock.
628 */
629static struct isa_pnp_id pcrtc_ids[] = {
630 { 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
631 { 0 }
632};
633
634static int
635pcrtc_probe(device_t dev)
636{
637 int result;
638
639 device_set_desc(dev, "PC Real Time Clock");
640 result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcrtc_ids);
641 /* ENXIO if wrong PnP-ID, ENOENT ifno PnP-ID, zero if good PnP-iD */
642 if (result != ENOENT)
643 return(result);
644 /* All PC's have an RTC, and we're hosed without it, so... */
645 return (BUS_PROBE_LOW_PRIORITY);
646}
647
648static int
649pcrtc_attach(device_t dev)
650{
651 struct pcrtc_softc *sc;
652
653 /*
654 * Not that we need them or anything, but grab our resources
655 * so they show up, correctly attributed, in the big picture.
656 */
657 sc = device_get_softc(dev);
658 sc->port_rid1 = 0;
659 bus_set_resource(dev, SYS_RES_IOPORT, sc->port_rid1, IO_RTC, 1);
660 if (!(sc->port_res1 = bus_alloc_resource(dev, SYS_RES_IOPORT,
661 &sc->port_rid1, IO_RTC, IO_RTC, 1, RF_ACTIVE)))
662 device_printf(dev, "Warning: Couldn't map I/O.\n");
663 sc->port_rid2 = 1;
664 bus_set_resource(dev, SYS_RES_IOPORT, sc->port_rid2, 0x33, 1);
665 if (!(sc->port_res2 = bus_alloc_resource(dev, SYS_RES_IOPORT,
666 &sc->port_rid2, 0x33, 0x33, 1, RF_ACTIVE)))
667 device_printf(dev, "Warning: Couldn't map I/O.\n");
668
669 clock_register(dev, 1000000);
670 return(0);
671}
672
673static int
674pcrtc_settime(device_t dev __unused, struct timespec *ts)
675{
676 struct clocktime ct;
677
678 clock_ts_to_ct(ts, &ct);
679
680 rtc_serialcom(0x01); /* Register shift command. */
681
682 rtc_outb(bin2bcd(ct.sec)); /* Write back Seconds */
683 rtc_outb(bin2bcd(ct.min)); /* Write back Minutes */
684 rtc_outb(bin2bcd(ct.hour)); /* Write back Hours */
685
686 rtc_outb(bin2bcd(ct.day)); /* Write back Day */
687 rtc_outb((ct.mon << 4) | ct.dow); /* Write back Month and DOW */
688 rtc_outb(bin2bcd(ct.year % 100)); /* Write back Year */
689
690 rtc_serialcom(0x02); /* Time set & Counter hold command. */
691 rtc_serialcom(0x00); /* Register hold command. */
692
693 return (0);
694}
695
696static int
697pcrtc_gettime(device_t dev, struct timespec *ts)
698{
699 struct clocktime ct;
700 int i;
701
702 rtc_serialcom(0x03); /* Time Read */
703 rtc_serialcom(0x01); /* Register shift command. */
704 DELAY(20);
705
706 ct.nsec = 0;
707 ct.sec = bcd2bin(rtc_inb() & 0xff); /* sec */
708 ct.min = bcd2bin(rtc_inb() & 0xff); /* min */
709 ct.hour = bcd2bin(rtc_inb() & 0xff); /* hour */
710 ct.day = bcd2bin(rtc_inb() & 0xff); /* date */
711 i = rtc_inb();
712 ct.dow = i & 0x0f; /* dow */
713 ct.mon = (i >> 4) & 0x0f; /* month */
714 ct.year = bcd2bin(rtc_inb() & 0xff) + 1900; /* year */
715 if (ct.year < 1995)
716 ct.year += 100;
717
718 /* Set dow = -1 because some clocks don't set it correctly. */
719 ct.dow = -1;
720
721 return (clock_ct_to_ts(&ct, ts));
722}
723
724static device_method_t pcrtc_methods[] = {
725 /* Device interface */
726 DEVMETHOD(device_probe, pcrtc_probe),
727 DEVMETHOD(device_attach, pcrtc_attach),
728 DEVMETHOD(device_detach, bus_generic_detach),
729 DEVMETHOD(device_shutdown, bus_generic_shutdown),
730 DEVMETHOD(device_suspend, bus_generic_suspend),
731 /* XXX stop statclock? */
732 DEVMETHOD(device_resume, bus_generic_resume),
733 /* XXX restart statclock? */
734
735 /* clock interface */
736 DEVMETHOD(clock_gettime, pcrtc_gettime),
737 DEVMETHOD(clock_settime, pcrtc_settime),
738
739 { 0, 0 }
740};
741
742static driver_t pcrtc_driver = {
743 "pcrtc",
744 pcrtc_methods,
745 sizeof(struct pcrtc_softc),
746};
747
748static devclass_t pcrtc_devclass;
749
750DRIVER_MODULE(pcrtc, isa, pcrtc_driver, pcrtc_devclass, 0, 0);
751
752#endif /* DEV_ISA */