~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/seabios/src/hw/rtc.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Support for MC146818 Real Time Clock chip.
 
2
//
 
3
// Copyright (C) 2008-2013  Kevin O'Connor <kevin@koconnor.net>
 
4
// Copyright (C) 2002  MandrakeSoft S.A.
 
5
//
 
6
// This file may be distributed under the terms of the GNU LGPLv3 license.
 
7
 
 
8
#include "biosvar.h" // GET_LOW
 
9
#include "rtc.h" // rtc_read
 
10
#include "stacks.h" // yield
 
11
#include "util.h" // timer_calc
 
12
#include "x86.h" // inb
 
13
 
 
14
u8
 
15
rtc_read(u8 index)
 
16
{
 
17
    index |= NMI_DISABLE_BIT;
 
18
    outb(index, PORT_CMOS_INDEX);
 
19
    return inb(PORT_CMOS_DATA);
 
20
}
 
21
 
 
22
void
 
23
rtc_write(u8 index, u8 val)
 
24
{
 
25
    index |= NMI_DISABLE_BIT;
 
26
    outb(index, PORT_CMOS_INDEX);
 
27
    outb(val, PORT_CMOS_DATA);
 
28
}
 
29
 
 
30
void
 
31
rtc_mask(u8 index, u8 off, u8 on)
 
32
{
 
33
    index |= NMI_DISABLE_BIT;
 
34
    outb(index, PORT_CMOS_INDEX);
 
35
    u8 val = inb(PORT_CMOS_DATA);
 
36
    outb((val & ~off) | on, PORT_CMOS_DATA);
 
37
}
 
38
 
 
39
int
 
40
rtc_updating(void)
 
41
{
 
42
    // This function checks to see if the update-in-progress bit
 
43
    // is set in CMOS Status Register A.  If not, it returns 0.
 
44
    // If it is set, it tries to wait until there is a transition
 
45
    // to 0, and will return 0 if such a transition occurs.  A -1
 
46
    // is returned only after timing out.  The maximum period
 
47
    // that this bit should be set is constrained to (1984+244)
 
48
    // useconds, but we wait for longer just to be sure.
 
49
 
 
50
    if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0)
 
51
        return 0;
 
52
    u32 end = timer_calc(15);
 
53
    for (;;) {
 
54
        if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0)
 
55
            return 0;
 
56
        if (timer_check(end))
 
57
            // update-in-progress never transitioned to 0
 
58
            return -1;
 
59
        yield();
 
60
    }
 
61
}
 
62
 
 
63
void
 
64
rtc_setup(void)
 
65
{
 
66
    if (!CONFIG_RTC_TIMER)
 
67
        return;
 
68
    rtc_write(CMOS_STATUS_A, 0x26);    // 32,768Khz src, 976.5625us updates
 
69
    rtc_mask(CMOS_STATUS_B, ~RTC_B_DSE, RTC_B_24HR);
 
70
    rtc_read(CMOS_STATUS_C);
 
71
    rtc_read(CMOS_STATUS_D);
 
72
}
 
73
 
 
74
int RTCusers VARLOW;
 
75
 
 
76
void
 
77
rtc_use(void)
 
78
{
 
79
    if (!CONFIG_RTC_TIMER)
 
80
        return;
 
81
    int count = GET_LOW(RTCusers);
 
82
    SET_LOW(RTCusers, count+1);
 
83
    if (count)
 
84
        return;
 
85
    // Turn on the Periodic Interrupt timer
 
86
    rtc_mask(CMOS_STATUS_B, 0, RTC_B_PIE);
 
87
}
 
88
 
 
89
void
 
90
rtc_release(void)
 
91
{
 
92
    if (!CONFIG_RTC_TIMER)
 
93
        return;
 
94
    int count = GET_LOW(RTCusers);
 
95
    SET_LOW(RTCusers, count-1);
 
96
    if (count != 1)
 
97
        return;
 
98
    // Clear the Periodic Interrupt.
 
99
    rtc_mask(CMOS_STATUS_B, RTC_B_PIE, 0);
 
100
}