.TITLE OPA - ONLINE POOL ANALYZER .IDENT /JN3SLL/ .ENABL LC ;ALLOW LOWER-CASE I/O AND LISTING ; WRITTEN BY J. NEELAND ; ;MODIFIED 801021. BY DANIEL STEINBERG -- RECOVER FROM ODD ADDR. TRAPS BETTER ; BY USING THREADED ROUTINE LIST ;MODIFIED 801102. BY J. NEELAND TO HANDLE FUNNY INTRP. VECTORS (DECNET) ; BETTER, ALSO IMPROVE OCB HANDLING ; ;MODIFIED 801209 BY SNLL VIRTUAL DISK CODE ADDED (FROM CPA) ; ALLOW USER TO DEFINE HIS OWN FILL CHARACTERS ; MORE EASILY ; ;MODIFIED 20-SEP-82 BY SNLL For RSX11M-V4.0 ; Increase Pool buffer to 12. K words ; Increase size of TCB & VCB ; Add Volume Set Control Block for Mag-Tape ; Add CLI Parser Blocks if A$$CLI defined .LIST MEB ;NEED TO SEE ALL CODE FOR DEBUGGING .MCALL QIOW$,DIR$,EXIT$S,GMCR$,GTIM$ .MCALL F11DF$,UCBDF$,DCBDF$,TCBDF$,PCBDF$,SCBDF$,MTADF$ F11DF$ MTADF$ UCBDF$ DCBDF$ TCBDF$ SCBDF$ V$$D11=0 ; HANDLE VIRTUAL DISKS MAXFRG=100. ; THESE DEFINITIONS DETERMINE WHAT CHARACTERS ARE USED TO FILL WHICH ; DATA STRUCTURES. ASTFIL = 56 ; '. FREFIL = 55 ; '- HDRFIL = 75 ; '= WAS '# ICBFIL = 40 ; ' UCBFIL = 75 ; '= WAS '% WBFIL = 75 ; '= ; ; THESE ARE THE DEFINITIONS OF THE BEGINNING CHARACTERS MARKING THE ; DATA STRUCTURES. DYNCHR = 176 ; '~ WAS '+ OCBCHR = 46 ; '& WAS '! SUBCHR = 57 ; '/ .PAGE .SBTTL Map Definitions ;=============================================================================* ; OPA - CPA Map Definitions ; ; Device Driver Data Structure ; I/O Packet in use ; Interrupt Control Block ; Task Control Block ; Attachment Discriptor Block ; [...] AST Control Block ; [Ax] Specify-AST Block w/type code ; [FDX TT:] Reserved by Terminal Driver ; [BIO TT:] Buffered I/O ; &prntnm Offspring Control Block ; /tasknmD\ Receive Data Queue ; /tasknmR\ Receive by Reference Queue ; (ctsknam) Checkpointed Task saved Sub-PCB ;
Task Header ; Window Block ; ( parnam) Main Partition Control Block ; (/parnam) Sub-Partition Control Block ; (/ dv: ) Driver Sub-Partition Control Block ; (~parnam) Dynamic Partition Control Block ; Volume Control Block ; File Control Block ; Virtual Disk Extension Block ; Volume Set Control Block (Magtape) ; Checkpoint File PCB ; CLI Parser Block w/position code ; Clock Queue Control Block w/type code ; Unused I/O Packet ; Logical Assignment Control Block w/type code ; MCR Command Line for Task ;=============================================================================* .PAGE .SBTTL OPA Entry Point OPA:: ;ENTRY POINT DIR$ #GMCR ;EMPTY OUR MCR BUFFER IF ONE EXISTS MOV $EXSIZ,POOLWD ;CALC. TOTAL POOL SPACE SUB #$POOL,POOLWD MOV POOLWD,MAPSIZ ;SET SIZE OF OUR MAP ASR MAPSIZ ; IN # SEGMENTS OF 4 BYTES EA. ASR MAPSIZ MOV #MAP,R0 ;SET MAP TO ALL '?????' FOR UNKNOWN/USED MOV MAPSIZ,R2 MOV #'?,R1 5$: MOVB R1,(R0)+ SOB R2,5$ MOV #THRLST,THREAD ;INIT THREADED ROUTINE LIST ADDRESS CALL $SWSTK,END ;GET ONTO SYSTEM STACK TO LOOK AT POOL MOV SP,OKSP ;SAVE SP FOR RESTORE ON ODD OR MP TRAP MOV @#PS,OKPS ;SAVE VALID PSW TOO MOV @#4,OLDODD ;SAVE OLD ODD ADDR. TRAP VECTOR MOV @#250,OLDMPV ; SAME FOR MEM. PROT. VIOLATION MOV #ODDTRP,@#4 ;PUT IN OUR OWN TRAP VECTORS MOV @MPVTRP,@#250 CLR BADPC ;CLEAR FLAG/BAD PC LOCATION MOV #FRLIST,R5 ;GET POINTER TO BUFFER AREA CLR R4 ;ZERO COUNT OF FRAGMENTS MOV #MAXFRG,R3 ;GET MAXIMUM # ENTRIES MOV $CRAVL,R2 ;GET LISTHEAD OF FREE POOL 10$: MOV R2,R0 ;SAVE CURRENT ADDRESS INC R4 ;FOUND FREE SEGMENT; COUNT IT SUB #$POOL,R0 ;CALC. ADDR. RELATIVE TO START OF POOL MOV R2,(R5)+ ;SAVE REL. ADDRESS MOV 2(R2),R1 ;GET SEGMENT SIZE MOV R1,(R5)+ ;THEN SAVE IT CALL MRKMP1 ;MARK THE MAP .WORD FREFIL ; WITH '-----' FOR FREE PIECES MOV (R2),R2 ;GET THE NEXT FREE SEGMENT ADDR. BEQ ENDFRE ;END IF POINTER TO NEXT IS ZERO SOB R3,10$ ;CONTINUE IF MORE ROOM IN LIST AREA ; ENDFRE: MOV R4,FRGMNT ;SAVE # FRAGMENTS ;+ ;AT THIS POINT, SYSTEM SP AND PS SHOULD BE CORRECT AND THREAD POINTS ; TO THE FIRST ENTRY IN THE THREADED ROUTINE LIST ;- NXTTHR: MOV @THREAD,R0 ;GET NEXT LIST ENTRY BEQ XITSYS ;IF ZERO, END OF TABLE ADD #2,THREAD ;ADVANCE POINTER TO NEXT ENTRY JMP (R0) ;GO DO THIS PHASE OF DECODING ;+ ;GO BACK TO USER STATE ;- XITSYS: MOV OLDODD,@#4 ;RESTORE STANDARD TRAP VECTORS MOV OLDMPV,@#250 RETURN ;RETURN TO USER STATE (TO END:) ;+ ;ENTRY HERE ON ODD ADDRESS OR MEM. PROTECT TRAPS ;- MPVTRP: INC (SP) ;FLAG MEM. PROTECT VIOLATIONS W/ ODD PC ODDTRP: MOV (SP),BADPC ;SAVE MOST RECENT PC FOR ERROR MESSAGE MOV OKSP,SP ;RESTORE VALID SP (ELIMINATE JUNK ON STACK) MOV OKPS,@#PS ; SAME FOR PSW BR NXTTHR ;THEN TRY NEXT THREADED CODE ENTRY .SBTTL TCB's / AD's / AST's / OCB's ;+ ;NOW MARK TCB'S W/ THEIR NAMES ;- STATCB: MOV $TSKHD,R4 ;GET FIRST TCB 10$: MOV R4,R0 ;COPY ADDR. FOR DESTRUCTIVE USE CALL GTMOFF ;GET MAP OFFSET BCS 22$ ;IF OUTSIDE POOL, JUST IGNORE IT MOV #TCBSTG,R1 ;INSERT ',(R0)+ ;FINISH OFF W/ CLOSING BRACKET 12$: MOV T.ATT(R4),R3 ;LOOK FOR ATTACHMENT DESCRIPTOR LIST BEQ 20$ ;NONE IF ZERO 15$: MOV R3,R0 ;MAKE A COPY FOR DESTRUCTIVE USE SUB #6,R0 ;ADJUST TO BEGINNING OF BLOCK CALL GTMOFF ;GET THE OFFSET FROM BEGINNING OF POOL BCS 20$ ;IGNORE IF OUTSIDE OF POOL MOVB #'<,(R0)+ ;MARK AREA WITH '' MOVB #'A,(R0)+ MOVB #'>,(R0)+ 18$: MOV (R3),R3 ;LOOK FOR MORE ATTACHMENTS BNE 15$ ; AND CONTINUE WITH THEM ;CHECK FOR VARIOUS AST CONTROL BLOCKS 20$: MOV T.SAST(R4),R3 ;CHECK FOR ANY SPECIFIED AST CONTROL BLOCKS CALL MRKAST ; & GO MARK THEM OFF MOV T.ASTL(R4),R3 ;Any active AST Block's queued? CALL MRKAST ; & GO MARK THEM OFF MOV T.OCBH(R4),R3 ;LOOK FOR OFFSPRING CONTROL BLOCKS BEQ 210$ ;QUIT SEARCH IF NONE 21$: MOV R3,R0 ;NEED COPY OF ADDRESS FOR DESTRUCTIVE USE CALL GTMOFF ;CONVERT TO MAP ADDRESS BCS 210$ ;QUIT SEARCH IF OUTSIDE MAP AREA CALL MRKOCB ;GO MARK THEM AS: '!PRNTNM' (PARENT NAME) MOV (R3),R3 ;GET NEXT OCB ADDRESS BNE 21$ ; & PROCESS IT (IF THERE IS ONE) 210$: MOV T.RCVL(R4),R3 ; Anything in Receive Data queue? BEQ 215$ ; If not, leave. 211$: MOV R3,R0 ; Save address. CALL GTMOFF ; Convert to MAP address. BCS 215$ ; Done if outside MAP area. MOVB #'/,(R0)+ ; Mark Receive Packet. CALL GTTSKN ; Copy in Task name. MOVB #'D,(R0)+ ; Mark as Receive Data. MOVB #'\,(R0)+ ; Close area. MOV (R3),R3 ; Get next one BNE 211$ ; if there is one. 215$: MOV T.RRFL(R4),R3 ; Anything in Receive by Reference queue? BEQ 219$ ; If not, leave. 216$: MOV R3,R0 ; Save address. CALL GTMOFF ; Convert to MAP address. BCS 219$ ; Done if outside MAP area. MOVB #'/,(R0)+ ; Mark Receive Packet. CALL GTTSKN ; Copy in Task name. MOVB #'R,(R0)+ ; Mark as Receive by Reference. MOVB #'\,(R0)+ ; Close area. MOV (R3),R3 ; Get next one BNE 216$ ; if there is one. 219$: ; Checkpointed file Sub-partition Control Block BIT #TS.CKP,T.STAT(R4) ; Is it checkpointed? BEQ 22$ ; No BIT #TS.OUT,T.STAT(R4) ; Is it out-of-memory? BEQ 22$ ; No MOV T.PCB(R4),R0 ; PCB address CALL GTMOFF ; Convert to Map address BCS 22$ ; Outside of Map MOVB #'(,(R0)+ ; Tag as "(cxxxxxx)" MOVB #'c,(R0)+ CALL GTTSKN ; Copy in Task name MOVB #'),(R0)+ ; Add terminator 22$: MOV T.TCBL(R4),R4 ;GET NEXT TCB BEQ ENDTCB ; UNTIL END OF LIST TST T.TCBL(R4) ;HAVE WE GOTTEN TO THE NULL TASK? BNE 10$ ;IF NO, CONTINUE ; ENDTCB: JMP NXTTHR ;GO DO NEXT ROUTINE .SBTTL Clock Queue Control Blocks '' MOVB #'C,(R0)+ ;WHERE n is REQUEST TYPE MOVB C.RQT(R3),R1 ;GET THE REQUEST TYPE CALL CNVASC ;PUT OUT AS ASCII MOVB #'>,(R0)+ 20$: MOV C.LNK(R3),R3 ;GET NEXT CONTROL BLOCK IF ANY BNE 10$ ; AND MARK THAT ONE ; ENDCLQ: JMP NXTTHR ;GO DO NEXT ROUTINE .SBTTL ASN Control Blocks '' ;+ ;Now mark CLI Parser Blocks ;- .IF DF A$$CLI STACPB: CLR R2 ; Initialize CLI count MOV #$CPTBL+2,R3 ; Point to 1st alternate CLI in table 10$: INC R2 ; CLI count MOV (R3)+,R0 ; Get CPB address in Pool BEQ ENDCPB ; Done if zero CALL GTMOFF ; Get offset into MAP BCS 20$ ; Ignore if outside Pool MOV #CPBSTG,R1 ; Mark with ',(R0)+ ; Add terminator 20$: CMP #$NMCLI-1,R2 ; Check if done BNE 10$ ; Not yet ENDCPB: JMP NXTTHR ; Go do next routine .ENDC ;A$$CLI .SBTTL PCB's / HDR's / WB's / Sub-PCB's ;+ ;NOW TRY TO DO PARTITION-CONTROL-BLOCKS ;- STAPAR: MOV $PARHD,R3 ;GET PTR TO 1ST PCB PARNXT: MOV R3,R0 ;MAKE A COPY TO CALCULATE MAP OFFSET CALL GTMOFF ;CONVERT TO BYTE OFFSET IN MAP BCS NXTPAR ;TRY NEXT IF OUTSIDE POOL MOVB #'(,(R0)+ ;MARK IT WITH A '(' CMP P.MAIN(R3),R3 ;IS THIS A 'MAIN' PARTITION? BNE NTMAIN MOVB #40,(R0)+ ;YES, NO SPECIAL SYMBOL INSERTED PARNM: MOV P.NAM(R3),R1 ;GET PARTITION NAME CALL $C5TA ; AND CONVERT TO ASCII MOV P.NAM+2(R3),R1 ;MARK AS '( PARNAM)' PARL: CALL $C5TA TRLPAR: MOVB #'),(R0) ;LOOK FOR TASK HEADERS IN POOL MOV P.HDR(R3),R0 ;SEE IF THIS PARTITION HAS A HEADER BEQ PARSYS ;NO IF ZERO MOV P.TCB(R3),R4 ;MAYBE, HAVE TO CHECK IF STILL IN MEMORY CMP T.PCB(R4),R3 ; Is it really the TCB for this PCB? BNE PARSYS ; If NE -- N0! ; TST P.ATT(R3) ; Is partition attached? ; BNE PARSYS ; If not, there should be no header. BIT #TS.OUT,T.STAT(R4) ;HEADER IS ALLOCATED UNTIL MARKED OUT BNE PARSYS ;IF OUT, THEN NO HEADER IN POOL MOV H.HDLN(R0),R1 ;IT'S THERE, GET IT'S LENGTH CALL GTMOFF ;GET OFFSET INTO MAP BCS PARSYS ;IF C SET, WASN'T IN POOL AREA MOV R0,-(SP) ;SAVE START OFFSET ADDRESS CALL MRKMP2 ;MARK THE WHOLE HEADER AREA .WORD HDRFIL ; Fill Area MOVB #'>,-(R0) ;MARK END W/ USUAL ANGLE BRACKET MOV (SP)+,R0 ;GET BACK BEGINNING OF HEADER MOV #HDRSTG,R1 ;INSERT '
' MOVB #'>,(R0)+ .IFDF V$$D11 ; This is for Stamerjohn's vd: disk driver CMP D.NAM(R3),#"VD ; Is it a VD: ? BNE ENDVDS ; Br if no MOV U.VCB+2(R2),R0 ; Any extension block ? BEQ ENDVDS ; Br if no CALL GTMOFF ; Get offset in map BCS ENDVDS ; Ignore if not in pool MOV R1,-(SP) ; Save the unit # MOV #VDASTG,R1 ; Point to starting '' CALL MOVSTG ; Stuff it ENDVDS: .ENDC ; V$$D11 ; NOW TRACK DOWN FILE-CONTROL-BLOCKS IN POOL FNDFCB: MOV U.VCB(R2),R1 ;GET THE VCB ADDRESS AGAIN MOV V.FCB(R1),R1 ;GET 1ST FCB CHKFCB: CMP R1,$EXSIZ ;IN POOL? BHI GETWB ;IF NOT, GIVE UP (ELSE HAVE TO MAP TO ACP) MOV R1,R0 ;COPY TO CONVERT TO MAP PTR CALL GTMOFF BCS GETWB ;GIVE UP ON THIS CHAIN IF OUTSIDE OF POOL MOV R1,-(SP) ;SAVE FCB FOR TRACING CHAIN MOV #FCBSTG,R1 ;MARK W/ ',-(R0) ; Add terminating char MOV U.VCB(R2),R0 ; Get address of VSCB again MOV V.MVL(R0),R0 ; Get address of Mounted Volume list CALL GTMOFF ; Get offset in Map BCS 20$ ; Ignore if outside Pool MOV #VMVLTG,R1 ; Mark '' INTO MAP CALL MOVSTG SUB #5,R0 ;BACK UP TO PUT IN ACTUAL DEVICE NAME & # MOV (SP),R1 ;RETREIVE DCB ADDRESS MOVB D.NAM(R1),(R0)+ ;COPY OVER DEVICE NAME MOVB D.NAM+1(R1),(R0)+ MOV UNITNO,R1 ;NOW GET CURRENT UNIT NUMBER CALL CNVASC ;CONVERT TO ASCII & INSERT IN MAP NXTPKT: TST R5 ;SEE IF LINK POINTS TO ANOTHER PACKET BEQ DOVEC ;IF NOT, OFF TO LOOK AT INTRP. VECTOR MOV R5,R0 ;GET COPY FOR DESTRUCTIVE USE MOV (R5),R5 ;ADVANCE POINTER TO POSSIBLE NEXT PACKET MOV CURPKT,R1 ;GET OLD PACKET ADDRESS BEQ IOPKT ;IF NONE, HAVE TO GET CONTENTS THE HARD WAY CALL GTMOFF ;CONVERT NEW PACKET ADDRESS TO MAP ENTRY BCS NXTPKT ;BACK FOR ANOTHER IF OUTSIDE POOL MOV #9.,-(SP) ;SET UP TO COPY 9 BYTES FROM OLD MAP ADDRESS 10$: MOVB (R1)+,(R0)+ DEC (SP) BNE 10$ TST (SP)+ ;CLEAR EXPENDED COUNT FROM STACK BR NXTPKT ; & BACK FOR POSSIBLE NEW PACKET DOVEC: MOVB S.VCT(R4),R5 ;THEN GET THE INTRP VECTOR ADDR. ASL R5 ;CONVERT TO ACTUAL ADDR ASL R5 CMP (R5),#$POOL ;DO WE HAVE AN INTRP-CONTROL-BLOCK IN POOL? BLO CLEANS ;IF NOT, GO TO NEXT UCB ; NOW LET'S MARK OFF AN ICB (OR POSSIBLY 2) CALL MRKICB ;DO MARKING VIA SUBROUTINE CMP (R5)+,(R5)+ ;THEN ADVANCE TO NEXT POSSIBLE VECTOR ADDR. CMP (R5),#$POOL ;IF THAT'S IN POOL, MAYBE DEVICE IS FULL-DUPLX BLO CLEANS ;IF NOT, GO RESTORE STACK/REGISTERS MOV (R5),R0 ;LOOK AT MAP CALL GTMOFF ; & SEE IF WE HAVE ANYTHING THERE BCS CLEANS ;QUIT IF BAD ADDRESS CMPB (R0),#'? ;SHOULD BE A '?' IF SO FAR UNIDENTIFIED BNE CLEANS CALL MRKICB ;IF SO, LET'S MARK AS PART OF THIS DEVICE ; IF WE'RE WRONG, WILL HOPEFULLY GET FIXED ; BY A LATER DEVICE INTRP VECTOR FIND CLEANS: MOV (SP),R0 ;GET FRESH COPY OF R0 FROM STACK NXTUCB: ADD D.UCBL(R0),R3 ;ADVANCE UCB POINTER TO NEXT UCB INC UNITNO ;INCR. UNIT # WE ARE TESTING DEC R2 ; & DECR. COUNT OF REMAINING UCB'S BNE TSTSCB ; & BACK TO TRY FOR ANOTHER UCB/SCB SUB D.UCBL(R0),R3 ;RESTORE UCB POINTER TO LAST GOOD UCB ADDR. CMP R0,#$POOL ;IS THIS DCB INSIDE POOL AREA? BLO NXTDCB ;NO IF LOWER, SO DONE W/ THIS DEVICE ; WE NOW HAVE ALL THE ASSOCIATED DATA STRUCTURES FOR THIS DEVICE. ; WE WILL ASSUME THAT THEY HAVE BEEN INSERTED IN STANDARD ORDER, I.E. ; DCB, UCB, SCB... ADD #S.MPR,R4 ;ADVANCE TO END OF SCB AREA BIT #FE.EXT,$FMASK ;DO WE HAVE TO WORRY ABOUT UMR AREA? BEQ 10$ BITB #UC.NPR,U.CTL(R3) ;YES, BUT IS THIS AN NPR DEVICE? BEQ 10$ ADD #12.,R4 ;YES, SO ADD IN SPACE FOR UMR ALLOCATION 10$: SUB R0,R4 ;CONVERT R4 TO SIZE OF AREA MOV R4,R1 ;SET UP FOR MARKING OFF AREA CALL GTMOFF ;CONVERT TO OFFSET IN POOL MAP MOV R0,-(SP) ;SAVE START OF AREA CALL MRKMP2 .WORD UCBFIL ;FILL AREA MOVB #'>,-(R0) ;END AREA W/ USUAL '>' MOV (SP)+,R0 ;RECOVER BEGINNING OF AREA MOV #DCBSTG,R1 ;INSERT ',(R0) ;FINISH OFF WITH ENDING DELIMITER MOV (R3),R3 ;GET NEXT MCR LINE ADDRESS BR 10$ ;AND GO TRY OUT THAT ONE ENDMCR: JMP NXTTHR ;GO DO NEXT ROUTINE .SBTTL Unused I/O Pkt's '' ;+ ;NOW GET ANY CURRENTLY UNUSED I/O PACKETS FROM I/O OPTIMIZATION ;- STAOPK: ;REF. LABEL .IF DF Q$$OPT MOV #$PKAVL,R2 ;GET POINTER TO PACKET TAIL MOV (R2)+,R0 ;GET ADDRESS OF 1ST PACKET BEQ ENDOPK ;DONE IF NONE AVAIL. MOVB (R2),R3 ;GET COUNT OF PACKETS AVAIL. OPKLUP: MOV R0,R2 ;SAVE COPY OF R0 CALL GTMOFF ;CONVERT TO OFFSET IN MAP BCS ENDOPK ;QUIT IF PACKET OUTSIDE POOL MOV #PKTOPT,R1 ;GET STRING ADDRESS TO INSERT IN MAP CALL MOVSTG ;INSERT '' MOV (R2),R0 ;GET NEXT PACKET ADDRESS SOB R3,OPKLUP ;ANY LEFT TO DO? .ENDC ;Q$$OPT ENDOPK: JMP NXTTHR ;GO DO NEXT ROUTINE .SBTTL Mount Control Blocks '' ;+ ;NOW FOR CHECKPOINT FILE PCB ;- STACKP: MOV $CFLPT,R3 ;GET LIST HEAD 10$: BEQ ENDCKP ;QUIT IF NO MORE ENTRIES MOV R3,R0 ;NEED A COPY FOR DISTRUCTIVE USE CALL GTMOFF ;CONVERT TO MAP ADDRESS BCS ENDCKP ;QUIT IF BAD ADDRESS MOV #CKPSTG,R1 ;LABEL W/ '' CALL MOVSTG MOV P.SUB(R3),R3 ;GET NEXT CP-PCB BR 10$ ; GO PROCESS IT ; ENDCKP: JMP NXTTHR ;GO DO NEXT ROUTINE .SBTTL Print Display of Pool Fragments ;+ ;NOW WE HAVE ALL THE DATA - WE NEED TO DISPLAY IT ;- END: ;REF. LABEL MOV #IO.ATT,QIO+Q.IOFN ;1ST ATTACH TERMINAL DIR$ #QIO MOV #IO.WVB,QIO+Q.IOFN ;THEN RESTORE TO NORMAL QIO MOV BADPC,R2 ;CHECK FOR TRAP WHILE ON SYSTEM STACK BEQ NOERR MOV #ODDMSG,R1 ;OOPS, DEFAULT TO ODD ADDRESS MESSAGE ASR R2 ;CHECK FOR FLAG FOR MEM. PROT VIOLATION BCC 10$ ;FLAG CLEAR IF EVEN ADDRESS MOV #MPVMSG,R2 ;WAS MEM. PROT. VIOLATION, CHANGE MESSAGE 10$: ASL R2 ;CONVERT BACK TO VALID PC CLR R3 ;SET FLAG FOR OCTAL PRINTOUT CALL PRMSNM ; AND OUTPUT MESSAGE W/ NUMBER NOERR: CMPB GMCR+G.MCRB+4,#'F ;INITIATED WITH 'OPA Free' COMMAND? BNE ENFRAG ;IF NO, SKIP FRAGMENT LIST MOV FRGMNT,R2 MOV #FRGMSG,R1 ;SET FOR MESSAGE ABOUT FRAGMENTS MOV PC,R3 ;SET FOR DECIMAL CONVERSION CALL PRMSNM ;PRINT #FRAGMENTS MOV POOLWD,R2 ASR R2 ;CONVERT TO # WORDS MOV #POOLMS,R1 CALL PRMSNM ;PRINT POOL SIZE MOV #TEXTBF,R0 ;OUTPUT MESSAGE ABOUT NEXT PRINTOUT MOV #SEGMSG,R1 ;IT'S LIST OF FREE SEGMENT ADDRS. CALL MOVSTG CALL OUTIT MOV FRGMNT,R5 ;SET LOOP COUNT FOR PRINTING MOV #FRLIST,R4 ;GET ADDRESS OF SEGMENT LIST CLR R3 ;ACCUMULATE SEGMENT LENGTHS IN R3 PRSEG: MOV (R4),R1 ;GET ADDRESS OF SEGMENT MOV #1,R2 ;NO ZERO SUPPRESSION MOV #TEXTBF,R0 ;SET START OF OUTPUT BUFFER CALL $CBOMG ;CONVERT TO OCTAL MOVB #'-,(R0)+ ;INSERT A DASH MOV (R4)+,R1 ;GET START ADDR. AGAIN ADD (R4),R1 ;ADD LENGTH DEC R1 ;ADJUST TO LAST FREE BYTE ADDRESS MOV #1,R2 ;NO ZERO SUPPRESS FOR OCTAL PRINTOUT CALL $CBOMG ;1ST PRINT VALUE IN OCTAL MOVB #40,(R0)+ ;SEPARATE VALUES W/ A SPACE MOV (R4)+,R1 ;RECOVER LENGTH TO PRINT IN DECIMAL ASR R1 ;CONVERT LENGTH TO WORDS ADD R1,R3 ;ACCUMULATE SEGMENT LENGTHS CLR R2 ;SUPPRESS ZEROS THIS TIME CALL $CBDMG ;CONVERT TO DECIMAL FOR SEGMENT LENGTH MOVB #'.,(R0)+ ;SHOW IT TO BE A DECIMAL VALUE CALL OUTIT SOB R5,PRSEG ;KEEP GOING UNTIL ALL SEGMENTS DONE MOV R3,R2 ;PRINT TOTAL OF FREE SEGMENTS MOV #NFRMSG,R1 MOV PC,R3 ;PRINT IN DECIMAL CALL PRMSNM ENFRAG: ;REF. LABEL .SBTTL Print Pool Map & Exit ;+ ;NOW PRINT MAP IN ROWS OF 64 CHARS. W/ ADDRESS OF EACH ROW ;- DIR$ #GTIM ; Get Date & Time MOV #DTEMSG+1,R0 ; Setup Date & Time Msg MOV #DTEBUF,R1 CALL $DAT ; Format Date dd-mm-yy MOV #DTEMSG+14,R0 MOV #2,R2 ; Format Time hh:mm CALL $TIM MOV #TEXTBF,R0 ;OUTPUT Date & Time MOV #DTEMSG,R1 CALL MOVSTG CALL OUTIT MOV #TEXTBF,R0 ;OUTPUT HEADER FOR MAP: MOV #MAPMSG,R1 CALL MOVSTG CALL OUTIT MOV #$POOL,R0 ;CALC. EVEN 100'S MAP ADDRESS TO START BIC #377,R0 MOV R0,POOLAD ;SAVE AS POOL ADDRESS MOV $EXSIZ,R5 ;CALC. MAP OUTPUT SIZE SUB R0,R5 ASR R5 ; IN # BYTES ASR R5 SUB #$POOL,R0 ASR R0 ;CONVERT TO MAP ADDRESS ASR R0 ADD #MAP,R0 MOV R0,MAPAD ;SAVE MAP ADDRESS PRTLUP: MOV POOLAD,R1 ;SET UP TO CONVERT POOL ADDRESS TO OCTAL ADD #400,POOLAD ;BUMP POOL ADDRESS TO NEXT LINE MOV #1,R2 ;SET FOR NO ZERO SUPPRESSION MOV #TEXTBF,R0 ;GET OUTPUT BUFFER ADDRESS CALL $CBOMG ;CONVERT TO OCTAL WORD MOVB #':,(R0)+ ;SEPARATE FROM MAP W/ ': ' MOVB #40,(R0)+ MOV MAPAD,R1 ;GET OUR CURRENT MAP ADDRESS MOV #64.,R4 ;SET R4 TO DEFAULT # BYTES/RECORD CMP R4,R5 ;IS THERE LESS REMAINING? BLE 10$ MOV R5,R4 ;YES, USE THE SMALLER # 10$: ADD R4,MAPAD ;ADVANCE MAP ADDRESS FOR NEXT RECORD SUB R4,R5 ;DECREASE #BYTES LEFT TO PRINT 11$: MOVB (R1)+,(R0)+ ;COPY MAP INTO BUFFER SOB R4,11$ ; UNTIL RECORD FILLED CALL OUTIT ;PRINT IT TST R5 ;ANYTHING LEFT TO PRINT? BNE PRTLUP ;IF SO, BACK FOR ANOTHER RECORD ; EXIT$S .SBTTL Subroutines ;+ ;SUBROUTINES ;- ;=============================================== ;PRMSNM: PRINT MESSAGE W/ TRAILING NUMBER ; ENTRY W/ R1 = ADDR. OF ASCIZ STRING TO OUTPUT ; R2 = VALUE TO APPEND ; R3 = FLAG FOR TYPE OF CONVERSION: ZERO=OCTAL, NON-ZERO=DECIMAL PRMSNM: MOV #TEXTBF,R0 ;SET START OF OUTPUT BUFFER CALL MOVSTG ;COPY IN THE TEXT MOVB #'=,(R0)+ ;SEPARATE MESSAGE FROM VALUE MOV R2,R1 ;GET THE VALUE TO CONVERT CLR R2 ;SUPPRESS LEADING ZEROS MOV R3,-(SP) ;SAVE R3 FOR USER REUSE BEQ CNVOCT ; AND CONVERT TO OCTAL IF FLAG WAS ZERO CALL $CBDMG ;CONVERT TO DECIMAL MAGNITUDE MOVB #'.,(R0)+ ;APPEND DECIMAL POINT BR RESR3 ; CNVOCT: CALL $CBOMG ;CONVERT TO OCTAL RESR3: MOV (SP)+,R3 ;RESTORE R3 OUTIT: SUB #TEXTBF,R0 ;CALC. LENGTH OF MESSAGE MOV R0,QIO+Q.IOPL+2 ;SET IN DIRECTIVE PARAM. BLOCK DIR$ #QIO ;PRINT # RETURN ;=============================================== ; MRKMAP: ;MAIN ENTRY POINT ;ENTRY WITH: R0=ABSOLUTE ADDRESS OF POOL ; R1=SIZE OF SEGMENT IN BYTES ; @0(SP)=CHAR. TO PUT IN MAP ; ENTRY AT MRKMP1 W/ R0=REL. ADDRESS IN POOL ; ENTRY AT MRKMP2 W/ R0= BYTE ADDRESS IN MAP ; ; EXIT W/ NO-OP & CARRY SET IF MAP OFFSET NEGATIVE, ELSE CARRY CLEAR SUB #$POOL,R0 ;ADJUST TO BEGINNING OF POOL MRKMP1: ASR R0 ;CONVERT TO SEGMENT NUMBER ASR R0 ADD #MAP,R0 ;GET START ADDRESS IN MAP MRKMP2: CMP R0,#MAP ;IN MAP AREA? BHIS 10$ SEC ;NO, FLAG ERROR RETURN ; & RETURN ; 10$: ADD #3,R1 ;ROUND SIZE TO NEXT LARGER #SEGMENTS ASR R1 ASR R1 STOCH: MOVB @0(SP),(R0)+ ;STUFF CHAR. IN MAP SOB R1,STOCH ; UNTIL ALL SEGMENTS MARKED ADD #2,(SP) ;MOVE RETURN PAST MARK CHARACTER CLC ;SHOW SUCCESSFUL OPERATION RETURN ;NOW DONE ;=============================================== ; GTMOFF: ;REF LABEL ; ENTERED W/ POOL ADDRESS IN R0 ; EXIT W/ MAP ADDRESS IN R0 ; RETURN W/ CARRY SET & NO-OP IF OUTSIDE POOL CMP R0,$EXSIZ ;ABOVE TOP OF POOL? BHI 5$ ;IF YES, SKIP CONVERSION SUB #$POOL,R0 ;1ST GET ADDR. REL TO START OF POOL BHIS 10$ ;LEGAL IF POSITIVE OFFSET 5$: SEC ;NO, SHOW ERROR CODE RETURN ; & EXIT W/O DOING ANYTHING ELSE ; 10$: ASR R0 ;THEN GET BLOCK # ASR R0 ADD #MAP,R0 ;FINALLY CALC. ACTUAL MAP ADDR. RETURN ;=============================================== ; CNVASC: ;REF LABEL ;ENTERED W/ HEX VALUE IN R1 ;EXIT W/ ASCII VALUE STORED @(R0)+ ADD #'0,R1 ;CONVERT TO ASCII CMP R1,#'9 ;USE HEX IF > 9. BLE 11$ ADD #<140-'9>,R1 ;BUMP TO ASCII 'a' 11$: MOVB R1,(R0)+ ;INSERT INTO MAP RETURN ;=============================================== ; MOVBYT: MOVB (R1)+,(R0)+ ;COPY A BYTE TO TARGET AREA MOVSTG: ;REF. LABEL ;ENTERED W/ OUTPUT ADDRESS IN R0 ; W/ INPUT ASCIZ STRING ADDRESS IN R1 TSTB (R1) ;AT END OF STRING? BNE MOVBYT RETURN ;NOT MUCH OF A ROUTINE, IS IT? ;=============================================== ; GPTSKN: ;REF. LABEL ;ENTERED W/ PCB ADDRESS IN R3 AT ENTRY GPTSKN ; OR W/ TCB ADDRESS IN R4 AT ENTRY GTTSKN ;OUTPUT IS TASK-NAME IN ASCII STORED AT ADDRESS IN R0 ; R0 IS UPDATED TO NEXT BYTE AFTER NAME MOV P.TCB(R3),R4 ;GET TCB ADDRESS TO GET TASK NAME GTTSKN: MOV T.NAM(R4),R1 ;GET TASK NAME FOR SUBPARTITION CALL $C5TA MOV T.NAM+2(R4),R1 CALL $C5TA ;CONVERT THIS 2ND HALF OF NAME RETURN ;DONE COPYING IN TASK NAME ;=============================================== ; MRKICB: ;REF. LABEL ;ENTERED WITH R5 CONTAINING A VECTOR ADDRESS WHICH APPEARS TO HAVE ; AN INTRP CONTROL BLOCK IN POOL MOV (R5),R1 ;GET ADDRESS OF ICB CMP (R1),#4537 ;IS THERE A CALL THERE TO PERHAPS INTSV? BEQ 10$ ;IF A CALL, PROBABLY OK CMP 6(R1),#4537 ;IF MULTI-CONTROLLER, THEN CALL IS FARTHER BNE 20$ ;ELSE IT'S SOMETHING WE CAN'T HANDLE FOR NOW 10$: CMP (R1)+,#207 ;LOOK FOR STANDARD END OF ICB BNE 10$ SUB (R5),R1 ;CALCULATE SIZE OF ICB MOV (R5),R0 ;GET START ADDR. INTO R0 CALL MRKMAP ;MARK OFF AREA W/ BLANKS .WORD ICBFIL ;(DON'T EXPECT IT TO BE LARGE) MOVB #'>,-(R0) ;PUT CLOSING MARK AT END MOV (R5),R0 ;GET BEGINNING AGAIN CALL GTMOFF ;(IN MAP COORDINATES) MOVB #'<,(R0)+ ;MARK AS: ',R1 ;ADJUST TO SIZE OF WHOLE WINDOW CALL GTMOFF ;GET START OF WINDOW POINTER IN MAP BCS XITWB ;SKIP THIS ONE IF OUTSIDE POOL MOV R0,-(SP) ;SAVE POINTER CALL MRKMP2 ;MARK OFF USED WINDOW AREA .WORD WBFIL ; WITH '=========' MOVB #'>,-(R0) ;STICK TRAILING DELIMITER ON MOV (SP)+,R0 ;GET BACK START ADDRESS MOVB #'<,(R0)+ ;STICK ' OUTBUF: ;REF. LABEL TEXTBF: .BLKW 40 GMCR: GMCR$ ;GET MCR LINE TO CLEAN POOL GTIM: GTIM$ DTEBUF ; Get Date & Time DTEBUF: .BLKW 8. .NLIST BEX ;DON'T NEED TO SEE ALL THE ASCII STRINGS ODDMSG: .ASCIZ /Odd Address Trap @ PC/ MPVMSG: .ASCIZ /Mem. Prot. Violation @ PC/ FRGMSG: .ASCIZ /# Free Pool Fragments/ POOLMS: .ASCIZ /Total Words of Pool/ NFRMSG: .ASCIZ /Total Free Words/ SEGMSG: .ASCIZ /Free Segment List:/ DTEMSG: .ASCIZ <14>/d-mmm-yy hh:mm/ MAPMSG: .ASCII /Pool Map................|...............|/ .ASCIZ /...............|.............../ IOP: .ASCIZ // TTEXT: .ASCIZ /[FDX TT:]/ BIOSTG: .ASCIZ /[BIO TT:]/ PKTOPT: .ASCIZ // HDRSTG: .ASCIZ /
/ .IFDF V$$D11 VDASTG: .ASCIZ // .ENDC PDVSTG: .ASCIZ /: )/ .EVEN .REPT 8. ;LEADING PAD OF BLANKS .ASCII / / .ENDR MAP:: .BLKB 6*1024. ;ENOUGH ROOM FOR 12.K WORDS OF POOL .END OPA