int32 todr_rd (void) { TOY *toy = (TOY *)clk_unit.filebuf; struct timespec base, now, val; if ((fault_PC&0xFFFE0000) == 0x20040000) { /* running from ROM? */ sim_debug (DBG_REG, &clk_dev, "todr_rd(ROM) - TODR=0x%X\n", todr_reg); return todr_reg; /* return counted value for ROM diags */ } if (0 == todr_reg) { /* clock running? */ sim_debug (DBG_REG, &clk_dev, "todr_rd(Not Running) - TODR=0x%X\n", todr_reg); return todr_reg; } /* Maximum number of seconds which can be represented as 10ms ticks in the 32bit TODR. This is the 33bit value 0x100000000/100 to get seconds */ #define TOY_MAX_SECS (0x40000000/25) sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ base.tv_sec = toy->toy_gmtbase; base.tv_nsec = toy->toy_gmtbasemsec * 1000000; sim_timespec_diff (&val, &now, &base); if (val.tv_sec >= TOY_MAX_SECS) { /* todr overflowed? */ sim_debug (DBG_REG, &clk_dev, "todr_rd(Overflowed) - TODR=0x%X\n", 0); return todr_reg = 0; /* stop counting */ } sim_debug (DBG_REG, &clk_dev, "todr_rd() - TODR=0x%X\n", (int32)(val.tv_sec*100 + val.tv_nsec/10000000)); return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */ }
t_stat todr_resync (void) { TOY *toy = (TOY *)clk_unit.filebuf; if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX TODR */ if (!toy->toy_gmtbase) /* Never set? */ todr_wr (0); /* Start ticking from 0 */ } else { /* Not-Attached means */ uint32 base; /* behave like simh VMS default */ time_t curr; struct tm *ctm; struct timespec now; sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ curr = (time_t)now.tv_sec; if (curr == (time_t) -1) /* error? */ return SCPE_NOFNC; ctm = localtime (&curr); /* decompose */ if (ctm == NULL) /* error? */ return SCPE_NOFNC; base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */ ctm->tm_hour) * 60) + ctm->tm_min) * 60) + ctm->tm_sec; todr_wr ((base * 100) + 0x10000000 + /* use VMS form */ (int32)(now.tv_nsec / 10000000)); } return SCPE_OK; }
int32 todr_rd (void) { TOY *toy = (TOY *)clk_unit.filebuf; struct timespec base, now, val; sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ base.tv_sec = toy->toy_gmtbase; base.tv_nsec = toy->toy_gmtbasemsec * 1000000; sim_timespec_diff (&val, &now, &base); sim_debug (TMR_DB_TODR, &clk_dev, "todr_rd() - TODR=0x%X - %s\n", (int32)(val.tv_sec*100 + val.tv_nsec/10000000), todr_fmt_vms_todr ((int32)(val.tv_sec*100 + val.tv_nsec/10000000))); return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */ }
void todr_wr (int32 data) { TOY *toy = (TOY *)clk_unit.filebuf; struct timespec now, val, base; /* Save the GMT time when set value was 0 to record the base for future read operations in "battery backed-up" state */ sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ val.tv_sec = ((uint32)data) / 100; val.tv_nsec = (((uint32)data) % 100) * 10000000; sim_timespec_diff (&base, &now, &val); /* base = now - data */ toy->toy_gmtbase = (uint32)base.tv_sec; toy->toy_gmtbasemsec = base.tv_nsec/1000000; sim_debug (TMR_DB_TODR, &tmr_dev, "todr_wr(0x%X)\n", data); }
void todr_wr (int32 data) { TOY *toy = (TOY *)clk_unit.filebuf; struct timespec now, val, base; if (data) { todr_blow = 0; /* Save the GMT time when set value is not 0 to record the base for future read operations in "battery backed-up" state */ sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ val.tv_sec = ((uint32)data) / 100; val.tv_nsec = (((uint32)data) % 100) * 10000000; sim_timespec_diff (&base, &now, &val); /* base = now - data */ toy->toy_gmtbase = (uint32)base.tv_sec; toy->toy_gmtbasemsec = base.tv_nsec/1000000; } else { /* stop the clock */ toy->toy_gmtbase = 0; toy->toy_gmtbasemsec = 0; } todr_reg = data; sim_debug (DBG_REG, &clk_dev, "todr_wr(0x%X) - TODR=0x%X blow=%d\n", data, todr_reg, todr_blow); }
int32 wtc_rd (int32 rg) { int32 val = 0; time_t curr; struct timespec now; static int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; struct tm *ctm = NULL; if (rg < 10) { /* time reg? */ sim_rtcn_get_time (&now, TMR_CLK); curr = now.tv_sec; /* get curr time */ if (curr == (time_t) -1) /* error? */ return 0; ctm = localtime (&curr); /* decompose */ if (ctm == NULL) /* error? */ return 0; if ((wtc_mode == WTC_MODE_VMS) && ((ctm->tm_year % 4) == 0)) { /* Leap Year? */ if (ctm->tm_mon > 1) { /* Past February? */ ++ctm->tm_mday; /* Adjust for Leap Day */ if (ctm->tm_mday > mdays[ctm->tm_mon]) { /* wrap to last day of prior month */ ++ctm->tm_mon; ctm->tm_mday = 1; } } else if ((ctm->tm_mon == 1) && /* February 29th? */ (ctm->tm_mday == 29)) { ctm->tm_mon = 2; /* Is March 1 in 1982 */ ctm->tm_mday = 1; } } } val = wtc_ram[rg]; /* start with RAM data */ if (rg < 14) { switch(rg) { case 0: /* seconds */ val = ctm->tm_sec; break; case 2: /* minutes */ val = ctm->tm_min; break; case 4: /* hours */ val = ctm->tm_hour; break; case 6: /* day of week */ val = ctm->tm_wday; break; case 7: /* day of month */ val = ctm->tm_mday; break; case 8: /* month */ val = ctm->tm_mon + 1; break; case 9: /* year */ if (wtc_mode == WTC_MODE_VMS) val = 82; /* always 1982 for VMS */ else val = (int32)(ctm->tm_year % 100); break; case 10: /* CSR A */ val = wtc_csra; break; case 11: /* CSR B */ val = wtc_csrb; break; case 12: /* CSR C */ val = wtc_csrc; break; case 13: /* CSR D */ val = wtc_csrd & WTC_CSRD_RD; wtc_set_valid (); break; } sim_debug(DBG_REG, &wtc_dev, "wtc_rd(rg=%d [%s], data=0x%X) ", rg, wtc_regs[rg], val); sim_debug_bits(DBG_REG, &wtc_dev, wtc_bitdefs[rg], (uint32)val, (uint32)val, TRUE); } else sim_debug(DBG_REG, &wtc_dev, "wtc_rd(rg=%d [RAM], data=0x%X)\n", rg, val); return val; }