2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include "base/bitfield.hh"
39 #include "base/time.hh"
40 #include "base/trace.hh"
41 #include "dev/mc146818.hh"
42 #include "dev/rtcreg.h"
46 MC146818::MC146818(EventManager
*em
, const string
&n
, const struct tm time
,
47 bool bcd
, Tick frequency
)
48 : EventManager(em
), _name(n
), event(this, frequency
)
50 memset(clock_data
, 0, sizeof(clock_data
));
51 stat_regA
= RTCA_32768HZ
| RTCA_1024HZ
;
52 stat_regB
= RTCB_PRDC_IE
| RTCB_24HR
;
54 stat_regB
|= RTCB_BIN
;
59 // The datasheet says that the year field can be either BCD or
60 // years since 1900. Linux seems to be happy with years since
65 year
= (tens
<< 4) + ones
;
68 // Unix is 0-11 for month, data seet says start at 1
69 mon
= time
.tm_mon
+ 1;
75 // Datasheet says 1 is sunday
76 wday
= time
.tm_wday
+ 1;
78 DPRINTFN("Real-time clock set to %s", asctime(&time
));
86 MC146818::writeData(const uint8_t addr
, const uint8_t data
)
88 if (addr
< RTC_STAT_REGA
)
89 clock_data
[addr
] = data
;
93 // The "update in progress" bit is read only.
94 if ((data
& ~RTCA_UIP
) != (RTCA_32768HZ
| RTCA_1024HZ
))
95 panic("Unimplemented RTC register A value write!\n");
96 replaceBits(stat_regA
, data
, 6, 0);
99 if ((data
& ~(RTCB_PRDC_IE
| RTCB_SQWE
)) != (RTCB_BIN
| RTCB_24HR
))
100 panic("Write to RTC reg B bits that are not implemented!\n");
102 if (data
& RTCB_PRDC_IE
) {
103 if (!event
.scheduled())
104 event
.scheduleIntr();
106 if (event
.scheduled())
113 panic("RTC status registers C and D are not implemented.\n");
120 MC146818::readData(uint8_t addr
)
122 if (addr
< RTC_STAT_REGA
)
123 return clock_data
[addr
];
127 // toggle UIP bit for linux
128 stat_regA
^= RTCA_UIP
;
139 panic("Shouldn't be here");
145 MC146818::serialize(const string
&base
, ostream
&os
)
147 arrayParamOut(os
, base
+ ".clock_data", clock_data
, sizeof(clock_data
));
148 paramOut(os
, base
+ ".stat_regA", stat_regA
);
149 paramOut(os
, base
+ ".stat_regB", stat_regB
);
153 MC146818::unserialize(const string
&base
, Checkpoint
*cp
,
154 const string
§ion
)
156 arrayParamIn(cp
, section
, base
+ ".clock_data", clock_data
,
158 paramIn(cp
, section
, base
+ ".stat_regA", stat_regA
);
159 paramIn(cp
, section
, base
+ ".stat_regB", stat_regB
);
161 // We're not unserializing the event here, but we need to
162 // rescehedule the event since curTick was moved forward by the
164 reschedule(event
, curTick
+ event
.interval
);
167 MC146818::RTCEvent::RTCEvent(MC146818
* _parent
, Tick i
)
168 : parent(_parent
), interval(i
)
170 DPRINTF(MC146818
, "RTC Event Initilizing\n");
171 parent
->schedule(this, curTick
+ interval
);
175 MC146818::RTCEvent::scheduleIntr()
177 parent
->schedule(this, curTick
+ interval
);
181 MC146818::RTCEvent::process()
183 DPRINTF(MC146818
, "RTC Timer Interrupt\n");
184 parent
->schedule(this, curTick
+ interval
);
185 parent
->handleEvent();
189 MC146818::RTCEvent::description() const
191 return "RTC interrupt";