RECORDFORMAT PARMF(INTEGER DEST, SRCE, P1, P2, P3, P4, P5, P6) EXTRINSICLONGINTEGER KMON ROUTINESPEC PRHEX(INTEGER H) ROUTINESPEC PRINTER(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC PON(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC GDC(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC OPMESS(STRING (23) MESS) SYSTEMROUTINESPEC ITOE(INTEGER A, L) IF MULTIOCP=YES THEN START EXTERNALROUTINESPEC SEMALOOP(INTEGERNAME SEMA,INTEGER PARM) ROUTINESPEC RESERVE LOG ROUTINESPEC RELEASE LOG ROUTINESPEC AWAIT LOG ROUTE FINISH !------------------------------------------------------------------------ !* !* Communications record format - extant from CHOPSUPE 22A onwards * !* RECORDFORMAT COMF(INTEGER OCPTYPE,SLIPL,SBLKS,SEPGS,NDISCS,DLVNADDR, C (INTEGER GPCTABSIZE,GPCA OR INTEGER DCUTABSIZE,DCUA), C INTEGER SFCTABSIZE,SFCA,SFCK,DIRSITE, C DCODEDA,SUPLVN,TOJDAY,DATE0,DATE1,DATE2, C TIME0,TIME1,TIME2,EPAGESIZE,USERS,CATTAD,SERVAAD, C BYTEINTEGER NSACS,RESV1,SACPORT1,SACPORT0, C NOCPS,RESV2,OCPPORT1,OCPPORT0,INTEGER ITINT,CONTYPEA, C (INTEGER GPCCONFA OR INTEGER DCUCONFA), C INTEGER FPCCONFA,SFCCONFA,BLKADDR,RATION, C (INTEGER SMACS OR INTEGER SCUS), C INTEGER TRANS,LONGINTEGER KMON, C INTEGER DITADDR,SMACPOS,SUPVSN,PSTVA,SECSFRMN,SECSTOCD, C SYNC1DEST,SYNC2DEST,ASYNCDEST,MAXPROCS,INSPERSEC,ELAPHEAD, C COMMSRECA,STOREAAD,PROCAAD,SFCCTAD,DRUMTAD,TSLICE,FEPS, C MAXCBT,PERFORMAD,SP1,SP2,SP3,SP4,SP5,SP6, C LSTL,LSTB,PSTL,PSTB,HKEYS,HOOT,SIM,CLKX,CLKY,CLKZ, C HBIT,SLAVEOFF,INHSSR,SDR1,SDR2,SDR3, C SDR4,SESR,HOFFBIT,BLOCKZBIT,BLKSHIFT,BLKSIZE,END) !* CONSTRECORD (COMF)NAME COM=X'80C00000' EXTERNALROUTINE MOVE ALIAS "S#MOVE" (INTEGER LENGTH, FROM, TO) *LB_LENGTH; *JAT_14,<L99> *LDTB_X'18000000'; *LDB_B ; *LDA_FROM *CYD_0; *LDA_TO; *MV_L =DR L99: END ; ! of MOVE CONSTBYTEINTEGERARRAY H(0 : 15) = C '0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F' EXTERNALSTRING (8) FN STRHEX(INTEGER VALUE) STRING (8) S INTEGER I I=ADDR(S) *LDTB_X'18000008'; *LDA_I; *LSS_8; *ST_(DR ) *INCA_1; *STD_TOS ; *STD_TOS *LSS_0; *LUH_VALUE *MPSR_X'24'; ! SET CC=1 *SUPK_L =8 *LD_TOS ; *ANDS_L =8,0,15; ! THROW AWAY ZONE CODES *LSS_H+4; *LUH_X'18000010' *LD_TOS ; *TTR_L =8 RESULT =S END EXTERNALSTRING (8) FN HTOS(INTEGER VALUE, PLACES) STRING (8) S INTEGER I,J J=ADDR(S) IF PLACES>8 THEN PLACES=8 I=64-4*PLACES *LDTB_X'18000008'; *LDA_J; *LSS_PLACES; *ST_(DR ) *INCA_1; *STD_TOS ; *STD_TOS *LSS_VALUE; *LUH_0; *USH_I *MPSR_X'24'; ! SET CC=1 *SUPK_L =8 *LD_TOS ; *ANDS_L =8,0,15; ! THROW AWAY ZONE CODES *LSS_H+4; *LUH_X'18000010' *LD_TOS ; *TTR_L =8 RESULT =S END !----------------------------------------------------------------------- EXTERNALSTRING (15) FN STRINT(INTEGER N) STRING (16) S INTEGER I,D0, D1, D2, D3 I=ADDR(S) *LSS_N; *CDEC_0 *LDTB_X'18000010'; *LDA_I; *INCA_1; ! PAST LENGTH BYTE *CPB_B ; ! SET CC=0 *SUPK_L =15,0,32; ! UNPACK 15 DIGITS SPACE FILL *STD_D2; ! FINAL DR FOR LENGTH CALCS *JCC_8,<WASZERO>; ! N=0 CASE *LSD_TOS ; *ST_D0; ! SIGN DESCRIPTOR STKED BY SUPK *LDTB_X'18000010'; *LDA_I; *INCA_1 *MVL_L =15,15,48; ! FORCE IN ISO ZONE CODES IF N<0 THEN BYTEINTEGER(D1)='-' AND D1=D1-1 BYTEINTEGER(D1)=D3-D1-1 RESULT =STRING(D1) WASZERO: RESULT ="0" END EXTERNALROUTINE PKMONREC(STRING (20)TEXT,RECORD (PARMF)NAME P) INTEGER I, J, SPTR, VAL STRING (131) S S=TEXT SPTR=LENGTH(S)+1 CHARNO(S,SPTR)=' '; SPTR=SPTR+1 CYCLE I=ADDR(P),4,ADDR(P)+28 VAL=INTEGER(I) CYCLE J=28,-4,0 CHARNO(S,SPTR)=H((VAL>>J)&15) SPTR=SPTR+1 REPEAT CHARNO(S,SPTR)=' ' SPTR=SPTR+1 REPEAT CYCLE I=ADDR(P)+8,1,ADDR(P)+31 J=BYTEINTEGER(I) IF J<32 OR J>95 THEN J='_' CHARNO(S,SPTR)=J SPTR=SPTR+1 REPEAT CHARNO(S,SPTR)=NL LENGTH(S)=SPTR PRINTSTRING(S) END EXTERNALINTEGERFN REALISE(INTEGER AD) !*********************************************************************** !* THIS FUNCTION TAKES A VIRTUAL ADDRESS AND VIA SEGMENT AND PAGE * !* TABLES RETURNS THE CORRESPONDING REAL ADDRESS. * !* NOTE: NO FACILITY FOR SHARED SEGMENTS CURRENTLY REQD. * !*********************************************************************** CONSTINTEGER RA128=X'0FFFFF80'; ! 128 BYTE ALIGNED MASK FOR NON-PAGED SEGMENT ENTRY CONSTINTEGER RA8=X'0FFFFFF8'; ! 8 BYTE ALIGNED MASK FOR PAGED SEGMENT ENTRY CONSTINTEGER RA1024=X'0FFFFC00'; ! PAGE ALIGNED MASK FOR PAGE TABLE ENTRY CONSTINTEGER PUBLIC=X'80000000'; ! THESE TWO MAKE UP REAL CORE BASE ADDRESS CONSTINTEGER SEG64=X'01000000'; ! WHICH IS AT PSEG 64 CONSTINTEGER PAGEDBIT=X'40000000' INTEGER VASE; ! VIRTUAL ADDRESS OF SEGMENT TABLE ENTRY INTEGER VAPE; ! VIRTUAL ADDRESS OF PAGE TABLE ENTRY VASE=PST VA+(AD>>15)&X'FFF8' IF INTEGER(VASE)&PAGEDBIT#0 START ; ! PAGED SEGMENT VAPE=((INTEGER(VASE+4)&RA8)+SEG64+(AD<<14>>24)<<2)! PUBLIC ! ! IF WE HAVE TRUTHFUL SEGMENT TABLES ! (CURRENTLY WE DO NOT - SEE CHOPSUPE ROUTINE 'CONFIG') ! THEN LEST STORE BE DISCONTIGUOUS :- ! VAPE=VAPE-(INTEGER(PST VA+((VAPE>>15)&X'FFF8')+4)&X'20000') ! RESULT =INTEGER(VAPE)&RA1024+(AD&X'3FF') FINISH ! UN-PAGED SEGMENT RESULT =(AD&X'3FFFF')+(INTEGER(VASE+4))&RA128 END !! CONSTSTRING (8) NAME DATE=X'80C0003F' CONSTSTRING (8) NAME TIME=X'80C0004B' !! !*********************************************************************** !* * !* THESE FUNCTIONS ALL USE A PACKED FORMAT OF DATE AND TIME OF ONE OF * !* THE FOLLOWING FORMS.BITS ARE NUMBERED FROM 31 (MOST SIGNIFICANT) TO * !* 0 (LEAST SIGNIFICANT) * !* OLD FORMAT * !* BITS USE * !* 31 ZERO FOR OLD FORMAT * !* 30-26 YEAR-70 (VALID FOR 1970-2033) * !* 25-22 MONTH * !* 21-17 DAY * !* 16-12 HOUR * !* 11- 6 MINUTE * !* 5- 0 SECOND * !* * !* NEW FORMAT * !* BIT31 1 FOR NEW FORMAT * !* ALL OTHER BITS HOLD DT AS SECS SINCE 0000HRS ON 1/1/70 * !* CALCULATED AS PER CACM COLLECTER ALGORITHMS NO 199Z * !* NB TO KEEP LEAP YEARS CORRECT ONE MUST USE THIS ALGORITH FROM * !* 1ST JAN 1900 AND THEN CORRECT. THIS INVOLVES 64BIT ARITHMETIC * !*********************************************************************** INTEGERFN CURRENT PACKED DT !*********************************************************************** !* GIVES CURRENT DT IN NEW PACKED FORM * !*********************************************************************** CONSTLONGINTEGER MILL=1000000 CONSTLONGINTEGER SECS70=X'0000000083AA7E80';! SECS DITTOM *RRTC_0; *USH_-1 *SHS_1; *USH_1 *IMDV_MILL *ISB_SECS70; *STUH_B *OR_X'80000000' *EXIT_-64 END EXTERNALROUTINE DUMPTABLE(INTEGER TABLE, ADD, LENGTH) OWNINTEGER NEXT INTEGER I, K, END, SPTR, VAL STRING (132) S ADD=ADD&(-4) IF MULTIOCP=YES THEN RESERVE LOG NEWLINE IF TABLE>0 THEN START NEXT=NEXT+1 PRINTSTRING("DT: ".DATE." ".TIME." **** SUPERVISOR DUMP TABLE: ". C STRINT(TABLE)." ADDR ".STRHEX(ADD)." LENGTH: " C .STRINT(LENGTH)." DUMP NO: ".STRINT(NEXT)."**** ") FINISH END=ADD+LENGTH; I=1 S=" " UNTIL ADD>=END CYCLE ->INVL IF ADD>=0; ! DUMP PUBLIC ADDRESSES ONLY *LDTB_X'18000020'; *LDA_ADD *VAL_(LNB +1); *JCC_3,<INVL> IF I=0 AND ADD+32<END THEN START CYCLE K=ADD,4,ADD+28 ->ON IF INTEGER(K)#INTEGER(K-32) REPEAT S="O"; ->UP FINISH ON: CHARNO(S,2)='('; SPTR=3 CYCLE I=28,-4,0 CHARNO(S,SPTR)=H((ADD>>I)&15) SPTR=SPTR+1 REPEAT CHARNO(S,SPTR)=')' CHARNO(S,SPTR+1)=' ' SPTR=SPTR+2 CYCLE K=ADD,4,ADD+28 VAL=INTEGER(K) CYCLE I=28,-4,0 CHARNO(S,SPTR)=H((VAL>>I)&15) SPTR=SPTR+1 REPEAT CHARNO(S,SPTR)=' ' SPTR=SPTR+1 REPEAT IF TABLE>=0 THEN START CHARNO(S,SPTR)=' ' SPTR=SPTR+1 CYCLE K=ADD,1,ADD+31 I=BYTEINTEGER(K)&X'7F' UNLESS 32<=I<127 THEN I=' ' CHARNO(S,SPTR)=I SPTR=SPTR+1 REPEAT FINISH CHARNO(S,SPTR)=NL BYTEINTEGER(ADDR(S))=SPTR PRINTSTRING(S) S=" " UP: ADD=ADD+32 I=0 REPEAT ->WAYOUT INVL: PRINTSTRING("ADDRESS VALIDATION FAILS ") WAYOUT: ! EXIT FREEING PATH IF MULTIOCP=YES THEN RELEASE LOG END ; !ROUTINE DUMP ! OWN VARIABLES FOR JOINT USE BY 'IOCP' AND 'PRINTER' CONSTINTEGER MASK=X'80FC3FFF', BUFFBASE=X'80FC0000', PAGEMASK= C X'80FC3000' EXTERNALINTEGER INPTR=X'80FC0000' EXTERNALINTEGER OUTPTR=X'80FC0000' OWNINTEGER BUSY, DINTPEND=0, INTPEND, TESTPEND=0, INIT=0 OWNINTEGER MODE=-1 CONSTINTEGER SPOOLING=1, PRINTING=0 IF MULTIOCP=YES THEN START OWNINTEGER LOGSEMA=-1 ; ! SEMAPHORE FOR IOCP AND PRINTER OWNINTEGER LOGROUTE=0; ! BOTTOM HALF HAS COUNT ! IF COUNT>0 TOPHALF HAS OCP PORT EXTERNALROUTINE RESERVE LOG !*********************************************************************** !* CLAIMS THE LOG FOR CALLING ROUTINE. WAITS IF NEEDED. THIS ROUTINE* !* IS USED IN DUALS TO PREVENT TABLES BEING MIXED UP * !* NESTED CLAIMS AND RELEASE BY SAME OCP ARE PERMITTED * !*********************************************************************** INTEGER MYPORT *LSS_(3); *USH_-26 *AND_3; *ST_MYPORT; ! PORT OF OCP EXECUTING THIS *INCT_LOGSEMA *JCC_8,<LSEMAGOT> SEMALOOP(LOGSEMA,0) LSEMAGOT: IF LOGROUTE&X'FFFF'=0 THEN ->WAYOUT IF LOGROUTE>>16=MYPORT THEN ->WAYOUT *TDEC_LOGSEMA AWAIT LOG ROUTE WAYOUT: LOGROUTE=(LOGROUTE&X'FFFF'+1)!MYPORT<<16 *TDEC_LOGSEMA END EXTERNALROUTINE RELEASE LOG !*********************************************************************** !* RELEASE THE LOG PATH * !*********************************************************************** INTEGER MYPORT *LSS_(3); *USH_-26 *AND_3; *ST_MYPORT; ! PORT OF OCP EXECUTING THIS *INCT_LOGSEMA *JCC_8,<LSEMAGOT> SEMALOOP(LOGSEMA,0) LSEMAGOT: IF LOGROUTE&X'FFFF'=0 OR LOGROUTE>>16#MYPORT THEN C OPMESS("LOGROUTE PATHS ? ".STRHEX(LOGROUTE)) C ELSE LOGROUTE=LOGROUTE-1 *TDEC_LOGSEMA END ROUTINE AWAIT LOG ROUTE !*********************************************************************** !* AWAITS LOGROUTE COMING FREE AND RETURNS WITH LOGSEMA HELD * !* TIMES OUT AFTER ABOUT 5 SECS ON 2970 * !*********************************************************************** INTEGER MYPORT,I,J IF MONLEVEL&4#0 START EXTRINSICLONGINTEGER SEMATIME INTEGER IT *LSS_(5); *ST_IT FINISH *LSS_(3); *USH_-26 *AND_3; *ST_MYPORT; ! PORT OF OCP EXECUTING THIS CYCLE J=1,1,2000 CYCLE I=1,1,COM_INSPERSEC; ! WAIT ABOUT 1 MILLESEC REPEAT ; ! DONT USE RTC IN CASE OTHER ! OCP HAS CLOCK&HAS DIED *INCT_LOGSEMA *JCC_8,<LSEMAGOT> SEMALOOP(LOGSEMA,0) LSEMAGOT: IF LOGROUTE&X'FFFF'=0 THEN ->WAYOUT *TDEC_LOGSEMA REPEAT OPMESS("LOGROUTE TIMEOUT") LOGROUTE=0; ! HAVE TIMED OUT WAYOUT: IF MONLEVEL&4#0 START ; ! RECORD WASTED TIME *LSS_(5); *IRSB_IT; *IMYD_1 *IAD_(SEMATIME); *ST_(DR ) FINISH END FINISH EXTERNALROUTINE IOCP ALIAS "S#IOCP" (INTEGER EP, N) !*********************************************************************** !* THIS ROUTINE RECEIVES ALL THE OUTPUT FROM MAIN VIA IMP STMTS * !* SUCH AS PRINTSTRING, AND SENDS IT TO THE MAIN PRINT FILE. * !* SEGMENT P63 IS USED AS THE BUFFER. IF OUTPUT ARRIVES FASTER * !* THAN THE PRINTER CAN COPE IT IS DISCARDED. * !* A SIMILAR ROUTINE IN SLOWFILE IS USED WITH A VIRTUAL PRINTER * !*********************************************************************** RECORD (PARMF) Q INTEGER I, J, ADR, L, OLDINPTR, SYM, NLSEEN, MYPORT, MYMASK STRING (63) S RETURN UNLESS X'280A8'&1<<EP¬=0;!CHECK FOR VALID ENTRY NLSEEN=0 IF EP=17 THEN START ; ! REPEATED SYMBOLS L=N>>8&63 ADR=ADDR(S)+1 ! J = L ! %WHILE J > 0 %CYCLE ! CHARNO(S,J) = N&127 ! J = J-1 ! %REPEAT ! ! EQUIVELANT OF ABOVE 5 LINES IS ! J=N&127 I=X'18000000'!L *LDTB_I *LDA_ADR *LB_J *MVL_L =DR FINISH ELSE START IF EP>=7 THEN START ; ! PRINT STRING L=BYTE INTEGER(N); ADR=N+1 FINISH ELSE START ; ! PRINT SYMBOL & PRINT CH L=1; ADR=ADDR(N)+3 FINISH FINISH ! ! NOW PUT MESSAGE INTO BUFFER IF THERE IS ROOM ! I=1 IF MULTIOCP=YES THEN START *INCT_LOGSEMA *JCC_8,<SEMAGOT> SEMALOOP(LOGSEMA,0) SEMAGOT: FINISH ! ! CHECK AND AWAIT THE LOGROUTE IN DUALS EXCEPT FOR SYSTEM ERRORS ! THE OTHER OCP IS HALTED HERE, SO NO POINT IN WAITING ! ALSO SYSTEM ERROR IN SINGLES CAN BREAK INTO DEVICE ERROR ! SO JOURNAL SYSTEM HAS TO BE ABLE TO COPE WITH THIS. ! IF MULTIOCP=YES AND LOGROUTE&X'FFFF'>0 START *LSS_(3); *ST_MYMASK; *USH_-26; *AND_3; *ST_MYPORT IF MYPORT#LOGROUTE>>16 AND MYMASK&1=0 START *TDEC_LOGSEMA AWAIT LOG ROUTE FINISH FINISH OLDINPTR=INPTR WHILE I<=L CYCLE ->END IF BUSY=1; ! BUFFERS BUSY DISCARD OUTPUT J=(INPTR+1)&MASK IF J&X'FFF'<=63 THEN INPTR=J!63 AND J=INPTR+1 IF J#OUTPTR THEN START ; ! ROOM FOR CURRENT CHAR SYM=BYTE INTEGER(ADR) BYTE INTEGER(J)=SYM IF SYM=133 THEN SYM=NL IF SYM=NL THEN NLSEEN=1 ADR=ADR+1; I=I+1 INPTR=J FINISH ELSE BUSY=1 AND ->END REPEAT ! ! PON A KICK TO PRINTER IF A LINE (OR PAGE IN DISC MODE) HAS BEEN COMPLETED ! AND PRINTER IS IDLE. HOWEVER IF REPORTING A RECOVERED ERROR (IE SYSERR ! INT IS MASKED OUT) REFRAIN FROM PONNING. RECOVERED ERROR MIGHT BE ! A SINGLE BIT OR RETRY FROM PON OR POFF ! *LSS_(3); *AND_1; *JAF_4,<END>;! JUMP IF SYSERR MASKED IF (OLDINPTR=OUTPTR AND NLSEEN#0) C OR (MODE=SPOOLING AND INPTR&PAGEMASK#OLDINPTR& C PAGEMASK) THEN Q_DEST=X'360000' AND PON(Q) END: IF MULTIOCP=YES START ; *TDEC_LOGSEMA; FINISH END ; ! OF ROUTINE IOCP !! EXTERNALROUTINE PRINTER(RECORD (PARMF)NAME P) !*********************************************************************** !* This (over elaborate) version of printer supports both a real * !* printer and a virtual (disc) printer allowing switching between * !* the two at any time. This was useful in development but in a * !* service situation a disc only version would be samller and easier* !* to maintain. * !*********************************************************************** ROUTINESPEC INITIALISE FILE ROUTINESPEC CHANGE FILE ROUTINESPEC DISCWRITE(INTEGER AD) ROUTINESPEC PREPORT(INTEGER VALUE) ROUTINESPEC DEALLOCATE MAIN PRINTER(INTEGER REPLY ACT) ROUTINESPEC ALLOCATE MAIN PRINTER(INTEGER REPLY ACT) INTEGER I, J, ACT, DMON, PAGE, PREVMODE OWNBYTEINTEGERARRAY BUFFER(0:133)=0(*) OWNINTEGER BUFFERAD=-1 IF SSERIES=YES START RECORDFORMAT TCBF(INTEGER COMMAND,STE,LEN,DATAD,NTCB,RESP, C INTEGERARRAY PREAMBLE,POSTAMBLE(0:3)) OWNRECORD (TCBF)NAME TCB CONSTINTEGER TCBM=X'2F004000' INTEGER LEN,DATAD FINISH ELSE START RECORDFORMAT RCBF(INTEGER LFLAG, LSTBA, LBL, LBA, ALL, ALA, INIT,SPARE) OWNRECORD (RCBF) RCB OWNINTEGER LBE=X'80700300',ALE1,ALE2 FINISH OWNINTEGER PAGESTATE=0; ! bitmask of pages with trnsfers CONSTINTEGER PONSRC=X'360000' CONSTINTEGER GPCSNO=X'300000' CONSTINTEGER AUTO=X'8000' OWNINTEGER MNEM=M'LP', ACTSIZE=0 OWNINTEGER DPAGE=0; ! disc address OWNINTEGER CFILE=0, SECTSIZE=0 OWNINTEGERARRAY DPAGES(0 : 1) = -1(2) OWNINTEGER DISCDEST,TRANSTABAD=0 ! file header block RECORDFORMAT HDRF(INTEGER HDR1,HDR2,HDR3,HDR4,HDR5,HDR6,HDR7,HDR8) IF SSERIES=YES START RECORDFORMAT ENTFORM(INTEGER C SER, PTSM, PROPADDR, SECS SINCE, CAA, GRCB AD, C BYTE INTEGER LAST ATTN, DACTAD, HALF INTEGER HALFSPARE, C INTEGER LAST TCB ADDR, C STATE, PAW, RESP1, SENSE1, SENSE2, SENSE3, SENSE4, C REPSNO, BASE, ID, DLVN, MNEMONIC, C STRING (6) LABEL, BYTE INTEGER HWCODE, C INTEGER ENTSIZE, URCB AD, SENSDAT AD, LOGMASK, TRTAB AD, C UA SIZE, UA AD, TIMEOUT,PROPS0,PROPS1) FINISH ELSE START RECORDFORMAT ENTFORM(INTEGER SER, PTSM, PROPADDR, C TICKS SINCE, CAA, GRCB AD, LBA, ALA, STATE, RESP0, C RESP1, SENSE1, SENSE2, SENSE3, SENSE4, REPSNO, BASE, C ID, DLVN, MNEMONIC, ENTSIZE, PAW, USAW0, URCB AD, C SENSDAT AD, LOGMASK, TRTAB AD, UA SIZE, UA AD, C TIMEOUT, PROPS0, PROPS1) FINISH RECORD (ENTFORM)NAME D OWNSTRING (8) OLDDATE, OLDTIME OWNINTEGER OLDPDT OWNINTEGER SOURCE8 CONSTINTEGER MAXACT=10 SWITCH DACT(0:MAXACT) !! !! !! IF INIT=0 THEN START ; ! first time in - initialise ALLOCATE MAIN PRINTER(10) INIT=-1 FINISH !! !! !! ACT=P_DEST&255 IF ACT>MAXACT THEN ACT=0; ! dont report for fear of starting loop IF MONLEVEL&2#0 THEN DMON=KMON>>54&1 IF MONLEVEL&2#0 AND DMON#0 AND ACT#0 AND C (ACT#2 OR P_P1&X'800000'=0) THEN PKMONREC("PRINT( IN):",P) ! dont monitor clock or normal terms ->DACT(ACT) !! !**************************************** !! NEXTLINE: IF MODE=PRINTING THEN BYTEINTEGER(BUFFERAD)=0 !! !!------------------------------------------------ DACT(0): ! alarm clock tick or equivalent IF MULTIOCP=YES THEN START *INCT_LOGSEMA *JCC_8,<SEMAGOT1> SEMALOOP(LOGSEMA,0) SEMAGOT1: FINISH IF MODE=SPOOLING START I=OUTPTR CYCLE J=1,1,4 IF (I-1)<=INPTR<(I+4096)&X'FFFFFFC0' C AND BUSY=0 THEN START IF MULTIOCP=YES START ; *TDEC_LOGSEMA; FINISH RETURN FINISH PAGE=(I-BUFFBASE)//(EPAGESIZE*1024) IF PAGESTATE&(1<<PAGE)=0 THEN DISCWRITE(I) I=(I+4096)&MASK REPEAT FINISH IF MODE!INTPEND!TESTPEND!DINTPEND#0 START IF MULTIOCP=YES START ; *TDEC_LOGSEMA; FINISH RETURN ; ! unless printing & no ints pending FINISH IF INPTR=OUTPTR THEN ->UNBUSY; ! nothing to print ! check we were not inhibited I=BYTEINTEGER(BUFFERAD) CYCLE J=BYTE INTEGER(OUTPTR) BYTE INTEGER(OUTPTR)=0 IF J=10 THEN J=133 IF J=133 OR J=12 OR I=132 START IF I=132 THEN BYTEINTEGER(OUTPTR)=J C AND J=133 ELSE START OUTPTR=(OUTPTR+1)&MASK IF OUTPTR&X'FFF'<=63 THEN OUTPTR=OUTPTR+64 FINISH I=I+1; BYTEINTEGER(BUFFERAD+I)=J BYTEINTEGER(BUFFERAD)=I IF SSERIES=YES START TCB_LEN=I DATAD=TCB_DATAD ITOE(DATAD,I) FINISH ELSE START ALE1=X'58000000'+I ITOE(ALE2,I) FINISH IF TRANSTABAD#0 START IF SSERIES=YES START LEN=X'58000000'+I *LDTB_LEN; *LDA_DATAD FINISH ELSE START *LD_ALE1 FINISH *LSS_TRANSTABAD *LUH_X'18000100' *TTR_L =DR ; ! non-printables to null FINISH EXIT FINISH OUTPTR=(OUTPTR+1)&MASK IF OUTPTR&X'FFF'<=63 THEN OUTPTR=OUTPTR+64 IF J#13 THEN I=I+1 AND BYTEINTEGER(BUFFERAD+I)=J IF INPTR=OUTPTR THEN BYTEINTEGER(BUFFERAD)=I AND ->UNBUSY ! incomplete line REPEAT IF MULTIOCP=YES START ; *TDEC_LOGSEMA; FINISH PRINT: ! print line in array buffer(again) P=0 IF SSERIES=YES START P_P1=ADDR(TCB) FINISH ELSE START P_P1=ADDR(RCB) P_P3=X'11'; ! PAW - do stream request, SAW - clear abnormal FINISH P_DEST=GPCSNO!12 P_SRCE=PONSRC!5 P_P2=INIT PON(P) INTPEND=1 RETURN !! !!----------------------------------------------- ! execute request rejected DACT(5): !! PREPORT(P_P1) RETURN !! !!----------------------------------------------- DACT(1): ! new log file ! P_P1=no of epages (16) ! P_P2=disc addr IF MONLEVEL&2#0 AND DMON=1 THEN C OPMESS("New log file ".HTOS(P_P2,8)) SECTSIZE=P_P1<<12 IF DPAGES(0)>0 AND DPAGES(1)>0 START PRINTSTRING("Spurious log file") RETURN FINISH IF DPAGES(CFILE)=0 THEN DPAGES(CFILE)=P_P2 C ELSE DPAGES((CFILE+1)&1)=P_P2 IF DPAGE=0 THEN INITIALISE FILE ->NEXTLINE !! !!------------------------------------------------ !! Printer interrupts terms&attns, come here DACT(2): J=(P_P1>>20)&15 IF J=1 START ; ! attention IF TESTPEND#0 AND P_P1&AUTO#0 C THEN TESTPEND=0 AND ->PRINT RETURN ; ! ignore all other attentions FINISH INTPEND=0 !! !! May be waiting for LP term before deallocating to avoid !! a spurious term going to the next owner !! IF MODE=SPOOLING THEN START DEALLOCATE MAIN PRINTER(9) RETURN FINISH !! IF J=8 THEN ->NEXTLINE; ! normal term ! abnormal term. OPMESS("Attend main LP") TESTPEND=1; RETURN !! !!------------------------------------------------ !! Reset to printer - after D/MAINLP (obeying allocation rules) !! DACT(8): SOURCE8=P_SRCE IF MODE#PRINTING START ALLOCATE MAIN PRINTER(3) RETURN FINISH P_P1=81; ! DIR error "already main lp" DACT(3): ! reply from above allocat P_DEST=SOURCE8 P_SRCE=PONSRC!8 IF 0#P_P1#81 THEN P_P1=95; ! DIR err "main lp fails" PON(P) RETURN IF P_P1¬=0; ! no allocate done DACT(10): ! reply from initial allocate EXIT6: IF P_P1#0 THEN PREPORT(P_P1) AND RETURN D==RECORD(P_P3) TRANSTABAD=D_TRTABAD INIT=P_P2 MNEM=P_P6 MODE=PRINTING BUFFERAD=ADDR(BUFFER(0)) ! use private areas where possible (but DCU1 TCBs must be in COM area) ! 'lest LP in use when 'grabbed' by PON X36 6 IF SSERIES=YES START TCB==RECORD(D_UA AD) TCB=0 TCB_COMMAND=TCBM!X'83'; ! write TCB_STE=REALISE(BUFFERAD&X'FFFC0000')!1 TCB_DATAD=BUFFERAD+1 FINISH ELSE START ALE2=BUFFERAD+1 RCB=0 RCB_LBL=4 RCB_LBA=ADDR(LBE) RCB_ALL=8 RCB_ALA=ADDR(ALE1) FINISH IF MULTIOCP=YES THEN START *INCT_LOGSEMA *JCC_8,<SEMAGOT4> SEMALOOP(LOGSEMA,0) SEMAGOT4: FINISH CHANGE FILE IF DPAGE>0 IF MULTIOCP=YES START ; *TDEC_LOGSEMA; FINISH INTPEND=0 ->NEXTLINE !! !!---------------------------------- !! DACT(6): ! emergency reset by hairy PON ! no reply. Use emergency allocate P_DEST=GPCSNO!8; ! emergency allocate P_P1=M'LP'; ! any LP will do P_P2=PONSRC!2 GDC(P); ! direct call for emergency allocate ->EXIT6; !!---------------------------------------------------- DACT(7): ! close current output IF MONLEVEL&2#0 AND DMON = 1 THEN C OPMESS("NLF ".HTOS(INPTR,8)." ".HTOS(OUTPTR,8)) PREVMODE=MODE DISCDEST=P_SRCE IF MULTIOCP=YES THEN START *INCT_LOGSEMA *JCC_8,<SEMAGOT5> SEMALOOP(LOGSEMA,0) SEMAGOT5: FINISH IF MODE=SPOOLING START BYTEINTEGER((INPTR+1)&MASK)=4; ! EOM character DISCWRITE(OUTPTR) ! Subtract unused space ACTSIZE=ACTSIZE-(X'1000'-((INPTR&X'FFF')+1)) INPTR=((INPTR+4096)&PAGEMASK)!63; ! move onto next page CHANGE FILE FINISH ELSE START ; ! zero front of first page IF INPTR<OUTPTR AND INPTR>>12=OUTPTR>>12 START BUSY=1 I=(INPTR&PAGEMASK)!64 WHILE I<=OUTPTR CYCLE BYTEINTEGER(I)=0 I=I+1 REPEAT FINISH MODE=SPOOLING IF DPAGES(0)=-1=DPAGES(1) THEN CHANGE FILE C ELSE INITIALISE FILE ! ACT to acquire new files if neccesary FINISH IF MULTIOCP=YES START ; *TDEC_LOGSEMA; FINISH IF PREVMODE=PRINTING THEN DEALLOCATE MAIN PRINTER(9) ->NEXTLINE !! !!------------------------------------------------ DACT(4): ! disc termination IF DINTPEND=0 START PRINTSTRING(" Spurious log disc int ") RETURN FINISH DINTPEND=DINTPEND-1 PAGESTATE=PAGESTATE&(X'FFFFFFFF'!!(1<<P_P1));! clear transfer bit J=BUFFBASE+(P_P1<<12) ! ! Zero block - null character ! *LDTB_X'18001000' *LDA_J *MVL_L =DR ,0,0 IF MULTIOCP=YES THEN START *INCT_LOGSEMA *JCC_8,<SEMAGOT6> SEMALOOP(LOGSEMA,0) SEMAGOT6: FINISH IF P_P2#0 START ; ! abnormal termination OPMESS(" Log file abterm ".HTOS(P_P2,2)) DINTPEND=0; ! forget other transfers outstanding on faulty file PAGESTATE=0 CHANGE FILE FINISH CYCLE PAGE=(OUTPTR-BUFFBASE)//(EPAGESIZE*1024) EXIT IF PAGESTATE&(1<<PAGE)#0 OUTPTR=((OUTPTR+4096)&PAGEMASK)!64 ->UNBUSY IF OUTPTR-1<=INPTR<(OUTPTR+4096) REPEAT IF MULTIOCP=YES START ; *TDEC_LOGSEMA; FINISH RETURN !!------------------------------ !! DACT(9): ! reply from dellocate ! after switch to spooling IF P_P1#0 THEN PREPORT(P_P1) TESTPEND=0 BUFFERAD=-1 RETURN !! !!------------------------------------------------- !! UNBUSY: ! restart if buffer oflow occurred ! LOGSEMA is claimed IF BUSY=1 THEN START IF MODE=SPOOLING THEN INPTR=OUTPTR IF MONLEVEL&2#0 AND DMON = 1 THEN OPMESS("Unbusy") BUSY=0 I=-1 FINISH ELSE I=0 IF MULTIOCP=YES START ; *TDEC_LOGSEMA; FINISH IF I=-1 THEN PRINTSTRING(" *** output lost *** ") RETURN ROUTINE INITIALISE FILE !*********************************************************************** !* SEMA must be claimed before calling this * !*********************************************************************** RETURN UNLESS MODE=SPOOLING ACTSIZE=0 OUTPTR=(OUTPTR&PAGEMASK)!64 IF BUSY=1 THEN INPTR=OUTPTR-1 ! pack date and time OLDPDT=CURRENT PACKED DT OLDTIME=TIME OLDDATE=DATE DPAGE=DPAGES(CFILE) END ROUTINE CHANGEFILE !*********************************************************************** !* SEMA must be held before calling this. Can not let other OCP in * !* while changing files * !* close current spool file and request another one * !* if both files closed , requests have already been sent, so return* !*********************************************************************** RETURN IF DPAGES(0)=0 AND DPAGES(1)=0 RETURN IF ACTSIZE=0 AND DPAGE#0; ! no empty files AGN: IF MONLEVEL&2#0 AND DMON=1 THEN C OPMESS("Change file ".HTOS(DPAGE,8)." ".HTOS(ACTSIZE,6)) P=0 P_DEST=DISCDEST P_SRCE=PONSRC!1 P_P1=DPAGE P_P2=ACTSIZE PON(P) ACTSIZE=0 DPAGES(CFILE)=0; ! mark file closed CFILE=(CFILE+1)&1; ! change to alternate file DPAGE=DPAGES(CFILE) IF DPAGE>0 THEN INITIALISE FILE ELSE START IF DPAGE=-1 THEN DPAGE=0 AND ->AGN FINISH END ROUTINE DISCWRITE(INTEGER AD) !*********************************************************************** !* SEMA must be held for call of change file * !*********************************************************************** RECORD (HDRF)NAME HDR CONSTBYTEINTEGERARRAY SYSTYPE(0:2)=M'P',M'S',M'S' STRING (32) SHEAD INTEGER STYPE AD=AD&PAGEMASK P=0 P_P1=(AD>>12)&3; ! block 0:3 ! Return unless no file available or page already sent RETURN IF DPAGE<=0 OR PAGESTATE&(1<<P_P1)#0 IF MONLEVEL&2#0 AND DMON=1 THEN C OPMESS("DISCW ".HTOS(AD,8)." ".HTOS(DPAGE,8)) IF DPAGE&15=0 START ; ! header page HDR==RECORD(AD) HDR_HDR1=SECTSIZE HDR_HDR2=32 HDR_HDR3=HDR_HDR1 HDR_HDR4=3 HDR_HDR5=0 HDR_HDR6=OLDPDT HDR_HDR7=-256 HDR_HDR8=0 *LSS_(16); *USH_-16; *AND_255; *ST_STYPE SHEAD="DT: ".OLDDATE." ".OLDTIME." OCP n t "." " BYTEINTEGER(ADDR(SHEAD)+28)=COM_OCPTYPE+48 BYTEINTEGER(ADDR(SHEAD)+30)=SYSTYPE(STYPE) MOVE(32,ADDR(SHEAD)+1,AD+32) FINISH P_DEST=X'210002' P_SRCE=PONSRC!4 P_P2=DPAGE P_P3=AD PON(P) DINTPEND=DINTPEND+1; ! remember disc term. pending PAGESTATE=PAGESTATE!(1<<P_P1); ! lock page until disc write complete ACTSIZE=ACTSIZE+4096 IF ACTSIZE>=SECTSIZE THEN CHANGE FILE C ELSE DPAGE=DPAGE+1 END ROUTINE PREPORT(INTEGER VALUE) OPMESS("MLP activity ".STRINT(ACT)." fails ".STRINT(VALUE)) END ROUTINE DEALLOCATE MAIN PRINTER(INTEGER REPLY ACT) RECORD (PARMF) Q IF INTPEND#0 THEN RETURN Q=0; Q_DEST=GPCSNO!5 Q_SRCE=PONSRC!REPLYACT Q_P1=MNEM PON(Q) END ROUTINE ALLOCATE MAIN PRINTER(INTEGER REPLYACT) RECORD (PARMF) Q Q=0 Q_DEST=GPCSNO!11 Q_P2=PONSRC!2 Q_SRCE=PONSRC!REPLYACT Q_P1=MNEM PON(Q) END END ; ! OF ROUTINE PRINTER !! !-------------------------------------------------------------- EXTERNALROUTINE WRITE ALIAS "S#WRITE" (INTEGER VALUE, PLACES) STRING (16) S INTEGER I,D0, D1, D2, D3, L I=ADDR(S) *LSS_VALUE; *CDEC_0 *LDTB_X'18000010'; *LDA_I; *INCA_1; *STD_TOS *CPB_B ; ! SET CC=0 *SUPK_L =15,0,32; ! UNPACK & SPACE FILL *STD_D2; *JCC_8,<WASZERO> *LD_TOS ; *STD_D0; ! FOR SIGN INSERTION *LD_TOS *MVL_L =15,63,0; ! FORCE ISO ZONE CODES IF VALUE<0 THEN BYTEINTEGER(D1)='-' L=D3-D1 OUT: IF PLACES>=L THEN L=PLACES+1 D3=D3-L-1 BYTEINTEGER(D3)=L PRINTSTRING(STRING(D3)) RETURN WASZERO: BYTEINTEGER(D3-1)='0' L=2; ->OUT END EXTERNALROUTINE PRHEX(INTEGER I) ! 8-DIGIT HEX PRINT PRINTSTRING(STRHEX(I)) END ; ! PRHEX ENDOFFILE