From - Wed Sep 17 11:17:49 1997 Path: news.mitre.org!blanket.mitre.org!agate!newsgate.duke.edu!nntprelay.mathworks.com!newsfeed.internetmci.com!198.108.1.18!aanews.merit.net!news.si.com!young_mike.si.com From: tillman_brian@si.com.no.junk (Brian Tillman) (Remove .no.junk) Newsgroups: comp.os.vms Subject: Re: Time change software SPRINGFOR.MAR - 3 Attachments [1/1] Date: 17 Sep 97 13:15:28 GMT Organization: Smiths Industries Lines: 452 Message-ID: <341fd7f0.0@news.si.com> References: <5vbhid$e7h$1@nntp3.interaccess.com> NNTP-Posting-Host: challenger.si.com Mime-Version: 1.0 Content-Type: multipart/mixed; Boundary="*- Boundary FhypIN3xBe5kvrZF/hrA" Keywords: daylight savings time X-Newsreader: WinVN 0.99.8 (beta 2) --*- Boundary FhypIN3xBe5kvrZF/hrA Content-Type: Text/Plain; charset=US-ASCII In article <5vbhid$e7h$1@nntp3.interaccess.com>, not-rcp@nteraccess.com says... > >That blessed twice a year event of changing to/from daylight savings time is >on us once again. I found a short macro program called SPRINGFOR that will >change the clock tick rate by 25% over a four hour period. Here's another one, from Digital, called TBO, for both VAXes and Alphas. TBO.CLD, TBO.HLP, and TBO.MAR are all attached (I hope. If not, give me a shout). -- Brian Tillman Internet: tillman_brian at si.com Smiths Industries, Inc. tillman at swdev.si.com 4141 Eastern Ave., MS239 Addresses modified to prevent Grand Rapids, MI 49518-8727 SPAM. Replace "at" with "@" This opinion doesn't represent that of my company --*- Boundary FhypIN3xBe5kvrZF/hrA Content-Type: Application/octet-stream; name=tbo.cld define verb TBO image mgr_tools:TBO noparameters qualifier RESET nonnegatable qualifier INFO nonnegatable qualifier DIRECTION nonnegatable, value(required, type=DIR_TYPE) qualifier DELTA nonnegatable, value(required, type=$NUMBER) qualifier RANGE nonnegatable, value(required, type=$NUMBER) disallow RESET and (DELTA or RANGE or DIRECTION) disallow DELTA and not (RANGE and DIRECTION) disallow RANGE and not (DELTA and DIRECTION) disallow DIRECTION and not (DELTA and RANGE) define type DIR_TYPE keyword BACKWARD keyword FORWARD --*- Boundary FhypIN3xBe5kvrZF/hrA Content-Type: Application/octet-stream; name=tbo.hlp 1 TBO TBO (Time Booster) is a OpenVMS VAX and AXP utility which allows privileged users to gradually move the OpenVMS time backward or forward. This utility is meant to be used when switching from standard time to daylight savings time or vice versa. Supplied by Digital without support !!!! Syntax: $ TBO /Qualifiers 2 Parameter TBO has no parameters 2 Example $ TBO /INFO %TBO-I-IDENT, VAX/VMS Time Booster Rev 1.0 %TBO-I-INFO, Systemtime: 2-APR-1996 10:28:05.58 Timeadjust: 0 Ticklength: 9765 $ TBO /DIRECTION=BACKWARD /RANGE=14400 /DELTA=3600 /INFO %TBO-I-IDENT, VAX/VMS Time Booster Rev 1.0 %TBO-I-INFO, Systemtime: 2-APR-1996 10:29:34.30 Timeadjust: 14745600 Ticklength: 7323 This command will move the clock 1 hour back over a period of 4 hours (summertime -> wintertime). /INFO will display the current time, the adjustment duration, and the reduced ticklength. Subsequent TBO /INFO commands will display the TBO progress (i.e. the Timeadjust value will reduce slowly to zero). Once TBO is active it can be stopped using the TBO /RESET command. $ TBO /RESET /INFO %TBO-I-IDENT, VAX/VMS Time Booster Rev 1.0 %TBO-I-RESET, Default ticklength restored %TBO-I-INFO, Systemtime: 2-APR-1996 10:34:17.57 Timeadjust: 0 Ticklength: 9765 2 /DIRECTION Format: TBO /DIRECTION=Keyword /RANGE=Number /DELTA=Number [/INFO] /DIRECTION is used to specify whether the time adjustment is made for summertime (/DIRECTION=FORWARD) or for wintertime (/DIRECTION= BACKWARD). This qualifier must be used together with /DELTA and /RANGE, /INFO is optional. 2 /RANGE Format: TBO /DIRECTION=Keyword /RANGE=Number /DELTA=Number [/INFO] /RANGE is used to specify the adjustment duration in seconds. So /RANGE=14400 specifies a 4 hour period during which the clock will be adjusted in the specified direction. This qualifier must be used together with /DIRECTION and /DELTA, /INFO is optional. 2 /DELTA Format: TBO /DIRECTION=Keyword /RANGE=Number /DELTA=Number [/INFO] /DELTA is used to specify the number of seconds the clock has to be adjusted. So /DELTA=3600 is used to move the clock 1 hour back- or forward (depends on the value of /DIRECTION). The duration of the adjustment is specified by /RANGE. This qualifier must be used together with /DIRECTION and /RANGE, /INFO is optional. 2 /RESET Format: TBO /RESET This command (no other qualifiers, except /INFO, are allowed) resets the clock update action. Whenever a TBO command is issued to change the time, 2 internal OpenVMS memory locations (EXE$GL_TICKLENGTH and EXE$GL_TIMEADJUST) are modified. /RESET forces the original values into the memory locations, thereby stopping the adjustment action. 2 /INFO Format: TBO /INFO Using /INFO will display the current system time, and the contents of the locations EXE$GL_TICKLENGTH and EXE$GL_TIMEADJUST. The first memory location specifies the number of hardware clock ticks which make up a 10 msec unit, the 2nd location specifies the number of hardware clock ticks which have to pass before the 1st location is reseted to it's original value. --*- Boundary FhypIN3xBe5kvrZF/hrA Content-Type: Application/octet-stream; name=tbo.mar .title Time_Booster .ident "Version 2.0" ; VAX has a 10millisecond clock (a tick). ALPHA has an interval timer that ; is determined by the value in the hardware restart parameter block (HWRPB) ; at offset HWRPB$IQ_CLOCK_INT_FREQ. This value will minimally be 1000 and ; and initially all ALPHA systems will generate 1024 interupts (ticks) per ; second. ; ; Note that we'll use the following: ; VAX & ALPHA: ; EXE$GL_SYSTICK - standard clock tick length ; EXE$GL_TICKLENGTH - increment added to clock at each hardware clock interrupt ; EXE$GL_TIMEADJUST - number of ticks to apply EXE$GL_TICKLENGTH ; ALPHA: ; EXE$GPL_HWRPB_L - hardware restart parameter block ; HWRPB$IL_CLOCK_FREQ_L - offset to clock interrupt frequency ; ; define ALPHA if R22 is a register and not a symbol ; .ntype ...IS_IT_ALPHA,r22 ;Get the type of R22 ...IS_IT_ALPHA = <...IS_IT_ALPHA@-4&^XF>-5 .iif eq,...IS_IT_ALPHA, ALPHA=1 .library "sys$share:lib.mlb" .if not_defined, ALPHA ; VAX only .link "sys$system:sys.stb" /selective_search .endc ; AXP use LINK/SYSEXE=SELECTIVE $clidef ; CLI codes .if defined, ALPHA $hwrpbdef ; hardware codes .endc $ssdef ; system service status codes .macro test_ret ?l blbs r0,l $exit_s r0 l: .endm test_ret .psect string, noexe, nowrt, quad ann: .ascid "%TBO-I-IDENT, OpenVMS Time Booster Rev 2.0" res_ann: .ascid "%TBO-I-RESET, Default ticklength restored" cntr_info: .ascid "%TBO-I-INFO, Systemtime: !AS!/ Timeadjust: !UL!/ Ticklength: !UL" noalq: .ascid "%TBO-E-NOTALLQUAL, Not all qualifiers are specified" res_entity: .ascid "reset" inf_entity: .ascid "info" del_entity: .ascid "delta" rang_entity: .ascid "range" dir_entity: .ascid "direction" dir_det: .ascii "B" .align long addend: .long 0 .page .psect data, noexe, wrt, quad lock_adr: .address lock_start .address lock_end deflen: .blkl 1 numargs: .long 0 direc_s: .long 1 ; Direction is forward range_s: .long 0 delta_s: .long 0 ticklength: .blkl 1 timeadjust: .blkl 1 .if defined, ALPHA clockfreq: .blkl 1 .endc systick: .blkl 1 remainder: .blkl 1 multipl: .blkl 1 .align quad product: .blkq 1 systime: .blkq 1 systime$: .ascid "xx-xxx-xxxx xx:xx:xx.xx" .align long out_desc: .long 132 .address faobuf faobuf: .blkb 132 .align long cvt_desc: .word 8 .word 270 .address cvtbuf cvtbuf: .blkb 8 .page .psect code, exe, nowrt, quad .entry main,^m<> pushal ann ; Push descriptor address calls #1,g^lib$put_output ; Let every one whats running $lkwset_s inadr=lock_adr ; Lock the privileged code in the working set test_ret ; Check the return value pushal res_entity calls #1,g^cli$present ; Do we want to reset? cmpl r0,#cli$_present ; If option is reset then bneq 10$ $cmkrnl_s routin=reset_hwclk ; Initiate reset routine test_ret ; Check the return value pushal res_ann ; Push success message calls #1,g^lib$put_output ; Cry it out! brw 20$ 10$: bsbw scan_cli ; See if there is something to mess around whith? tstl numargs ; No qualifiers? beql 20$ ; Then there is only one item to check left. cmpl #3, numargs ; Are there three items beql 22$ ; If not, then exit pushal noalq calls #1,g^lib$put_output brb 30$ 22$: bsbw calc_ticks ; Calculate needed correction 20$: pushal inf_entity calls #1,g^cli$present ; Do we want info? cmpl r0,#cli$_present ; If option is info then bneq 30$ bsbw hwclk_info ; try to find out the current settings 30$: $exit_s ; Initiate image rundown ret hwclk_info: .iif defined, ALPHA, .jsb_entry $cmkrnl_s routin=copy_info test_ret ; Check the return value $asctim_s timlen=deflen, - ; Convert quad word to system time string timbuf=systime$, - timadr=systime, - cvtflg=#0 $fao_s ctrstr=cntr_info, - ; Make everything readable and outbuf=out_desc, - ; store it in a buffer p1=#systime$, - p2=timeadjust, - p3=ticklength pushal out_desc calls #1,g^lib$put_output ; Cry it out! rsb scan_cli: .iif defined, ALPHA, .jsb_entry output=r0, preserve=r1 clrl numargs pushal dir_entity calls #1,g^cli$present ; Test the precense of the direction qualifier cmpl r0,#cli$_present ; Which way do we want to travel? bneq 110$ ; No direction?!, check the user for another errors! incl numargs ; Increment the parameter counter pushal cvt_desc pushal dir_entity calls #2,g^cli$get_value ; Return the value assigned to the qualifier moval cvtbuf,r1 cmpb dir_det,(r1) ; If direction is backward bneq 110$ movl #-1,direc_s ; Direc_s is negative 110$: pushal del_entity ; Check next entity calls #1,g^cli$present ; Test the presence of the delta qualifier cmpl r0,#cli$_present ; How many seconds are involved bneq 115$ ; And no delta? What are we doing? incl numargs movl #8,cvt_desc ; Restore buffer size pushal cvt_desc ; Let the return value set up the descriptor pushal cvt_desc pushal del_entity calls #3,g^cli$get_value ; Return the delta value pushal delta_s pushal cvt_desc calls #2,g^ots$cvt_tu_l ; Convert delta string to unsigned long word test_ret 115$: pushal rang_entity ; Check next entity calls #1,g^cli$present ; Test the presence of the range qualifier cmpl r0,#cli$_present ; How many seconds are involved bneq 120$ ; Even no range, we better exit this routine incl numargs movl #8,cvt_desc ; Restore buffer size pushal cvt_desc ; Let the return value set up the descriptor pushal cvt_desc pushal rang_entity calls #3,g^cli$get_value ; Return the range value pushal range_s pushal cvt_desc calls #2,g^ots$cvt_tu_l ; Convert delta string to unsigned long word test_ret 120$: movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl rsb calc_ticks: .iif defined, ALPHA, .jsb_entry preserve= $cmkrnl_s routin=get_systick ; Retrieve systick .if defined, ALPHA ; If AXP Derive the clock resolution movl clockfreq,r1 ;; Load ticks per second movl systick,r3 ;; Load standard clock tick length mull2 r3,r1 ;; Formula: (freq*systick) .iff ; Else movl #10000000,r1 ; If VAX Load clock resolution (1/100ns) .endc movl range_s,r2 ; Load range in seconds movl systick,r3 ; Load exe$gl_systick divl2 r3,r1 ; r1 contains number of ticks required to adjust time mull2 r2,r1 ; Formula: (1E7*range/systick) movl r1,timeadjust ; Save it movl delta_s,r4 ; Load delta value movl direc_s,r5 ; Load direction mull2 r5,r4 ; Calc direction addl2 r2,r4 movl r4,multipl ; Store r4 pushal product ; Push the arguments pushal addend pushal systick pushal multipl calls #4,g^lib$emul ; Perform a 64 bit multiplication pushal remainder pushal ticklength pushal product pushal range_s calls #4,g^lib$ediv ; Formula: ((range+(delta*direc))*systick/range) => new ticklength $cmkrnl_s routin=store_ticks ; Store calculated values in hwclk data structures rsb .page .psect prcode, exe, nowrt ; This psect contains code which runs at an elevated ipl .if defined, ALPHA .call_entry max_args=0,home_args=false,label=reset_hwclk,output=r0 .iff .entry reset_hwclk,^m<> .endc lock_start: ; and is locked in the working set lock lockname=hwclk ; Lock hardware clock data structures clrl g^exe$gl_timeadjust ; Disable clock adjustment movl g^exe$gl_systick,g^exe$gl_ticklength ; Restore standard tick unlock lockname=hwclk, newipl=#0 ; Release the hardware clock lock movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl ret .if defined, ALPHA .call_entry max_args=0,home_args=false,label=copy_info,output=r0 .iff .entry copy_info,^m<> .endc lock lockname=hwclk ; Lock hardware clock data structures movl g^exe$gl_timeadjust, timeadjust ; Save timeadjust value in order to release lock as quick as possible movl g^exe$gl_ticklength, ticklength ; Do the same with the ticklength value movq g^exe$gq_systime, systime ; Even system time is saved for whatever the purpose may be unlock lockname=hwclk, newipl=#0 ; Release the hardware clock lock movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl ret .if defined, ALPHA .call_entry max_args=0,home_args=false,label=get_systick,output=r0 .iff .entry get_systick,^m<> .endc lock lockname=hwclk ; Lock hardware clock data structures movl g^exe$gl_systick,systick ; Copy systick value .if defined, ALPHA ; Copy clock interrupt frequency ; and adjust for it's scaling ; the clock interrupt frequency rate is given to the system in the ; HWRPB. The value is a scaled up value (*4096) of the real ticks ; per second value. ; (VMS Source Listings - [V62.SYS.LIS]TIMESCHDL_MIN.LIS) movl exe$gpl_hwrpb_l, r0 ashl #-12, hwrpb$il_clock_int_freq_l(r0), clockfreq .endc unlock lockname=hwclk, newipl=#0 ; Release the hardware clock lock movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl ret .if defined, ALPHA .call_entry max_args=0,home_args=false,label=store_ticks,output=r0 .iff .entry store_ticks,^m<> .endc lock lockname=hwclk ; Lock hardware clock data structures movl timeadjust, g^exe$gl_timeadjust ; Store timeadjust value movl ticklength, g^exe$gl_ticklength ; Store new ticklength value unlock lockname=hwclk, newipl=#0 ; Release the hardware clock lock movl #ss$_normal,r0 ; Restore the success return value for sys$cmkrnl ret lock_end: .end main --*- Boundary FhypIN3xBe5kvrZF/hrA--