*B ; 02-DEC-71 ; CLOCK INITIALIZE ROUTINE ; * G U L F E L E C T R O N I C S Y S T E M S * .TITLE CLINIT .DEF CLINIT .REF T.30HD,T.31HD,T.32HD,T.33HD,T.34HD,T.35HD,T.36HD .REF HEADER,TSTAT,TPRTY,TASKS .REF TWAITB,TTBPTR,TFIRST,TLAST,RESTAB,CURTAB,TIMBSY,BASCNT .REF THDTAB,CURTHD,SWAITB,STBPTR,COUNTR,SKDBSY,ABMPLR CLINIT: ;INIT SUBROUTINE FOR TIMERS AND SCHEDULER MOV #TWAITB,R0 ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "EMTRAP" * ; * EMULATOR TRAP SERVICE ROUTINE * ; * * ; * PURPOSE: DECODES ALL EMT CALLS AND TRANSFERS CONTROL TO PROPER* ; * SUBROUTINE, AFTER ALTERING STACK TO LOOK IDENTICAL TO A * ; * "JSR PC,SBRTNE". ; 09-DEC-71 ; TIMER TASK MODULE FOR TESTING TIMERS .DEF T.30HD,T.31HD,T.32HD,T.33HD,T.34HD,T.35HD,T.36HD .DEF T.37HD,T.38HD .TITLE MWKTST SP=%6 EXIT = 4 QTIME = 7 DQTIME = 10 QSKED = 11 DQSKED = 12 TTYOUT = 13 NN = 20. ;# WORDS RESERVED IN EACH TASK'S STACK T.30PR = 1 T.31PR = 1 T.32PR = 2 T.33PR = 3 T.34PR = 4 T.35PR = 5 T.36PR = 1 T.30IN = 0 T.31IN = 0 T.32IN = 0 T.33IN.t!s@}@&y@.;K}@hfp@f@[g4@m@.[qj@y@ ` @LC @R:@.(eht!hxh-Zh.D~hA*}hEhtJ&) hm4phr.>) h!? MOV R0,TTBPTR MOV #$TWATZ+1+$NRES,R1 A.: CLR (R0)+ ;CLEAR BOTH WAIT AND FIRST TABLES DEC R1 BNE A. MOV #TLAST-2,R0 MOV #$NRES-1*2,R1 B.: MOV R0,TLAST(R1) ;INIT ALL "LASTS" WITH ADDR'S OF FIRSTS TST -(R0) DEC R1 DEC R1 BGE B. MOV #RESTAB+$NRES,R0 MOV #$NRES-1,R1 C.: MOVB -(R0),CURTAB(R1) ;INIT RESOLUTION COUNT * ; * * ; * USAGE: ALL EXTERNAL LINKS TO MONITOR SUBROUTINES ARE MADE VIA * ; * CALLS OF THE FORM: "EMT SNUMBER", WHERE "SNUMBER" IS A * ; * PRE-ASSIGNED INDEX TO THE TABLE OF MONITOR SUBROUTINES. ANY * ; * ARGUMENTS REQUIRED BY THE SUBROUTINE MUST BE PUSHED ONTO THE * ; * STACK PRIOR TO THE CALL. UPON ENTRY TO THE SUBROUTINE THE STACK* ; * WILL LOOK THE SAME AS IF A "JSR PC,SBRTNE" HAD BEE ; ******************************************************************** ; * * ; * PROGRAM IDENTIFICATION: "SETGET" * ; * SET TIME SET DATE GET TIME GET DATE * ; * * ; * ROUTINES TO SET AND GET CURRENT TIME AND DATE * ; * = 0 T.34IN = 0 T.35IN = 0 T.36IN = 0 TMWRD0: .BYTE 5 ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD1: .BYTE 10. ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD2: .BYTE 15. ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD3: .BYTE 5 ;DELAY COUNT .BYTE 5 ;RESET TIME TMWRD4: .BYTE 10. ;DELAY COUNT .BYTE 10. ;RESET TIME TMWRD5: .BYTE 15. ;DELAY COUNT .BYTE 15. ;RESET TIME ERS DEC R1 BGE C. MOVB #-1,TIMBSY MOVB #-1,SKDBSY CLRB BASCNT CLR ABMPLR MOV #THDTAB,CURTHD ;FOR SCHEDULER MOV #SWAITB,STBPTR CLR COUNTR .PAGE ; NOW INIT TASKS FOR TEST PGM MOV #HDLIST,R0 MOV #HEADER+60.,R1 MOV #TSTAT+30.,R2 MOV #TPRTY+30.,R3 MOV #7,R4 A: MOV (R0)+,(R1)+ CLRB (R2)+ N THE CALL. * ; * THIS ALLOWS CALLS OF THE JSR-TYPE TO BE COMPATIBLE WITH THE * ; * EMT-TYPE CALLS. ALTHOUGH PROCESSOR STATUS IS RAISED TO LEVEL * ; * SEVEN DURING THE TRAP ROUTINE, IT IS RETURNED TO ITS STATE * ; * AT THE TIME OF CALL WHEN THE CALLED SUBROUTINE IS ENTERED. * ; * * ; * STACK ON ENTRY: * ; * 2(SP): (PS) AT TIME OF TRAP / * ; * USAGE: * ; * USED BY GENERAL ROUTINES TO FETCH CURRENT TIME * ; * AND/OR DATE. USED BY OPERATOR INPUT PROGRAM TO SET * ; * TIME AND/OR DATE FROM TTY KEYBOARD. * ; * * ; * CALLING SEQUENCES: * ; * MOV NEWHR,-(SP) ;PUSH NEW HOUR  TMWRD6: .BYTE 0 ;DELAY COUNT .BYTE 0 ;RESET TIME .PAGE T.30HD: .WORD 1 ;THREAD WORD .WORD T.30BG ;TASK ENTRY .WORD T.30IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.30PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;S MOVB R4,(R3)+ DEC R4 BNE A CMP TASKS,#36. BGE X MOV #36.,TASKS RTS PC HDLIST: .WORD T.30HD,T.31HD,T.32HD,T.33HD,T.34HD,T.35HD,T.36HD .END }hQ@hRehS@~h.U; hCmh2w_h|xhy2ghz.Yzb;hD~*}hk~[h ph.7" @ : 7f$R:(f.&)-e7 E.LC LC  ` "y(,L&  B.[qj&y;K}";K}&&y{,p9  * ; * (SP): (PC) CALLER RETURN ADDRESS * ; * * ; * STACK ON EXIT: * ; * (SP): (PC) CALLER RETURN ADDRESS * ; * * ; * ERROR RETURNS: IF AN EMT CODE IS USED WHICH IS INVALID * ; * ---EITHER OUTSIDE THE LIMITS OF THTATUS .BYTE 30. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.31HD: .WORD 1 ;THREAD WORD .WORD T.31BG ;TASK ENTRY .WORD T.31IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.31PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 .u~#"hfp@H[g4@Hm@H.[qj@Hz4f@H4f@HLC @HR:@Hl.( h*}hM:hzimRh.[q*}h}shbu~hu~"h~yh"2gh6b;h8F, & 7T&;K}LC s}X,&fЕ<<9<2  ,- "PPP8,)mȵ  @p&, ɕe` ,$%!G7& ^ ,H< 72e1 "E EMT TABLE, OR AN INVALID * ; * CODE WITHIN THE TABLE--- A RETURN IS MADE IMMEDIATELY TO THE * ; * CALLER WITH NO ACTION TAKEN. * ; * THE CALLER SHOULD NOTE THAT HE MAY BE INTERRUPTED BETWEEN HIS * ; * EMT CALL AND THE EVENTUAL RETURN, EVEN IN THE CASE OF AN ERROR.* ; * * ; * PROGRAMMER: 52 * ; * VERSION: 002.003  ;STATUS .BYTE 31. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.32HD: .WORD 1 ;THREAD WORD .WORD T.32BG ;TASK ENTRY .WORD T.32IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.32PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT &-&` e?B ``,$ 6  e,H[oLC z4fB,lS& w "[g4,%%E Cw0  ebBA  J6 w  b*hfp,0 "$:8,l"2 7B f 9 0 D &  ‹ & & N & *m70 yeEw$[qj*,57&  ,5E -?- ,(   Ν{,L   Be,p (- * ; * DATE: 02-DEC-71 * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .TITLE EMTRAP .REF QUEUE,SUSPND,UNSPND,EXIT,FRETSK,ABORT,QTIME,DQTIME  .BYTE 0 ;STATUS .BYTE 32. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.33HD: .WORD 1 ;THREAD WORD .WORD T.33BG ;TASK ENTRY .WORD T.33IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.33PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WOR  ,2EW  9W &F0$1 7  fb`E"b*,L7vBABWCEq,pJ7œ& ‹  J, & 5@& Œ ŒD4fm,$Œ&&f A, b`BAW,Jf -- ,ee  Eg, E EvÝ],;`Ý1`Ý*`%<< %, ÝÜ    ,$ UU&-E &,HE eet?p6 ,l w %[g4 .% .REF QSKED,DQSKED,TTYOUT,TTYIN,BINASC,ASCBIN .REF MASK,UNMASK,ERRTYP .IFNZ NDISCS .REF DISCIO .ENDC NDISCS .DEF EMTRAP,EMTABL,MAXEMT .PAGE EMTRAP = . ;ENTRY TO EMT SERVICE ROUTINE ;TIMING: 64 MICROSECONDS TST -(SP) ;PUSH STACK TO MAKE ROOM FOR SBRTNE ADDR MOV R0,-(SP) ;SAVE IT MOV 4(SP),R0 ;CALLER RETURN ADDR MOV 6(SP), D 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 33. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.34HD: .WORD 1 ;THREAD WORD .WORD T.34BG ;TASK ENTRY .WORD T.34IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.34PR ;TASK PRIORTY .WORD 0 ;TASK TIME!b&, b   bZ$ww8f[qj8bY(bp e(P Ed 5d $ +  (BA  J6 w (hfp. U  "(  G#4(SP) ;MOVE CALLER'S PS FOR RTI EXIT MOV R0,6(SP) ;WILL LEAVE CALLER'S PC ON STACK @ EXIT DEC R0 ;BACK POINTER ONE BYTE MOVB -(R0),R0 ;BACK POINTER TO EMT INSTR&GET EMT CODE ASL R0 ;NEED TO INDEX WORDS IN TABLE CMP R0,#MAXEMT*2 ;SEE IF CODE IS VALID BHI EMTA20 ;INVALID: OUTSIDE TABLE RANGE EMTA10: MOV EMTABL(R0),2(SP) ;LOAD STACK WITH SUBROUTINE ADDR ; IF $R .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 34. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.35HD: .WORD 1 ;THREAD WORD .WORD T.35BG ;TASK ENTRY .WORD T.35IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.35PR ;TASK PRIORTY .WORD 0 &&- e?e ,$U 6  e  2HLC  z4f*,rw %%E  [g4 ,CeBA  J 6 w  &hfp,0@Q @"$@Q@,'AN INVALID CODE IS USED, THE TABLE ENTRY WILL POINT TO "EMTERR". MOV (SP)+,R0 ;RESTORE USER'S RTI ;POP SUBRTNE ADDRESS AND OLD STATUS ;TO EFFECT TRANSFER, LEAVING RTN TO ;CALLER ON TOP. EMTA20: CLR R0 ;RANGE ERROR: USE ENTRY 0... BR EMTA10 ;...AND FORCE EXIT VIA "EMTERR" .PAGE EMTERR: RTS PC ;ERROR RETURN USED FOR I( ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 35. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.36HD: .WORD 1 ;THREAD WORD .WORD T.36BG ;TASK ENTRY .WORD T.36IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.36PR ;TASK PRIORTY .W)NOT "SKED" MOV R0,-(SP) MOV R1,-(SP) MOV #CLOCK,R0 ;POINTER TO TIME & DATE BYTES MOVB #TICRES,(R0)+ ;RESET [TICTOC] INCB (R0) ;NEXT SECOND CMPB (R0),#60. ;NEW MINUTE? BLT CALA40 ;NO: BUT GO TO END TO RUN "SKNSRT" INCB SKSWCH ;SET TO RUN "SKED" AND NOT "SKNSRT" CLRB (R0)+ ;RESET [SECOND] & GO ON TO... INCB (R0) ;...BU*EW 0 9 1  7 Q A  Q*0*`BACEqJ 7 * ,R7œ& ‹ @ $4f,v& 5@& Œ ŒmM,$Œ A  " Ew+NVALID CODES EMTABL = . ;TOP OF EMT LINK TABLE .WORD EMTERR ;#0 ALWAYS AN ERROR .WORD QUEUE ;#1 .WORD SUSPND ;#2 .WORD UNSPND ;#3 .WORD EXIT ;#4 .WORD FRETSK ;#5 .WORD ABORT ;#6 .WORD QTIME ;#7 .WORD DQTIME ;#10 .WORD QSKED ;#11 .WORD DQSKED ;#12 ,ORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 36. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.37HD: .WORD 1 ;T/W .WORD T.37BG ;ENTRY .WORD 0 ;TASK INIT .WORD 0 ;MAX X-TIME .BYTE NN ;STACK SIZE .BYTE 0 ;PRIORIT-MP [MINUTE] CMPB (R0),#60. ;NEW HOUR? BLT CALA40 ;NO: BUT GO RUN SCHEDULER CLRB (R0)+ ;RESET [MINUTE]... INCB (R0) ;...AND BUMP [HOUR] CMPB (R0),#24. ;NEW DAY? BLT CALA40 ;NO CLRB (R0)+ ;YES: RESET [HOUR]... INC (R0) ;...AND BUMP [JDATE] CMP (R0),(PC)+ ;NEW YEAR? MXDAYS: .WORD 0 ;HOLDS #DAYS IN CU.[qj(  (  @@d  PPd a a .WORD TTYOUT ;#13 .WORD TTYIN ;#14 .WORD EMTERR ;#15 CURRENTLY UNUSED .WORD BINASC ;#16 .WORD ASCBIN ;#17 .WORD MASK ;#20 .WORD UNMASK ;#21 .WORD ERRTYP ;#22 .IFNZ NDISCS .WORD DISCIO ;#23 .ENDC NDISCS MAXEMT = .-EMTABL/2 .END 0Y .WORD 0 ;TIMER .WORD 0 ;ARG .BYTE 0 ;STATUS .BYTE 37. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.38HD: .WORD 1 ;T/W .WORD T.38BG ;ENTRY .WORD 0 ;TASK INIT .WORD 0 ;MAX X-TIME .BYTE NN ;STACK SIZE .BYTE 0 ;PRIORITY .WOR1RRENT YEAR BLE CALA30 ;NO: GO TO NEXT DAY + MAYBE NEW MONTH ;HAPPY NEW YEAR!! MOV #1,R1 MOV R1,(R0)+ ;RESET [JDATE] MOVB R1,(R0)+ ;RESET [MONTH] MOVB R1,(R0)+ ;RESET [MDAY] INCB (R0) ;BUMP TO NEW YEAR MOVB #28.,FEBARY ;RESET FEBRUARY MOV #365.,MXDAYS ;RESET YEAR LENGTH BITB #3,(R0) ;IS THIS A LEAP YEAR3 * ; * MOV NEWMIN,-(SP) ;PUSH NEW MINUTE * ; * JSR PC,STIME ;CALL "SET TIME" * ; * TST (SP)+ ;POP ERROR WORD * ; * BNE ERROR ;CALL PARAMETERS IN ERROR * ; * ---------------- * ; * MOV NEWMTH,-(SP) ;PUSH NEW MONTH * ; * MOV NEWDAY,-(SP) ;PUSH NEW 4D 0 ;TIMER .WORD 0 ;ARG .BYTE 0 ;STATUS .BYTE 38. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.30BG: ;TASK #30 BEGIN MOV #MODUL0,-(SP) MOV TMWRD0,-(SP) EMT QTIME ;QUEUE ONE TIMER MODULE TST (SP)+ MOV #LIST30,-(SP) EMT TTYOUT ;TYPE TASK I.D. 5? BNE CALA35 ;NO INC MXDAYS ;YES: BUMP YEAR LENGTH INCB FEBARY ;...AND FEBRUARY BR CALA35 CALA30: ;HERE @ BEGIN OF DAY & NOT NEW YEAR MOV #MONTH,R1 ;INIT POINTER TO DATE BYTE TABLE MOVB (R1)+,R0 ;[MONTH]: USED AS INDEX INCB (R1) ;[MDAY]: NEW DAY CMPB (R1),DAYTAB(R0 ;[MDAY]: END OF MONTH BLE CALA40 ;NO 6.X @H-Z@H*}@H.D~@H2@H[q*}@Hy2g@HYzb;@H].;}G@H}s@HD~*}@Hu~@H~y@H4.@H ` @H"2g@Hb;@Hļ@H3.@HD@H@H@H@Hj&D@H7DAY * ; * MOV NEWYR,-(SP) ;PUSH NEW YEAR * ; * JSR PC,SDATE ;CALL "SET DATE" * ; * TST (SP)+ ;POP ERROR WORD * ; * BNE ERROR ;CALL PARAMETERS IN ERROR * ; * ---------------- * ; * JSR PC,GDATE ;CALL "GET DATE" * ; * MOV (SP*+,CURYR ;PE EMT EXIT T.31BG: ;TASK #31 MOV #LIST31,-(SP) EMT TTYOUT MOV #MODUL2,-(SP) MOV TMWRD1,-(SP) EMT QTIME TST (SP)+ MOV #LIST31,-(SP) EMT TTYOUT EMT EXIT T.32BG: ;TASK #32 MOV #MODUL3,-(SP) MOV TMWRD0,-(SP) EMT QTIME TST (SP)+ MOV #MODUL4,-(SP) MOV TMWRD1,-(SP) EMT F MOVB #1,(R1) ;RESET DAY TO FIRST OF MONTH INCB -(R1) ;NEXT MONTH: CAN'T BE JANUARY (ABOVE) CALA35: ;HERE TO ADJUST THE THREAD POINTER POINTER AT THE BEGIN ; OF EACH MONTH. "CURTHD" ALWAYS POINTS TO "TH1BGN" DURING ; ODD-NUMBERED MONTHS, AND TO "TH2BGN" DURING EVEN MONTHS. MOV #THDTAB,CURTHD ;INIT THREAD-START TABLE POINTER BITB #1,MONTH ;ODD-NUMBERED MONTH? BNE CALA40 ;YG(Xh,7% 1 M&b; "2g~y ~y($1 776[q*}*}u~  D~*}"D~D7 |<2Yzb;y2g -Z|2< ` ,Z -$$&;}G";}G&ļ~lHOP CURRENT YEAR (-1900) * ; * MOV (SP*+,CURDAY ;POP CURRENT DATE * ; * MOV (SP*+,CURMTH ;POP CURRENT MONTH * ; * ---------------- * ; * JSR PC,GTIME ;CALL "GET TIME" * ; * MOV (SP*+,CURHR ;POP CURRENT HOUR * ; * MOV (SP*+,CURMIN ;POP CURRENT MINUTE * ; * MOV (SP*+,CURS""D """"""""""@DD""D"""DDDDDDDDDDDDDDD""""""""""""""""ADD*B B CX4d8 \!4d8 +T 4d@#t!^w,4d8xu~#"^!t!4d8|6V6.. /2G* K)u~#"4d618N.//$D?3333333333LLff&DTUfffffffff"""""""a ͋,L w:B8 ` 5 &  E >w   f5eU@  [*   & * G &( 8L'4e Q$ BBB"   U@ U e  "U%Gef. U U Bb 0 * B.&0 M &0 & I QTIME TST (SP)+ MOV #MODUL5,-(SP) MOV TMWRD2,-(SP) EMT QTIME TST (SP)+ MOV #LIST32,-(SP) EMT TTYOUT EMT EXIT .PAGE T.33BG: ;TASK #33 MOV T.33HD+14,T.33AR ;TRANSFER ARGUMENT MOV #LIST33,-(SP) EMT TTYOUT EMT EXIT T.34BG: ;TASK #34 MOV T.34HD+14,T.34AR ;TRANSFER ARGUMENT MOV #LIST34,-(JES: LEAVE AS IS ADD #2,CURTHD ;EVEN: ADVANCE TO POINT TO THREAD #2 CALA40: ;HERE ON EVERY MINUTE BOUNDARY TO RUN... ;...THE SCHEDULER. ON THE OTHER 59 SECONDS, RUN "INSERT" ROUTINE. MOV (SP)+,R1 ;RESTORE USER'S FOR "SAVE" MOV (SP)+,R0 ;ALSO INCB SKDBSY ;MARK AND TEST BUSY FLAG BEFORE ENTERING BNE CALA09 ;LOG-JAM: SCHEDULER CURRENTLY RUNNING... ;...DON'T RE-ENTER: IT WILL CLEA.D   jDLEC ;POP CURRENT SECOND * ; * * ; * PROGRAMMER: 52 * ; * VERSION: 001.002 * ; * DATE: 02-DEC-71 * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; **********************MSP) EMT TTYOUT EMT EXIT T.35BG: ;TASK #35 MOV T.35HD+14,T.35AR ;TRANSFER ARGUMENT MOV #LIST35,-(SP) EMT TTYOUT EMT EXIT T.36BG: MOV #MODUL0,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL1,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL2,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL3,-(SP) EMT NN UP AFTER ITSELF. ; O.K. TO ENTER "SKNSRT" OR ""SKED". SAVE ;SAVE REGS OF INTERRUPTED PGM & RTN HERE SKSWCH: BR .+2 ;SWITCH NORMALLY OPEN TO FALL THROUGH... BR SKRELY ;...TO SKIP "SKED" AND RUN "SKNSRT" ; ON THE MINUTE IT IS CLOSED TO FORCE RUN OF "SKED" INSTEAD. .PAGE SKED: ;THIS IS THE SCHEDULER ;ENTER HERE EVERY MINUTE ON THE MINUTE FROM "CALENDAR" MOV @CURTHD,R0 ;[TH1BOhNhN1~NHt:~hN7 zhN`bfOrnT]nwl[hwf ]w[^~Nw r  Oh1'h vbg      w8U7%  V1V >V1?V 7~XO7YD YJ 7 6 OgEhh -$$PLPPPP4QnQ &6  ,6O~O OhfjktjjTjT YNYZ<[Oe0effg P********************************************** .DEF STIME,SDATE,GTIME,GDATE .REF MONTH,MDAY,YEAR,JDATE,SECOND,MINUTE,HOUR .REF TICTOC,DAYTAB,PUSHR,POPR,MXDAYS,JANARY,FEBARY .PAGE STIME: ;SUBROUTINE TO SET NEW TIME MOV R0,-(SP) ;SAVE USER'S MOV 4(SP),R0 ;PULL NEW MINUTE OFF STACK MOV PS,4(SP) ;REPLACE WITH CURRENT STATUS FOR RTI USE CMP R0,#60. ;SEE IQ DQTIME TST (SP)+ MOV #MODUL4,-(SP) EMT DQTIME TST (SP)+ MOV #LIST36,-(SP) EMT TTYOUT EMT EXIT .PAGE T.37BG: ;TASK # 37 MOV #MODUL6,-(SP) EMT QSKED TST (SP)+ BR T.37A MOV #MODUL7,-(SP) EMT QSKED TST (SP)+ T.37A: MOV #LIST37,-(SP) EMT TTYOUT EMT EXIT T.38BG: RGN] OR [TH2BGN] MOV R0,R1 ;SAVE CURRENT THREAD ADDRESS FOR... ;...POSSIBLE MODULE REMOVAL (BELOW) MOV (R0),R0 ;NEXT MODULE'S ADDRESS BEQ SKDEX2 ;END OF THREAD: EXIT MOV R4,PS ;DROP CPU LEVEL TO BE FAIR TO OTHERS MOV STRTWD(R0),-(SP);STACK THIS MODULE'S START WORD FOR... JSR PC,UNPACK ;...CALL TO UNPACK SUBROUTINE, WHICH ; RETURNS WITH TIME & DAS Q~HPQQ I~PR!R"R~8Q#,R$XST ~Q \R R tS< RTF MINUTE WITHIN RANGE BHIS STIM10 ;NO: EXIT IN ERROR CMP 6(SP),#24. ;SEE IF NEW HOUR WITHIN RANGE BLO STIM20 ;YES: PROCEED STIM10: ;ROUTINE EXIT POINT: FOR GOOD AND BAD MOV (SP)+,R0 ;RESTORE USER'S RTI ;RETURN AND RESTORE OLD CPU STATUS STIM20: ;HERE WHEN PARAMTERS ARE WITHIN RANGE MOV #340,PS ;LOCK OUT INTERFERENCE FROU ;TASK # 38 MOV #MODUL6,-(SP) EMT DQSKED TST (SP)+ MOV #MODUL7,-(SP) EMT DQSKED TST (SP)+ EMT EXIT .PAGE LIST30: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG VTE OF MODULE'S START WORD SPREAD ON STACK ; (SP) = DAY OF MONTH 2(SP) = HOUR 4(SP) = MINUTE CMPB (SP),MDAY ;SEE IF MODULE IS FOR TODAY BGT SKDEX1 ;FOR TOMORROW OR BEYOND: EXIT BLT SKDB10 ;FOR YESTERDAY OR EARLIER: EXECUTE MODULE CMPB 2(SP),HOUR ;TODAY: THIS HOUR? BGT SKDEX1 ;MODULE IS EARLY: EXIT BLT SKDB10 ;MODULE IS LATE: EXECUTE CMPB 4(SP),MINUTE ;FOR TW S& S S R R R  Sb~(R XS fS tS S S 4S jRTASK #30 ARG= RTASK #31 ARG=~R RTASK #32 ARG= RTASK #33 ARG= RTASK #34 ARG= ~SSTASK #35 ARG= BSTASK #36 ARG= !SSSS"#SS!SXM CLOCK MOVB R0,MINUTE ;UPDATE CURRENT MINUTE MOVB 6(SP),HOUR ;UPDATE CURRENT HOUR CLR TICTOC ;RESET "TICS" [AND] "SECOND" COUNTERS CLR 6(SP) ;CLEAR ERROR CODE BR STIM10 ;GO EXIT .PAGE SDATE: ;SUBROUTINE TO UPDATE CURRENT MONTH,DAY, AND YEAR JSR R5,PUSHR ;SAVE ALL REGISTERS MOV SP,R0 ;UTILIZE AS SECONDARY STACK POINTER ADD Y .WORD , ;SYS RESERVE .WORD T.30BF ;MSG BUFFER T.30BF: .WORD MSG30X-T.30BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #30 ARG=" T.30AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG30X =. .EVEN .PAGE LIST31: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEZHIS HOUR. THIS MINUTE? BGT SKDEX1 ;TOO SOON SKDB10: MOV #340,PS ;LOCK OUT INTERFERENCE FROM "DQSKED" CMP (R0),#1 ;ALREADY DE-QUEUED? BNE SKDB20 ;STILL O.K. SKDB15: ;ALSO RETURN POINT FROM [SKDD10] ADD #6,SP ;POP SP DUE TO "UNPACK"... BR SKED ;...AND GO BACK FOR ANOTHER ONE SKRELY: BR SKNSRT ;RELAY POINT FOR SKIP TO 'INSERT' RTNE [~S"S#SfS 12345\~T&-U e?U@: 6  egfjw ~T%%E CeUBA  JV6 w 0.V?V .V!u~TE 9V1V 7 ?V >U`ҪBACqVœ\ #16,R0 ;POINT TO NEW "YEAR" ON STACK MOV (R0)+,R1 ;REMOVE YEAR MOV (R0)+,R2 ;AND NEW DAY MOV (R0),R3 ;GET MONTH FROM STACK MOV PS,-(R0) ;LOAD CURRENT PSW ON STACK FOR RTI USE MOV -4(R0),-(R0) ;AND MOVE RTN ADDR INTO PROPER PLACE,TOO CMP R3,#12. ;SEE IF MONTH IS WITHIN RANGE BHI SDAT30 ;ERROR: EXIT MOVB #28.,FEBARY ;RESET FEBRUARY IN PREP ]DIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.31BF ;MSG BUFFER T.31BF: .WORD MSG31X-T.31BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #31 ARG=" T.31AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG31X =. .EVEN LIST32^ .PAGE SKDB20: ;O.K. TO WORK ON THIS MODULE MOV (R0),(R1) ;FIRST: REMOVE MODULE BY "BRIDGING" THE ;THREAD OVER ITSELF, CONNECTING PREVIOUS ;MODULE WITH FOLLOWING ONE MOV #1,(R0) ;SET THIS MODULE INACTIVE... MOV R4,PS ;...DROP CPU LEVEL TO INTERRUPTED LEVEL MOV R0,R1 ;...AND SET UP THE SECONDARY MODULE PNTR MOV 2(R1),R2 ;G_& ‹ Z & 5~pU@ & > 5 $5 U  E@FwU~UUUUUUUUUUVVVVV V Vdd P!H ~`VB < Bg ggg9 gj N7&YЕ<<=z<61 "?~VЕЕmȵ  YY`FOR NEW YEAR MOV #365.,MXDAYS ;RESET MAX DAYS COUNT BIT #3,R1 ;IS NEW YEAR A LEAP? BNE SDAT40 ;NO: NO EXTRA DAY INCB FEBARY ;YES: ADD FEB 29 INC MXDAYS ;EXTRA DAY IN LEAP YEAR SDAT40: CMPB R2,DAYTAB(R3) ;CHECK DATE FOR PROPER RANGE THIS MONTH BLO SDAT50 ;O.K.: WITHIN RANGE MOVB DAYTAB(R3),R2 ;ERROR: USE LAST DAY RATHER THAN ERR OUT SDAT50: MOV R3,-(SP)a: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.32BF ;MSG BUFFER .PAGE T.32BF: .WORD MSG32X-T.32BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED bET OPTION & TASK WORD BPL SKDC10 ;"R" REPEAT FLAG NOT SET MOV DELTA(R1),-(SP) ;GET REPEAT WORD & STACK IT FOR CALL... JSR PC,UNPACK ;...TO SPREAD IT ON STACK ;NOW THE STACK HAS BOTH THE MODULE'S ;"START" AND "DELTA" WORDS SPREAD ON IT: ;(SP)= D-DATE 2(SP)= D-HOUR 4(SP)= D-MINUTE ["D" MEANS "DELTA"] ;6(SP)= S-DATE 8(SP)= S-HOUR 10(SP)= S-MINUTE ["S" MEANS "START"] cev!jy7& v~PWr mh"eq 7vB~bڝf&> fZ Z&f&M & & N wc~b ENdDSdQUdXXdTM~cDTEX dc cc  %7 ~zvb  b$ wc 8bC~ccZc J ;RESTORE USER'S MOV (SP)+,R1 ;ALSO RTI ;ZAP! RETURN TO CALLER WITH HIS STATUS ; ...AND THREE PARAMETERS ON STACK. .END } ;SYS RESERVE .WORD T.37BF ;MSG BUFFER T.37BF: .WORD MSG37X-T.37BF-4 ;BUFFER LENGTH .WORD 0 ;RES .ASCII "TASK #37 ARG:" T.37AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG37X =. .EVEN .PAGE MODUL0: .WORD 1 ;THREAD WORD .BYTE 33. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/R~" TO RUN REQUESTED TASK TST (SP)+ ;...AND POP ERROR CODE ON RETURN SKDD10: ;QUEUEING OR NO, NOW CHECK FOR FLAG-SET ASL R2 ;IS THE "F" FLAG OPTION SET? BPL SKDB15 ;NO: THIS MODULE DONE: BACK FOR MORE BISB 8.(R1),@6(R1) ;YES: DO [IOR] OF MASK INTO FLAG LOC'N BR SKDB15 ;DONE WITH MODULE: LOOK FOR MORE SKDEX1: ADD #6,SP ;ADJUST SP FROM CALL TO "UNPACK" SKDEX2cD bS#  d*c   &d~cdAC: ? ILL CMD! ILL PAR! NON-QUIESCENT 7 7 7 aLdc Fd /~pd  dde(e W,4 2!/ +!( &7!#:y|d0'h4'h c~d'h'h 4dc  'hꚇ&& &  & x w  ы Dĥ  D0; ******************************************************************** ; * PROGRAM IDENTIFICATION: "CALENDAR" * ; * DATE & TIME-OF-DAY ROUTINE * ; * * ; * PURPOSE: * ; * --KEEPS 24-HOUR CLOCK AND PERPETUAL CALENDAR UPDATED. * ; * --CALLS THE SCHEDULER ONCE A MINUTE, ON THE MINUTE. ESET .WORD ARG1 ;ARG .WORD FLAG1 ;FLAG ADDR .WORD MASK1 ;FLAG MASK .WORD JSRTNE ;JSR TARGET MODUL1: .WORD 1 ;THREAD WORD .BYTE 34. ;TASK # .BYTE 43 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG2 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 : ;SCHEDULER EXIT WITH NO STACK POP MOV #340,PS ;PROTECT CHECK OF BUSY FLAG MOVB #-1,SKDBSY ;RESET FLAG TO ALLOW NEXT ENTRY JMP RESTOR ;RETURN TO INTERRUPTED PGM ==>[RESTOR] .PAGE UNPACK: ;INTERNAL SUBROUTINE TO SPREAD A SCHEDULER TIME&DATE ;WORD ONTO THE STACK ;UPON ENTRY, ROUTINE ASSUMES PACKED WORD IS ON TOP OF STACK; ; 15 11 10 6 5 1 ; ~`e C ``a - v6 w 6'd w e Օ+  d 0B` eG~e0  w l%Օ- ҋ  ~  VfZf&f&8~Pf%  2|v jwb 7 wfxg~ff( ERROR XXXXX SXXXXX SXXXXX SXXXXX SXXXXXfffffw > w Ҙ * ; * * ; * USAGE: * ; * TRIGGERED BY TIME-OF-DAY CLOCK INTERRUPT. * ; * IF TIME OR DATE IS ALTERED BY OUTSIDE PROGRAM(S), * ; * CPU MUST BE ON LEVEL 7 TO AVOID INTERFERENCE. * ; * WHEN READING TIME OR DATE, SAME PRECAUTION SHOULD * ; * BE TAKEN. ;JSR TARGET MODUL2: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 243 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG1 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL3: .WORD 1 ;THREAD WORD .BYTE 33. ;TASK # .BYTE 3 DAY ^ HOUR ^ MINUTE ;UPON EXIT, STACK HAS THREE WORDS ON IT: ; (SP)= DAY 2(SP)= HOUR 4(SP)= MINUTE MOV (SP),R3 ;COPY T&D WORD MOV R3,R5 ;SAVE IT FOR BELOW BIC #177700,(SP) ;LEAVE MINUTE ALL BY ITSELF ASL R3 ASL R3 SWAB R3 ;GET "HOUR" INTO LOW BYTE BIC #177740,R3 ;CLEAR ALL OTHER STUFF MOV R3,-(SP) ;PUT IT IN ITS OWN PLACE SWABw " 7 v~@g#wpfjf& D  lf @  ~x7 .nggggggggc~gb~0h~hf&& 6 7!`×ߕ'h 'h * ; * PROGRAMMER: 52 * ; * VERSION: 003.003 * ; * DATE: 02-DEC-71 * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; ******************************************************************** SAVE = 3 ;OP-CODE FOR CAL ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG2 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL4: .WORD 1 ;THREAD WORD .BYTE 34. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG3 ;ARG .WORD 0 ;FLAG ADDR R5 ASR R5 ASR R5 ASR R5 ;GET [DAY] INTO LOWER BYTE... BIC #177740,R5 ; ...CLEAR GARBAGE... MOV R5,-(SP) ; ...AND PUT IN ITS OWN PLACE RTS PC .PAGE SKNSRT: ;ROUTINE TO INSERT SCHEDULER MODULES FROM THE WAITING ;TABLE. ALSO LOOP RE-ENTRY POINT FROM END MOV #340,PS ;LOCK OUT INTERFERENCE FROM "QSKED" SKNA10: ;LOOP REWYhS'h g "Hߐ ~ ihW r "4ߕ gg'h4Yh ߐ  @ ee &w~i 6 ߕ K7 fv g 6 6×ߕB~j& 7 'h 'hߐ'h <gg0gg0ggߐ& qqr*sn2 CURRENT TASK TIMER BGT CALA08 ;STILL SOME LIFE LEFT INC COUNTR ;RESTORE IN CASE WAS ZERO BEQ CALA08 ;IT WAS. WE IGNORE ZEROES AS "OFF" .PAGE .IFNZ $TMSLC ;OPTION FOR TIME SLICING MOV R1,-(SP) ;SAVE USER'S MOV $PRIOR,R1 ;PRIORITY OF TASK INVOLUNTARILY ; SUSPENDED BY INTERRUPT, OR OF MOST RECENTLY RUN TASK. TSTB PPTAB(R1) ;CHECK FOR TIME-SLICING ON THIS LEVEORD 0 ;"DELTA" .WORD ARG5 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK MODUL8: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSREN USE CURRENT MINUTE .PAGE SKNA40: ;NOW THAT MODULE'S TIME IS READY, BEGIN SEARCH FOR ITS ;PLACE IN ONE OF THE TWO SCHEDULER THREADS. MOV CURTHD,R1 ;POINTS TO [THDTAB] OR [THDTAB+2] CMPB (SP),MDAY ;MODULE DATE :: TODAY'S DATE BGT SKNA60 ;AFTER TODAY: USE CURRENT THREAD BLT SKNA50 ;BEFORE TODAY: USE "FUTURE" THREAD CMPB 2(SP),HOUR ;MODULE HOUR :: CURRENT HOUR ~Hnzn TASK ## 2 ln &o2~no TASK ## 3 o & & & ~8o o2~oo TASK ## 4 o & &  |p2L BLE CALA06 ;NOT A T/S LEVEL: GO DO ABORT SEQUENCE MOV R2,-(SP) &SAVE USER'S ASL R1 ;USED AS A WORD INDEX MOV FIRST(R1),R2 ;ADDRESS OF FIRST TASK BEQ CALA05 ;NO TASKS IN QUEUE: DON'T SLICE MOV R2,@LAST(R1) ;LINK FRONT TASK TO END OF THREAD... MOV R2,LAST(R1) ;...AND UPDATE THE "LAST" POINTER MOV (R2),FIRST(R1) ;THEN MAKE "FIRST" POINT TO WHAT WAS TARGET MODUL9: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET .PAGE MASK1 = 123 MASK2 = 234 MASK3 = 345 JSRTNE: MOV #MODUL1,-(SP) MOV TMWRD0BGT SKNA60 ;LATER TODAY: USE CURRENT THREAD BLT SKNA50 ;WAS EARLIER TODAY: PUT IN "FUTURE" CMPB 4(SP),MINUTE ;MODULE MINUTE :: CURRENT MINUTE BGE SKNA60 ;NOW OR WITHIN HOUR: CURRENT THREAD SKNA50: TST (R1)+ ;WE ARE PAST MODULE'S TIME: USE "FUTURE" SKNA60: ;NOW THAT PROPER THREAD BEGIN WORD'S ADDRESS IS IN R1, ;WE CAN BEGIN SEARCH OF THAT THREAD. MOV (R1),R2 ;ADDR OF~(plp TASK ## 5 ^p & & &  &q2~pq ~qTASK ## 6 q & &  q2~qq TASK ## 7 ;THE SECOND TASK IN QUEUE CLR @LAST(R1) ;ZERO THREAD WORD OF NEW LAST TASK CALA05: ;EXIT FROM TIME-SLICE MOV (SP)+,R2 ;RESTORE USER'S MOV (SP)+,R1 ;LIKEWISE BR CALA08 ;BYPASS ABORT SEQUENCE CALA06: ;HERE WHEN LEVEL IS NOT A SLICER: DO ABORT==> MOV (SP)+,R1 ;RESTORE USER'S .ENDC $TMSLC ; ABORT SEQUENCE: TASK'S ABORT COU,-(SP) EMT QTIME TST (SP)+ RTS PC ARG1: '1 ARG2: '2 ARG3: '3 ARG4: '4 ARG5: '5 FLAG1: .BYTE 0 FLAG2: .BYTE 0 FLAG3: .BYTE 0 .END ONE OF THE THREAD-BEGIN WORDS BR SKNB00 ;ENTER LOOP FOR FIRST TIME SKNB10: ;THIS IS THE LOOP RETURN POINT AS LONG AS SEARCH CONT'S ADD #6,SP ;POP STACK POINTER FROM "UNPACK" BELOW SKNB00: ;HERE FOR FIRST-TIME ENTRY MOV R2,R1 ;SAVE OLD T/W ADDRESS MOV (R2),R2 ;GET NEXT MODULE'S (T/W) ADDRESS BEQ SKNB30 ;AT END OF THREAD ;NOT @ END: TEST MODULE FOR TIME q pr2~r`r TASK ## 8 Rr &  ~rs2 <~rs TASK ## 9 r  s2 ~psNTER REACHED ZERO (@TIMA40) MOV $CTASK,-(SP) ;STACK CURRENTLY ACTIVE TASK'S NUMBER... JSR PC,ABORT ;...AND REQUEST ITS ABORTION CALA08: ;HERE WHEN READY TO RUN THE CLOCK DECB TICTOC ;# OF TICS PER SECOND BEQ CALA10 ;NEW SECOND CALA09: RTI ;USED AS RETURN ALSO FROM[CALA40] .PAGE CALA10: ;ON EACH SECOND COME HERE CLRB SKSWCH ;INIT TO RUNFIRST TASK BEQ TIMA50 ;NO TASKS IN QUEUE. MOV R2,@LAST(R1) ;LINK FRONT TASK TO END OF THREAD... MOV R2,LAST(R1) ;...AND UPDATE THE "LAST" POINTER MOV (R2),FIRST(R1) ;THEN MAKE "FIRST" POINT TO WHAT WAS ;THE SECOND TASK IN QUEUE CLR @LAST(R1) ;ZERO THREAD WORD OF NEW LAST TASK BR TIMB10 ;BYPASS ABORT SEQUENCE TIMA50: .ENDC $TMSLC ;END OF TI MOV 4(R2),-(SP) ;STACK TEST MODULE'S DATE WORD... JSR PC,UNPACK ;...FOR CALL TO SPREAD IT ON STACK CMP 6(SP),(SP) ;NEW MOD'S DATE :: TEST MOD'S DATE BGT SKNB10 ;LATER: KEEP LOOKING BLT SKNB20 ;EARLIER: THREAD NOW CMP 10(SP),2(SP) ;NEW MOD'S HOUR :: TEST MOD'S HOUR BGT SKNB10 ;STILL LATER BLT SKNB20 ;EARLIER CMP 12(SP),4(SP) ;COMPARE MINs TASK ## 10 s  ||||~shNnO OPTRVOhNYg.........k~`tx 7r ww 7ts~~w  7^w w >ĝ\7Z70 , Z"{Rw.& d^@~t D A  &DCc  w 2w  w  ' 7  &w \w wXw w  fw ~Pu|t w  "SKNSRT" AND NOT "SKED" MOV R0,-(SP) MOV R1,-(SP) MOV #CLOCK,R0 ;POINTER TO TIME & DATE BYTES MOVB #TICRES,(R0)+ ;RESET [TICTOC] INCB (R0) ;NEXT SECOND CMPB (R0),#60. ;NEW MINUTE? BLT CALA40 ;NO: BUT GO TO END TO RUN "SKNSRT" INCB SKSWCH ;SET TO RUN "SKED" AND NOT "SKNSRT" CLRB (R0)+ ;RESET [SECOND] & GO ON TO... INCB (R0) ME-SLICING .PAGE ; ABORT SEQUENCE: TASK'S ABORT COUNTER REACHED ZERO (@TIMA40) MOV $CTASK,-(SP) ;STACK CURRENTLY ACTIVE TASK'S NUMBER... JSR PC,ABORT ;...AND REQUEST ITS ABORTION TIMB10: ;NOW WE BEGIN TRAVELING THE THREADS ;ALSO LOOP RE-ENTRY POINT FOR EACH RESOLUTION MOV #340,PS ;AVOID INTERFERENCE FROM "DQTIME" MOV #TFIRST,R1 ;CALC ADDRESS IN THE QUEUE POINTER TABLE UTES BGT SKNB10 .PAGE SKNB20: ;HAVE FINALLY FOUND SLOT FOR NEW MODULE. R1 CONTAINS ;ADDR OF PREVIOUS OR "UPSTREAM" MODULE (MIGHT BE THE ;THREAD START WORD) AND R2 CONTAINS ADDR OF DOWNSTREAM ;MODULE, OR ZERO IF NEW MODULE IS BEING PLACED AT END ;OF THREAD. R0 CONTAINS ADDR OF NEW MODULE. ADD #6,SP ;POP SP FROM 1ST CALL TO "UNPACK" SKNB30: ADD #6,SP ;POP SP FROM 2ND7 wtwhw  %-E es wh6 ~ =w F6 / w :( w 2! w * ~uw "w * 7 w 7w 77~~ Jw7  ww (b ww w A B` ~@vr% w| 7twrjwhg E 7tpwhP E ttP tIw ~v-% w  =w 7 t=w e0w ,w %@w ~ke ;...BUMP [MINUTE] CMPB (R0),#60. ;NEW HOUR? BLT CALA40 ;NO: BUT GO RUN SCHEDULER CLRB (R0)+ ;RESET [MINUTE]... INCB (R0) ;...AND BUMP [HOUR] CMPB (R0),#24. ;NEW DAY? BLT CALA40 ;NO CLRB (R0)+ ;YES: RESET [HOUR]... INC (R0) ;...AND BUMP [JDATE] CMP (R0),(PC)+ ;NEW YEAR? MXDAYS: .WORD 0 ;HOL ADD R0,R1 ;...OF POINTER FOR CURRENT RESOLUTION TIMB15: ;LOOP HERE FOR EACH SUCCESSIVE MODULE MOV R1,R2 ;REMEMBER UPSTREAM MODULE ADDRESS... ;...FOR USE IN DE-QUEUEING "ONE-SHOTS" MOV (R1),R1 ;NEXT MODULE'S THREAD WORD ADDRESS BEQ TIMA35 ;END OF THREAD: GO DOWN TO NEXT RES'N DECB TIMBYT(R1) ;COUNT DOWN MODULE'S TIMER BNE TIMB15 CALL TO "UNPACK" MOV R0,(R1) ;LOAD UPSTREAM THREAD-WORD FOR NEW MOD MOV R2,(R0) ;LOAD NEW T/W FOR DOWNSTREAM MOD BR SKNSRT ;GO BACK FOR POSSIBLE MORE MODULES. .PAGE ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "QSKED" * ; * SYSTEM SUBROUTINE TO QUEUE A SCHEDULER MODULE * ; * =~0ww @w Xwww=w  w  dw *Ae0w v,w nHBFw 6- .27t,`~w ( B:8w ?w 7 w 777     w %0 %7E `  1 q~ xW ֆ m7 yDx|xxxxjuzxvxNyrvyz z`yz$v,vVvvwHwwwPwuttZ7U<D ;~x2 7.7(%  w %=w w  w w wwDS #DAYS IN CURRENT YEAR BLE CALA30 ;NO: GO TO NEXT DAY + MAYBE NEW MONTH ;HAPPY NEW YEAR!! MOV #1,R1 MOV R1,(R0)+ ;RESET [JDATE] MOVB R1,(R0)+ ;RESET [MONTH] MOVB R1,(R0)+ ;RESET [MDAY] INCB (R0) ;BUMP TO NEW YEAR MOVB #28.,FEBARY ;RESET FEBRUARY MOV #365.,MXDAYS ;RESET YEAR LENGTH BITB #3,(R0) ;IS TH ;NOT EXPIRED: GET NEXT MODULE ;TIMER EXPIRED! IT IS MODULE'S TIME. MOVB RESET(R1),TIMBYT(R1) ;RESET TIMER BYTE BNE TIMB20 ;MODULE IS A REPEATER: LEAVE IN THREAD MOV (R1),(R2) ;"ONE-SHOT": REMOVE FROM THREAD ... BNE TIMB22 ;...BY "BRIDGING". BRANCH IF NOT LAST MOV R2,TLAST(R0) ;BUT UPDATE "LAST" POINTER IF WAS END TIMB22: MOV #1,(R1) ;SET THREAD WORD INACT * ; * PURPOSE: * ; * PUTS ADDRESS OF CALLER'S MODULE IN INTERNAL STACK. * ; * THIS TABLE IS EMPTIED BY THE ROUTINE "SKNSRT" WHICH IS * ; * CALLED BY THE SCHEDULER EACH MINUTE JUST BEFORE IT RUNS* ; * THIS METHOD AVOIDS QUEUEING AND SCHEDULER CONFLICTS WHE* ; * ACCESSING THE TWO SCHEDULER THREADS(THE SCHEDULER DROPS* ; * THE CPU LEVEL SO AS    7~ymw w %/w \ z \pp.  L et  ! tB !~y t=L !64t4 $t .!4t6t4 $t % w   @w @ % % w  K~zww  D  &C@AEPA&fw w /w w :w   ` ~xz E ` H 8 wFLw 7IS A LEAP YEAR? BNE CALA35 ;NO INC MXDAYS ;YES: BUMP YEAR LENGTH INCB FEBARY ;...AND FEBRUARY BR CALA35 CALA30: ;HERE @ BEGIN OF DAY & NOT NEW YEAR MOV #MONTH,R1 ;INIT POINTER TO DATE BYTE TABLE MOVB (R1)+,R0 ;[MONTH]: USED AS INDEX INCB (R1) ;[MDAY]: NEW DAY CMPB (R1),DAYTAB(R0 ;[MDAY]: END OF MONTH BLE CALA40 IVE IN EITHER CASE TIMB20: MOV R4,PS ;UNLOCK INTERRUPTS: SAFE NOW MOV R1,R3 ;COPY MODULE ADDRESS TO PRESERVE R1... ;...IN CASE OF "J" OPTION MOVB OPTION(R1),R2 ;GET OPTION BYTE FOR THIS MODULE TSTB TASKNO(R1) ;IS MODULE TASK-RELATED? BEQ TIMB54 ;NO: CHECK FOR OTHER OPTIONS ;YES: SET UP STACK FOR CALL TO EITHER ;[SUSPNOT TO LOCK OUT INTERRUPTS UNNECES-* ; * SARILY), REDUCING THE CONFLICT AREA TO JUST THE FIFO * ; * TABLE. THIS CONFLICT IS AVOIDED, THEN, BY RUNNING * ; * "QSKED" (A SHORT ROUTINE) AND THE FEW WORDS OF CODE * ; * IN "SKNSRT" WHICH ACCESS THE TABLE, UNDER INTERRUPT- * ; * LOCKOUT. * ; * * ; * USAGE: U4E(w T76 ~z p$tw V׭脷U7w @ŝŝwt G~h{wt!t w w J~~w @eZ%ĕtt72 $t$tw Bw .e` w ;w ĝ~{tw wsf&f 4t6tt 0.7$7$ ~X|w r5gb ;NO MOVB #1,(R1) ;RESET DAY TO FIRST OF MONTH INCB -(R1) ;NEXT MONTH: CAN'T BE JANUARY (ABOVE) CALA35: ;HERE TO ADJUST THE THREAD POINTER POINTER AT THE BEGIN ; OF EACH MONTH. "CURTHD" ALWAYS POINTS TO "TH1BGN" DURING ; ODD-NUMBERED MONTHS, AND TO "TH2BGN" DURING EVEN MONTHS. MOV #THDTAB,CURTHD ;INIT THREAD-START TABLE POINTER BITB #1,MONTH ;ODD-NUMBERED MONTH? BNE CALAEND] OR [QUEUE] MOVB TASKNO(R3),-(SP);PUSH TASK # FIRST CLR -(SP) ;IMMEDIATE RETURN REQUEST FOR BOTH, OR ;INIT OF PRIORITY IF NEEDED FOR [QUEUE]. TSTB R2 ;IS "SUSPEND" OPTION SELECTED? BPL TIMB30 ;NO: GO DO QUEUEING JSR PC,UNSPND ;CALL TO "UN-SUSPEND" BR TIMB50 ;GO POP ERROR WORD & CHECK FLAG OPTION TIMB30: ;HERE TO QUEUE A TASK. TASK # * ; * USERS CAN CALL "QSKED" EITHER VIA JSR (IF LINKED) OR * ; * VIA EMT. IN EITHER CASE THE ADDRESS OF THE MODULE TO BE* ; * THREADED MUST FIRST BE PLACED ON THE STACK.THE STACK * ; * POINTER IS LEFT UNCHANGED ON RETURN. THE STACK LOCATION* ; * ITSELF WILL BE CLEARED IF THE TABLE HAS ROOM FOR * ; * IT AND THE MODULE ITSELF IS INACTIVE (ITS THREAD WORD * ; * MUSTV  <6tt !%& &e N @ e0w &  ~| t 7~rnE w   w ׭4 ^w T~H}Uw sw nj  7,tXRt-P Dw@ 78 %(!  %~}??~~w N%w 77w Z e0w ,w w p~8~40 ;YES: LEAVE AS IS ADD #2,CURTHD ;EVEN: ADVANCE TO POINT TO THREAD #2 CALA40: ;HERE ON EVERY MINUTE BOUNDARY TO RUN... ;...THE SCHEDULER. ON THE OTHER 59 SECONDS, RUN "INSERT" ROUTINE. MOV (SP)+,R1 ;RESTORE USER'S FOR "SAVE" MOV (SP)+,R0 ;ALSO INCB SKDBSY ;MARK AND TEST BUSY FLAG BEFORE ENTERING BNE CALA09 ;LOG-JAM: SCHEDULER CURRENTLY RUNNING... ;...DON'T RE-ENTER AND RETURN CODE ;(OR INITED PRIORITY) ALREADY PUSHED ONTO STACK. .IFNZ DPRTY ;DYNAMIC PRIORITIES OPTION CLR -(SP) ;USE SYSTEM-ASSIGNED PRIORITY ; (ACTUALLY LEAVES ZERO AS PRIORITY AND PUSHES NEW RETURN CODE OF ZERO, ; POSSIBLY INITING STACK SPACE FOR PASSED ARGUMENT, IF OPTION IS ON.) .ENDC DPRTY .IFNZ ARG ;SYSTEM OPTION TO PASS ARGUMENT ON QUEUE BIT #100,R2 ;DOES MODULE HAVE AN ARGUMENT BE =1). IN CASE OF ONE OF THE ABOVE ERRORS, THE * ; * STACK LOCATION IS LEFT UNCHANGED (NON-ZERO) FOR TESTING* ; * BY THE CALLER. * ; * "QSKED" SAVES & RESTORES ALL REGISTERS THAT IT USES. * ; * IT MAY BE CALLED BY ANY TYPE OF USER AT ANY TIME. * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; ******** Cå å$ נA   e` ~  Ëנe em~~e e ѐ  @(ZUZUZ@ ODT-11R V002ABETZUZU *;/\ $G _<^,OWEBP@>SRC-FI!XASPMCFR~(B=))eL x  N N Ê <%! ,c ѐhˋÜyf`E $  P   LwZ ɋr p~N-: IT WILL CLEAN UP AFTER ITSELF. ; O.K. TO ENTER "SKNSRT" OR ""SKED". SAVE ;SAVE REGS OF INTERRUPTED PGM & RTN HERE SKSWCH: BR .+2 ;SWITCH NORMALLY OPEN TO FALL THROUGH... BR SKRELY ;...TO SKIP "SKED" AND RUN "SKNSRT" ; ON THE MINUTE IT IS CLOSED TO FORCE RUN OF "SKED" INSTEAD. .PAGE SKED: ;THIS IS THE SCHEDULER ;ENTER HERE EVERY MINUTE ON THE MINUTE FROM "CALENDAR" MOV @CURTHD,TO PASS? BEQ TIMB40 ;NO MOV @TIMARG(R4),(SP);YES: REPLACE THE ZERO WITH ACTUAL ARG.. TST (R3)+ ;...AND BUMP SECONDARY MODULE POINTER ;SO THAT REFERENCES BELOW WILL ALLOW FOR ;THE EXTRA MODULE WORD THAT "ARG" USED. TIMB40: CLR -(SP) ;MUST PUSH RETURN CODE SINCE ARGUMENT .ENDC ARG ;USED UP LAST ONE. JSR PC,QUEUE ;CALL QUEU************************************************************ .PAGE QSKED: ;SUBROUTINE TO QUEUE A SCHEDULER MODULE ;TO WAIT FOR INSERTION INTO ONE OF THE ;TWO SCHEDULER THREADS MOV (SP),-(SP) ;MOVE RETURN ADDRESS UP FOR RTI LATER MOV PS,2(SP) ;...AND SET UP PS FOR RTI, TOO MOV R0,-(SP) ;SAVE USER'S MOV #340,PS ;RAISE CPU LEVELR0 ;[TH1BGN] OR [TH2BGN] MOV R0,R1 ;SAVE CURRENT THREAD ADDRESS FOR... ;...POSSIBLE MODULE REMOVAL (BELOW) MOV (R0),R0 ;NEXT MODULE'S ADDRESS BEQ SKDEX2 ;END OF THREAD: EXIT MOV R4,PS ;DROP CPU LEVEL TO BE FAIR TO OTHERS MOV STRTWD(R0),-(SP);STACK THIS MODULE'S START WORD FOR... JSR PC,UNPACK ;...CALL TO UNPACK SUBROUTINE, WHICH ; RETURNS E TIMB50: ;HERE AFTER [QUEUE] OR [UNSPND] TST (SP)+ ;POP ERROR RETURN CODE TIMB54: ;HERE WHEN NOT TASK-RELATED BIT #40,R2 ;TEST "FLAG" OPTION BEQ TIMB60 ;NOT SELECTED BISB TIMASK(R3),@TMFLAG(R3) ;"IOR" MASK INTO FLAG LOCATION CMP (R3)+,(R3)+ ;BUMP SECONDARY MODULE POINTER FOR FLAGS TIMB60: BIT #20,R2 ;IS "JSR" OPTION SELECTED? BEQ TI TO AVOID INTERFERENCE CMP STBPTR,#SKTBND ;IS TABLE FULL? BLOS QSKA40 ;YES: POINTER IS AT BOTTOM, SO ERROR XIT MOV 6(SP),R0 ;MODULE'S ADDRESS BIC #10000,2(R0) ;CLEAR "D" FLAG IN CASE WAS DE-QUEUED DEC (R0) ;IS MODULE INACTIVE (THREAD WORD = 1)? BEQ QSKA20 ;O.K. ADD #2,(R0) ;SEE IF IN "WAIT" TABLE BEQ QSKA30 ;YES: O.K. TO TAKE GOOD EXIT NOW ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "QTIME" * ; * TIMER MODULE QUEUEING SUBROUTINE * ; * * ; * PURPOSE: LOADS TIMER MODULES ONTO "WAIT" STACK FOR "TIMER" * ; * "TMNSRT" IS RESPONSIBLE FOR UNLOADING FROM THE STACK * ; * AND STRINGING ONTO PROPER THREAD WITH TIME & DATE OF MODULE'S START WORD SPREAD ON STACK ; (SP) = DAY OF MONTH 2(SP) = HOUR 4(SP) = MINUTE CMPB (SP),MDAY ;SEE IF MODULE IS FOR TODAY BGT SKDEX1 ;FOR TOMORROW OR BEYOND: EXIT BLT SKDB10 ;FOR YESTERDAY OR EARLIER: EXECUTE MODULE CMPB 2(SP),HOUR ;TODAY: THIS HOUR? BGT SKDEX1 ;MODULE IS EARLY: EXIT BLT SKDB10 ;MODULE IS LATE: EXECUTE CMPB 4(SP),MIMB15 ;NO: SKIP "J" LINK AND LOOP FOR MORE JSR PC,JSTARG(R3) ;LINK TO USER RTNE. (R1)=MODULE BEGIN BR TIMB15 ;LOOP BACK FOR MORE MODULES TIMEXT: ;EXIT POINT FOR [TIMER] MOV #340,PS ;PROTECT AGAINST THIS INTERRUPT DURING ;EXIT SEQUENCE DECB TIMBSY ;NESTING "BUSY" COUNTER BGE TIMA15 ;NORMALLY RESIDES @ ZERO DURING ROUTINE BR QSKA35 ;IN THREAD: TAKE ERROR EXIT QSKA20: ;MODULE READY FOR INSERTION IN TABLE SUB #2,STBPTR ;PUSH TABLE POINTER MOV R0,@STBPTR ;LOAD NEW MODULE INTO TABLE QSKA30: CLR 6(SP) ;NOW READY TO EXIT. CLEAR ERROR FLAG QSKA35: DEC (R0) ;EITHER SETS T/W = -1 TO SHOW IN "WAIT" ;...OR RESTORES T/W TO ORIGINAL, IF NOT THREADED QSKA40: MOV (SP)+,R0 ;RESTORE USER'S * ; * * ; * USAGE: CALLED BY ANY ROUTINE WISHING TO ACTIVATE A TIMER * ; * MODULE. CALLING SEQUENCE: * ; * MOV #MODULE,-(SP) ;STACK MODULE'S ADDRESS * ; * MOV TIME,-(SP) ;STACK TIMER-RESET WORD * ; * EMT QTIME ;REQUEST TO QUEUE MODULE * ; * OR NUTE ;FOR THIS HOUR. THIS MINUTE? BGT SKDEX1 ;TOO SOON SKDB10: MOV #340,PS ;LOCK OUT INTERFERENCE FROM "DQSKED" CMP (R0),#1 ;ALREADY DE-QUEUED? BNE SKDB20 ;STILL O.K. SKDB15: ;ALSO RETURN POINT FROM [SKDD10] ADD #6,SP ;POP SP DUE TO "UNPACK"... BR SKED ;...AND GO BACK FOR ANOTHER ONE SKRELY: BR SKNSRT ;RELAY POINT FOR SKIP TO 'INSERT ;EXECUTION. GOES ABOVE IF ADDITIONAL ;OCCASIONS TO ENTER ROUTINE HAVE ;OCCURRED DURING EXECUTION. IN THIS ;CASE ROUTINE IS RE-EXECUTED IMMEDIATELY ;IN AN ATTEMPT TO RE-SYNCHRONIZE JMP RESTOR ;NORMAL RETURN TO INTERRUPTED PROGRAM .PAGE TTBPTR: .WORD 0 ;TIMER TABLE POINTER TO "WAIT" STACK TWAITB: .WORD 0 RTI ;RESTORE USER'S PS & RETURN .PAGE DQSKED: ;SYSTEM SUBROUTINE TO DE-QUEUE A SCHEDULER MODULE MOV (SP),-(SP) ;RE-ORDER STACK FOR "RTI" RETURN AT END MOV PS,2(SP) ;STACK NOW READY FOR "RTI" JSR R5,PUSHR ;PUSH ALL REGS ONTO STACK MOV 20(SP),R0 ;MODULE'S ADDRESS MOV #340,PS ;LOCK OUT INTERFERENCE FROM SCHEDULER CMP #1,(R0) ;HAS MODULE BEEN D * ; * JSR PC,QTIME * ; * TST (SP)+ ;TEST ERROR RETURN CODE * ; * * ; * THE MODULE MUST BE SET UP, PRIOR TO THE CALL, AS DESCRIBED * ; * IN THE ROS USER'S MANUAL. NOTE THAT CALLS FOR MODULES HAVING * ; * THE "S" SUSPEND OPTION SET WILL CAUSE TRANSFER TO THE * ; * DISPATCHER, AND WILL NOT RETURN UNLESS THE' RTNE .PAGE SKDB20: ;O.K. TO WORK ON THIS MODULE MOV (R0),(R1) ;FIRST: REMOVE MODULE BY "BRIDGING" THE ;THREAD OVER ITSELF, CONNECTING PREVIOUS ;MODULE WITH FOLLOWING ONE MOV #1,(R0) ;SET THIS MODULE INACTIVE... MOV R4,PS ;...DROP CPU LEVEL TO INTERRUPTED LEVEL MOV R0,R1 ;...AND SET UP THE SECONDARY MODULE PNTR MOV 2(R1 ;FIRST LOC'N OF "WAIT" TABLE IS ALWAYS 0 .=$TWATZ*2+. ;RESERVE SPACE FOR TABLE TMTBND = .-2 ;ADDRESS OF LAST TALBE LOCATION TFIRST: ;TABLE OF POINTERS TO FIRST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN ZERO ;WHEN THREAD IS EMPTY. .=$NRES*2+. ;RESERVE ONE WORD PER RESOLUTION TLAST: ;TABLE OF POINTERS TO LAST ME-QUEUED ALREADY? BEQ DQSK20 ;YES: INACTIVE,SO IGNORE CMP #-1,(R0) ;IS IT STILL IN "WAIT" TABLE? BEQ DQSK50 ;YES: GO SET THE "D" FLAG MOV #2,R5 ;INIT COUNTER TO SEARCH BOTH THREADS MOV #TH1BGN,R1 ;START BY SEARCHING THREAD #1 DQSK10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;COPY ADDRESS OF UPSTREAM MODULE MOV (R1),R1 ;GET DOWNSTREAM MODULE CALL IS IN ERROR. * ; * ON THESE CALLS THE MODULE'S TASK NUMBER IS AUTOMATICALLY SET * ; * TO THE CURRENTLY ACTIVE TASK'S NUMBER. * ; * IF THE "WAIT" STACK IS FULL, "QTIME" WILL EXIT WITH THE ERROR * ; * CODE WORD ON THE STACK NON-ZERO. THE MODULE WILL NOT BE QUEUED* ; * "QTIME" TAKES ITS ERROR EXIT IF THE REQUESTED MODULE IS ALREADY* ; * IN EITHER A TIMER THREAD OR THE "WAIT" STACK, AND HAS NOT BEEN * ; * FLAGGED FOR DE-QUEUEING. GOOD RET),R2 ;GET OPTION & TASK WORD BPL SKDC10 ;"R" REPEAT FLAG NOT SET MOV DELTA(R1),-(SP) ;GET REPEAT WORD & STACK IT FOR CALL... JSR PC,UNPACK ;...TO SPREAD IT ON STACK ;NOW THE STACK HAS BOTH THE MODULE'S ;"START" AND "DELTA" WORDS SPREAD ON IT: ;(SP)= D-DATE 2(SP)= D-HOUR 4(SP)= D-MINUTE ["D" MEANS "DELTA"] ;6(SP)= S-DATE 8(SP)= S-HOUR 10(SP)= S-MINUTE ["S" MEANSODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN THE ;ADDRESS OF [TFIRST(R)] WHEN THREAD ;IS EMPTY. .=$NRES*2+. RESTAB: ;RESOLUTION COUNTER TABLE: PERMANENT .BYTE RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8,RES9 .BYTE RES10,RES11,RES12,RES13,RES14,RES15,RES16 .=RESTAB+$NRES .BYTE 0 ;END BYTE CURTAB: .BYTE RE; ******************************************************************** ; * * ; * PROGRAM IDENTIFICATION: * ; * SET TIME SET DATE GET TIME GET DATE * ; * * ; * ROUTINES TO SET AND GET CURRENT TIME AND DATE * ; * URNS ARE MADE WHEN THE MODULE* ; * IS FOUND INACTIVE OR MARKED FOR DE-QUEUEING IN THE "WAIT" STACK* ; * IN THIS LAST CASE, THE MARK FOR DE-QUEUEING WILL BE REMOVED, * ; * AND THE MODULE WILL REMAIN WHERE IT IS ON THE "WAIT" STACK. * ; * * ; * PROGRAMMER: 52 * ; * VERSION: 002.009 * ; * DATE: 30-NOV-71 'S ADDRESS BEQ DQSK40 ;END OF THREAD CMP R0,R1 ;IS THIS THE MODULE WE ARE LOOKING FOR? BNE DQSK10 ;NO MOV (R1),(R2) ;YES: "BRIDGE" OVER THIS MODULE IN THREAD MOV #1,(R1) ;...AND SET T/W = 1 TO SHOW INACTIVE DQSK20: ;HERE UPON SUCCESSFUL DE-QUEUE CLR 20(SP) ;ERROR RETURN STATUS: O.K. DQSK30: ;HERE FOR GENERAL EXIT FROM ROUTINE JSR R5,POPR S1,RES2,RES3,RES4,RES5,RES6,RES7,RES8,RES9 .BYTE RES10,RES11,RES12,RES13,RES14,RES15,RES16 .=CURTAB+$NRES .BYTE 0 ;END BYTE TIMBSY: .BYTE 0 ;FLAG & NESTING COUNTER FOR [TIMER] BASCNT: .BYTE 0 ;OPTIONAL SUB-RESOLUTION PULSE COUNTER .END "START"] MOV SP,R5 ;INIT SECONDARY STACK POINTER ADD #6,R5 ;POINT TO "S-DATE" ADD (SP)+,(R5)+ ;[D-DATE] + [S-DATE]: ACCUMULATE DAYS ADD (SP)+,(R5)+ ;[D-HOUR] + [S-HOUR]: ACCUMULATE HOURS ADD (SP)+,(R5)+ ;[D-MIN] + [S-MIN]: ACCUMULATE MINUTES CMP #60.,(R5) ;SEE IF MINUTES OVERFLOWED BGT SKDB30 ;NO: O.K. SUB #60.,(R5) :YES: STRIP MODULUS... * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .TITLE TIMER .DEF QTIME .DEF TIMER .DEF TWAITB,TTBPTR,TFIRST,TLAST,RESTAB,CURTAB,TIMBSY,BASCNT .REF UNSPND,QUEUE ;POP REGS FROM STACK RTI ;RETURN SET ABOVE: RESTORE ORIGINAL CPU STATUS & RETURN DQSK40: ;HERE WHEN END OF THREAD REACHED MOV #TH2BGN,R1 ;SET UP FOR POSSIBLE SEARCH OF THREAD #2 DEC R5 ;LOOP COUNTER BNE DQSK10 ;STILL MUST DO THREAD #2 BR DQSK30 ;SEARCH FAIL: EXIT WITH NON-ZERO ERROR DQSK50: ;HERE WHEN MODULE STILL IN WAIT" TABLE. MUST SET THE ; "D" DE-QUEUE FLAELAY COUNT .BYTE 0 ;RESET TIME TMWRD1: .BYTE 10. ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD2: .BYTE 15. ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD3: .BYTE 5 ;DELAY COUNT .BYTE 5 ;RESET TIME TMWRD4: .BYTE 10. ;DELAY COUNT .BYTE 10. ;RESET TIME TMWRD5: .BYTE 15. ;DELAY COUNT .BYTE 15. ;RESET TIME TMWRD6: .BYTE 0 ;DELAY COUNT .BYTE 0 ;RESET INC -(R5) ;...AND BUMP HOURS TST (R5)+ ;(EQUALIZE POINTER IN CASE OF BRANCH) SKDB30: CMP #24.,-(R5) ;SEE IF HOURS OVERFLOWED BGT SKDB32 ;NO SUB #24.,(R5) ;YES: STRIP MODULUS... INC (SP) ;...AND BUMP DAYS SKDB32: MOVB MONTH,R3 ;USE CURRENT MONTH AS INDEX MOVB DAYTAB(R3),R3 ;GET # DAYS/MONTH INTO A WORD CMP R3,(SP) ;CHECK IF PAST END OF E EMT TABLE, OR AN INVALID * ; * CODE WITHIN THE TABLE--- A RETURN IS MADE IMMEDIATELY TO THE * ; * CALLER WITH NO ACTION TAKEN. * ; * THE CALLER SHOULD NOTE THAT HE MAY BE INTERRUPTED BETWEEN HIS * ; * EMT CALL AND THE EVENTUAL RETURN, EVEN IN THE CASE OF AN ERROR.* ; * * ; * PROGRAMMER: 52 * ; * VERSION: 002.002 G IN MODULE TO FORCE IGNORE WHEN ; "SKNSRT" RUNS. IF MODULE IS QUEUED AGAIN BEFORE ; "SKNSRT" RUNS, THIS "D" FLAG WILL BE CLEREAD, AND MODULE ; WILL BE LEFT IN THE "WAIT" TABLE. BIS #10000,2(R0) ;SET "D" FLAG IN MODULE OPTION BYTE BR DQSK20 ;TAKE GOOD EXIT COUNTR: .WORD 0 ;THIS IS THE ABORT/TIME-SLICE COUNTER!! ABMPLR .WORD 0 ;MULTIPLIER FOR ABORT AND TIME/SLICE CURTHD: .WORD TIME .PAGE T.30HD: .WORD 1 ;THREAD WORD .WORD T.30BG ;TASK ENTRY .WORD T.30IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.30PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 30. ;TASK # .WORD 0 .REF $CTASK,$PRIOR,SUSPND .REF PUSHR,POPR,RESTOR .PAGE QTIME: ;ROUTINE TO PUT TIMER MODULE IN "WAIT" STACK MOV PS,-(SP) ;SAVE USER'S PS MOV #340,PS ;RAISE CPU LEVEL TO PROTECT ROUTINE MOV R0,-(SP) ;SAVE USER'S CMP TTBPTR,#TMTBND ;SEE IF STACK IS FULL BHI QTIM50 ;YES: ERROR EXIT MOV 10(SP),R0 ;ADDRESS OF MODULE DEC (R0) MONTH BGE SKDB40 ;STILL THIS MONTH SUB R3,(SP) ;GET DAY OF NEXT MONTH .PAGE SKDB40: ;NOW RESTORE MODULE START WORD & STACK SWAB (SP) ;POSITION "DATE"... ASL (SP) ASL (SP) ASL (SP) ;...FOR PLACE BACK IN "START" WORD SWAB 2(SP) ;POSITION "HOUR" ASR 2(SP) ASR 2(SP) ;...FOR ITS PLACE BIS THDTAB ;POINTER TO CURRENT THREAD BEGIN WORD THDTAB: .WORD TH1BGN ;THREAD BEGIN TABLE .WORD TH2BGN .WORD TH1BGN TH1BGN: .WORD 0 ;ACTUAL BEGIN OF THREAD #1 TH2BGN: .WORD 0 ;#2 STBPTR: .WORD SWAITB ;SCHEDULER "WAIT" TABLE POINTER SWAITB: .WORD 0 ;TOP OF "WAIT" STACK IS ALWAYS ZERO .=$SWATZ*2+. ;THE SCHEDULER "WAIT" TABLE SKTBND = .-2 ;END OF "WAIT" TABLE .t!s@&y@;K}@.hfp@f@[g4@m@[qj@.LC @R:@(xh-ZhR.D~hVA*}hEhm4ph!?}h.Q@hRehS@~hCmhw_h.y2ghbYz ;IS TIMER MODULE INACTIVE? (T/W=0?) BNE QTIM30 ;NO: SEE IF ACTIVE OR IN "WAIT" STATE QTIM20: ;HERE WHEN CLEARED TO STACK UP MODULE ADD #2,TTBPTR ;PUSH "WAIT" STACK POINTER MOV R0,@TTBPTR ;ENTER MODULE ADDRESS INTO "WAIT" STACK BIS #C1CBIT,C1COMD ;START UP CLOCK IF IT WAS OFF TST 2(R0) ;CHECK OPTION FLAG FOR "SUSPEND" BMI QTIM60 ;"SUSPEND" SELECTED QTIM40: ;STACK SAVE .=NN*2+. T.31HD: .WORD 1 ;THREAD WORD .WORD T.31BG ;TASK ENTRY .WORD T.31IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.31PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 31. ;TASK # DAYTAB = .-1 ;THIS IS THE 12-BYTE TABLE OF DAYS-PER-MONTH JANARY = . FEBARY = .+1 .BYTE 31.,28.,31.,30.,31.,30.,31.,31.,30.,31.,30.,31. CLOCK: ;EXTERNAL REFERENCE FOR TIME-OF-DAY CLOCK AND CALENDAR TICTOC: .BYTE 0 ;COUNTS CLOCK BEATS PER SECOND SECOND: .BYTE 0 ;CURRENT TIME MINUTE: .BYTE 0 ;CURRENT TIME HOUR: .BYTE 0 ;CURRENT TIME JDATE: .WORD 0 ;CURRENT JULIAN DATE MONT (SP)+,(SP) ;[OR] DATE & HOUR... BIS (SP)+,(SP) ;...WITH MINUTE... MOV (SP)+,STRTWD(R1);...AND RE-STORE INTO START WORD TST (R1)+ ;BUMP POINTER TO ALLOW FOR "DELTA" WORD MOV R0,-(SP) JSR PC,QSKED ;RE-QUEUE MODULE IN NEW TIME SLOT TST (SP)+ ;POP RETURN ERROR WORD SKDC10: ;CONTINUE PROCESSING MODULE... ;...WHETHER OR NOT IT WAS REPE ;THIS IS THE "SUCCESSFUL" EXIT CLR 10(SP) ;PREPARE ERROR RETURN CODE TO SHOW O.K. QTIM45: ;HERE WHEN EXITING TO "SUSPEND". AVOID CLEARING 10(SP) MOV 6(SP),4(R0) ;LOAD NEW TIMER/RESET WORD INTO MODULE ; THIS SERVES AS NORMAL INIT FOR TIMER MODULE, AND ALSO RESETS ; THE "RESET" BYTE IN CASE MODULE IS BEING RE-QUEUED AFTER BEING ; DE-QUEUED, ALL WHILE REMAINING IN "WAIT" STACK. QTIM50: ;HERE WHEN EXIT IS .WORD 0 ;STACK SAVE .=NN*2+. T.32HD: .WORD 1 ;THREAD WORD .WORD T.32BG ;TASK ENTRY .WORD T.32IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.32PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 32. H: .BYTE 0 ;CURRENT MONTH MDAY: .BYTE 0 ;CURRENT DAY OF MONTH YEAR: .BYTE 0 ;CURRENT YEAR (MINUS 1900) SKDBSY: .BYTE -1 ;SCHEDULER BUSY FLAG: IDLE=-1; .END ATED TSTB R2 ;TASK NUMBER BEQ SKDD10 ;NO QUEUEING WHEN IT IS ZERO MOVB R2,-(SP) ;STACK TASK # IN PREP FOR CALL TO QUEUE .IFNZ DPRTY ;OPTION FOR DYNAMIC PRIORITIES CLR -(SP) ;USE SYSTEM-ASSIGNED PRIORITIES .ENDC DPRTY CLR -(SP) ;IMMEDIATE RETURN REQUESTED... ;...OR INIT OF [ARG] IF NEEDED ASL R2 ;IS THE "A" TO LEAVE NON-ZERO ERROR CODE ON STACK DEC (R0) ;SET T/W=-1 TO SHOW IN "WAIT" STATE... ;...OR TO RESTORE MODULE'S T/W IF IT IS FOUND ALREADY ACTIVE... ; ...OR ALREADY IN "WAIT" STATE MOV (SP)+,R0 ;RESTORE USER'S MOV (SP)+,2(SP) ;MOVE OLD [PS] IN PREP FOR RTI RTI ;ZAP! RETURN TO USER OR GO TO SUSPEND ;ON OLD CPU LEVEL QTIM30: ADD #2,(R0) ;NOT INACTIVE. SEE I;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.33HD: .WORD 1 ;THREAD WORD .WORD T.33BG ;TASK ENTRY .WORD T.33IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.33PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS P #-1,(R0) ;IS IT STILL IN "WAIT" TABLE? BEQ DQSK50 ;YES: GO SET THE "D" FLAG MOV #2,R5 ;INIT COUNTER TO SEARCH BOTH THREADS MOV #TH1BGN,R1 ;START BY SEARCHING THREAD #1 DQSK10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;COPY ADDRESS OF UPSTREAM MODULE MOV (R1),R1 ;GET DOWNSTREAM MODULE'S ADDRESS BEQ DQSK40 ;END OF THREAD CMP R0,R1 (ARGUMENT) FLAG SET? BPL SKDC20 ;NO: LEAVE THE ZERO ON STACK FOR ARG'MNT .IFNZ ARG ;OPTION FOR TRANSMITTING ARGUMENT MOV @6(R1),(SP) ;YES: PUT ACTUAL ARG IN PLACE OF ZERO .ENDC ARG TST (R1)+ ;BUMP POINTER IN ANY CASE IF "A" IS SET SKDC20: .IFNZ ARG ;OPTION FOR TRANSMITTING ARGUMENT CLR -(SP) ;PUSH RETURN CODE .ENDC ARG JSR PC,QUEUE ;NF ACTIVE OR "WAIT" BNE QTIM50 ;ACTIVE: TAKE ERROR EXIT CMPB 5(R0),#-1 ;IN "WAIT": IS IT FLAGGED FOR DE-QUEUE? BNE QTIM50 ;NO: ERROR EXIT BR QTIM40 ;YES: LEAVE THERE AND REMOVE D-Q FLAG .PAGE QTIM60: ;HERE WHEN TASK IS TO BE SUSPENDED UNTIL TIMER EXPIRES MOVB $CTASK,2(R0) ;LOAD MODULE TASK # WITH CURRENT TASK MOV 4(SP),10(SP) ;SET CALLER RTN TO LOOK LIKE "JSR" .BYTE 33. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.34HD: .WORD 1 ;THREAD WORD .WORD T.34BG ;TASK ENTRY .WORD T.34IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.34PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;IS THIS THE MODULE WE ARE LOOKING FOR? BNE DQSK10 ;NO MOV (R1),(R2) ;YES: "BRIDGE" OVER THIS MODULE IN THREAD MOV #1,(R1) ;...AND SET T/W = 1 TO SHOW INACTIVE DQSK20: ;HERE UPON SUCCESSFUL DE-QUEUE CLR 20(SP) ;ERROR RETURN STATUS: O.K. DQSK30: ;HERE FOR GENERAL EXIT FROM ROUTINE JSR R5,POPR ;POP REGS FROM STACK RTI ;RETURN SET ABOVE: RESTORE ORIGINAL CPU STATUS &OW CALL "QUEUE" TO RUN REQUESTED TASK TST (SP)+ ;...AND POP ERROR CODE ON RETURN SKDD10: ;QUEUEING OR NO, NOW CHECK FOR FLAG-SET ASL R2 ;IS THE "F" FLAG OPTION SET? BPL SKDB15 ;NO: THIS MODULE DONE: BACK FOR MORE BISB 8.(R1),@6(R1) ;YES: DO [IOR] OF MASK INTO FLAG LOC'N BR SKDB15 ;DONE WITH MODULE: LOOK FOR MORE SKDEX1: ADD #6,SP ;ADJUST SP FROM CALL TO "U MOV #SUSPND,4(SP) ;SET STACK SO RTI WILL GO TO "SUSPEND" BR QTIM45 ;INSTEAD OF RETURNING TO CALLER .PAGE ; ******************************************************************** ; * * ; * PROGRAM IDENTIFICATION: "DQTIME" * ; * TIMER MODULE DE-QUEUEING SUBROUTINE * ; * ;STATUS .BYTE 34. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.35HD: .WORD 1 ;THREAD WORD .WORD T.35BG ;TASK ENTRY .WORD T.35IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.35PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT RETURN DQSK40: ;HERE WHEN END OF THREAD REACHED MOV #TH2BGN,R1 ;SET UP FOR POSSIBLE SEARCH OF THREAD #2 DEC R5 ;LOOP COUNTER BNE DQSK10 ;STILL MUST DO THREAD #2 BR DQSK30 ;SEARCH FAIL: EXIT WITH NON-ZERO ERROR DQSK50: ;HERE WHEN MODULE STILL IN WAIT" TABLE. MUST SET THE ; "D" DE-QUEUE FLAG IN MODULE TO FORCE IGNORE WHEN ; "SKNSRT" RUNS. IF MODULE IS QUEUED AGNPACK" SKDEX2: ;SCHEDULER EXIT WITH NO STACK POP MOV #340,PS ;PROTECT CHECK OF BUSY FLAG MOVB #-1,SKDBSY ;RESET FLAG TO ALLOW NEXT ENTRY JMP RESTOR ;RETURN TO INTERRUPTED PGM ==>[RESTOR] .PAGE UNPACK: ;INTERNAL SUBROUTINE TO SPREAD A SCHEDULER TIME&DATE ;WORD ONTO THE STACK ;UPON ENTRY, ROUTINE ASSUMES PACKED WORD IS ON TOP OF STACK; ; 15 11 10 6 5 1  * ; * PURPOSE: * ; * REMOVES TIMER MODULES FROM TIMER THREADS, IF ACTIVE * ; * AND IF FOUND IN ITS PROPER THREAD. IF ACTIVE BUT NOT * ; * FOUND, ERROR EXIT IS TAKEN. IF STILL IN "WAIT" STACK * ; * IT IS MARKED FOR REMOVAL WHEN "TMNSRT" IS RUN. * ; * IF MODULE IS ALREADY INACTIVE, NO ACTION TAKEN, AND * ; * GOOD EXIT IS TAKEN..BYTE 0 ;STATUS .BYTE 35. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.36HD: .WORD 1 ;THREAD WORD .WORD T.36BG ;TASK ENTRY .WORD T.36IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.36PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGAIN BEFORE ; "SKNSRT" RUNS, THIS "D" FLAG WILL BE CLEREAD, AND MODULE ; WILL BE LEFT IN THE "WAIT" TABLE. BIS #10000,2(R0) ;SET "D" FLAG IN MODULE OPTION BYTE BR DQSK20 ;TAKE GOOD EXIT COUNTR: .WORD 0 ;THIS IS THE ABORT/TIME-SLICE COUNTER!! ABMPLR: .WORD 0 ;CLOCK BASE PERIOD MULTIPLIER CURTHD: .WORD THDTAB ;POINTER TO CURRENT THREAD BEGIN WORD THDTAB: .WORD TH1BGN ;THREAD BE; DAY ^ HOUR ^ MINUTE ;UPON EXIT, STACK HAS THREE WORDS ON IT: ; (SP)= DAY 2(SP)= HOUR 4(SP)= MINUTE MOV (SP),R3 ;COPY T&D WORD MOV R3,R5 ;SAVE IT FOR BELOW BIC #177700,(SP) ;LEAVE MINUTE ALL BY ITSELF ASL R3 ASL R3 SWAB R3 ;GET "HOUR" INTO LOW BYTE BIC #177740,R3 ;CLEAR ALL OTHER STUFF MOV R3,-(SP) ;PUT IT IN ITS OWN PLACE .REF QSKED,DQSKED,TTYOUT,TTYIN,BINASC,ASCBIN .REF MASK,UNMASK,ERRTYP .REF DISCIO,CHKPIO,PFRITE .DEF EMTRAP,EMTABL,MAXEMT .PAGE .ASECT .=30 .WORD EMTRAP,340 ;INIT TRAP LOCATION: RUNS AT LEVEL 7. .CSECT EMTRAP = . ;ENTRY TO EMT SERVICE ROUTINE TST -(SP) ;PUSH STACK TO MAKE ROOM FOR SBRTNE ADDR MOV R0,-(SP) ;SAVE IT MOV 4(SP),R0 UMENT .BYTE 0 ;STATUS .BYTE 36. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.30BG: ;TASK #30 BEGIN MOV #MODUL0,-(SP) MOV TMWRD0,-(SP) EMT QTIME ;QUEUE ONE TIMER MODULE TST (SP)+ MOV #LIST30,-(SP) EMT TTYOUT ;TYPE TASK I.D. EMT EXIT T.31BG: ;TASK #31 GIN TABLE .WORD TH2BGN .WORD TH1BGN TH1BGN: .WORD 0 ;ACTUAL BEGIN OF THREAD #1 TH2BGN: .WORD 0 ;#2 STBPTR: .WORD SWAITB ;SCHEDULER "WAIT" TABLE POINTER SWAITB: .WORD 0 ;TOP OF "WAIT" STACK IS ALWAYS ZERO .=$SWATZ*2+. ;THE SCHEDULER "WAIT" TABLE SKTBND = .-2 ;END OF "WAIT" TABLE DAYTAB: ;THIS IS THE 12-BYTE TABLE OF DAYS-PER-MONTH .BYTE 31.,28.,31.,30.,31.,30.u~(ļhhH].Dhhhh0Dhj(  HH SWAB R5 ASR R5 ASR R5 ASR R5 ;GET [DAY] INTO LOWER BYTE... BIC #177740,R5 ; ...CLEAR GARBAGE... MOV R5,-(SP) ; ...AND PUT IN ITS OWN PLACE RTS PC .PAGE SKNSRT: ;ROUTINE TO INSERT SCHEDULER MODULES FROM THE WAITING ;TABLE. ALSO LOOP RE-ENTRY POINT FROM END MOV #340,PS ;LOCK OUT INTERFERENCE FROM "QSKED" SKNA10: MOV #LIST31,-(SP) EMT TTYOUT MOV #MODUL2,-(SP) MOV TMWRD1,-(SP) EMT QTIME TST (SP)+ MOV #LIST31,-(SP) EMT TTYOUT EMT EXIT T.32BG: ;TASK #32 MOV #MODUL3,-(SP) MOV TMWRD0,-(SP) EMT QTIME TST (SP)+ MOV #MODUL4,-(SP) MOV TMWRD1,-(SP) EMT QTIME TST (SP)+ MOV #MODUL5,.,31.,31.,30.,31.,30.,31. CLOCK: ;EXTERNAL REFERENCE FOR TIME-OF-DAY CLOCK AND CALENDAR TICTOC: .BYTE 0 ;COUNTS CLOCK BEATS PER SECOND SECOND: .BYTE 0 ;CURRENT TIME MINUTE: .BYTE 0 ;CURRENT TIME HOUR: .BYTE 0 ;CURRENT TIME JDATE: .WORD 0 ;CURRENT JULIAN DATE MDAY: .BYTE 0 ;CURRENT DAY OF MONTH MONTH: .BYTE 0 ;CURRENT MONTH YEAR: .BYTE 0 ;CURRENT YEA VO! " 00#XjWj($(,TT X | p<ZTX| p. | ~&  |~(Z0    ;LOOP RETURN WHEN LOCKOUT IS ALREADY SET MOV @STBPTR,R0 ;GET ADDRESS OF NEXT MODULE BEQ SKDEX2 ;TABLE EMPTY: EXIT VIA "RESTOR" ADD #2,STBPTR ;NOT EMPTY: POP POINTER BACK ONE CELL MOV #1,(R0) ;SET INACTIVE IN CASE DE-QUEUED BIT #10000,2(R0) ;WAS IT DE-QUEUED WHILE IN TABLE? BNE SKNA10 ;YES: IGNORE AND CONTINUE MOV R4,PS ;RESTORE PREVIOUS CPU LEVEL -(SP) MOV TMWRD2,-(SP) EMT QTIME TST (SP)+ MOV #LIST32,-(SP) EMT TTYOUT EMT EXIT .PAGE T.33BG: ;TASK #33 MOV T.33HD+14,T.33AR ;TRANSFER ARGUMENT MOV #LIST33,-(SP) EMT TTYOUT EMT EXIT T.34BG: ;TASK #34 MOV T.34HD+14,T.34AR ;TRANSFER ARGUMENT MOV #LIST34,-(SP) EMT TTYOUT EMT EXIT T.35R (MINUS 1900) .BYTE 0 ;PAD .END '*@.    T b p. T b(p3,< ~  0  ~0m#`fTASK #30 ARG= f|+|TASK #31 ARG= 7+TASK #32 ARG= ^+TASK #33 ARG=  MOV 4(R0),-(SP) ;STACK MODULE'S DATE WORD FOR... JSR PC,UNPACK ;...CALL TO SPREAD IT ON STACK TST (SP) ;IF "DATE" = 0,... BNE SKNA20 MOVB MDAY,(SP) ;...THEN USE TODAY'S DATE SKNA20: CMP 2(SP),#37 ;IF "HOUR" IS ALL ONES... BNE SKNA30 MOVB HOUR,2(SP) ;...THEN USE CURRENT HOUR SKNA30: CMP 4(SP),#77 ;IF "MIN" IS ALL ONES... BNE SKNA40 MOVB MINUTE,4BG: ;TASK #35 MOV T.35HD+14,T.35AR ;TRANSFER ARGUMENT MOV #LIST35,-(SP) EMT TTYOUT EMT EXIT T.36BG: MOV #MODUL0,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL1,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL2,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL3,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL * ; * * ; * USAGE: CALLED BY ANY ROUTINE WISHING TO DE-ACTIVATE A TIMER * ; * MODULE. CALLING SEQUENCE: * ; * * ; * MOV #MODULE,-(SP) ;STACK MODULE'S ADDRESS * ; * EMT DQTIME ;REQUEST TO DE-QUEUE MODULE * ; * +TASK #34 ARG= \ + TASK #35 ARG= 0+0>TASK #36 ARG= >T<,T!S"#b  &,x!"!,# , (SP) ;...THEN USE CURRENT MINUTE .PAGE SKNA40: ;NOW THAT MODULE'S TIME IS READY, BEGIN SEARCH FOR ITS ;PLACE IN ONE OF THE TWO SCHEDULER THREADS. MOV CURTHD,R1 ;POINTS TO [THDTAB] OR [THDTAB+2] CMPB (SP),MDAY ;MODULE DATE :: TODAY'S DATE BGT SKNA60 ;AFTER TODAY: USE CURRENT THREAD BLT SKNA50 ;BEFORE TODAY: USE "FUTURE" THREAD CMPB 2(SP),HOUR ;MODULE HOUR :: CURRENT 4,-(SP) EMT DQTIME TST (SP)+ MOV #LIST36,-(SP) EMT TTYOUT EMT EXIT .PAGE LIST30: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.30  OR * ; * JSR PC,DQTIME ;DIRECT CALL WITH PROPER LINK * ; * TST (SP)+ ;POP ERROR RETURN CODE * ; * * ; * NOTE THAT THE THREE ROUTINES: [TIMER], [QTIME], AND * ; * [DQTIME] ALLOW AN UNLIMITED NUMBER OF CALLS TO QUEUE * ; * OR DE-QUEUE THE SAME MODULE, REGARDLESS OF ITS STATUS * ; * AT b &be 12345 HOUR BGT SKNA60 ;LATER TODAY: USE CURRENT THREAD BLT SKNA50 ;WAS EARLIER TODAY: PUT IN "FUTURE" CMPB 4(SP),MINUTE ;MODULE MINUTE :: CURRENT MINUTE BGE SKNA60 ;NOW OR WITHIN HOUR: CURRENT THREAD SKNA50: TST (R1)+ ;WE ARE PAST MODULE'S TIME: USE "FUTURE" SKNA60: ;NOW THAT PROPER THREAD BEGIN WORD'S ADDRESS IS IN R1, ;WE CAN BEGIN SEARCH OF THAT THREAD. MOV (R1),R2 BF ;MSG BUFFER T.30BF: .WORD MSG30X-T.30BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #30 ARG=" T.30AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG30X = .-1 .EVEN .PAGE LIST31: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT ANY GIVEN TIME. THE STATE UPON THE RETURN FROM A * ; * CALL TO [QTIME] OR [DQTIME], ASSUMING A ZERO ERROR CODE* ; * ASSURES THAT THE MODULE IS IN THE MOST RECENTLY * ; * REQUESTED STATE. THE ONLY EXCEPTION IS WHEN A CALL TO * ; * [DQTIME] HAS BEEN MADE AFTER THE REQUESTED MODULE HAS * ; * TIMED OUT AND BEGUN EXECUTION. STRICTLY SPEAKING, THE * ; * CALL IN THIS CASE CAME AFTER THE MODULE WAS RUN. * ; * YEAR * ; * JSR PC,SDATE ;CALL "SET DATE" * ; * * ; * TST (SP)+ ;POP ERROR WORD * ; * TST (SP)+ ;POP ERROR WORD * ; * BNE ERROR ;CALL PARAMETERS IN ERROR * ; * BNE ERROR ;CALL PARAMETERS IN ERROR * ; *  ;ADDR OF ONE OF THE THREAD-BEGIN WORDS BR SKNB00 ;ENTER LOOP FOR FIRST TIME SKNB10: ;THIS IS THE LOOP RETURN POINT AS LONG AS SEARCH CONT'S ADD #6,SP ;POP STACK POINTER FROM "UNPACK" BELOW SKNB00: ;HERE FOR FIRST-TIME ENTRY MOV R2,R1 ;SAVE OLD T/W ADDRESS MOV (R2),R2 ;GET NEXT MODULE'S (T/W) ADDRESS BEQ SKNB30 ;AT END OF THREAD ;NOT @ END: TEST MODUL .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.31BF ;MSG BUFFER T.31BF: .WORD MSG31X-T.31BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #31 ARG=" T.31AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG31X = .-1 .EVEN LIST32: .WORD 1 ;THREAD WORD; ******************************************************************** ; * PROGRAM IDENTIFICATION: "QTIME" * ; * TIMER MODULE QUEUEING SUBROUTINE * ; * * ; * PURPOSE: LOADS TIMER MODULES ONTO "WAIT" STACK FOR "TIMER" * ; * "TMNSRT" IS RESPONSIBLE FOR UNLOADING FROM THE STACK * ; * AND STRINGING ONTO PROPER THREAD  * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .DEF DQTIME .PAGE DQTIME: ;SYSTEM SUBROUTINE TO DE-QUEUE A TIMER MODULE MOV (SP),-(SP) ;MOVE RTN ADDR IN PREP FOR "RTI" AT END MOV PS,2(SP) ;PLACE [PS] ALSE FOR TIME MOV 4(R2),-(SP) ;STACK TEST MODULE'S DATE WORD... JSR PC,UNPACK ;...FOR CALL TO SPREAD IT ON STACK CMP 6(SP),(SP) ;NEW MOD'S DATE :: TEST MOD'S DATE BGT SKNB10 ;LATER: KEEP LOOKING BLT SKNB20 ;EARLIER: THREAD NOW CMP 10(SP),2(SP) ;NEW MOD'S HOUR :: TEST MOD'S HOUR BGT SKNB10 ;STILL LATER BLT SKNB20 ;EARLIER CMP 12(SP),4(SP)  .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.32BF ;MSG BUFFER .PAGE T.32BF: .WORD MSG32X-T.32BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #32 ARG=" T.32AR: .ASCII " " * ; * * ; * USAGE: CALLED BY ANY ROUTINE WISHING TO ACTIVATE A TIMER * ; * MODULE. CALLING SEQUENCE: * ; * MOV #MODULE,-(SP) ;STACK MODULE'S ADDRESS * ; * MOV TIME,-(SP) ;STACK TIMER-RESET WORD * ; * EMT QTIME ;REQUEST TO QUEUE MODULE * ; * OR O FOR "RTI" MOV #340,PS ;RAISE CPU LEVEL: PROTECT AGAINST "TIMER" JSR R5, PUSHR ;SAVE ALL REGISTERS MOV 20(SP),R0 ;GET MODULE'S ADDRESS CMP #1,(R0) ;IS MODULE ALREADY INACTIVE? BEQ DQTM20 ;YES: TAKE GOOD EXIT CMP #-1,(R0) ;IS MODULE STILL IN "WAIT" STACK? BEQ DQTM40 ;YES: GO SET "DE-QUEUE" FLAG MOVB 3(R0),R1 ;IS IN ACTIVE QUEUE: TAKE IT OUT  ;COMPARE MINUTES BGT SKNB10 .PAGE SKNB20: ;HAVE FINALLY FOUND SLOT FOR NEW MODULE. R1 CONTAINS ;ADDR OF PREVIOUS OR "UPSTREAM" MODULE (MIGHT BE THE ;THREAD START WORD) AND R2 CONTAINS ADDR OF DOWNSTREAM ;MODULE, OR ZERO IF NEW MODULE IS BEING PLACED AT END ;OF THREAD. R0 CONTAINS ADDR OF NEW MODULE. ADD #6,SP ;POP SP FROM 1ST CALL TO "UNPACK" SKNB30: ADD #6,SP ;P ;TRANSMITTED ARG .BYTE 15 ;CR MSG32X = .-1 .EVEN LIST33: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.33BF ;MSG BUFFER T.33BF:  * ; * JSR PC,QTIME * ; * TST (SP)+ ;TEST ERROR RETURN CODE * ; * * ; * THE MODULE MUST BE SET UP, PRIOR TO THE CALL, AS DESCRIBED * ; * IN THE ROS USER'S MANUAL. NOTE THAT CALLS FOR MODULES HAVING * ; * THE "S" SUSPEND OPTION SET WILL CAUSE TRANSFER TO THE * ; * DISPATCHER, AND WILL NOT RETURN UNLESS THE BIC #177760,R1 ;GET MODULE'S RESOLUTION ASL R1 ;USED AS WORD INDEX BELOW MOV R1,R3 ;SAVE RESOLUTION IN CASE NEEDED BELOW ADD #TFIRST,R1 ;ADDR OF RESOLUTION'S "FIRST" WORD DQTM10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;SAVE UPSTREAM MODULE'S ADDR MOV (R1),R1 ;ADDR OF DOWNSTREAM MODULE BEQ DQTM30 ;END OF THREAD: SEARCH FAIL ERROR OP SP FROM 2ND CALL TO "UNPACK" MOV R0,(R1) ;LOAD UPSTREAM THREAD-WORD FOR NEW MOD MOV R2,(R0) ;LOAD NEW T/W FOR DOWNSTREAM MOD BR SKNSRT ;GO BACK FOR POSSIBLE MORE MODULES. .PAGE ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "QSKED" * ; * SYSTEM SUBROUTINE TO QUEUE A SCHEDULER MODULE * ; * .WORD MSG33X-T.33BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #33 ARG=" T.33AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG33X = .-1 .EVEN .PAGE LIST34: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE  CALL IS IN ERROR. * ; * ON THESE CALLS THE MODULE'S TASK NUMBER IS AUTOMATICALLY SET * ; * TO THE CURRENTLY ACTIVE TASK'S NUMBER. * ; * IF THE "WAIT" STACK IS FULL, "QTIME" WILL EXIT WITH THE ERROR * ; * CODE WORD ON THE STACK NON-ZERO. THE MODULE WILL NOT BE QUEUED* ; * "QTIME" TAKES ITS ERROR EXIT IF THE REQUESTED MODULE IS ALREADY* ; * IN EITHER A TIMER THREAD OR THE "WAIT" STACK, AND HAS NOT BEEN * ; * FLAGGED FOR DE-QUEUEING. GOOD RET! CMP R0,R1 ;IS THIS THE MODULE TO BE DE-QUEUED? BNE DQTM10 ;NO: KEEP LOOKING MOV (R1),(R2) ;FOUND IT! BRIDGE OVER THIS MODULE... BNE DQTM15 ;...AND EXIT IF NOT LAST MODULE MOV R2,TLAST(R3) ;...BUT UPDATE "LAST" ENTRY IF WAS @ END DQTM15: MOV #1,(R1) ;FINALLY, FLAG MODULE INACTIVE DQTM20: CLR 20(SP) ;CLEAR RETURN ERROR FLAG FOR GOOD EXIT DQTM30: JSR R5,POPR ;RESTORE SAVED " * ; * PURPOSE: * ; * PUTS ADDRESS OF CALLER'S MODULE IN INTERNAL STACK. * ; * THIS TABLE IS EMPTIED BY THE ROUTINE "SKNSRT" WHICH IS * ; * CALLED BY THE SCHEDULER EACH MINUTE JUST BEFORE IT RUNS* ; * THIS METHOD AVOIDS QUEUEING AND SCHEDULER CONFLICTS WHE* ; * ACCESSING THE TWO SCHEDULER THREADS(THE SCHEDULER DROPS* ; * THE CP# .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.34BF ;MSG BUFFER T.34BF: .WORD MSG34X-T.34BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #34 ARG=" T.34AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG34X = .-1 .EVEN .PAGE LIST35: .WORD 1 ;THREAD WORD .BYTE 0 $URNS ARE MADE WHEN THE MODULE* ; * IS FOUND INACTIVE OR MARKED FOR DE-QUEUEING IN THE "WAIT" STACK* ; * IN THIS LAST CASE, THE MARK FOR DE-QUEUEING WILL BE REMOVED, * ; * AND THE MODULE WILL REMAIN WHERE IT IS ON THE "WAIT" STACK. * ; * * ; * PROGRAMMER: 52 * ; * VERSION: 002.008 * ; * DATE: 23-NOV-71 %REGISTERS... RTI ;...AND RETURN TO CALLER WITH HIS PS DQTM40: ;HERE IF MODULE IS STILL IN "WAIT" STACK MOVB #-1,5(R0) ;SET "RESET" BYTE TO ALL ONES TO SHOW ;"TMNSRT" TO IGNORE THIS MODULE BR DQTM20 ;GO TAKE GOOD EXIT .PAGE ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "TIMER" * ; * &U LEVEL SO AS NOT TO LOCK OUT INTERRUPTS UNNECES-* ; * SARILY), REDUCING THE CONFLICT AREA TO JUST THE FIFO * ; * TABLE. THIS CONFLICT IS AVOIDED, THEN, BY RUNNING * ; * "QSKED" (A SHORT ROUTINE) AND THE FEW WORDS OF CODE * ; * IN "SKNSRT" WHICH ACCESS THE TABLE, UNDER INTERRUPT- * ; * LOCKOUT. * ; * * ; * USAGE:' ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.35BF ;MSG BUFFER T.35BF: .WORD MSG35X-T.35BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #35 ARG=" T.35AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15( * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .TITLE TIMER .DEF QTIME .DEF TIMER .DEF TWAITB,TTBPTR,TFIRST,TLAST,RESTAB,CURTAB,TIMBSY,BASCNT .REF UNSPND,QUEUE ) HIGH-RESOLUTION CLOCK PULSE SERVICE ROUTINE * ; * * ; * PURPOSE: --SERVICES ALL TIMER MODULES AT THEIR RESPECTIVE * ; * RESOLUTIONS, PROVIDING THE FEATURES OF TASK * ; * TIME-DELAY, PERIODIC OR ONE-SHOT QUEUEING, * ; * FLAG-SETTING,AND COMPLETION-ROUTINE CALLS. * ; * --KEEPS TRACK OF THE TASK-EXECUTION TIME (ABORT) * ; * * ; * USERS CAN CALL "QSKED" EITHER VIA JSR (IF LINKED) OR * ; * VIA EMT. IN EITHER CASE THE ADDRESS OF THE MODULE TO BE* ; * THREADED MUST FIRST BE PLACED ON THE STACK.THE STACK * ; * POINTER IS LEFT UNCHANGED ON RETURN. THE STACK LOCATION* ; * ITSELF WILL BE CLEARED IF THE TABLE HAS ROOM FOR * ; * IT AND THE MODULE ITSELF IS INACTIVE (ITS THREAD WORD * ; * + ;CR MSG35X = .-1 .EVEN LIST36: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.36BF ;MSG BUFFER T.36BF: .WORD MSG36X-T.36BF-4 ;BUFFER LENGTH , .REF $CTASK,$PRIOR,SUSPND .REF PUSHR,POPR,RESTOR .PAGE QTIME: ;ROUTINE TO PUT TIMER MODULE IN "WAIT" STACK MOV PS,-(SP) ;SAVE USER'S PS MOV #340,PS ;RAISE CPU LEVEL TO PROTECT ROUTINE MOV R0,-(SP) ;SAVE USER'S CMP TTBPTR,#TMTBND ;SEE IF STACK IS FULL BHI QTIM50 ;YES: ERROR EXIT MOV 10(SP),R0 ;ADDRESS OF MODULE DEC (R0) - * COUNTER, AND CALLS FOR TASK ABORT IF TIME * ; * RUNS OUT. * ; * --PROVIDES (OPTIONAL) TIME-SLICE FEATURE BY * ; * PERIODICALLY ROTATING THE TASKS IN A QUEUE. * ; * * ; * USAGE: ACTIVATED BY CLOCK INTERRUPT. ALL PROGRAMS HANDLE * ; * COMMUNICATION VIA "QTIME" AND "DQTIME". "TIMER" . MUST BE =1). IN CASE OF ONE OF THE ABOVE ERRORS, THE * ; * STACK LOCATION IS LEFT UNCHANGED (NON-ZERO) FOR TESTING* ; * BY THE CALLER. * ; * "QSKED" SAVES & RESTORES ALL REGISTERS THAT IT USES. * ; * IT MAY BE CALLED BY ANY TYPE OF USER AT ANY TIME. * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S */.WORD 0 ;SYSTEM RESERVED .ASCII "TASK #36 ARG=" T.36AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG36X = .-1 .EVEN .PAGE MODUL0: .WORD 1 ;THREAD WORD .BYTE 33. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG1 ;ARG .WORD FLAG1 ;FLAG ADDR .WORD MASK1 0 ;IS TIMER MODULE INACTIVE? (T/W=0?) BNE QTIM30 ;NO: SEE IF ACTIVE OR IN "WAIT" STATE QTIM20: ;HERE WHEN CLEARED TO STACK UP MODULE ADD #2,TTBPTR ;PUSH "WAIT" STACK POINTER MOV R0,@TTBPTR ;ENTER MODULE ADDRESS INTO "WAIT" STACK BIS #C1CBIT,C1COMD ;START UP CLOCK IF IT WAS OFF TST 2(R0) ;CHECK OPTION FLAG FOR "SUSPEND" BMI QTIM60 ;"SUSPEND" SELECTED QTIM40: 1 * ; * CALLS SYSTEM SUBROUTINES "QUEUE", "SAVE", "UNSPND", * ; * AND "ABORT". * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** ; FOLLOWING ARE OFFSET PARAMETERS FOR TIMER MODUL2 ; ******************************************************************** .PAGE QSKED: ;SUBROUTINE TO QUEUE A SCHEDULER MODULE ;TO WAIT FOR INSERTION INTO ONE OF THE ;TWO SCHEDULER THREADS MOV (SP),-(SP) ;MOVE RETURN ADDRESS UP FOR RTI LATER MOV PS,2(SP) ;...AND SET UP PS FOR RTI, TOO MOV R0,-(SP) ;SAVE USER'S MOV #340,PS ;R3 ;FLAG MASK .WORD JSRTNE ;JSR TARGET MODUL1: .WORD 1 ;THREAD WORD .BYTE 34. ;TASK # .BYTE 43 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG2 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL2: .WORD 1 ;THREAD WORD .BYTE 2 4 ;THIS IS THE "SUCCESSFUL" EXIT CLR 10(SP) ;PREPARE ERROR RETURN CODE TO SHOW O.K. QTIM45: ;HERE WHEN EXITING TO "SUSPEND". AVOID CLEARING 10(SP) MOV 6(SP),4(R0) ;LOAD NEW TIMER/RESET WORD INTO MODULE ; THIS SERVES AS NORMAL INIT FOR TIMER MODULE, AND ALSO RESETS ; THE "RESET" BYTE IN CASE MODULE IS BEING RE-QUEUED AFTER BEING ; DE-QUEUED, ALL WHILE REMAINING IN "WAIT" STACK. QTIM50: ;HERE WHEN EXIT IS 5E REFERENCES SAVE = 3 ;OP-CODE FOR TRAP TO "SAVE" SUBROUTINE TASKNO = 2 ;TASK NUMBER BYTE OPTION = 3 ;OPTION FLAGS BYTE TIMBYT = 4 ;MODULE TIMER BYTE RESET = 5 ;TIMER RESET BYTE TIMARG = 6 ;ARGUMENT (FOR QUEUEING) ADDRESS WORD TMFLAG = 6 ;FLAG ADDRESS WORD (DYNAMIC OFFSET) TIMASK = 8. ;FLAG MASK WORD (DYNAMIC OFFSET) JSTARG 6AISE CPU LEVEL TO AVOID INTERFERENCE CMP STBPTR,#SKTBND ;IS TABLE FULL? BLOS QSKA40 ;YES: POINTER IS AT BOTTOM, SO ERROR XIT MOV 6(SP),R0 ;MODULE'S ADDRESS BIC #10000,2(R0) ;CLEAR "D" FLAG IN CASE WAS DE-QUEUED DEC (R0) ;IS MODULE INACTIVE (THREAD WORD = 1)? BEQ QSKA20 ;O.K. ADD #2,(R0) ;SEE IF IN "WAIT" TABLE BEQ QSKA30 ;YES: O.K. TO TAKE GOO7 ;TASK # .BYTE 243 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG1 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL3: .WORD 1 ;THREAD WORD .BYTE 33. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG2 ;ARG 8TO LEAVE NON-ZERO ERROR CODE ON STACK DEC (R0) ;SET T/W=-1 TO SHOW IN "WAIT" STATE... ;...OR TO RESTORE MODULE'S T/W IF IT IS FOUND ALREADY ACTIVE... ; ...OR ALREADY IN "WAIT" STATE MOV (SP)+,R0 ;RESTORE USER'S MOV (SP)+,2(SP) ;MOVE OLD [PS] IN PREP FOR RTI RTI ;ZAP! RETURN TO USER OR GO TO SUSPEND ;ON OLD CPU LEVEL QTIM30: ADD #2,(R0) ;NOT INACTIVE. SEE I9 = 6 ;USER ROUTINE ADDRESS WORD (DYN OFFSET) .PAGE TIMA00: RTI ;RETURN USED IF CLOCK IS RE-ENTERED ;TO PROCESS QUEUE WHILE PREVIOUS REQUEST IN PROGRESS. TIMA70: ;HERE TO RESET RESOLUTION COUNTERS ;WHEN THEY EXPIRE (FROM TIMA20) MOVB RESTAB(R0),CURTAB(R0) ;RESET FROM PERM TABLE INC R0 ;BUMP TO NEXT RESOLUTION... TSTB RESTAB(R0:D EXIT NOW BR QSKA35 ;IN THREAD: TAKE ERROR EXIT QSKA20: ;MODULE READY FOR INSERTION IN TABLE SUB #2,STBPTR ;PUSH TABLE POINTER MOV R0,@STBPTR ;LOAD NEW MODULE INTO TABLE QSKA30: CLR 6(SP) ;NOW READY TO EXIT. CLEAR ERROR FLAG QSKA35: DEC (R0) ;EITHER SETS T/W = -1 TO SHOW IN "WAIT" ;...OR RESTORES T/W TO ORIGINAL, IF NOT THREADED QSKA40: MOV (SP)+,R0 ;RESTORE; .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL4: .WORD 1 ;THREAD WORD .BYTE 34. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG3 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET .PAGE MODU<F ACTIVE OR "WAIT" BNE QTIM50 ;ACTIVE: TAKE ERROR EXIT CMPB 5(R0),#-1 ;IN "WAIT": IS IT FLAGGED FOR DE-QUEUE? BNE QTIM50 ;NO: ERROR EXIT BR QTIM40 ;YES: LEAVE THERE AND REMOVE D-Q FLAG .PAGE QTIM60: ;HERE WHEN TASK IS TO BE SUSPENDED UNTIL TIMER EXPIRES MOVB $CTASK,2(R0) ;LOAD MODULE TASK # WITH CURRENT TASK MOV 4(SP),10(SP) ;SET CALLER RTN TO LOOK LIKE "JSR" =) ;...AND SEE IF THIS IS THE END BNE TIMA20 ;NOT YET: MORE BR TIMA30 ;END OF COUNTERS: DO ALL THREADS TIMER: ;ENTRY FROM INTERRUPT: CPU LEVEL 7 .IFNZ $TMBAS ;OPTION ALLOWS RESOLUTION FINER THAN RES1 DECB BASCNT ;COUNT DOWN BASIC MULTIPLIER BEQ TIMA10 ;TURNED OVER: ENTER TIMER PROGRAM RTI ;NO NEED TO ENTER TIMA10: ;HERE WHE> USER'S RTI ;RESTORE USER'S PS & RETURN .PAGE DQSKED: ;SYSTEM SUBROUTINE TO DE-QUEUE A SCHEDULER MODULE MOV (SP),-(SP) ;RE-ORDER STACK FOR "RTI" RETURN AT END MOV PS,2(SP) ;STACK NOW READY FOR "RTI" JSR R5,PUSHR ;PUSH ALL REGS ONTO STACK MOV 20(SP),R0 ;MODULE'S ADDRESS MOV #340,PS ;LOCK OUT INTERFERENCE FROM SCHEDULER CMP #1,(R0) ;HAS?L5: .WORD 1 ;THREAD WORD .BYTE 35. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG4 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL6: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD @ MOV #SUSPND,4(SP) ;SET STACK SO RTI WILL GO TO "SUSPEND" BR QTIM45 ;INSTEAD OF RETURNING TO CALLER .PAGE ; ******************************************************************** ; * * ; * PROGRAM IDENTIFICATION: "DQTIME" * ; * TIMER MODULE DE-QUEUEING SUBROUTINE * ; * AN BASIC RES'N TURNS OVER MOVB #$TMBAS,BASCNT ;RESET BASE PERIOD MULTIPLIER .ENDC $TMBAS INCB TIMBSY ;CHECK FOR PREVIOUS CALL STILL ACTIVE BNE TIMA00 ;YES: LEAVE INDICATOR SET TO SHOW ;PENDING REQUEST TO RUN; AND RETURN. SAVE ;NOT ACTIVE, SO SAFE TO ENTER. CALL TO ;SAVE ENVIRONMENT AND RETURN WITH: ;(R4) = (PS) B MODULE BEEN DE-QUEUED ALREADY? BEQ DQSK20 ;YES: INACTIVE,SO IGNORE CMP #-1,(R0) ;IS IT STILL IN "WAIT" TABLE? BEQ DQSK50 ;YES: GO SET THE "D" FLAG MOV #2,R5 ;INIT COUNTER TO SEARCH BOTH THREADS MOV #TH1BGN,R1 ;START BY SEARCHING THREAD #1 DQSK10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;COPY ADDRESS OF UPSTREAM MODULE MOV (R1),R1 ;GET DOWC 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL7: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAD * ; * PURPOSE: * ; * REMOVES TIMER MODULES FROM TIMER THREADS, IF ACTIVE * ; * AND IF FOUND IN ITS PROPER THREAD. IF ACTIVE BUT NOT * ; * FOUND, ERROR EXIT IS TAKEN. IF STILL IN "WAIT" STACK * ; * IT IS MARKED FOR REMOVAL WHEN "TMNSRT" IS RUN. * ; * IF MODULE IS ALREADY INACTIVE, NO ACTION TAKEN, AND * ; * GOOD EXIT IS TAKEN.EBEFORE CLOCK INTERRUPT ;(R5) = ADDRESS OF "RESTOR" ROUTINE .PAGE TMNSRT: ;TIMER INSERT ROUTINE: TRANSFERS TIMER MODULE ADDRESS ; FROM WAIT STACK TO APPROPRIATE QUEUE WHEN CONVENIENT FOR TIMER. ; CPU LEVEL SEVEN: AVOID INTERFERENCE WITH "QTIME". MOV @TTBPTR,R0 ;ADDRESS OF TIMER MODULE FROM TOP OF ;"WAIT" STACK BEQ TIMA15 ;STACK EMPTY SUB #2,TTBPTR FNSTREAM MODULE'S ADDRESS BEQ DQSK40 ;END OF THREAD CMP R0,R1 ;IS THIS THE MODULE WE ARE LOOKING FOR? BNE DQSK10 ;NO MOV (R1),(R2) ;YES: "BRIDGE" OVER THIS MODULE IN THREAD MOV #1,(R1) ;...AND SET T/W = 1 TO SHOW INACTIVE DQSK20: ;HERE UPON SUCCESSFUL DE-QUEUE CLR 20(SP) ;ERROR RETURN STATUS: O.K. DQSK30: ;HERE FOR GENERAL EXIT FROM ROUTINE JSR GG MASK .WORD 0 ;JSR TARGET MODUL8: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL9: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK H * ; * * ; * USAGE: CALLED BY ANY ROUTINE WISHING TO DE-ACTIVATE A TIMER * ; * MODULE. CALLING SEQUENCE: * ; * * ; * MOV #MODULE,-(SP) ;STACK MODULE'S ADDRESS * ; * EMT DQTIME ;REQUEST TO DE-QUEUE MODULE * ; * I ;NOT EMPTY: POP STACK ONE CELL MOV #1,(R0) ;SET T/W INACTIVE IN CASE WAS DE-QUEUED CMPB 5(R0),#-1 ;IS "RESET" ALL ONES? BEQ TMNSRT ;YES: MODULE WAS "DE-QUEUED": IGNORE IT MOVB 3(R0),R1 ;GET OPTION BYTE BIC #177760,R1 ;ISOLATE RESOLUTION CMP R1,#$NRES-1 ;IS RESOLUTION IN RANGE? BGT TMNSRT ;NO: TOO LARGE ASL R1 ;USED AS WORD INDEX BELOW JR5,POPR ;POP REGS FROM STACK RTI ;RETURN SET ABOVE: RESTORE ORIGINAL CPU STATUS & RETURN DQSK40: ;HERE WHEN END OF THREAD REACHED MOV #TH2BGN,R1 ;SET UP FOR POSSIBLE SEARCH OF THREAD #2 DEC R5 ;LOOP COUNTER BNE DQSK10 ;STILL MUST DO THREAD #2 BR DQSK30 ;SEARCH FAIL: EXIT WITH NON-ZERO ERROR DQSK50: ;HERE WHEN MODULE STILL IN WAIT" TABLE. MUST SET THE ; "DK# .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET .PAGE MASK1 = 123 MASK2 = 234 MASK3 = 345 JSRTNE: MOV #MODUL1,-(SP) MOV TMWRD0,-(SP) EMT QTIME TST (SP)+ RTS PC ARG1: '1 ARG2: '2 ARG3L OR * ; * JSR PC,DQTIME ;DIRECT CALL WITH PROPER LINK * ; * TST (SP)+ ;POP ERROR RETURN CODE * ; * * ; * NOTE THAT THE THREE ROUTINES: [TIMER], [QTIME], AND * ; * [DQTIME] ALLOW AN UNLIMITED NUMBER OF CALLS TO QUEUE * ; * OR DE-QUEUE THE SAME MODULE, REGARDLESS OF ITS STATUS * ; * AT M MOV R0,@TLAST(R1) ;PUT NEW MODULE'S ADDR @ END PROPER THD> MOV R0,TLAST(R1) ;...AND UPDATE THE "LAST" POINTER ITSELF CLR (R0) ;CLEAR MODULE'S T/W: END OF THREAD BR TMNSRT ;NOW GO BACK AND POP ANY MORE MODULES .PAGE TIMA15: ;RE-ENTER HERE FOR REPEATS (TIMBSY>/=1) MOV R4,PS ;RESTORE PROCESSOR LEVEL TO PREVIOUS CLR R0 ;INIT RESOLUTION INDEX TIMA2N" DE-QUEUE FLAG IN MODULE TO FORCE IGNORE WHEN ; "SKNSRT" RUNS. IF MODULE IS QUEUED AGAIN BEFORE ; "SKNSRT" RUNS, THIS "D" FLAG WILL BE CLEREAD, AND MODULE ; WILL BE LEFT IN THE "WAIT" TABLE. BIS #10000,2(R0) ;SET "D" FLAG IN MODULE OPTION BYTE BR DQSK20 ;TAKE GOOD EXIT COUNTR: .WORD 0 ;THIS IS THE ABORT/TIME-SLICE COUNTER!! ABMPLR .WORD 0 ;MULTIPLIER FOR ABORT AND TIME/SLICE CU: '3 ARG4: '4 ARG5: '5 FLAG1: .BYTE 0 FLAG2: .BYTE 0 FLAG3: .BYTE 0 .EVEN .END PANY GIVEN TIME. THE STATE UPON THE RETURN FROM A * ; * CALL TO [QTIME] OR [DQTIME], ASSUMING A ZERO ERROR CODE* ; * ASSURES THAT THE MODULE IS IN THE MOST RECENTLY * ; * REQUESTED STATE. THE ONLY EXCEPTION IS WHEN A CALL TO * ; * [DQTIME] HAS BEEN MADE AFTER THE REQUESTED MODULE HAS * ; * TIMED OUT AND BEGUN EXECUTION. STRICTLY SPEAKING, THE * ; * CALL IN THIS CASE CAME AFTER THE MODULE WAS RUN. * ; * Q0: ;RETURN HERE WHEN ADVANCING TO NEXT RESN DECB CURTAB(R0) ;COUNT DOWN A RESOLUTION COUNTER BEQ TIMA70 ;EXPIRED: GO RESET IT & BUMP RES'N INDEX TIMA30: ;FALL THROUGH HERE WHEN A RESOLUTION COUNTER IS FOUND ; THAT HAS NOT EXPIRED. SINCE THE RESOLUTIONS ARE COUNTED STARTING ; FROM THE FINEST TOWARDS THE COARSEST, THE RESOLUTION CURRENTLY IN R0 ; IS THE FINEST RESOLUTION THAT HAS NOT EXPIRED. BY DECREMENTING R0, ; THE COARRRTHD: .WORD THDTAB ;POINTER TO CURRENT THREAD BEGIN WORD THDTAB: .WORD TH1BGN ;THREAD BEGIN TABLE .WORD TH2BGN .WORD TH1BGN TH1BGN: .WORD 0 ;ACTUAL BEGIN OF THREAD #1 TH2BGN: .WORD 0 ;#2 STBPTR: .WORD SWAITB ;SCHEDULER "WAIT" TABLE POINTER SWAITB: .WORD 0 ;TOP OF "WAIT" STACK IS ALWAYS ZERO .=$SWATZ*2+. ;THE SCHEDULER "WAIT" TABLE SKTBND = .-2 ;END OF T * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .DEF DQTIME .PAGE DQTIME: ;SYSTEM SUBROUTINE TO DE-QUEUE A TIMER MODULE MOV (SP),-(SP) ;MOVE RTN ADDR IN PREP FOR "RTI" AT END MOV PS,2(SP) ;PLACE [PS] ALSUSEST RESOLUTION TO EXPIRE IS FOUND. FALLS THROUGH HERE ALSO ; IF ALL RESOLUTIONS EXPIRE, WHICH WILL HAPPEN FROM TIME TO TIME. ASL R0 ;RESOLUTION*2: USE AS WORD INDEX TIMA35: ;LOOP BACK HERE FOR SUCCESSIVE RESOLUTIONS DEC R0 DEC R0 ;COUNT DOWN RESOLUTION INDEX (TWICE, ; SINCE IT WAS MADE INTO A WORD INDEX ABOVE). ON THE FIRST PASS AFTER ; FINDING THE FIRST RES'N NOT TO EXPIRE, THIS BRINGS COUNTER BACK TO ; (DOUBLE)V"WAIT" TABLE DAYTAB = .-1 ;THIS IS THE 12-BYTE TABLE OF DAYS-PER-MONTH JANARY = . FEBARY = .+1 .BYTE 31.,28.,31.,30.,31.,30.,31.,31.,30.,31.,30.,31. CLOCK: ;EXTERNAL REFERENCE FOR TIME-OF-DAY CLOCK AND CALENDAR TICTOC: .BYTE 0 ;COUNTS CLOCK BEATS PER SECOND SECOND: .BYTE 0 ;CURRENT TIME MINUTE: .BYTE 0 ;CURRENT TIME HOUR: .BYTE 0 ;CURRENT TIME JDATE: .WORD 0 ;CURRENT JULXO FOR "RTI" MOV #340,PS ;RAISE CPU LEVEL: PROTECT AGAINST "TIMER" JSR R5, PUSHR ;SAVE ALL REGISTERS MOV 20(SP),R0 ;GET MODULE'S ADDRESS CMP #1,(R0) ;IS MODULE ALREADY INACTIVE? BEQ DQTM20 ;YES: TAKE GOOD EXIT CMP #-1,(R0) ;IS MODULE STILL IN "WAIT" STACK? BEQ DQTM40 ;YES: GO SET "DE-QUEUE" FLAG MOVB 3(R0),R1 ;IS IN ACTIVE QUEUE: TAKE IT OUT Y THE COARSEST RES'N TO EXPIRE. ON SUCCESSIVE PASSES THIS ; MOVES TO NEXT FINER RES'N FOR SERVICING. BLT TIMEXT ;EXIT HERE WHEN ALL RESOLUTIONS HAVE ; BEEN SERVICED, OR IF NO LEVELS ACTUALLY EXPIRED. .PAGE TIMB10: ;NOW WE BEGIN TRAVELING THE THREADS ;ALSO LOOP RE-ENTRY POINT FOR EACH RESOLUTION MOV #TFIRST,R1 ;CALC ADDRESS IN THE QUEUE POINTER TABLE ADD R0,R1 ;...OF POINTER FOR CURRIAN DATE MONTH: .BYTE 0 ;CURRENT MONTH MDAY: .BYTE 0 ;CURRENT DAY OF MONTH YEAR: .BYTE 0 ;CURRENT YEAR (MINUS 1900) SKDBSY: .BYTE -1 ;SCHEDULER BUSY FLAG: IDLE=-1; .END \ BIC #177760,R1 ;GET MODULE'S RESOLUTION ASL R1 ;USED AS WORD INDEX BELOW MOV R1,R3 ;SAVE RESOLUTION IN CASE NEEDED BELOW ADD #TFIRST,R1 ;ADDR OF RESOLUTION'S "FIRST" WORD DQTM10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;SAVE UPSTREAM MODULE'S ADDR MOV (R1),R1 ;ADDR OF DOWNSTREAM MODULE BEQ DQTM30 ;END OF THREAD: SEARCH FAIL ERROR ]ENT RESOLUTION TIMB15: ;LOOP HERE FOR EACH SUCCESSIVE MODULE MOV #340,PS ;AVOID INTERFERENCE WITH "DQTIME" TIMB16: ;LOOP RE-ENTRY POINT MOV R1,R2 ;REMEMBER UPSTREAM MODULE ADDRESS... ;...FOR USE IN DE-QUEUEING "ONE-SHOTS" MOV (R1),R1 ;NEXT MODULE'S THREAD WORD ADDRESS BEQ TIMA35 ;END OF THREAD: GO DOWN TO NEXT RES'N DECB T^B~Hp~pQ~8q~q` CMP R0,R1 ;IS THIS THE MODULE TO BE DE-QUEUED? BNE DQTM10 ;NO: KEEP LOOKING MOV (R1),(R2) ;FOUND IT! BRIDGE OVER THIS MODULE... BNE DQTM15 ;...AND EXIT IF NOT LAST MODULE MOV R2,TLAST(R3) ;...BUT UPDATE "LAST" ENTRY IF WAS @ END DQTM15: MOV #1,(R1) ;FINALLY, FLAG MODULE INACTIVE DQTM20: CLR 20(SP) ;CLEAR RETURN ERROR FLAG FOR GOOD EXIT DQTM30: JSR R5,POPR ;RESTORE SAVED aIMBYT(R1) ;COUNT DOWN MODULE'S TIMER BNE TIMB16 ;NOT EXPIRED: GET NEXT MODULE ;TIMER EXPIRED! IT IS MODULE'S TIME. ; SINCE COMPLETION ROUTINES RUN UNDER THE "J" OPTION ASSUME R1 POINTS TO ; THE CURRENT MODULE (IT'S THREAD WORD), R1 MUST BE PRESERVED AS SUCH ; UNTIL THE POSSIBLE ROUTINE IS RUN. BUT TWO OTHER POINTERS ARE NEEDED: ; R3 MOVES DOWN THE MODULE TO COMPENSATE FOR OPTIONAL PARAMTERS WHICH ; MAKE THE LIST LONGER, AND R5 IS RESET Tb`~(r~ro~sdREGISTERS... RTI ;...AND RETURN TO CALLER WITH HIS PS DQTM40: ;HERE IF MODULE IS STILL IN "WAIT" STACK MOVB #-1,5(R0) ;SET "RESET" BYTE TO ALL ONES TO SHOW ;"TMNSRT" TO IGNORE THIS MODULE BR DQTM20 ;GO TAKE GOOD EXIT .PAGE ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "TIMER" * ; * eO POINT TO THE UPSTREAM MODULE ; IN CASE THE CURRENT MODULE IS A "ONE-SHOT" AND IS REMOVED FROM THE ; THREAD. R1 IS LOADED FROM R5 AT THE END OF THE LOOP TO ALLOW THIS. MOV R1,R3 ;INIT R3 AS DYNAMIC LIST POINTER MOV R1,R5 ;INIT R5 IN PREP FOR R1 RESET BELOW MOVB RESET(R1),TIMBYT(R1) ;RESET TIMER BYTE BNE TIMB20 ;MODULE IS A REPEATER: LEAVE IN THREAD MOV (R1),(R2) ;"ONE-SHOT": REMOVE FROM THREAD .f~s~~t~t~th HIGH-RESOLUTION CLOCK PULSE SERVICE ROUTINE * ; * * ; * PURPOSE: --SERVICES ALL TIMER MODULES AT THEIR RESPECTIVE * ; * RESOLUTIONS, PROVIDING THE FEATURES OF TASK * ; * TIME-DELAY, PERIODIC OR ONE-SHOT QUEUEING, * ; * FLAG-SETTING,AND COMPLETION-ROUTINE CALLS. * ; * --KEEPS TRACK OF THE TASK-EXECUTION TIME (ABORT) * ; i.. BNE TIMB22 ;...BY "BRIDGING". BRANCH IF NOT LAST MOV R2,TLAST(R0) ;BUT UPDATE "LAST" POINTER IF WAS END TIMB22: MOV #1,(R1) ;SET THREAD WORD INACTIVE IN EITHER CASE MOV R2,R5 ;BACK POINTER TO UPSTREAM MODULE TIMB20: MOV R4,PS ;UNLOCK INTERRUPTS: SAFE NOW MOVB OPTION(R3),R2 ;GET OPTION BYTE FOR THIS MODULE TSTB TASKNO(R3) ;IS MODULE TASK-RELATED? BEQ TIMB54 ;NOj~pu~u$~`v~vl * COUNTER, AND CALLS FOR TASK ABORT IF TIME * ; * RUNS OUT. * ; * --PROVIDES (OPTIONAL) TIME-SLICE FEATURE BY * ; * PERIODICALLY ROTATING THE TASKS IN A QUEUE. * ; * * ; * USAGE: ACTIVATED BY CLOCK INTERRUPT. ALL PROGRAMS HANDLE * ; * COMMUNICATION VIA "QTIME" AND "DQTIME". "TIMER" m: CHECK FOR OTHER OPTIONS ;YES: SET UP STACK FOR CALL TO EITHER ;[SUSPEND] OR [QUEUE] MOVB TASKNO(R3),-(SP);PUSH TASK # FIRST CLR -(SP) ;IMMEDIATE RETURN REQUEST FOR BOTH, OR ;INIT OF PRIORITY IF NEEDED FOR [QUEUE]. TSTB R2 ;IS "SUSPEND" OPTION SELECTED? BPL TIMB30 ;NO: GO DO QUEUEING JSR PC,UNSPND ;CALL Tn3~Pw~wB~@x~xp * ; * CALLS SYSTEM SUBROUTINES "QUEUE", "SAVE", "UNSPND", * ; * AND "ABORT". * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** ; FOLLOWING ARE OFFSET PARAMETERS FOR TIMER MODULqO "UN-SUSPEND" BR TIMB50 ;GO POP ERROR WORD & CHECK FLAG OPTION TIMB30: ;HERE TO QUEUE A TASK. TASK # AND RETURN CODE ;(OR INITED PRIORITY) ALREADY PUSHED ONTO STACK. .IFNZ DPRTY ;DYNAMIC PRIORITIES OPTION CLR -(SP) ;USE SYSTEM-ASSIGNED PRIORITY ; (ACTUALLY LEAVES ZERO AS PRIORITY AND PUSHES NEW RETURN CODE OF ZERO, ; POSSIBLY INITING STACK SPACE FOR PASSED ARGUMENT, IF OPTION IS ON.) .ENDC DPRTY rQ~0y~y`~ z~ztE REFERENCES SAVE = 3 ;OP-CODE FOR TRAP TO "SAVE" SUBROUTINE TASKNO = 2 ;TASK NUMBER BYTE OPTION = 3 ;OPTION FLAGS BYTE TIMBYT = 4 ;MODULE TIMER BYTE RESET = 5 ;TIMER RESET BYTE TIMARG = 6 ;ARGUMENT (FOR QUEUEING) ADDRESS WORD TMFLAG = 6 ;FLAG ADDRESS WORD (DYNAMIC OFFSET) TIMASK = 8. ;FLAG MASK WORD (DYNAMIC OFFSET) JSTARG u .IFNZ ARG ;SYSTEM OPTION TO PASS ARGUMENT ON QUEUE BIT #100,R2 ;DOES MODULE HAVE AN ARGUMENT TO PASS? BEQ TIMB40 ;NO MOV @TIMARG(R3),(SP);YES: REPLACE THE ZERO WITH ACTUAL ARG TIMB40: CLR -(SP) ;MUST PUSH RETURN CODE SINCE ARGUMENT .ENDC ARG ;USED UP LAST ONE. JSR PC,QUEUE ;CALL QUEUE TIMB50: ;HERE AFTER [QUEUE] OR [UNSPND] TST (SP)+ vo~{~{~~|x = 6 ;USER ROUTINE ADDRESS WORD (DYN OFFSET) .PAGE TIMA00: RTI ;RETURN USED IF CLOCK IS RE-ENTERED ;TO PROCESS QUEUE WHILE PREVIOUS REQUEST IN PROGRESS. TIMA70: ;HERE TO RESET RESOLUTION COUNTERS ;WHEN THEY EXPIRE (FROM TIMA20) MOVB RESTAB(R0),CURTAB(R0) ;RESET FROM PERM TABLE INC R0 ;BUMP TO NEXT RESOLUTION... TSTB RESTAB(R0y ;POP ERROR RETURN CODE TIMB54: ;HERE WHEN NOT TASK-RELATED ASLB R2 ;MOVE "ARG" OPTION INTO SIGN BIT BPL TIMB56 ;"A" NOT SET TST (R3)+ ;PASS POINTER OVER ARG, WHETHER USED OR NOT TIMB56: ASLB R2 ;GET "FLAG" OPTION BIT INTO SIGN BPL TIMB60 ;NO FLAG OPTION BISB TIMASK(R3),@TMFLAG(R3) ;"IOR" MASK INTO FLAG LOCATION CMP (R3)+,(R3)+ ;BUMP SECONDARY MODULz~x|~|~h}~}|) ;...AND SEE IF THIS IS THE END BNE TIMA20 ;NOT YET: MORE BR TIMA30 ;END OF COUNTERS: DO ALL THREADS TIMER: ;ENTRY FROM INTERRUPT: CPU LEVEL 7 .IFNZ $TMBAS ;OPTION ALLOWS RESOLUTION FINER THAN RES1 DECB BASCNT ;COUNT DOWN BASIC MULTIPLIER BEQ TIMA10 ;TURNED OVER: ENTER TIMER PROGRAM RTI ;NO NEED TO ENTER TIMA10: ;HERE WHE}E POINTER FOR FLAGS TIMB60: ASLB R2 ;GET "J" OPTION BIT INTO SIGN BPL TIMB70 ;NOT SELECTED JSR PC,@JSTARG(R3) ;LINK TO USER RTNE. (R1)= MODULE BEGIN TIMB70: MOV R5,R1 ;RESET MODULE POINTER (SEE EXPLN. ABOVE) BR TIMB15 ;LOOP BACK FOR MORE MODULES TIMEXT: ;EXIT POINT FOR [TIMER] MOV #TFIRST,R0 ;PREPARE TO SCAN LIST OF "FIRST" WORDS MOV #$NRES,R1 ~$~X~~~ 4{w)ew~HL x  N N Ê <%! ,c ѐhˋÜ`E $  P -F   LwZ ɋr pN BASIC RES'N TURNS OVER MOVB #$TMBAS,BASCNT ;RESET BASE PERIOD MULTIPLIER .ENDC $TMBAS INCB TIMBSY ;CHECK FOR PREVIOUS CALL STILL ACTIVE BNE TIMA00 ;YES: LEAVE INDICATOR SET TO SHOW ;PENDING REQUEST TO RUN; AND RETURN. SAVE ;NOT ACTIVE, SO SAFE TO ENTER. CALL TO ;SAVE ENVIRONMENT AND RETURN WITH: ;(R4) = (PS)  ;LIST SIZE MOV #340,PS ;LOCK OUT PULSE DURING EXIT SEQUENCE TIMEX1: TST (R0)+ ;IF ANY IS NON-ZERO... BNE TIMEX2 ;...DON'T TURN OFF CLOCK DEC R1 ;BE SURE TO DO WHOLE LIST BNE TIMEX1 TST @TTBPTR ;CHECK FOR EMPTY "WAIT" LIST BNE TIMEX2 ;NOT EMPTY: LEAVE CLOCK ON BIC #C1CBIT,C1COMD ;NO MODULES ACTIVE: KILL INTERRUPT TIMEX2: DECB TIMBSY BEFORE CLOCK INTERRUPT ;(R5) = ADDRESS OF "RESTOR" ROUTINE .PAGE TMNSRT: ;TIMER INSERT ROUTINE: TRANSFERS TIMER MODULE ADDRESS ; FROM WAIT STACK TO APPROPRIATE QUEUE WHEN CONVENIENT FOR TIMER. ; CPU LEVEL SEVEN: AVOID INTERFERENCE WITH "QTIME". MOV @TTBPTR,R0 ;ADDRESS OF TIMER MODULE FROM TOP OF ;"WAIT" STACK BEQ TIMA15 ;STACK EMPTY SUB #2,TTBPTR  ;NESTING "BUSY" COUNTER BGE TIMA15 ;NORMALLY RESIDES @ ZERO DURING ROUTINE ;EXECUTION. GOES ABOVE IF ADDITIONAL ;OCCASIONS TO ENTER ROUTINE HAVE ;OCCURRED DURING EXECUTION. IN THIS ;CASE ROUTINE IS RE-EXECUTED IMMEDIATELY ;IN AN ATTEMPT TO RE-SYNCHRONIZE JMP RESTOR ;NORMAL RETURN TO INTERRU ;NOT EMPTY: POP STACK ONE CELL MOV #1,(R0) ;SET T/W INACTIVE IN CASE WAS DE-QUEUED CMPB 5(R0),#-1 ;IS "RESET" ALL ONES? BEQ TMNSRT ;YES: MODULE WAS "DE-QUEUED": IGNORE IT MOVB 3(R0),R1 ;GET OPTION BYTE BIC #177760,R1 ;ISOLATE RESOLUTION ASL R1 ;USED AS WORD INDEX BELOW MOV R0,@TLAST(R1) ;PUT NEW MODULE'S ADDR @ END PROPER THD> MOV R0,TLAST(R1) PTED PROGRAM .PAGE TTBPTR: .WORD TWAITB ;TIMER TABLE POINTER TO "WAIT" STACK TWAITB: .WORD 0 ;FIRST LOC'N OF "WAIT" TABLE IS ALWAYS 0 .=$TWATZ*2+. ;RESERVE SPACE FOR TABLE TMTBND = .-2 ;ADDRESS OF LAST TALBE LOCATION TFIRST: ;TABLE OF POINTERS TO FIRST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN ZERO ;WHEN THREAD IS EMPTY.  ;...AND UPDATE THE "LAST" POINTER ITSELF CLR (R0) ;CLEAR MODULE'S T/W: END OF THREAD BR TMNSRT ;NOW GO BACK AND POP ANY MORE MODULES .PAGE TIMA15: ;RE-ENTER HERE FOR REPEATS (TIMBSY>/=1) MOV R4,PS ;RESTORE PROCESSOR LEVEL TO PREVIOUS CLR R0 ;INIT RESOLUTION INDEX TIMA20: ;RETURN HERE WHEN ADVANCING TO NEXT RESN DECB CURTAB(R0) ;COUN .WORD ,,,,,,,,,,,,,,, ;MAX TABLE SIZE: 16 WORDS .=$NRES*2+TFIRST ;ACTUAL TABLE SIZE = [$NRES] WORDS TLAST: ;TABLE OF POINTERS TO LAST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN THE ;ADDRESS OF [TFIRST(R)] WHEN THREAD ;IS EMPTY. .WORD ,,,,,,,,,,,,,,, ;MAX TABLE SIZE: 16 WORDS .=$NRES*2+TLAST ;ACTUAL TABLE SIZE = [$NRES] WORDS T DOWN A RESOLUTION COUNTER BEQ TIMA70 ;EXPIRED: GO RESET IT & BUMP RES'N INDEX TIMA30: ;FALL THROUGH HERE WHEN A RESOLUTION COUNTER IS FOUND ; THAT HAS NOT EXPIRED. SINCE THE RESOLUTIONS ARE COUNTED STARTING ; FROM THE FINEST TOWARDS THE COARSEST, THE RESOLUTION CURRENTLY IN R0 ; IS THE FINEST RESOLUTION THAT HAS NOT EXPIRED. BY DECREMENTING R0, ; THE COARSEST RESOLUTION TO EXPIRE IS FOUND. FALLS THROUGH HERE ALSO ; IF ALL RESOLUTIONS EXPIRE, WHICH WILL HA .PAGE RESTAB: ;RESOLUTION COUNTER TABLE: PERMANENT .BYTE RES0,RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8 .BYTE RES9,RES10,RES11,RES12,RES13,RES14,RES15 .=RESTAB+$NRES ;SET TO ACTUAL TABLE SIZE .BYTE 0 ;END BYTE CURTAB: .BYTE RES0,RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8 .BYTE RES9,RES10,RES11,RES12,RES13,RES14,RES15 .=CURTAB+$NRES ;SET TO ACTUAL TABLE SIZE TIMBSY:PPEN FROM TIME TO TIME. ASL R0 ;RESOLUTION*2: USE AS WORD INDEX TIMA35: ;LOOP BACK HERE FOR SUCCESSIVE RESOLUTIONS DEC R0 DEC R0 ;COUNT DOWN RESOLUTION INDEX (TWICE, ; SINCE IT WAS MADE INTO A WORD INDEX ABOVE). ON THE FIRST PASS AFTER ; FINDING THE FIRST RES'N NOT TO EXPIRE, THIS BRINGS COUNTER BACK TO ; (DOUBLE) THE COARSEST RES'N TO EXPIRE. ON SUCCESSIVE PASSES THIS ; MOVES TO NEXT FINER RES'N FOR SERVICING. .BYTE 0 ;FLAG & NESTING COUNTER FOR [TIMER] BASCNT: .BYTE 0 ;OPTIONAL SUB-RESOLUTION PULSE COUNTER .END  BLT TIMEXT ;EXIT HERE WHEN ALL RESOLUTIONS HAVE ; BEEN SERVICED, OR IF NO LEVELS ACTUALLY EXPIRED. .PAGE TIMB10: ;NOW WE BEGIN TRAVELING THE THREADS ;ALSO LOOP RE-ENTRY POINT FOR EACH RESOLUTION MOV #TFIRST,R1 ;CALC ADDRESS IN THE QUEUE POINTER TABLE ADD R0,R1 ;...OF POINTER FOR CURRENT RESOLUTION TIMB15: ;LOOP HERE FOR EACH SUCCESSIVE MODULE MOV #340,PS ;AVOID INTERFERENCE WITH "DQTIME" MOV R1,R2 ;REMEMBER UPSTREAM MODULE ADDRESS... ;...FOR USE IN DE-QUEUEING "ONE-SHOTS" MOV (R1),R1 ;NEXT MODULE'S THREAD WORD ADDRESS BEQ TIMA35 ;END OF THREAD: GO DOWN TO NEXT RES'N DECB TIMBYT(R1) ;COUNT DOWN MODULE'S TIMER BNE TIMB15 ;NOT EXPIRED: GET NEXT MODULE ;TIMER EXPIRED! IT IS MODULE'S TIME. MOVB RESET(R1),TIMBYT(R1) ;RESET TIMER BYTE BNE TIMB20 ;MODULE IS A REPEATER: LEAVE IN THREAD MOV (R1),(R2) ;"ONE-SHOT": REMOVE FROM THREAD ... BNE TIMB22 ;...BY "BRIDGING". BRANCH IF NOT LAST MOV R2,TLAST(R0) ;BUT UPDATE "LAST" POINTER IF WAS END TIMB22: MOV #1,(R1) ;SET THREAD WORD INACTIVE IN EITHER CASE TIMB20: MOV R4,PS ;UNLOCK INTERRUPTS: SAFE NOW MOV R1,R3 ;COPY MODULE ADDRESS TO PRESERVE R1... ;...IN CASE OF "J" OPTION MOVB OPTION(R1),R2 ;GET OPTION BYTE FOR THIS MODULE TSTB TASKNO(R1) ;IS MODULE TASK-RELATED? BEQ TIMB54 ;NO: CHECK FOR OTHER OPTIONS ;YES: SET UP STACK FOR CALL TO EITHER ;[SUSPEND] OR [QUEUE] MOVB TASKNO(R3),-(SP);PUSH TASK # FIRST CLR -(SP)  ;IMMEDIATE RETURN REQUEST FOR BOTH, OR ;INIT OF PRIORITY IF NEEDED FOR [QUEUE]. TSTB R2 ;IS "SUSPEND" OPTION SELECTED? BPL TIMB30 ;NO: GO DO QUEUEING JSR PC,UNSPND ;CALL TO "UN-SUSPEND" BR TIMB50 ;GO POP ERROR WORD & CHECK FLAG OPTION TIMB30: ;HERE TO QUEUE A TASK. TASK # AND RETURN CODE ;(OR INITED PRIORITY) ALREADY PUSHED ONTO STACK. .IFNZ DPRTY ;DYNAMIC PRIORITIES OPTION CLR -(SP) ;USE SYSTEM-ASSIGNED PRIORITY ; (ACTUALLY LEAVES ZERO AS PRIORITY AND PUSHES NEW RETURN CODE OF ZERO, ; POSSIBLY INITING STACK SPACE FOR PASSED ARGUMENT, IF OPTION IS ON.) .ENDC DPRTY .IFNZ ARG ;SYSTEM OPTION TO PASS ARGUMENT ON QUEUE BIT #100,R2 ;DOES MODULE HAVE AN ARGUMENT TO PASS? BEQ TIMB40 ;NO MOV @TIMARG(R4),(SP);YES: REPLACE THE ZERO WITH ACTUAL ARG.. TST (R3)+ ;...AND BUMP SECONDARY MODULE POINTER ;SO THAT REFERENCES BELOW WILL ALLOW FOR ;THE EXTRA MODULE WORD THAT "ARG" USED. TIMB40: CLR -(SP) ;MUST PUSH RETURN CODE SINCE ARGUMENT .ENDC ARG ;USED UP LAST ONE. JSR PC,QUEUE ;CALL QUEUE TIMB50: ;HERE AFTER [QUEUE] OR [UNSPND] TST (SP)+ ;POP ERROR RETURN CODE TIMB54: ;HERE WHEN NOT TASK-RELATED BIT #40,R2 ;TEST "FLAG" OPTION BEQ TIMB60 ;NOT SELECTED BISB TIMASK(R3),@TMFLAG(R3) ;"IOR" MASK INTO FLAG LOCATION CMP (R3)+,(R3)+ ;BUMP SECONDARY MODULE POINTER FOR FLAGS TIMB60: BIT #20,R2 ;IS "JSR" OPTION SELECTED? BEQ TIMB15 ;NO: SKIP "J" LINK AND LOOP FOR MORE JSR PC,JSTARG(R3) ;LINK TO USER RTNE. (R1)=MODULE BEGIN BR TIMB15 ;LOOP BACK FOR MORE MODULES TIMEXT: ;EXIT POINT FOR [TIMER] MOV #TFIRST,R0 ;PREPARE TO SCAN LIST OF "FIRST" WORDS MOV #$NRES,R1 ;LIST SIZE TIMEX1: TST (R0)+ ;IF ANY IS NON-ZERO... BNE TIMEX2 ;...DON'T TURN OFF CLOCK DEC R1 ;BE SURE TO DO WHOLE LIST BNE TIMEX1 BIC #C1CBIT,C1COMD ;NO MODULES ACTIVE: KILL INTERRUPT TIMEX2: MOV #340,PS ;PROTECT AGAINST THIS INTERRUPT DURING ;EXIT SEQUENCE DECB TIMBSY ;NESTING "BUSY" COUNTER BGE TIMA15 ;NORMALLY RESIDES @ ZERO DURING ROUTINE ;EXECUTION. GOES ABOVE IF ADDITIONAL ;OCCASIONS TO ENTER ROUTINE HAVE ;OCCURRED DURING EXECUTION. IN THIS  ;CASE ROUTINE IS RE-EXECUTED IMMEDIATELY ;IN AN ATTEMPT TO RE-SYNCHRONIZE JMP RESTOR ;NORMAL RETURN TO INTERRUPTED PROGRAM .PAGE TTBPTR: .WORD TWAITB ;TIMER TABLE POINTER TO "WAIT" STACK TWAITB: .WORD 0 ;FIRST LOC'N OF "WAIT" TABLE IS ALWAYS 0 .=$TWATZ*2+. ;RESERVE SPACE FOR TABLE TMTBND = .-2 ;ADDRESS OF LAST TALBE LOCATION TFIRST:  ;TABLE OF POINTERS TO FIRST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN ZERO ;WHEN THREAD IS EMPTY. .WORD ,,,,,,,,,,,,,,, ;MAX TABLE SIZE: 16 WORDS .=$NRES*2+TFIRST ;ACTUAL TABLE SIZE = [$NRES] WORDS TLAST: ;TABLE OF POINTERS TO LAST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN THE ;ADDRESS OF [TFIRST(R)] WHEN THREAD ;IS EMPTY. .WORD ,,,,,,,,,,,,,,, ;MAX TABLE SIZE: 16 WORDS .=$NRES*2+TLAST ;ACTUAL TABLE SIZE = [$NRES] WORDS .PAGE RESTAB: ;RESOLUTION COUNTER TABLE: PERMANENT .BYTE RES0,RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8 .BYTE RES9,RES10,RES11,RES12,RES13,RES14,RES15 .=RESTAB+$NRES ;SET TO ACTUAL TABLE SIZE .BYTE 0 ;END BYTE CURTAB: .BYTE RES0,RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8 .BYTE RES9,RES10,RES11,RES12,RES13,RES14,RES15 .=CURTAB+$NRES ;SET TO ACTUAL TABLE SIZE TIMBSY: .BYTE 0 ;FLAG & NESTING COUNTER FOR [TIMER] BASCNT: .BYTE 0 ;OPTIONAL SUB-RESOLUTION PULSE COUNTER .END