.Title TCU .Ident /V 2.04/ .Enable Lc ; ; Tcu - Program to control the Digital Pathways TCU-100/TCU-150 ; time of day clocks. ; ; Author: ; Michael Lynch ; Engineering Systems and Technology Labs ; 3M Co. ; 3M Center ; St. Paul, Mn., 55144 ; ; Revision History: ; ; 18-Jul-80 Release 2.00 ; ; 28-Jul-80 ML2.01 -- add notes to help command ; ; 31-Aug-80 ML2.02 -- remove SPL instruction from code ; ; 3-Sep-80 Ml2.03 -- fix TCU-150 UPDATE bug for date ; ; 26-Sep-80 Ml2.04 -- clean up error exits from TPars ; .Page .Sbttl Macros and Constants .Mcall Dir$,Qiow$,Gmcr$,ExSt$S .MCall Gcml$,GcmlB$,GcmlD$,Finit$,Fsrsz$ .MCall Mrkt$s,Wtse$S .MCall GLun$S ; ; Print macro definition ; .Macro Print Add,Length .If Nb,Length Mov Add,TTyOut+Q.IoPl Mov Length,TTyOut+Q.Iopl+2 .IFF Mov R0,-(Sp) Mov add,R0 Movb (R0)+,Ttyout+Q.Iopl+2 Mov R0,TtyOut+Q.iopl Mov (Sp)+,R0 .Endc Dir$ #TTYout .Endm ; ; String macro definition ; .MACRO String STR,SEQUEN .IF B,SEQUEN $$T$$$=0 $$l$$$=. .BYTE 0 .IFF .if eq,<''SEQUEN-'B> $$T$$$=0 $$l$$$=. .BYTE 0 .endc .ENDC .IF NB, .ASCII STR .ENDC .IF B,SEQUEN $$E$$$=. .=$$L$$$ $$T$$$=$$E$$$-$$L$$$-1 .BYTE $$T$$$ .=$$E$$$ .IFF .IF EQ,<''SEQUEN-'E> $$E$$$=. .=$$L$$$ $$T$$$=$$E$$$-$$L$$$-1 .BYTE $$T$$$ .=$$E$$$ .ENDC .endc .ENDM ; ; Lun Table ; GmlLun = 4 ;Lun for get command line TTyLun = 5 ;Lun for TI: ; ; Event Flag Table ; TTyEfn = 5 ;event flag for TI: I/O ; ; Set up Ascii codes ; Bell=7 Lf=12 Cr=15 Tab = 11 ; ; Tpars stuff ; ; ParBug=0 ;remove leading ";" to assemble tpars debugger ; ; Tpars parser return mask bit definitions ; ; ; command mask bits ; Hp.Msk == 1 ;just print help message Id.Msk == 2 ;print Tcu's current version Rd.Msk == 4 ;read time/date from tcu St.Msk == 10 ;set time/date in TCU Up.Msk == 20 ;update RSX time/date from TCU Cn.Msk == 40 ;set/request configuration ; ; Sub-command mask bits ; Tm.Msk == 100 ;indicate that time was specified Da.Msk == 200 ;indicate that date was specified Cs.Msk == 400 ;indicate that CSR was entered Ve.Msk == 1000 ;indicate that VEC was entered Yr.Msk == 2000 ;update year was specified ; ; Non-TPars main code mask bits ; T0.Msk == 1 ;set if TCU-100 is in configuration T5.Msk == 2 ;set if TCU-150 is in configuration On.Msk == 4 ;set if TCU is online Pr.Msk == 10 ;set if user is RSX privileged .Page .Sbttl Message strings and Program data storage area ; ; Print Qio Directive Parameter Block ; TTYout:: Qiow$ Io.Wvb,TTyLun,TTyEfn,,TTysts,, TTYsts:: .BlkW 2 ; ; Tcu CSR AND VEC definitions ; TcuCsr::.word 0 ;filled in at task build time TcuVec::.word 0 ;filled in at task build time IntDon::.Word 0 ;interrupt done flag for TCU-100 ; ; Get command line macros and buffers ; Fsrsz$ 1 ;ask for buffer GcmlD$ ;define GcmlB$ offsets CmdBuf: GcmlB$ 1,Tcu,LinBuf,4 ;Lun 4 = command line input LinBuf: .BlkW 41. ; ; Get TI: Lun information buffer ; LunBuf: .BlkW 8. ;storage for local LUN info ; ; Main code features mask word ; CodMsk: .word 0 ; ; Tpars -- returned value storage ; Mask:: .Word 0 ;TPars line component mask word ; ; Note: the following 2 bytes must start on a word boundary ; and must be inseperable. ; Minute::.Byte 0 ;storage for inputted minutes Hour:: .Byte 0 ;storage for inputted hour Day:: .word 0 ;storage for day of month Month:: .word 0 ;storage for month of year Year:: .word 0 ;storage for year (00-99) CsrVal::.word 0 ;storage for CSR VecVal::.word 0 ;storage for VEC ; ; ID function storage ; IdMsg:: String <"Tcu -- My current version is ">,B ID:: .BlkB 6 ;storage for Ident field String <>,E ; ; Help funtion messages Help1: String <"Available commands to Tcu are:"> Help2: String <"Configuration [Csr = ] [Vec = ]"> Help3: String <"Help - print this message"> help4: String <"ID - Prints Tcu's current version"> Help5: String <"Read - read the time and date from the TCU"> Help6: String <"Set - set the time and date"> Help7: String <"Update [Year=] - read TCU time/date and set RSX-11M time"> Help8: String <"Tcu allows command abbreviation to 3 letters"> Help9: String <"Notes: Tcu-100 & Tcu-150 do not allow setting of seconds."> Help10: String <" Tcu-100 ignores any setting of year."> Help11: String <" Tcu-150 ignores any VEC setting."> ; ; Configuration message ; ConMsg: String <"Type = ">,B TypBlk: .BlkB 6 ;filled in from choices listed below String <", Status = ">,E OnOff: .BlkB 3 ;either " ON" or "OFF" String <"Line, ">,C String <"Csr = ">,C CsrStr: .BlkB 6 ;storage for CSR octal ascii String <", Vector = ">,C VecStr: .BlkB 3 ;storage for vector octal ascii String <>,E ;end of message On: .Ascii " On" Off: .Ascii "Off" Tunk:: .Ascii " ?? " T100: .Ascii "Tcu100" T150:: .Ascii "Tcu150" ; ; Update command MCR string ; ; ; The following 8 words are in the GTim$ RSX-11M executive directive ; standard format ; .Even McrDat: .Word 0 ;year .word 0 ;month .word 0 ;day McrTim: .Word 0 ;hours .Word 0 ;minutes .Word 0 ;seconds .Word 0,0 McrMsg: String <"Tim ">,B TimDat: .BLKB 17. String <" "<0>>,E ; ; Error messages ; Yr5Err:: String <"Tcu -- Fatal ERROR - TCU-150 requires year specification"> YrErr:: String <"Tcu -- FATAL ERROR - TCU-100 requires year specification"> SynErr:: String <"Tcu -- Syntax Error"> OffErr:: String <"Tcu -- FATAL ERROR - Tcu unit is not in system"> DynErr:: String <"Tcu -- FATAL ERROR - Insufficient RSX Pool"> PrvErr:: String <"Tcu -- Sorry, but you must be a Privileged RSX user for this command"> .Even .Page .Sbttl Main code Tcu: Finit$ Mov #Id,R0 ;save Ident field Mov R3,R1 ;get 1st 3 Rad50 characters Call $C5ta ;convert to ascii Mov R4,R1 ;get 2cd 3 Rad50 characters Call $C5ta ;convert to ascii GLun$S #5,#LunBuf ;get TI: info from Exec Restrt: Mov #CmdBuf,R0 ;point to command buffer Gcml$ #CmdBuf Bcc 20$ ;if no error, jump around CmpB CmdBuf+G.Err,#Ge.Eof ;end of file? Bne Restrt ;if not, error, try again Jmp Exit ;take normal exit 20$: Mov CmdBuf+G.cmld,R3 ;load length of command line Beq Restrt ;if empty, loop back and try again Mov #3*256.,R1 ;skip blanks in command lines ;keywords must match up to 3 chars Mov #LogKtb,R2 ;point to keyword table Mov CmdBuf+G.cmld+2,R4 ;load address of command line Mov #LogSrt,R5 ;point to initial state Clr Mask ;initialize tpars mask Clr CodMsk ;initialize main code mask .If Df,ParBug ;if Tpars debugger is to be assembled Mov #TDebug,.TpDeb ;point to Tpars debugging trace routine Call .TparD ;parse command line, with Debug .IFF ;if tpars debugger NOT assembled Call .Tpars ;parse command line .EndC ;end of Tpars debugger conditional Bcc 30$ ;if no error, jump around ; ; Tpars syntax error, print line and error message, try again if we can ; Mov #TTYout,R0 ;point to print-out DPB Mov #40,Q.iopl+4(R0) ;use carriage control MovB SynErr,Q.iopl+2(R0) ;get length of string Mov #Synerr+1,Q.iopl(R0) ;starting address Dir$ R0 ;print it Call PriErr ;print syntax error Br Restrt ;get next command line ; ; Command line parsed successfully ; 30$: Bit #Hp.Msk,Mask ;was help pleaded for ? Beq 35$ ;if not, jump around Call Help ;print help message Br Restrt ;re-dispatch 35$: Bit #Id.Msk,Mask ;Ident asked for? Beq 40$ ;if not, jump around Print #IdMsg ;print I.D. Br Restrt ;get next command 40$: Bit #Cn.Msk,Mask ;configuration request? Beq 50$ ;if not, search on Call ConFig ;do it Br Restrt ;re-dispatch 50$: Bit #St.Msk,Mask ;Set TCU command Beq 70$ ;if not, search on Call PriChk ;check for privilege, don't return on error Call Set ;set time in TCU Br Restrt ;re-dispatch 70$: Bit #Rd.Msk!Up.Msk,Mask ;Read/Update Rsx-11M time from TCU? Beq Restrt ;if not, re-dispatch Bit #Up.Msk,Mask ;Update command? Beq 75$ ;if not, jump around Call PriChk ;check for privilege, don't return on error 75$: Call Update ;read OR set RSX time Br Restrt ;re-dispatch .Page .SbTTl HELP command - Print a help message Help: Print #Help1 ;print help messages Print #help2 Print #Help3 Print #Help4 Print #Help5 Print #Help6 Print #Help7 Print #Help8 Print #Help9 Print #Help10 Print #Help11 Return .Page .Sbttl Configuration command ConFig: Bit #Cs.Msk!Ve.Msk,Mask ;CSR or VEC set? Bne 100$ ;if so, jump around ; ; Display current configuration ; Call DevChk ;find out whats out there Mov #CsrStr,R0 ;load up pointer to CSR message Mov TcuCsr,R1 ;get csr Inc R2 ;want leading zeros Call $Cbomg ;convert Mov #VecStr+3,R0 ;point to vec area Mov TcuVec,R1 ;get vector Clr R2 ;suppress leading zeros Mov #3,R3 40$: ClrB -(R0) ;clean out storage Sob R3,40$ Call $CBomg Mov #Tunk,R4 ;assume TCU offline Mov #off,R5 ;"Off" Bit #On.Msk,CodMsk ;tcu online? Beq 50$ ;if not, jump around Mov #On,R5 ;assume device on line ; ; Set up type byte with proper TCU type ; Mov #T100,R4 ;assume tcu-100 Bit #T0.Msk,CodMsk ;TCU-100 on line? Bne 50$ ;if so, all done, jump around Mov #T150,R4 ;assume TCU-150 Bit #T5.Msk,CodMsk ;TCU-150 on line ? Bne 50$ ;if so, all done, jump around ; ; Place new TCU types here as they become available ; ; ; Print configuration message ; 50$: Mov #6,R0 ;6 bytes to move Mov #TypBlk,R1 ;point to destination 60$: MovB (R4)+,(R1)+ ;load up type Sob R0,60$ ;loop till done Mov #3,R0 ;number of bytes to move Mov #OnOff,R1 ;point to destination 70$: MovB (R5)+,(R1)+ ;move proper message Sob R0,70$ ;loop till done Print #ConMsg Return 100$: Call PriChk ;check for privilege, don't return on error Bit #Cs.Msk,Mask ;csr set? Beq 110$ ;if not, jump around Mov CsrVal,TCUCsr ;move it in 110$: Bit #Ve.Msk,Mask ;Vec set? Beq 120$ ;if not, jump Mov VecVal,TcuVec ;mov it in 120$: Return .Page .Sbttl Privilege Check subroutine ; ; Check to see if user's TI: has the bit U2.Prv set in his ; second characteristics word, obtained via a GLun$s exec directive. ; PriChk: Bit #U2.Prv,LunBuf+6 ;check 4th word of GLun$s buffer Bne 10$ ;if set, user privileged, OK Print #PrvErr ;print error message Jmp Restrt 10$: Return .Page .Sbttl Obtain TCU type and online status ; ; Obtain TCU typ info ; .MCall Svtk$S VecTbl: .Word Trp4 ;odd address or non-existant memory VecLen = .-VecTbl ; ; Trap 4 (odd address or non-existant memory hardware trap) ; ; Note: SST routines must be re-entrant, for an AST or SST may ; interrupt a SST. All registers MUST be saved in a SST ; ; This service routine simply sets the C-bit in the saved processor ; status register and returns from the trap ; Trp4: Bis #1,2(Sp) ;indicate non-existant device Rti DevChk: SVtk$S #VecTbl,#VecLen ;specify SST vector table Mov R0,-(Sp) ;save R0 for now Mov TcuCsr,R0 ;get TCU's control and status reg. Bic #T0.Msk!T5.Msk!On.Msk,CodMsk ;assume offline Tst (R0) ;Tcu online Bcs 50$ ;if not, jump Bis #On.Msk,CodMsk ;declare on line ; ; Switch to system state to guarentee we have the CPU for a while ; Bis #T0.Msk,CodMsk ;assume TCU-100 online for now Call $Swstk,30$ ;switch to system state MTPS #340 ;declare priority 7 (non-interruptable) Mov #160000,4(R0) ;try to get delta-T of 2 seconds Bit #100,6(R0) ;is interrupt set? Bne 20$ ;if so, TCU-100 present Bis #T5.Msk,CodMsk ;if not, TCU-150 present Bic #T0.Msk,CodMsk ;clear default (TCU-100) setting 20$: Clr 4(R0) ;turn off pending interrupt MTPS #0 ;restore processor priority Return 30$: ;reference label for return from $SWSTK 50$: Svtk$s ;declare no SST routines Mov (Sp)+,R0 ;restore R0 Return .Page .Sbttl Set command Set: Call DevChk ;find out about configuration Bit #On.Msk,COdMsk ;is TCU online? Bne 20$ ;if so, jump around Print #OffErr ;"Tcu - ERROR -- Tcu unit is offline" Return ; ; TCU is in system, set time/date ; 20$: Mov TcuCsr,R1 ;get TCU CSR address Bit #T0.Msk,CodMsk ;TCU-100 on line? Beq 100$ ;if not, jump to next type ; ; TCU-100 set ; Call $SwStk,90$ ;switch to system state Mov TcuVec,R0 ;;;get TCU interrupt vector Mov (R0),-(Sp) ;;;store old system vector Mov 2(R0),-(Sp) ;;;ditto Mov #80$,(R0) ;;;move in interrupt service routine Mov #340,2(R0) ;;;set up PSW ; ; TCU-100 date set ; Bit #Da.Msk,Mask ;;;Date specified? Beq 50$ ;;;no, check for time Mov Month,R2 ;;;get month setting from TPars SwaB R2 ;;;put it into the high byte Bis Day,R2 ;;;get days in low byte Bis #100,R2 ;;;set up TCU-100 control bit Clr IntDon ;;;clean out interrupt done flag Mov R2,(R1) ;;;set date 30$: Tst IntDon ;;;wait for interrupt Beq 30$ ;;;loop till interrupt ; ; TCU-100 time set ; 50$: Bit #Tm.Msk,Mask ;;;time specified on command line? Beq 70$ ;;;if not, exit $Swstk Bis #40100,Minute ;;;set up TCU-100 control bits Clr IntDon ;;;clean out interrupt done flag Mov Minute,2(R1) ;;;set time 60$: Tst IntDon ;;;wait for interrupt Beq 60$ ;;;loop till interrupt ; ; Exit from system state ; 70$: Mov (Sp)+,2(R0) ;;;restore old PSW in vector Mov (Sp)+,(R0) ;;;restore old PC in vector Return ;;;return through address specified at ;;; Call $Swstk ; ; TCU-100 interrupt service routine ; 80$: Inc IntDon ;;;indicate interrupt happened RTI ;;;return from interrupt ; ; TCU-100 Set command Exit ; 90$: Return ;return to Tcu dispatcher ; ; Tcu-150 SET command code ; ; R1 points to TCU CSR and TCU is online 100$: Bit #T5.Msk,COdMsk ;TCU-150 specified? Beq 160$ ;if not, search for next device Bit #Da.Msk,Mask ;date specified? Beq 140$ ;if not, check time ; ; TCU-150 set date code ; Bit #Yr.Msk,Mask ;year must be specified for TCU-150 Bne 105$ ;if present, ok, jump Print #Yr5Err ;print TCU-150 year error Jmp Restrt ;re-dispatch 105$: Mov Day,R2 ;get day of month from TPars Mov Month,R0 ;get month setting from TPars Ash #5,R0 ;shift up to bits 5-8 Bis R0,R2 ;include with day Mov Year,R0 ;get year setting from TPars Ash #9.,R0 ;shift up to bits 9-15 Bis R0,R2 ;include with day, month Call $SwStk,140$ ;switch to system state MTPS #340 ;set priority to uninterruptable Mov R2,(R1) ;start fast clock 110$: Cmp (R1),R2 ;has TCU-150 clocked to desired date? Bne 110$ ;loop back until it has Mov R2,4(R1) ;reset clock MTPS #0 ;restore priority Return ;return to task state ; ; TCU-150 Time set ; 140$: Bit #Tm.Msk,Mask ;was time specified? Beq 160$ ;if not, exit Mov Minute,R0 ;pick up hour/minute setting Call $SwStk,160$ ;switch to system state MTPS #340 ;set priority to uninterruptable Mov R0,2(R1) ;start fast clock 150$: Cmp 2(R1),R0 ;has TCU-150 clocked to desired date? Bne 150$ ;loop back until it has Mov R0,4(R1) ;reset clock MTPS #0 ;restore priority Return ;return to task state 160$: Return ;return to Tcu dispatcher .Page .Sbttl Update Command Update: ; ; *** get time from Tcu-100/Tcu-150 and optionally set time in RSX-11M/M PLUS ; Call DevChk ;find out whats out there Bit #On.Msk,CodMsk ;is TCU online? Bne 20$ ;if so, jump around Print #OffErr ;"Tcu - ERROR -- Tcu unit is offline" Return ; ; Which kind of TCU do we have? ; 20$: Mov TcuCsr,R0 ;get CSR pointer for this TCU Mov (R0),-(Sp) ;get date from hardware Bit #T0.Msk,CodMsk ;is this a TCU-100? Beq 50$ ;if not, search on ; ; TCU-100 ; Bit #Rd.Msk,Mask ;read request? Bne 25$ ;if so, YEAR= not required Bit #Yr.Msk,Mask ;user specify year? Bne 30$ ;if so, jump around Tst (Sp)+ ;clean out stack Print #YrErr ;TCU-100 must have Year specified Return 25$: Clr Year ;year can't be read from TCU-100 30$: Mov Year,McrDat ;pick up user supplied year Bic #170340,(Sp) ;get rid of junk MovB 1(Sp),MCRDat+2 ;move month into local store MovB (Sp),MCRDat+4 ;move day into local store Br 200$ ;jump to send time to MCR 50$: Bit #T5.Msk,CodMsk ;is this a TCU-150? Beq 100$ ;if not, search on ; ; TCU-150 ; MovB 1(Sp),McrDat ;get year Clc ;clear carry bit RorB McrDat ;shift year into proper position ClrB McrDat+1 ;clean out unused area ; ; Month ; Mov (Sp),R1 ;get month and other junk Ash #-5,R1 ;shift month into proper position Bic #177760,R1 ;clear out junk; Mov R1,McrDat+2 ;load month MovB (Sp),McrDat+4 ;get day Bic #177740,McrDat+4 ;clear out junk Br 200$ ;join common code ; ; Place new TCU types here ; 100$: ; ; Common code used to send time to MCR and user ; 200$: ; ; Get hours/minutes/seconds from TCU 100/150 ; Mov 2(R0),(Sp) ;get hour,min from TCU Bic #160300,(Sp) ;get rid of junk MovB 1(Sp),McrTim ;move hour into local storage MovB (Sp)+,McrTim+2 ;move minutes into local storage Mov 4(R0),McrTim+4 ;get seconds Bic #177700,McrTim+4 ;clear out junk ; ; Convert date/time to ascii ; Mov #TimDat,R0 ;point R0 to output buffer Mov #McrDat,R1 ;point to binary input buffer Call $DAT ;convert binary to ascii MovB #' ,(R0)+ ;put blank in between date, time Mov #3.,R2 ;ask for hh:mm:ss format Call $TIM ;convert binary time to ascii Bit #Rd.Msk,Mask ;are we just reading time from TCU? Bne 250$ ;if so, jump around Mov #McrMSG+1,R5 ;point to MCR message Call Send ;send tim command to mcr 250$: Print #McrMsg ;send time command to TI: Return .Page .Sbttl Send - Send a command line to MCR ;+ ; Send a command line to MCR (or any installed task) ; ; Inputs: ; R5 - pointer to MCR message, terminated by and ; ; SEND: ; ; Find our TI: Unit Control Block (UCB) ; Mov $TkTCB,R4 ;Get our Task Control Block (TCB) address Mov T.UCB(R4),R4 ;get TI: UCB address 10$: Mov U.RED(R4),R4 ;follow redirect pointer Cmp R4,U.RED(R4) ;end of redirect list ? Bne 10$ ;if not, loop back till done ; ; TI: UCB Found, try to give command line to MCR ; Mov #3,R1 ; make 3 attempts to give to MCR 15$: Call 30$ ; attempt to give line MCR Bcc 20$ ; if no problem, jump around Call Wait1 ; wait 1 second for pool to become available Sob R1,15$ ; Retry R1 times Print #DynErr ; print pool error message Return 20$: Bit #U2.AT.,U.CW2(R4) ; Has MCR indicated task accomplished ? Beq 25$ ; if so, all done, exit Call Wait1 ; wait 1 second before checking again Br 20$ ; go back and check again 25$: Return ; ; Give command line to MCR ; ; Note: A better method is to SPAWN MCR, but this is restricted to ; Rsx-11M Ver 3.2 or later, and RSX-11M/PLUS. ; ; Inputs: ; R4 - UCB pointer ; 30$: Call $SWSTK,60$ ; switch to system state Mov #84.,R1 ;;; set length of MCR buffer Call $AlocB ;;; try to get MCR buffer Bcc 40$ ;;; got it Mov @$HeadR,R0 ;;; get our user stack pointer Inc 6(R0) ;;; set user mode CS Return ;;; return to user state with error ; ; Successful command line buffer allocation ; ; R0 - pointer to buffer ; R4 - pointer to our TI: UCB ; R5 - pointer to MCR command Asciz string ; 40$: Mov R0,R1 ;;; copy address of buffer Clr (R0)+ ;;; zero pool link word Mov R4,(R0)+ ;;; copy our TI: UCB pointer into buffer for MCR 50$: MovB (R5)+,(R0)+ ;;; copy MCR command into buffer Bne 50$ ;;; loop back until null byte detected and copied Bis #U2.AT.,U.CW2(R4) ;;; use AT.'s MCR synchronization Call $QMCRL ;;; que command to MCR 60$: Return ;;; return to user state ; ; 1 Second wait subroutine ; Wait1: MRKT$S #2,#1,#2 ; mark time for one second and go to sleep WTSE$S #2 ; wait for alarm to ring Return ; wake up and tell caller .Page .Sbttl Exit to RSX-11M Exit: ExSt$s #Ex$Suc ExErr: ExSt$s #Ex$Err ;indicate error .Page .SbTtl Tpars State Tables .MCALL ISTAT$,STATE$,TRAN$ .If DF, ParBug ISTAT$ LogSTB,LogKTB,$DEBUG .IFF ISTAT$ LogStb,LogKtb .EndC ;end of ParBug conditional State$ LogSrt Tran$ "HELP",$EXIT,,Hp.Msk,Mask Tran$ "CONFIGURATION",ConSta,,Cn.Msk,Mask Tran$ "ID",$Exit,,Id.Msk,Mask Tran$ "READ",$Exit,,Rd.Msk,Mask Tran$ "SET",SetSta,,St.Msk,Mask Tran$ "UPDATE",UPstat,,Up.Msk,Mask ; ; SET keyword subparsing ; State$ SetSta Tran$ !TimPar,DatChk,TimRej ;check for time, then date Tran$ !DatPar,TimChk,DatRej ;check for date, then time State$ DatChk Tran$ !DatPar,$Exit ;if date, mask will be set State$ TimChk Tran$ !TimPar,$Exit ;if time, mask will be set ; ; Time sub-expression ; State$ TimPar ;time parse sub-expression Tran$ $DNumb,SetCol ;get potential hour Tran$ $Lamda,$Exit ;else return without mask set State$ SetCol Tran$ ':,SetMin,SavHr ;if :, then time, save hours Tran$ $Lamda,$Exit ;else exit w/out mask set State$ SetMin ;arive here if time Tran$ $DNumb,$Exit,SavMin,Tm.Msk,Mask;save minutes, indicate time ; ; Date sup-expression ; State$ DatPar Tran$ $DNumb,SetMns,SavDay ;save days, look for "-" Tran$ $Lamda,$Exit ;else exit w/out mask set State$ SetMns ;look for - Tran$ '-,SetMon,SetClr ;if -, look for months Tran$ $Lamda,$Exit ;else exit w/out mask set State$ SetMon ;look for months Tran$ "JAN",SetDl2,,1,Month Tran$ "FEB",SetDl2,,2,Month Tran$ "MAR",SetDl2,,3,Month Tran$ "APR",SetDl2,,4,Month Tran$ "MAY",SetDl2,,5,Month Tran$ "JUN",SetDl2,,6,Month Tran$ "JUL",SetDl2,,7,Month Tran$ "AUG",SetDl2,,8.,Month Tran$ "SEP",SetDl2,,9.,Month Tran$ "OCT",SetDl2,,10.,Month Tran$ "NOV",SetDl2,,11.,Month Tran$ "DEC",SetDl2,,12.,Month State$ SetDl2 ;look for - or end of line. Tran$ $EOS,$Exit,,Da.Msk,Mask ;if end of line, just exit Tran$ '-,SetYr,,Da.Msk,Mask ;if -, look for months State$ SetYr Tran$ $DNumb,$Exit,SavYr,Yr.Msk,Mask ;if found, complete date ; ; Configuration parsing ; State$ ConSta Tran$ !CsrPar,VecChk,CsrRej ;check for CSR, then VEC Tran$ !VecPar,CsrChk,VecRej ;check for VEC, then CSR Tran$ $lamda,$Exit ;else just exit State$ VecChk Tran$ !VecPar,$Exit ;if VEC, mask will be set State$ CsrChk Tran$ !CsrPar,$Exit ;if CSR, mask will be set ; ; CSR sub-expression ; State$ CsrPar ;CSR parse sub-expression Tran$ "CSR",EquChk ;look for CSR Tran$ $Lamda,$Exit ;else return without mask set State$ EquChk Tran$ '=,GetCsr ;look for = State$ GetCsr ;arive here if CSR= Tran$ $NumbR,$Exit,SavCSR,Cs.Msk,Mask ;save CSR, set mask bit ; ; VEC sub-expression ; State$ VecPar ;VEC parse sub-expression Tran$ "VEC",ChkEqu ;look for CSR Tran$ $Lamda,$Exit ;else return without mask set State$ ChkEqu Tran$ '=,GetVec ;look for = State$ GetVec ;arive here if CSR= Tran$ $NumbR,$Exit,SavVec,Ve.Msk,Mask ;save VEC, set mask bit ; ; Update sub-parsing ; State$ Upstat Tran$ $Eos,$Exit ;if no "YEAR=", just exit Tran$ "YEAR",UpdEqu State$ UpdEqu Tran$ '=,GetYr State$ GetYr Tran$ $DNumb,$Exit,SavYr,Yr.Msk,Mask ;got a year State$ .Page .SbTtl Tpars action routines DatRej: Bit #Da.Msk,Mask ;has date been properly specified? Beq AltErr ;if not, reject transition Return TimRej: Bit #Tm.Msk,Mask ;has time been properly inputted Beq AltErr ;if not, reject transition Return CsrRej: Bit #Cs.Msk,Mask ;has CSR been properly inputted? Beq AltERr ;if not, jump Return VecRej: Bit #Ve.Msk,Mask ;has VEC been properly inputted Beq AltErr ;if not, jump Return SavHr: Cmp .PNumb,#23. ;too large? Bhi SetErr ;if so, jump Tst .PNumb ;too small? Blt SetErr ;if so, jump MovB .Pnumb,Hour ;store hour Return SavMin: Cmp .PNumb,#59. ;too large? Bhi SetErr ;if so, jump Tst .PNumb ;too small? Blt SetErr ;if so, jump MovB .Pnumb,Minute ;store minute Return SavDay: Cmp .PNumb,#31. ;too large? Bhi SetErr ;if so, jump Tst .PNumb ;too small? Ble SetErr ;if so, jump Mov .Pnumb,Day ;store day Return SavYr: Cmp .PNumb,#99. ;too large? Bhi SetErr ;if so, jump Tst .PNumb ;too small? Ble SetErr ;if so, jump Mov .Pnumb,Year ;store year Return SavCsr: Cmp .PNumb,#160000 ;not in I/O page ? Blo SetERr ;if not, reject transition Mov .PNumb,CsrVal ;save CSR Return SavVec: Cmp .PNumb,#1000 ;not in interrupt vector table Bhis SetErr ;if not, reject transition Mov .PNumb,VecVal ;sav Vec Return SetClr: Clr Month ;set up for month parsing Return SetErr: AltErr: Add #2,(Sp) ;reject transition Return .Page .SbTTl Tpars Debugger ;+ ; ; *** TDebug -- The Tpars Debugger ; ; Inputs: ; R3 = Length of remainder of input string ; R4 = Address of remainder of input string ; R5 = Current address of Transition table ; ; Outputs: ; The following is printed for every Tpars State transition: ; ; Current Transition table Address = (some octal address) ; Tcu TT34: ; .......^..... ; ;- Pointr: .Rept 72. .Byte '. .EndM .IF Df,ParBug ;if Tpars debugger to be asembled TraAdd: String <"Current Transition Table Address = ">,B AddBuf: .BlkB 6 ;storage for octal ASCII address String <>,E .even TDebug: Call $Saval ;save all of the registers Mov #40,TTyout+Q.iopl+4 ;ask for lf and cr Mov R5,R1 ;get transition address Sub #LogStb,R1 ;get rid of Bias Mov #AddBuf,R0 ;point to output buffer Clr R2 ;suppress leading zeros Call $CBOMG ;convert binary to octal ASCII Print #TraAdd ;print transition address .EndC ;end of tpars debugger conditional PriErr: Print CmdBuf+G.cmld+2,CmdBuf+G.cmld ;print entire line to be parsed Sub CmdBuf+G.cmld+2,R4 ;calculate relative address of remainder MovB #'^,Pointr(R4) ;point to remainder of string Inc R4 ;adjust byte count of message Print #Pointr,R4 ;print the pointer Dec R4 ;restore ^ pointer MovB #'.,Pointr(R4) ;restore default character Return .End Tcu