DmaDevice: fix minor type in error message.
[gem5.git] / src / dev / mc146818.cc
1 /*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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.
15 *
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.
27 *
28 * Authors: Ali Saidi
29 * Andrew Schultz
30 * Miguel Serrano
31 */
32
33 #include <sys/time.h>
34 #include <time.h>
35
36 #include <string>
37
38 #include "base/time.hh"
39 #include "base/trace.hh"
40 #include "dev/mc146818.hh"
41 #include "dev/rtcreg.h"
42
43 using namespace std;
44
45 MC146818::MC146818(EventManager *em, const string &n, const struct tm time,
46 bool bcd, Tick frequency)
47 : EventManager(em), _name(n), event(this, frequency)
48 {
49 memset(clock_data, 0, sizeof(clock_data));
50 stat_regA = RTCA_32768HZ | RTCA_1024HZ;
51 stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
52
53 year = time.tm_year;
54
55 if (bcd) {
56 // The datasheet says that the year field can be either BCD or
57 // years since 1900. Linux seems to be happy with years since
58 // 1900.
59 year = year % 100;
60 int tens = year / 10;
61 int ones = year % 10;
62 year = (tens << 4) + ones;
63 }
64
65 // Unix is 0-11 for month, data seet says start at 1
66 mon = time.tm_mon + 1;
67 mday = time.tm_mday;
68 hour = time.tm_hour;
69 min = time.tm_min;
70 sec = time.tm_sec;
71
72 // Datasheet says 1 is sunday
73 wday = time.tm_wday + 1;
74
75 DPRINTFN("Real-time clock set to %s", asctime(&time));
76 }
77
78 MC146818::~MC146818()
79 {
80 }
81
82 void
83 MC146818::writeData(const uint8_t addr, const uint8_t data)
84 {
85 if (addr < RTC_STAT_REGA)
86 clock_data[addr] = data;
87 else {
88 switch (addr) {
89 case RTC_STAT_REGA:
90 if (data != (RTCA_32768HZ | RTCA_1024HZ))
91 panic("Unimplemented RTC register A value write!\n");
92 stat_regA = data;
93 break;
94 case RTC_STAT_REGB:
95 if ((data & ~(RTCB_PRDC_IE | RTCB_SQWE)) != (RTCB_BIN | RTCB_24HR))
96 panic("Write to RTC reg B bits that are not implemented!\n");
97
98 if (data & RTCB_PRDC_IE) {
99 if (!event.scheduled())
100 event.scheduleIntr();
101 } else {
102 if (event.scheduled())
103 deschedule(event);
104 }
105 stat_regB = data;
106 break;
107 case RTC_STAT_REGC:
108 case RTC_STAT_REGD:
109 panic("RTC status registers C and D are not implemented.\n");
110 break;
111 }
112 }
113 }
114
115 uint8_t
116 MC146818::readData(uint8_t addr)
117 {
118 if (addr < RTC_STAT_REGA)
119 return clock_data[addr];
120 else {
121 switch (addr) {
122 case RTC_STAT_REGA:
123 // toggle UIP bit for linux
124 stat_regA ^= RTCA_UIP;
125 return stat_regA;
126 break;
127 case RTC_STAT_REGB:
128 return stat_regB;
129 break;
130 case RTC_STAT_REGC:
131 case RTC_STAT_REGD:
132 return 0x00;
133 break;
134 default:
135 panic("Shouldn't be here");
136 }
137 }
138 }
139
140 void
141 MC146818::serialize(const string &base, ostream &os)
142 {
143 arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data));
144 paramOut(os, base + ".stat_regA", stat_regA);
145 paramOut(os, base + ".stat_regB", stat_regB);
146 }
147
148 void
149 MC146818::unserialize(const string &base, Checkpoint *cp,
150 const string &section)
151 {
152 arrayParamIn(cp, section, base + ".clock_data", clock_data,
153 sizeof(clock_data));
154 paramIn(cp, section, base + ".stat_regA", stat_regA);
155 paramIn(cp, section, base + ".stat_regB", stat_regB);
156
157 // We're not unserializing the event here, but we need to
158 // rescehedule the event since curTick was moved forward by the
159 // checkpoint
160 reschedule(event, curTick + event.interval);
161 }
162
163 MC146818::RTCEvent::RTCEvent(MC146818 * _parent, Tick i)
164 : parent(_parent), interval(i)
165 {
166 DPRINTF(MC146818, "RTC Event Initilizing\n");
167 parent->schedule(this, curTick + interval);
168 }
169
170 void
171 MC146818::RTCEvent::scheduleIntr()
172 {
173 parent->schedule(this, curTick + interval);
174 }
175
176 void
177 MC146818::RTCEvent::process()
178 {
179 DPRINTF(MC146818, "RTC Timer Interrupt\n");
180 parent->schedule(this, curTick + interval);
181 parent->handleEvent();
182 }
183
184 const char *
185 MC146818::RTCEvent::description() const
186 {
187 return "RTC interrupt";
188 }