1 /* DS1287-based DEC 5000/200 Real-Time Clock emulation.
2    Copyright 2003 Brian R. Gaeke.
3 
4 This file is part of VMIPS.
5 
6 VMIPS is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2 of the License, or (at your
9 option) any later version.
10 
11 VMIPS is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License along
17 with VMIPS; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
19 
20 /* Dallas Semiconductor DS1287 real-time clock chip, as implemented
21  * as a memory-mapped device in the DEC 5000/200 (KN02).
22  */
23 
24 #include "devicemap.h"
25 #include "clock.h"
26 #include "decrtcreg.h"
27 #include "decrtc.h"
28 #include "mapper.h"
29 #include "vmips.h"
30 #include <cstdio>
31 #include <cassert>
32 
33 static const uint32 int_freqs [16] = {
34   0, 3906250, 7812500, 122070, 244141, 488281, 976562, 1953125,
35   3906250, 7812500, 15625000, 31250000, 62500000, 125000000,
36   250000000, 500000000
37 };
38 
39 #if defined(RTC_DEBUG)
40 static const char *reg_names [15] = {
41   "RTC_SEC", "RTC_ALMS", "RTC_MIN", "RTC_ALMM", "RTC_HOUR",
42   "RTC_ALMH", "RTC_DOW", "RTC_DAY", "RTC_MON", "RTC_YEAR",
43   "RTC_REGA", "RTC_REGB", "RTC_REGC", "RTC_REGD", "RTC_RAM"
44 };
45 #endif
46 
DECRTCDevice(Clock * _clock,uint32 _irq)47 DECRTCDevice::DECRTCDevice (Clock *_clock, uint32 _irq) :
48   clock(_clock), frequency_ns (0), irq (_irq), interrupt_enable (false)
49 {
50   extent = 0x80000;
51   // Initialize registers
52   for (int i = 0; i < 64; ++i) {
53     rtc_reg[i] = 0x00;
54   }
55   rtc_reg[RTC_REGA] = 0x20;  // Timebase divisor = 010 (32.768 kHz)
56   // Set up write masks
57   for (int i = 0; i < 64; ++i) {
58     write_masks[i] = 0xff;
59   }
60   write_masks[RTC_REGA] = 0x7f;
61   write_masks[RTC_REGB] = 0xd7;
62   write_masks[RTC_REGC] = 0x00;
63   write_masks[RTC_REGD] = 0x00;
64 }
65 
66 const struct tm *
get_host_time() const67 DECRTCDevice::get_host_time () const {
68   time_t real_time = clock->get_time().tv_sec;
69   return gmtime(&real_time);
70 }
71 
72 uint32
fetch_word(uint32 offset,int mode,DeviceExc * client)73 DECRTCDevice::fetch_word(uint32 offset, int mode, DeviceExc *client)
74 {
75   uint32 reg_no = (offset / 4);
76   uint32 rv = 0;
77 #if defined(RTC_DEBUG)
78   fprintf(stderr, "RTC fetch word, offset=0x%x\n", offset);
79 #endif
80   if (reg_no == RTC_REGA) {
81     // Fake "update in progress" once a second
82     time_t real_nanos = clock->get_time().tv_nsec;
83     if ((real_nanos + ((244 + 1948)*1000)) > 1000000000) {
84 	  rtc_reg[RTC_REGA] |= REGA_UIP;
85 	} else {
86 	  rtc_reg[RTC_REGA] &= ~REGA_UIP;
87 	}
88   }
89   if (reg_no < 10)
90     update_host_time ();
91   if (reg_no < 64)
92     rv = rtc_reg[reg_no];
93   if (reg_no == RTC_REGC) {
94 #if defined(RTC_DEBUG)
95     fprintf(stderr, "RTC read REGC -- deassert IRQ\n");
96 #endif
97     unready_clock ();
98   }
99 
100   return machine->physmem->mips_to_host_word(rv);
101 }
102 
103 void
update_host_time()104 DECRTCDevice::update_host_time ()
105 {
106   const struct tm *host_time = get_host_time ();
107   rtc_reg[RTC_SEC]  = host_time->tm_sec; /* second 0..59 */
108   rtc_reg[RTC_MIN]  = host_time->tm_min; /* minute 0..59 */
109   rtc_reg[RTC_HOUR] = host_time->tm_hour; /* hour 0..23 */
110   rtc_reg[RTC_DOW]  = 1 + host_time->tm_wday; /* day of week 1..7 */
111   rtc_reg[RTC_MON]  = 1 + host_time->tm_mon; /* month 1..12 */
112   rtc_reg[RTC_YEAR] = host_time->tm_year % 100; /* year 0..99 */
113 }
114 
115 void
store_word(uint32 offset,uint32 data,DeviceExc * client)116 DECRTCDevice::store_word(uint32 offset, uint32 data, DeviceExc *client)
117 {
118   data = machine->physmem->host_to_mips_word(data);
119 
120   bool old_interrupt_enable = rtc_reg[RTC_REGB] & REGB_PIE;
121   uint32 reg_no = (offset / 4);
122 #if defined(RTC_DEBUG)
123   fprintf (stderr, "RTC %s (%u) written with 0x%x\n",
124 	reg_names[(reg_no > 14) ? 14 : reg_no], reg_no, data);
125 #endif
126   if (reg_no < 64)
127     rtc_reg[reg_no] = (rtc_reg[reg_no] & ~write_masks[reg_no])
128 	| (((uint8) data) & write_masks[reg_no]);
129   if (reg_no == RTC_REGA) {
130     /* Maybe they changed the interrupt rate selector. */
131     uint8 rate_selector = rtc_reg[RTC_REGA] & REGA_RSX;
132 #if defined(RTC_DEBUG)
133     fprintf (stderr, "RTC rate_selector set to 0x%x (%u)\n", rate_selector,
134 	  int_freqs[rate_selector]);
135 #endif
136     frequency_ns = int_freqs[rate_selector];
137   } else if (reg_no == RTC_REGB) {
138     /* Maybe they enabled or disabled interrupts. */
139     bool new_interrupt_enable = rtc_reg[RTC_REGB] & REGB_PIE;
140 #if defined(RTC_DEBUG)
141     fprintf (stderr, "RTC interrupt_enable set to %d\n", new_interrupt_enable);
142 #endif
143     if ((!old_interrupt_enable) && new_interrupt_enable) {
144 #if defined(RTC_DEBUG)
145       fprintf (stderr, "RTC turning interrupts on\n");
146 #endif
147       ready_clock ();
148     } else if (old_interrupt_enable && (!new_interrupt_enable)) {
149 #if defined(RTC_DEBUG)
150       fprintf (stderr, "RTC turning interrupts off\n");
151 #endif
152       unready_clock ();
153     }
154     interrupt_enable = new_interrupt_enable;
155   }
156 }
157 
158 void
ready_clock()159 DECRTCDevice::ready_clock ()
160 {
161   if (interrupt_enable) {
162 #if defined(RTC_DEBUG)
163     static unsigned long counter = 0;
164     counter++;
165     if ((counter % 50000) == 0)
166 	   fprintf (stderr, "RTC counted %lu interrupts\n", counter);
167 #endif
168     assertInt (irq);
169   }
170 
171   if (frequency_ns > 0) {
172       clock_trigger = new ClockTrigger (this);
173       clock->add_deferred_task (clock_trigger, frequency_ns);
174   } else {
175       clock_trigger = NULL;
176   }
177 }
178 
179 void
unready_clock()180 DECRTCDevice::unready_clock ()
181 {
182   deassertInt (irq);
183 }
184 
~DECRTCDevice()185 DECRTCDevice::~DECRTCDevice ()
186 {
187   if (clock_trigger) {
188 	  clock_trigger->cancel ();
189 	  //delete clock_trigger;
190 	  // If the clock_trigger exists, it will have been added to
191 	  // a DeferredTasks list, and so the destruction of the
192 	  // Clock will cause it to be deleted.
193 	  // So don't delete it here; otherwise, we risk a crash
194 	  // due to double deletion.
195   }
196 }
197 
ClockTrigger(DECRTCDevice * clock_device)198 DECRTCDevice::ClockTrigger::ClockTrigger (DECRTCDevice *clock_device)
199   : rtc (clock_device)
200 {
201   assert (rtc);
202 }
203 
~ClockTrigger()204 DECRTCDevice::ClockTrigger::~ClockTrigger ()
205 {
206 }
207 
208 void
real_task()209 DECRTCDevice::ClockTrigger::real_task ()
210 {
211   rtc->ready_clock ();
212 }
213