blob: afbb166080a7777d3b962e0ed6e13e0affbc8152 [file] [log] [blame] [raw]
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -08001/* vax_watch.c: VAX watch chip
2
3 Copyright (c) 2011-2012, Matt Burke
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the author shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the author.
25
26 wtc Watch chip
27
28 08-Nov-2012 MB First version
29
30 This file covers the watch chip (MC146818) which is used by several VAX
31 models including the KA620, KA630, KA410, KA420 and KA820.
32*/
33
34#include "vax_defs.h"
35#include <time.h>
36
37/* control/status registers */
38
Mark Pizzolato19d30d92013-08-21 13:54:00 -070039#define WTC_CSRA_RS 0x0F /* Rate Select Bits (Not Used by VMS) */
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -080040#define WTC_CSRA_V_DV 4
41#define WTC_CSRA_M_DV 0x7
42#define WTC_CSRA_DV (WTC_CSRA_M_DV << WTC_CSRA_V_DV)
Mark Pizzolato19d30d92013-08-21 13:54:00 -070043#define WTC_CSRA_UIP 0x80 /* update in progess (BUSY) */
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -080044#define WTC_CSRA_WR (WTC_CSRA_RS | WTC_CSRA_DV)
Mark Pizzolatodb91afb2013-09-05 23:30:22 -070045const char *wtc_dv_modes[] = {"4.194304MHz", "1.048576MHz", "32.768KHz", "Any", "Any", "Test-Only", "Test-Only", "Test-Only"};
Mark Pizzolato19d30d92013-08-21 13:54:00 -070046BITFIELD wtc_csra_bits[] = {
47 BITNCF(4), /* Rate Select - unused MBZ for VMS */
48 BITFNAM(DV,3,wtc_dv_modes), /* Divider Select */
49 BIT(UIP), /* Update In Progress */
50 ENDBITS
51};
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -080052
53#define WTC_CSRB_DSE 0x01 /* daylight saving en */
Mark Pizzolato19d30d92013-08-21 13:54:00 -070054#define WTC_CSRB_2412 0x02 /* 24/12hr select (1 -> 24 hr) */
55#define WTC_CSRB_DM 0x04 /* data mode (1 -> binary, 0 -> BCD) */
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -080056#define WTC_CSRB_SET 0x80 /* set time */
Mark Pizzolato19d30d92013-08-21 13:54:00 -070057#define WTC_CSRB_PIE 0x40 /* periodic interrupt enable (Not Used by VMS) */
58#define WTC_CSRB_AIE 0x20 /* alarm interrupt enable (Not Used by VMS) */
59#define WTC_CSRB_UIE 0x10 /* update ended interrupt enable (Not Used by VMS) */
60#define WTC_CSRB_SQWE 0x08 /* square wave enable (Not Used by VMS) */
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -080061#define WTC_CSRB_WR (WTC_CSRB_DSE | WTC_CSRB_2412 | WTC_CSRB_DM | WTC_CSRB_SET)
Mark Pizzolatodb91afb2013-09-05 23:30:22 -070062const char *wtc_dse_modes[] = {"Disabled", "Enabled"};
63const char *wtc_hr_modes[] = {"12Hr", "24Hr"};
64const char *wtc_data_modes[] = {"BCD", "Binary"};
Mark Pizzolato19d30d92013-08-21 13:54:00 -070065BITFIELD wtc_csrb_bits[] = {
66 BITFNAM(DST,1,wtc_dse_modes), /* Daylight Savings Time Enable */
67 BITFNAM(24HR,1,wtc_hr_modes), /* 24/12 Hour Mode */
68 BITFNAM(DM,1,wtc_data_modes), /* Data Mode */
69 BITNCF(4), /* Unused SQWE, UIE, AIE, PIE */
70 BIT(SET), /* Set In Progress */
71 ENDBITS
72};
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -080073
Mark Pizzolato19d30d92013-08-21 13:54:00 -070074BITFIELD wtc_csrc_bits[] = {
75 BITF(VALUE,8), /* Should be unused */
76 ENDBITS
77};
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -080078#define WTC_CSRD_VRT 0x80 /* valid time */
79#define WTC_CSRD_RD (WTC_CSRD_VRT)
Mark Pizzolato19d30d92013-08-21 13:54:00 -070080#define WTC_CSRD_WR (WTC_CSRD_VRT)
81BITFIELD wtc_csrd_bits[] = {
82 BITNCF(7),
83 BIT(VALID), /* Valid RAM and Time (VRT) */
84 ENDBITS
85};
86
87BITFIELD wtc_value_bits[] = {
88 BITFFMT(VALUE,8,%d), /* Decimal Value */
89 ENDBITS
90};
91BITFIELD* wtc_bitdefs[] = {wtc_value_bits, wtc_value_bits, wtc_value_bits, wtc_value_bits,
92 wtc_value_bits, wtc_value_bits, wtc_value_bits, wtc_value_bits,
93 wtc_value_bits, wtc_value_bits, wtc_csra_bits, wtc_csrb_bits,
94 wtc_csrc_bits, wtc_csrd_bits, wtc_value_bits, wtc_value_bits};
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -080095
96#define WTC_MODE_STD 0
97#define WTC_MODE_VMS 1
Mark Pizzolatodb91afb2013-09-05 23:30:22 -070098const char *wtc_modes[] = {"Std", "VMS"};
Mark Pizzolato19d30d92013-08-21 13:54:00 -070099BITFIELD wtc_mode_bits[] = {
100 BITFNAM(MODE,1,wtc_modes), /* Watch Date/Time mode */
101 ENDBITS
102};
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800103
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800104int32 wtc_csra = 0;
105int32 wtc_csrb = 0;
106int32 wtc_csrc = 0;
107int32 wtc_csrd = 0;
108int32 wtc_mode = WTC_MODE_VMS;
109
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700110t_stat wtc_set (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
111t_stat wtc_show (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
Mark Pizzolatoef9d1ad2015-02-13 06:18:24 -0800112t_stat wtc_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
113const char *wtc_description (DEVICE *dptr);
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800114t_stat wtc_reset (DEVICE *dptr);
115void wtc_set_valid (void);
116void wtc_set_invalid (void);
117
118UNIT wtc_unit = { UDATA (NULL, 0, 0) };
119
120REG wtc_reg[] = {
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700121 { HRDATADF (CSRA, wtc_csra, 8, "CSRA", wtc_csra_bits) },
122 { HRDATADF (CSRB, wtc_csrb, 8, "CSRB", wtc_csrb_bits) },
123 { HRDATADF (CSRC, wtc_csrc, 8, "CSRC", wtc_csrc_bits) },
124 { HRDATADF (CSRD, wtc_csrd, 8, "CSRD", wtc_csrd_bits) },
125 { HRDATADF (MODE, wtc_mode, 8, "Watch Mode", wtc_mode_bits) },
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800126 { NULL }
127 };
128
129MTAB wtc_mod[] = {
Mark Pizzolato28b90552013-02-02 16:29:38 -0800130 { MTAB_XTD|MTAB_VDV, 0, "TIME", "TIME={VMS|STD}", &wtc_set, &wtc_show, NULL, "Display watch time mode" },
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800131 { 0 }
132 };
133
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700134/* debugging bitmaps */
135#define DBG_REG 0x0001 /* trace read/write registers */
136
137DEBTAB wtc_debug[] = {
138 {"REG", DBG_REG},
139 {0}
140};
141
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800142DEVICE wtc_dev = {
143 "WTC", &wtc_unit, wtc_reg, wtc_mod,
144 1, 16, 16, 1, 16, 8,
145 NULL, NULL, &wtc_reset,
146 NULL, NULL, NULL,
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700147 NULL, DEV_DEBUG, 0, wtc_debug, NULL, NULL, &wtc_help, NULL, NULL,
Mark Pizzolatocbe11142013-01-25 12:04:25 -0800148 &wtc_description
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800149 };
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700150
151/* Register names for Debug tracing */
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700152static const char *wtc_regs[] =
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700153 {"SEC ", "SECA", "MIN ", "MINA",
154 "HR ", "HRA ", "DOW ", "DOM ",
155 "MON ", "YEAR", "CSRA", "CSRB",
156 "CSRC", "CSRD" };
157
158
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800159
160int32 wtc_rd (int32 pa)
161{
162int32 rg = (pa >> 1) & 0xF;
163int32 val = 0;
164time_t curr;
Mark Pizzolato39d29442016-11-16 23:50:53 -0800165struct timespec now;
Mark Pizzolatob4b4a882016-04-13 12:12:29 -0700166static int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
Mark Pizzolato50cf91d2012-12-18 09:52:14 -0800167struct tm *ctm = NULL;
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800168
169if (rg < 10) { /* time reg? */
Mark Pizzolato39d29442016-11-16 23:50:53 -0800170 sim_rtcn_get_time (&now, TMR_CLK);
171 curr = now.tv_sec; /* get curr time */
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800172 if (curr == (time_t) -1) /* error? */
173 return 0;
174 ctm = localtime (&curr); /* decompose */
175 if (ctm == NULL) /* error? */
176 return 0;
Mark Pizzolatob4b4a882016-04-13 12:12:29 -0700177 if ((wtc_mode == WTC_MODE_VMS) &&
178 ((ctm->tm_year % 4) == 0)) { /* Leap Year? */
179 if (ctm->tm_mon > 1) { /* Past February? */
180 ++ctm->tm_mday; /* Adjust for Leap Day */
181 if (ctm->tm_mday > mdays[ctm->tm_mon]) { /* wrap to last day of prior month */
182 ++ctm->tm_mon;
183 ctm->tm_mday = 1;
184 }
185 }
186 else
187 if ((ctm->tm_mon == 1) && /* February 29th? */
188 (ctm->tm_mday == 29)) {
189 ctm->tm_mon = 2; /* Is March 1 in 1982 */
190 ctm->tm_mday = 1;
191 }
192 }
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800193 }
194
195switch(rg) {
196
197 case 0: /* seconds */
198 val = ctm->tm_sec;
199 break;
200
201 case 2: /* minutes */
202 val = ctm->tm_min;
203 break;
204
205 case 4: /* hours */
206 val = ctm->tm_hour;
207 break;
208
209 case 6: /* day of week */
210 val = ctm->tm_wday;
211 break;
212
213 case 7: /* day of month */
214 val = ctm->tm_mday;
215 break;
216
217 case 8: /* month */
Mark Pizzolatob4b4a882016-04-13 12:12:29 -0700218 val = ctm->tm_mon + 1;
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800219 break;
220
221 case 9: /* year */
222 if (wtc_mode == WTC_MODE_VMS)
223 val = 82; /* always 1982 for VMS */
224 else
225 val = (int32)(ctm->tm_year % 100);
226 break;
227
228 case 10: /* CSR A */
229 val = wtc_csra;
230 break;
231
232 case 11: /* CSR B */
233 val = wtc_csrb;
234 break;
235
236 case 12: /* CSR C */
237 val = wtc_csrc;
238 break;
239
240 case 13: /* CSR D */
241 val = wtc_csrd & WTC_CSRD_RD;
242 break;
243 }
244
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700245sim_debug(DBG_REG, &wtc_dev, "wtc_rd(pa=0x%08X [%s], data=0x%X) ", pa, wtc_regs[rg], val);
246sim_debug_bits(DBG_REG, &wtc_dev, wtc_bitdefs[rg], (uint32)val, (uint32)val, TRUE);
247
248if (rg & 1)
249 val = (val << 16); /* word aligned? */
250
251return val;
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800252}
253
254void wtc_wr (int32 pa, int32 val, int32 lnt)
255{
256int32 rg = (pa >> 1) & 0xF;
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700257int32 new_val = val;
258
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800259val = val & 0xFF;
260
261switch(rg) {
262
263 case 10: /* CSR A */
264 val = val & WTC_CSRA_WR;
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700265 new_val = wtc_csra = (wtc_csra & ~WTC_CSRA_WR) | val;
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800266 break;
267
268 case 11: /* CSR B */
269 val = val & WTC_CSRB_WR;
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700270 new_val = wtc_csrb = (wtc_csrb & ~WTC_CSRB_WR) | val;
271 break;
272
273 case 12: /* CSR C */
274 break;
275
276 case 13: /* CSR D */
277 val = val & WTC_CSRD_WR;
278 new_val = wtc_csrd = (wtc_csrd & ~WTC_CSRD_WR) | val;
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800279 break;
280 }
Mark Pizzolato19d30d92013-08-21 13:54:00 -0700281
282sim_debug(DBG_REG, &wtc_dev, "wtc_wr(pa=0x%08X [%s], data=0x%X) ", pa, wtc_regs[rg], val);
283sim_debug_bits(DBG_REG, &wtc_dev, wtc_bitdefs[rg], (uint32)new_val, (uint32)new_val, TRUE);
284
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800285}
286
287t_stat wtc_reset (DEVICE *dptr)
288{
289if (sim_switches & SWMASK ('P')) { /* powerup? */
290 wtc_csra = 0;
291 wtc_csrb = 0;
292 wtc_csrc = 0;
293 wtc_csrd = 0;
294 wtc_mode = WTC_MODE_VMS;
295 }
296return SCPE_OK;
297}
298
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700299t_stat wtc_set (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800300{
Mark Pizzolato39d29442016-11-16 23:50:53 -0800301if (cptr != NULL)
302 wtc_mode = ((strcmp(cptr, "STD") != 0) ? WTC_MODE_VMS : WTC_MODE_STD);
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800303return SCPE_OK;
304}
305
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700306t_stat wtc_show (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
Mark Pizzolatob01fa8f2012-11-09 12:18:15 -0800307{
308fprintf(st, "time=%s", (wtc_mode ? "vms" :"std"));
309return SCPE_OK;
310}
311
312void wtc_set_valid (void)
313{
314wtc_csra |= (2 << WTC_CSRA_V_DV);
315wtc_csrb |= (WTC_CSRB_DM | WTC_CSRB_2412);
316wtc_csrd |= WTC_CSRD_VRT;
317}
318
319void wtc_set_invalid (void)
320{
321wtc_csrd &= ~WTC_CSRD_VRT;
322}
Mark Pizzolatocbe11142013-01-25 12:04:25 -0800323
Mark Pizzolatoef9d1ad2015-02-13 06:18:24 -0800324t_stat wtc_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
Mark Pizzolatoe2fb3642013-01-30 07:33:24 -0800325{
326fprintf (st, "Watch Chip (WTC)\n\n");
327fprintf (st, "The WTC simulates the MC146818 watch chip. It recognizes the following options:\n\n");
Mark Pizzolato651780c2013-06-03 06:29:01 -0700328fprintf (st, " SET WTC TIME=STD standard time mode\n");
329fprintf (st, " SET WTC TIME=VMS VMS time mode\n\n");
Mark Pizzolatoe2fb3642013-01-30 07:33:24 -0800330fprintf (st, "When running in standard mode the current year reported by the watch chip is\n");
331fprintf (st, "determined by the date/time of the host system. When running in VMS mode the\n");
332fprintf (st, "year is fixed at 1982, which is one of the conditions VMS expects in order to\n");
333fprintf (st, "verify that the time reported is valid. The default mode is VMS.\n\n");
334return SCPE_OK;
335}
336
Mark Pizzolatoef9d1ad2015-02-13 06:18:24 -0800337const char *wtc_description (DEVICE *dptr)
Mark Pizzolatocbe11142013-01-25 12:04:25 -0800338{
339return "watch chip";
340}