.TITLE DSRDMP ;DUMP DSR. .IDENT /02/ ;FIRST RELEASE. .ENABLE LC ; ; DESCRIPTION: ; THIS MODULE PERFORMS DUMPS ON THE SYSTEM'S DSR AREA. IT FIRST CALLS ; "DSRDM1" TASK TO DO A SNAPSHOT OF THE relevant parts of the EXEC, DSR ; and F11ACP, LOADING INTO THIS ; TASK IN BUFFER "OFFSET". THIS BUFFER IS LARGE ENOUGH TO HOLD A ; MAXIMUM OF 20K. ; ; ; THE DUMPS PERFORMED ARE: ; ; 1) SUMMARY OF AREAS THAT USE DSR. ; ; 2) BITMAP OF DSR USAGE ; ; 3) AREAS OF DSR THAT ARE NOT IN FREE LIST, AND CANNOT BE ACCOUNTED FOR. ; ; HISTORY: ; 01 13-DEC-78 D.ALDRIDGE ; 02 29-Jul-80 Phil Stephensen-Payne ; c/o Systime Ltd., ; Concourse Computer Centre, ; 432 Dewsbury Road, ; LEEDS LS11 7DF, ; England. ; ; ; .PAGE .SBTTL LOCAL Macros and Local Symbols .MCALL FSRSZ$,FINIT$,FDBDF$,FDOP$A,FDAT$A ; for FILES-11 .MCALL FDRC$A,FDBK$A,FDBF$A,NMBLK$ ; .MCALL OPEN$,CLOSE$,GET$,PUT$,ALTP$S,DSCP$S,ENCP$S ; .MCALL QIOW$S,EXIT$S,ALUN$S,GTIM$S,SVTK$S ;general use .MCALL SDAT$S, RQST$S, RCVD$S, MRKT$S, WTSE$S ,OPEN$W .MCALL TCBDF$,PCBDF$,HDRDF$,CLKDF$,PKTDF$,LCBDF$,DCBDF$,F11DF$ .MCALL UCBDF$,SCBDF$,HWDDF$,MTADF$,CVCDF$,EMBDF$,ITBDF$ TCBDF$ ; TCB offsets PCBDF$ ; PCB offsets HDRDF$ ; Task Header offsets CLKDF$ ; Clock Queue offsets PKTDF$ ; I/O Packet etc. offsets LCBDF$ ; LCB offsets L1.LGT=L.ASG+2 ; to avoid multiple definition ; (for LCB) DCBDF$ ; DCB offsets R$$11M=0 ; We must be on RSX-11M F11DF$ ; Files-11 VCB offsets L2.LGT=L.VB1+4 ; (for LDLB) UCBDF$ ; UCB offsets SCBDF$ ; SCB offsets MTADF$ ; ANSI VSCB/UVLB/MVLB offsets CVCDF$ ; Comms VCB offsets HWDDF$ ; Hardware registers & suchlike ITBDF$ ; ITB offsets EMBDF$ ; EMB offsets ; RTVSZ=6 ; 6 Bytes for an RTV FE.CLI=4000 ; Fake a function mask bit for M$$CLI ; ; K4= 4.*2048. ;4K (BYTES). K20= 20.*1024. ;20K (WORDS). ; TIMOUT= 50.*5 ;NUMBER OF TICKS TO ALLOW "DSRDM1". INPLUN=1 REPLUN=1 ; Same LUN for output (open serially) ERRLUN=2 DMPLUN=3 LOWPRI=50. ; Priority to lower ourselves to ; ; ; M A C R O S ; .MACRO FERR,X,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14 .IIF NB , MOV P1,RCVPKT ;Arguments for insertion .IIF NB , MOV P2,RCVPKT+2 .IIF NB , MOV P3,RCVPKT+4 .IIF NB , MOV P4,RCVPKT+6 .IIF NB , MOV P5,RCVPKT+8. .IIF NB , MOV P6,RCVPKT+10. .IIF NB , MOV P7,RCVPKT+12. .IIF NB , MOV P8,RCVPKT+14. .IIF NB , MOV P9,RCVPKT+16. .IIF NB , MOV P10,RCVPKT+18. .IIF NB , MOV P11,RCVPKT+20. .IIF NB , MOV P12,RCVPKT+22. .IIF NB , MOV P13,RCVPKT+24. .IIF NB , MOV P14,RCVPKT+26. MOV #I.'X,R1 ;Address of Error String JMP FERR .ENDM .MACRO DIAG,X,P1,P2,P3,P4 .IIF NB , MOV P1,RCVPKT .IIF NB , MOV P2,RCVPKT+2 .IIF NB , MOV P3,RCVPKT+4 .IIF NB , MOV P4,RCVPKT+6 MOV #I.'X,R1 CALL DIAG .ENDM ; ; .PAGE .SBTTL DATA General Data Areas ; ; M O D U L E D A T A B A S E ; ; ; OFFSET: .BLKW K20 ;BUFFER TO GET EXEC. ;(Should BE FIRST VARIABLE IN TASK) BITMAP: .BLKW K20/16. ;BITMAP FOR UP TO 20K EXEC+DSR. ; ; FSRSZ$ 1 ; DMPFDB: FDBDF$ ;DEFINE DUMP FDB. FDAT$A R.VAR,FD.CR ; FDRC$A ; FDOP$A DMPLUN,,DMPDFN ; DMPDFN: NMBLK$ DSRDMP,DMP ;FILENAME. ; REPFDB: FDBDF$ ;DEFINE REPORT FDB. FDAT$A R.VAR,FD.CR ; FDRC$A ; FDOP$A REPLUN,,REPDFN ; REPDFN: NMBLK$ DSRDMP,REP ;FILENAME. ; OUTFDB: .WORD ; Store for output FDB address ; INPFDB: FDBDF$ FDOP$A INPLUN,INPDSD,,FO.RD INPDSD: .WORD DEVL,DEVN .WORD DIRL,DIRN .WORD FILL,FILN DEVN: .ASCII /LB:/ DEVL=.-DEVN DIRN: .ASCII /[1,54]/ DIRL=.-DIRN FILN: .ASCII /RSX11M.STB/ FILL=.-FILN .EVEN ; LINCNT: .WORD 66. ; Line Count PAGCNT: .WORD ; Page Count RPTCNT: .WORD 0 ; DSR Line Repeat Count SHEAD: .WORD 0 ; Address of Subheading DSRDM1: .RAD50 \DSRDM1\ ;NAME OF TASK TO GIVE ME THE EXEC+DSR. OFFDIF: .WORD ; Current R4 offset RCVPKT: .BLKW 15. ;Packet BUFFER. REPBUF: ; Buffer for output BUFF: .BLKB 512. ; Buffer for input and $EDMSG output OUTBLK: .BLKB 80. ; To build error message in ARGBLK: .BLKW 25. ; Argument block for $EDMSG ENTNUM=25. NUMENT: .BLKW ENTNUM ;NUMBER OF ENTRIES COUNTERS. SIZENT: .BLKW ENTNUM ;SIZE OF ENTRIES. TCBNAM: .BLKW 2 ; Stored taskname from TCB DEVNAM: .WORD ; Device Name SCBADD: .WORD ; Address of last SCB SCBNUM: .BYTE ; Count of SCBs for device SCBERR: .BYTE ; Device Error Logging Flag DEVUNT: .WORD ; Device unit NUMUNT: .WORD ; Number of units for DCB CHWRD1: .WORD ; First Characteristics word from UCB UCBLEN: .WORD ; Saved UCB length UTSTA: .WORD ; Unit Triple Status Word (Full Dup TT) USTS: .BYTE ; Unit Status from UCB UCTL: .BYTE ; Unit Control Byte from UCB RPTFLG: .BYTE ; Repeat flag for DSR. HDRFLG: .BYTE ; PCB flag to indicate header required SSTTAB: .WORD SSTOD ; Odd Address Trap .WORD SSTMP ; Memory Protect .WORD SSTBE ; BPT .WORD SSTIO ; IOT .WORD SSTIL ; Reserved Instruction .WORD SSTEM ; Non-RSX EMT .WORD SSTTE ; TRAP .WORD SSTFP ; Floating Point SSTNUM: .WORD 0 ; Store for SST Number SYMTAB: ACTHD: .RAD50 /$ACTHD/ CFLPT: .RAD50 /$CFLPT/ CLKHD: .RAD50 /$CLKHD/ CRAVL: .RAD50 /$CRAVL/ DEVHD: .RAD50 /$DEVHD/ ERRHD: .RAD50 /$ERRHD/ EXSIZ: .RAD50 /$EXSIZ/ FMASK: .RAD50 /$FMASK/ FRKHD: .RAD50 /$FRKHD/ GGEF: .RAD50 /$GGEF/ LOGHD: .RAD50 /$LOGHD/ MCRCB: .RAD50 /$MCRCB/ MOULS: .RAD50 /$MOULS/ PARHD: .RAD50 /$PARHD/ PKAVL: .RAD50 /$PKAVL/ TSKHD: .RAD50 /$TSKHD/ UMRHD: .RAD50 /$UMRHD/ UMRWT: .RAD50 /$UMRWT/ SYMNM2=<.-SYMTAB>/4 .WORD 0,0 ; Force a file rewind DVCER: .RAD50 /$DVCER/ MCRPT: .RAD50 /$MCRPT/ SYMNM1=<.-SYMTAB>/4 PHDR: .RAD50 /P.HDR/ PLGTH: .RAD50 /P.LGTH/ TLGTH: .RAD50 /T.LGTH/ TOCBH: .RAD50 /T.OCBH/ XLEN: .RAD50 /X.LEN/ POOL: .RAD50 /$POOL/ SYMNUM=<.-SYMTAB>/4 SLGTH: .WORD ; Length of an SCB DLGTH: .WORD ; Length of a DCB TOTALO: .BLKW 1 ;TOTAL AREA ALLOCATED FOR DSR. TOTDSR: .BLKW 1 ;TOTAL SIZE OF DSR. .PAGE .SBTTL STRING ASCII Strings .NLIST BEX ; I.SND: .ASCIZ /DSRDMP - Send or Request Task for DSRDM1 Failed - DSW = %D/ I.TIM: .ASCIZ /DSRDMP - Timeout while waiting for DSRDM1/ I.RCV: .ASCIZ /DSRDMP - Error = %D returned by DSRDM1/ I.ERR: .ASCIZ /DSRDMP - Error = %D on output file/ I.RNGE: .ASCII /DSRDMP - Address %P not in relocatable range, / .ASCIZ /Return Address = %P/ I.NSYM: .ASCIZ /DSRDMP - Symbol %R%R not in RSX11M.STB/ I.OPNI: .ASCIZ /DSRDMP - Open Error = %D on RSX11M.STB/ I.JOB: .ASCIZ /DSRDMP - Job Complete/<7> I.SST: .ASCII /DSRDMP - SST Trap = %D at PC %P/<7><7> .ASCII /%N R0=%P, R1=%P, R2=%P, R3=%P/ .ASCIZ /%N R4=%P, R5=%P, R6=%P, (SP)=%P, OFFDIF=%P/ ; HDR1: .ASCII /%FRSX-11M DYNAMIC STORAGE REGION ANALYSER %Y/ .ASCIZ / %2Z PAGE %D%N/ HDRV: .ASCIZ /LOW VECTOR AREA%N/ HDRDV: .ASCIZ /DEVICE TABLES%N/ HDRFI: .ASCIZ /F11ACP%N/ HDRSY: .ASCIZ /SYSCM%N/ HDRP: .ASCIZ /POOL DUMP%N/ HDRT: .ASCIZ /TERMINAL CONTROL BLOCKS%N/ HDRQ: .ASCIZ /PARTITION CONTROL BLOCKS%N/ HDRF: .ASCIZ /FREE POOL%N/ HDRU: .ASCIZ /UNDETERMINED POOL%N/ HDRM: .ASCIZ /MISCELLANEOUS%N/ HDRS: .ASCIZ /SUMMARY%N/ HDRD: .ASCIZ /DEVICE CONTROL BLOCKS%N/ HDRC: .ASCIZ /SYSTEM COMMON LABELLED DUMP%N/ ; G.FRE: .ASCIZ / Free Pool from %P to %P/ G.TCB: .ASCIZ / TCB for %R%R from %P to %P/ G.ITB: .ASCIZ / ITB for %R%R from %P to %P/ G.RCV: .ASCIZ / Rcv Pkt for %R%R from %P to %P/ G.RRF: .ASCIZ / RRF Pkt for %R%R from %P to %P/ G.AST: .ASCIZ / AST Ctl Blk for %R%R from %P to %P/ G.OFF: .ASCIZ / OCB for %R%R from %P to %P/ G.ATT: .ASCIZ / Att Descr for %R%R from %P to %P/ G.PCB: .ASCIZ / PCB for %R%R from %P to %P/ G.HDR: .ASCIZ / Header for %R%R from %P to %P/ G.WND: .ASCIZ / Wndw Blk for %P,%P from %P to %P/ G.FCB: .ASCIZ / FCB for %P,%P from %P to %P/ G.LBL: .ASCIZ / LBLB for %P,%P from %P to %P/ G.DCB: .ASCIZ / DCB for %2A %14Sfrom %P to %P/ G.DDT: .ASCIZ / DDT for %2A %14Sfrom %P to %P/ G.UCB: .ASCIZ / UCB for %2A%O: %14Sfrom %P to %P/ G.SCB: .ASCIZ / SCB for %2A%O: %14Sfrom %P to %P/ G.VCB: .ASCIZ / VCB for %2A%O: %14Sfrom %P to %P/ G.IOP: .ASCIZ / IOP for %2A%O: %14Sfrom %P to %P/ G.ICB: .ASCIZ / ICB for %2A %14Sfrom %P to %P/ G.CLK: .ASCIZ / Clock Queue Entry %16Sfrom %P to %P/ G.CHK: .ASCIZ / Checkpoint PCB %19Sfrom %P to %P/ G.LCB: .ASCIZ / Logical Assignment Block %9Sfrom %P to %P/ G.GEF: .ASCIZ / Group Global EF Block %12Sfrom %P to %P/ G.MOU: .ASCIZ / Mounted Device Block %13Sfrom %P to %P/ G.FRK: .ASCIZ / Fork Queue Block %17Sfrom %P to %P/ G.MCR: .ASCIZ / MCR Command Line %17Sfrom %P to %P/ G.UMR: .ASCIZ / Mapping Assignment Block %9Sfrom %P to %P/ G.ERR: .ASCIZ / Error Message Block %14Sfrom %P to %P/ ; REPSYS: .ASCIZ / %R%R %P %R%R %P %R%R %P %R%R %P%N/ REPFRE: .ASCII /%N%N %D Pool Fragments, totalling %D words./ .ASCIZ /%N Largest Fragment = %D words./ RLNFRE=2 ; Extra lines RPT: .ASCIZ /%N%21S[ABOVE LINE REPEATED %D. TIMES]%N/ DSRLST: .ASCIZ / %P %P %P %P %P !%R %R %R %R!!%VE!/ REPTC1: .ASCII /%N%2S%U TCBS %38Scomprising %U words plus/ .ASCII /%N%9S%U Receive Packets %20Scomprising %U words/ .ASCIZ /%N%9S%U AST control blocks %17Scomprising %U words/ REPTC2: .ASCII /%9S%U Attachment Descriptors %13Scomprising %U words/ .ASCII /%N%9S%U Offspring Control Blocks %11Scomprising %U words/ .ASCIZ /%N%9S%U Interrupt Transfer Blocks %10Scomprising %U words/ REPTC3: .ASCIZ /%9S%U Dormant PCBs %23Scomprising %U words/ REPTOT: .ASCIZ /%N%54S Total: %U words/ RLNTCB=8. ; Number of extra lines REPPC1: .ASCII /%N%2S%U PCBs %38Scomprising %U words plus/ .ASCII /%N%9S%U Task Headers %23Scomprising %U words/ .ASCIZ /%N%9S%U Window Blocks %22Scomprising %U words/ REPPC2: .ASCII /%9S%U FCBs %31Scomprising %U words/ .ASCIZ /%N%9S%U LBLBs %30Scomprising %U words/ RLNPCB=6 REPSUM: .ASCII / Total DSR %19S%U words/ .ASCII /%N Total Allocated %13S%U words/ .ASCIZ /%N Total Undetermined %10S%U words/ REPMS1: .ASCII /%N%2S%U Checkpoint PCBs %27Scomprising %U words/ .ASCII /%N%2S%U Clock Queue Entries %23Scomprising %U words/ .ASCIZ /%N%2S%U Logical Assignment Blocks %17Scomprising %U words/ REPMS2: .ASCII /%2S%U Group Global EF Blocks %20Scomprising %U words/ .ASCII /%N%2S%U Mounted Device List Blocks %16Scomprising %U words/ .ASCIZ /%N%2S%U Fork Queue Control Blocks %17Scomprising %U words/ REPMS3: .ASCII /%2S%U MCR Command Lines %25Scomprising %U words/ .ASCII /%N%2S%U Error Message Blocks %22Scomprising %U words/ .ASCIZ /%N%2S%U Mapping Assignment Blocks %17Scomprising %U words/ RLNMSC=10. REPDC1: .ASCII /%N%2S%U DCBs %38Scomprising %U words plus/ .ASCII /%N%9S%U DDTs %31Scomprising %U words/ .ASCIZ /%N%9S%U UCBs %31Scomprising %U words/ REPDC2: .ASCII \%9S%U SCBs %31Scomprising %U words\ .ASCII /%N%9S%U VCBs %31Scomprising %U words/ .ASCIZ \%N%9S%U I/O Packets %24Scomprising %U words\ REPDC3: .ASCII /%9S%U FCBs %31Scomprising %U words/ .ASCII /%N%9S%U LBLBs %30Scomprising %U words/ .ASCIZ /%N%9S%U Window Blocks %22Scomprising %U words/ REPDC4: .ASCIZ /%9S%U ICBs %31Scomprising %U words/ RLNDCB=11. BLANKL: .ASCII / / BLANKZ= .-BLANKL ; Blank Line GUES: .ASCII <15><12>/Next Block Probably a Window Block/ .ASCII / for Checkpointed Task/ GUESL=.-GUES .EVEN .PAGE .SBTTL DSRDMP Main Routine .LIST BEX ; DSRDMP: ; DSCP$S ; Disable Checkpointing for now SVTK$S #SSTTAB,#8. ; Specify SST Table BIS #2000,$CBDMG+2 ; Force $EDMSG %U type to right-adjust ;****** This modifies a system routine FINIT$ ; ; ; For the System Common Labelled Dump we need all the variable names and ; their values. As STBRTN will overwrite the names we copy them into ; ARGBLK first. Note that we are using ARGBLK/NUMENT/SIZENT as 75 words ; of consecutive storage and will hit problems if we try to dump more ; than 25 variables, or if we use any of ARGBLK/NUMENT/SIZENT before ; outputting the variables. ; ALUN$S #ERRLUN,#"TI,#0 ; Assign the error LUN MOV #ARGBLK,R0 ; Get argument block address MOV #SYMTAB,R1 ; and symbol table address MOV #SYMNM2,R2 ; and number of symbols for labelled dump ; 5$: MOV (R1)+,(R0)+ ; Copy in symbol name MOV (R1)+,(R0)+ ; TST (R0)+ ; Leave space for address SOB R2,5$ ; Carry on CALL STBRTN ; Set up the STB values ; ; Now we get DSRDM1 to fill in our buffer with the Exec, DSR & F11ACP ; ; 10$: RCVD$S ,#RCVPKT ; CLEAN UP ANY PACKETS THAT BCC 10$ ; ARE OUTSTANDING. ; ; SEND "OFFSET" TO "DSRDM1", AND AWAIT REPLY. ; 40$: MOV #OFFSET,RCVPKT ;GIVE VALUE OF "OFFSET" SDAT$S #DSRDM1,#RCVPKT ; TO TASK "DSRDM1". BCS 60$ ;BRANCH IF IT FAILED. ; RQST$S #DSRDM1 ;RUN "DSRDM1". BCC 80$ ;BRANCH IF OK. ; 60$: FERR SND,$DSW ; Log the message and exit ; 80$: MOV #TIMOUT,R5 ;GET "DSRDM1" TIMEOUT COUNT. ; 100$: RCVD$S #DSRDM1,#RCVPKT ;GET A Packet from DSRDM1. BCC 140$ ; If OK carry on ; 120$: MRKT$S #2,#1,#1 ;WAIT FOR WTSE$S #2 ; A TICK. SOB R5,100$ ;TRY AGAIN. ; FERR TIM ; Log Timeout ; ; TEST IF "DSRDM1" SAID SUCCESSFUL. ; 140$: TST RCVPKT+4 ;BRANCH IF BEQ 145$ ; OK. FERR RCV,RCVPKT+4 ; Log the error ; ; OFFSET has been filled in with the relevant areas of the Exec, DSR ; and F11ACP, but the descriptors defining these areas still contain the ; addresses relative to the Exec. We must now modify them so that they ; are relative to our task. ; As the vital stuff is now over we can re-enable checkpointing and ; drop our priority. ; 145$: ENCP$S ; Reenable checkpointing ALTP$S ,#LOWPRI ; Lower our priority MOV #OFFSET,R0 ; First finish setting up first bit MOV #3,R1 ; Three calculations MOV R0,4(R0) ; Store first offset ADD #24.,4(R0) ; Allow for specials at start ; 150$: MOV 4(R0),R2 ; Get last offset TST (R0)+ ; Ignore last start address ADD (R0)+,R2 ; Add last end address TST (R0)+ ; Skip over old offset SUB (R0),R2 ; Subtract current virtual address MOV R2,4(R0) ; Store new offset SOB R1,150$ ; and so on ADD #2,POOL ; Round the start of pool address to.. BIC #2,POOL ; ..DSR granularity ; ; Now we can fill in the values for the variables in the System Common ; Labelled Dump and output the report. ; MOV #ARGBLK,R0 ; Get argument block address MOV #SYMTAB,R1 ; and symbol table address MOV #SYMNM2,R2 ; and number of symbols for labelled dump ; 155$: TST (R0)+ ; Skip over name TST (R0)+ ; MOV (R1),R3 ; Get un-relocated address BEQ 157$ ; If EQ doesn't exist - skip relocation ADD OFFSET+10.,R3 ; Relocate the address (must all be in SYSCM) MOV (R3),(R0)+ ; Insert contents of location ; 157$: MOV R3,(R1)+ ; Replace relocated address TST (R1)+ ; Skip over irrelevant word SOB R2,155$ ; Carry on MOV #SYMNM1-SYMNM2,R2 ; Get number left to relocate ; 158$: TST (R1) ; Does symbol exist? BEQ 159$ ; If EQ no - don't relocate it ADD OFFSET+10.,(R1) ; Yes - relocate it ; 159$: TST (R1)+ ; Skip past word TST (R1)+ ; Skip over irrelevant word SOB R2,158$ ; Carry on ; ; Output the System Common Labelled Dump ; CALL OPEND ;OPEN Dump FILE. MOV #HDRC,SHEAD ; Set up the sub-heading MOV #ARGBLK,R2 ; Get the address of the arguments MOV #SYMNM2/4,R3 ; Get number of complete lines ; 160$: MOV #REPSYS,R1 ; Address of skeleton CALL EDIT1 ; Edit and output it SOB R3,160$ ; MOV #SYMNM2,R1 ; Calculate number left BIC #177774,R1 ; BEQ 165$ ; If EQ none - finished MUL #13.,R1 ; Yes - calculate equivalent end-of-string CLRB REPSYS(R1) ; Truncate the skeleton MOV #REPSYS,R1 ; and output last line CALL EDIT1 ; ; 165$: ; ; Most of the characteristics we are interested in are defined either ; in SYSGEN-independent macro definitions or in the RSX11M.STB file. ; However there are a few that must be calculated by more esoteric means:- ; ; Length of a DCB: ; ; #D.PCB - Basic ; +2 - for systems with Loadable Driver Support ; ; Length of an SCB: ; ; #S.FRK+10 - Basic ; +2 - for systems with Loadable Driver Support ; ; Whether M$$CLI was defined: ; ; If the word after $MCRPT has an odd value then it was (for in ; that case the word holds .BYTE 15,12), otherwise it was not ; (for in that case the word holds a TCB address) ; MOV #S.FRK+10,SLGTH ; Initialise SCB length MOV #D.PCB,DLGTH ; Initialise DCB length BIT #FE.DRV,@FMASK ; Loadable Driver Support? BEQ 170$ ; If EQ no - check for extended memory ADD #2,SLGTH ; Yes - allow a word in the SCB ADD #2,DLGTH ; Yes - allow a word in the DCB ; 170$: MOV MCRPT,R0 ; Get address of $MCRPT ADD #2,R0 ; Set to either CLI string or a TCB address BIT #1,(R0) ; Which is it? BEQ 183$ ; If EQ cannot be M$$CLI defined BIS #FE.CLI,@FMASK ; M$$CLI is defined ; 183$: ; ; Now for convenience we allocate all the words that precede or follow DSR ; MOV POOL,R5 ;GET NUMBER OF ASR R5 ; WORDS THAT BIC #100000,R5 ; PRECEDE DSR. CLR R4 ;START ADDRESS OF EXEC TO ALLOCATE. CLR R3 ;ALLOCATE AREA CALL ALOCATE ; PRECEDING EXEC. ; MOV @EXSIZ,R4 ;GET ADDRESS OF END OF DSR. MOV R4,R3 ;CONVERT TO NUMBER ASR R3 ; OF WORDS BIC #100000,R3 ; IN EXEC+DSR. MOV #K20,R5 ;GET NUMBER OF WORDS THAT FOLLOW SUB R3,R5 ; EXEC+DSR (NOT USED). CLR R3 ;ALLOCATE UNUSED AREA CALL ALOCATE ; FOLLOWING EXEC+DSR. CLR TOTALO ;PREPARE TO GENERATE TOTAL KNOWN DSR ALLOCATED. ; ; Dump the Low Vector Area ; MOV #HDRV,SHEAD ; Set up Sub-Heading MOV #OFFSET,R4 ; Get start address of data MOV (R4)+,R0 ; Get start address MOV (R4)+,R1 ; Get end address MOV (R4)+,OFFDIF ; And the offset difference INCB RPTFLG ; We don't want repeats flagged CALL 190$ ; Dump it to the dump file ; ; Dump SYSCM ; MOV #HDRSY,SHEAD ; Set up Sub-Heading MOV (R4)+,R0 ; Get start address MOV (R4)+,R1 ; Get end address MOV (R4)+,OFFDIF ; And the offset difference INCB RPTFLG ; We don't want repeats flagged CALL 190$ ; Dump it to the dump file ; ; Dump the Device Tables ; MOV #HDRDV,SHEAD ; Set up Sub-Heading MOV (R4)+,R0 ; Get start address MOV (R4)+,-(SP) ; Save end address MOV POOL,R1 ; Get the end address MOV (R4)+,OFFDIF ; And the offset difference INCB RPTFLG ; We don't want repeats flagged CALL 190$ ; Dump it to the dump file ; ; Dump all of pool ; MOV #HDRP,SHEAD ; Set up address of sub-heading MOV POOL,R0 ; Start of pool MOV (SP)+,R1 ; end of pool CLRB RPTFLG ; We want repeats flagged as such CALL 190$ ; Output the report ; ; Dump F11ACP ; MOV #HDRFI,SHEAD ; Set up Sub-Heading MOV (R4)+,R0 ; Get start address MOV (R4)+,R1 ; Get end address MOV (R4)+,OFFDIF ; And the offset difference CLRB RPTFLG ; We want repeats flagged as such CALL 190$ ; Dump it to the dump file BR 200$ ; Branch around subroutine ; ; Output Memory Dump ; 190$: MOV #66.,LINCNT ; Force a new line SUB R0,R1 ; Length of area ASR R1 ; " " (in words) CALL REPOR1 ; Format & output it RETURN ; 200$: CALL OPENR ; Close Dump File & Open Report File ; ; ALLOCATE ALL KNOWN LISTS/TABLES IN DSR. ; MOV #HDRF,SHEAD ; Set up address of sub-heading MOV #66.,LINCNT ; Force new page CALL FRE ;FREE POOL. MOV #HDRT,SHEAD ; Set up address of sub-heading MOV #66.,LINCNT ; Force new page CALL TCB ;TASKS. MOV #HDRQ,SHEAD ; Set up address of sub-heading MOV #66.,LINCNT ; Force new page CALL PCB ;PARTITIONS AND HEADERS. MOV #HDRD,SHEAD ; Set up address of sub-heading MOV #66.,LINCNT ; Force new page CALL DCB ;DEVICE CONTROL BLOCKS. MOV #HDRM,SHEAD ; Set up address of sub-heading MOV #66.,LINCNT ; Force new page CALL MISC ; MISCELLANEOUS ; ; FINISH REPORT 1 WITH SUMMARY OF DSR USAGE. ; MOV #66.,LINCNT ; Force a new line MOV #HDRS,SHEAD ; Set up address of sub-heading MOV OFFSET+16.,OFFDIF ; All must be in pool MOV @EXSIZ,R3 ;CALCULATE TOTAL SUB POOL,R3 ; SIZE OF ASR R3 ; DSR IN BIC #100003,R3 ; WORDS. MOV R3,ARGBLK ;(SAVE IT). MOV TOTALO,ARGBLK+2 ; Get Size Allocated MOV ARGBLK+2,ARGBLK+4 ; Calculate the difference NEG ARGBLK+4 ; ADD R3,ARGBLK+4 ; MOV #REPSUM,R1 ; Print the report CALL EDIT ; ; ; REPORT 2, DSR BITMAP. ; CALL REPMAP ; ; ; REPORT 3, UNALLOCATED DSR. ; MOV #66.,LINCNT ; Force a new line MOV #HDRU,SHEAD ; Set up address of sub-heading CALL REPUNA ; ; ; EXIT. ; EXIT: DIAG JOB ; Report Job Completion CLOSE$ OUTFDB ; Close the output file EXIT$S ; .PAGE .SBTTL FRE ALLOCATE FREE POOL. ; ; DESCRIPTION: ; ALLOCATE KNOWN FREE POOL. ; ; Remarks: ; This allocates all free pool as defined in the list chained from ; $CRAVL and also any unused pre-allocated I/O packets as defined in the ; list chained from $PKAVL. ; FRE: MOV OFFSET+16.,OFFDIF ; All must be in pool CALL CLRNS ;PREPARE GENERATE STATISTICS MOV @CRAVL,R4 ;GET ADDRESS OF FIRST FREE BLOCK. BEQ 40$ ;BRANCH IF NONE. ; 20$: ADD OFFDIF,R4 ; Offset to table address MOV 2(R4),R5 ;GET SIZE OF FREE ASR R5 ; BLOCK (IN WORDS). BIC #100000,R5 ; CMP R5,SIZENT+2 ;RESET IF NEW BLE 30$ ; LARGEST SIZED MOV R5,SIZENT+2 ; ENTRY. ; 30$: CLR R3 ;ALLOCATE CALL ALOCT1 ; BLOCK. MOV #ARGBLK,R0 ; Set up line report MOV 2(R4),2(R0) ; Insert length of element MOV #G.FRE,R1 ; Get address of report line skeleton CALL LINREP ; Output the report line MOV (R4),R4 ;GET ADDRESS OF NEXT BLOCK. BNE 20$ ;GO BACK AND ALLOCATE IT. ; ; 40$: MOV PKAVL,R4 ; Get address of address of ; first pre-allocated I/O pkt MOV #I.LGTH/2,R5 ; and the length (in words) CLR R3 ; 1st entry MOV #ARGBLK,R0 ; Get address of argument block MOV #I.LGTH,2(R0) ; Insert length MOV #G.FRE,R1 ; Get address of skeleton CLR R2 ; Linked through first word CALL COMLNK ; Allocate and report the queue ; MOV #ARGBLK,R0 ; Get address of argument block MOV NUMENT,(R0)+ ; Insert number of fragments MOV SIZENT,(R0)+ ; and total size MOV SIZENT+2,(R0)+ ; and largest fragment ADD #RLNFRE,LINCNT ; Increment line count first MOV #REPFRE,R1 ; Get address of skeleton CALL EDIT ; Edit and output it RETURN ; .PAGE .SBTTL TCB ALLOCATE TASK CONTROL BLOCKS. ; ; DESCRIPTION: ; ALLOCATE SPACE USED BY ALL TASK CONTROL BLOCKS. THIS INCLUDES ; LISTS ASSOCIATED WITH THE TCB. ; ; Remarks: ; The TCBs are chained via T.TCBL from $TSKHD (the STD). ; The second linked list via T.ACTL from $ACTHD (the ATL) is a duplication. ; The link T.LNK is used for linking TCBs into other queues. ; All TCBs in a system have the same length - T.LGTH bytes. ; ; The associated lists handled here are:- ; ; Interrupt Transfer Blocks ; Receive Packets ; Receive by Reference Packets ; Attachment Descriptors ; Offspring Control Blocks ; Specified AST Control Blocks ; Pending AST Control Blocks ; ; Checkpoint PCBs which are also referenced in the TCB are more readily ; handled elsewhere. ; ; TCB: MOV OFFSET+16.,OFFDIF ; All must be in pool CALL CLRNS ;PREPARE GENERATE STATISTICS MOV @TSKHD,R4 ;GET ADDRESS OF FIRST TASK. ; 20$: CMP R4,OFFSET+12. ; Below DSR? (i.e. the Loader) BLO 40$ ; If LO yes - we've done the lot ADD OFFDIF,R4 ; Offset R4 to table address MOV T.TCBL(R4),-(SP) ;SAVE ADDRESS OF NEXT TASK. CALL TCBX ;ALLOCATE THAT TCB and its lists MOV (SP)+,R4 ;GO BACK TO BR 20$ ; DO NEXT. ; 40$: MOV #RLNTCB-1,R3 ; Get the number to move CALL COPENT ; Copy the data entries to the argument block ADD #RLNTCB,LINCNT ; Count extra lines needed first MOV #REPTC1,R1 ; Get address of report skeleton CALL EDIT ; Edit and output it SUB #RLNTCB,LINCNT ; Recount extra lines needed first MOV #REPTC2,R1 ; Get address of second half CALL EDIT1 ; Do that as well MOV #REPTC3,R1 ; Get address of third half CALL EDIT1 ; Do that as well MOV #REPTOT,R1 ; and the totals line CALL EDIT1 ; RETURN ; ; TCBX: ;ALLOCATE A TCB & LISTS. MOV TLGTH,R5 ;GET SIZE OF A BLOCK IN WORDS. ASR R5 ; CLR R3 ;ALLOCATE FOR CALL ALOCT1 ; THAT TCB. MOV #ARGBLK,R0 ; Set up line report MOV T.NAM(R4),(R0)+ ; Insert TCB name MOV T.NAM+2(R4),(R0)+ ; MOV TLGTH,2(R0) ; Insert length of element MOV #G.TCB,R1 ; Get address of report line skeleton CALL LINREP ; Output the report line MOV #ARGBLK+4,R0 ; Reset R0 MOV R4,-(SP) ; Save relocated TCB address ; ; Interrupt Transfer Blocks. ; These can only exist for non-checkpointable tasks, so we check the ; bit T2.CHK in T.ST2 of the TCB. ; The first is linked from T.CPCB and all others via X.LNK from the previous. ; All ITBs are fixed length - X.LEN bytes. ; They contain no information on further DSR usage. ; BIT #T2.CHK,T.ST2(R4) ; Task checkpointable? BEQ 10$ ; If EQ yes - cannot have ITBs MOV #G.ITB,R1 ; No - Get Report Line Skeleton Address MOV #X.LNK,R2 ; Get offset in element to address of next MOV #10.,R3 ; Set NUMENT/SIZENT offset ADD #T.CPCB,R4 ; Offset to address of address of first MOV XLEN,R5 ; Get the length in bytes MOV R5,2(R0) ; Store it in the argument block ASR R5 ; Convert it to words CALL COMLNK ; Call the common routine ; ; Receive Packets. ; The first is linked from T.RCVL and all others via 0 from the previous. ; All pkts are fixed length - I.LGTH bytes. ; They contain no information on further DSR usage. ; 10$: MOV (SP),R4 ; Restore the TCB address MOV #G.RCV,R1 ; Get Report Line Skeleton Address CLR R2 ; Get offset in element to address of next MOV #2,R3 ; Set NUMENT/SIZENT offset ADD #T.RCVL,R4 ; Offset to address of address of first MOV #I.LGTH/2,R5 ; Get the length in words MOV #I.LGTH,2(R0) ; and in bytes CALL COMLNK ; Call the common routine ; ; Receive by Reference Packets. ; These only occur in systems with PLAS support. ; The first is linked from T.RRFL and all others via 0 from the previous. ; All pkts are fixed length - I.LGTH bytes. ; They contain no information on further DSR usage. ; BIT #FE.PLA,@FMASK ; Does system have PLAS support? BEQ 20$ ; If EQ no - omit PLAS stuff MOV (SP),R4 ; Restore the TCB address MOV #G.RRF,R1 ; Get Report Line Skeleton Address ADD #T.RRFL,R4 ; Offset to address of address of first CALL COMLNK ; Call the common routine ; ; Attachment Descriptors. ; These also only occur for systems with PLAS support. ; The first is linked from T.ATT and all others via A.TCBL from the previous. ; All Attachment Descriptors are fixed length - A.LGTH bytes. ; They contain no information on further DSR usage. ; MOV (SP),R4 ; Restore the TCB address MOV #G.ATT,R1 ; Get Report Line Skeleton Address MOV #A.TCBL,R2 ; Get offset in element to address of next MOV #6,R3 ; Set NUMENT/SIZENT offset ADD #T.ATT,R4 ; Offset to address of address of first MOV #A.LGTH/2,R5 ; Get the length in words MOV #A.LGTH,2(R0) ; and in bytes CALL COMLNK ; Call the common routine ; ; Offspring Control Blocks. ; These exist only on systems with Parent/Offspring Tasking. ; The first is linked from T.OCBH and all others via O.LNK from the previous. ; All OCBs are fixed length - O.LGTH bytes. ; They contain the address in DSR of the passed command line, but ; this can more logically be picked up later. ; 20$: BIT #FE.OFF,@FMASK ; Does system have Parent/Offspring support? BEQ 30$ ; If EQ no - omit OCBs MOV (SP),R4 ; Restore the TCB address MOV #G.OFF,R1 ; Get Report Line Skeleton Address MOV #O.LNK,R2 ; Get offset in element to address of next MOV #8.,R3 ; Set NUMENT/SIZENT offset ADD TOCBH,R4 ; Offset to address of address of first MOV #O.LGTH/2,R5 ; Get the length in words MOV #O.LGTH,2(R0) ; and in bytes CALL COMLNK ; Call the common routine ; ; Specified ASTs. ; The first is linked from T.SAST and all others via 0 from the previous. ; All Specified AST blocks are fixed length - C.LGTH bytes. ; They contain no information on further DSR usage. ; 30$: MOV (SP),R4 ; Restore the TCB address MOV #G.AST,R1 ; Get Report Line Skeleton Address CLR R2 ; Get offset in element to address of next MOV #4,R3 ; Set NUMENT/SIZENT offset ADD #T.SAST,R4 ; Offset to address of address of first MOV #C.LGTH/2,R5 ; Get the length in words MOV #C.LGTH,2(R0) ; and in bytes CALL COMLNK ; Call the common routine ; ; Pending AST Control Blocks ; The first is linked from T.ASTL and all others via 0 from the previous. ; Pending AST Control Blocks are variable length as follows:- ; If A.CBL (byte) > 0 then length = A.CBL (byte) bytes ; If A.CBL (byte) = 200 then length = #I.LGTH bytes ; If A.CBL (byte) = 300 then length = #O.LGTH bytes ; If A.CBL (word) = 0 then length = 6 bytes and block starts ; 2 bytes before link word ; If A.CBL (byte) = 0 but A.CBL (word) <> 0 the length = #C.LGTH bytes ; They contain no information on further DSR usage. ; MOV (SP),R4 ; Restore the TCB address ADD #T.ASTL,R4 ; Set to address of address of first ; 40$: MOV (R4),R4 ; Get address of next BEQ 90$ ; If EQ end of list - exit CALL RELOC4 ; Else relocate it BCS 90$ ; If CS can't - exit MOV R4,-(SP) ; Save address of link word MOVB A.CBL(R4),R5 ; Get the type/length byte BGT 70$ ; If GT it was the length - finished BNE 50$ ; If NE not 0 - keep checking MOV #C.LGTH,R5 ; Assume Specified AST TSTB A.CBL+1(R4) ; Was it BNE 70$ ; If NE yes - we got the length MOV #6,R5 ; No - its the weird kind SUB #2,R4 ; BR 70$ ; Do the reporting and all ; 50$: CMPB R5,#200 ; For terminal input buffering BNE 60$ ; If ne no - keep checking MOV #I.LGTH,R5 ; Yes - set length BR 70$ ; Branch to common code ; 60$: MOV #O.LGTH,R5 ; Must be OCB ; 70$: MOV #4,R3 ; Set NUMENT/SIZENT offset MOV R5,ARGBLK+6 ; Store length for later ASR R5 ; Convert to words CALL ALOCT1 ; Allocate it BCS 80$ ; If CS not in DSR - omit line report MOV #ARGBLK+4,R0 ; Set up argument block address MOV #G.AST,R1 ; and line skeleton address CALL LINREP ; report the line ; 80$: MOV (SP)+,R4 ; Restore the link word address BR 40$ ; Do the next one ; 90$: ; ; Partition Control Blocks. ; For tasks that are out of memory, the only link to the PCB ; (which still resides in DSR) is via the TCB. ; MOV (SP),R4 ; Get the TCB address back BIT #TS.EXE,T.STAT(R4) ; Is it executing? BNE 100$ ; If NE no - carry on BIT #TS.OUT,T.STAT(R4) ; Is it Out of Memory? BEQ 100$ ; If EQ no - ignore it MOV T.PCB(R4),R4 ; Yes - get the PCB address CALL RELOC4 ; Relocate it BCS 100$ ; If CS we can't - error MOV P.TCB(R4),R1 ; Get the TCB address corresponding ADD OFFDIF,R1 ; Relocate it CMP R1,(SP) ; Does it correspond? BNE 100$ ; If NE no - ignore it (2 tasks in TASK ptn) MOV #12.,R3 ; Set SIZENT/NUMENT offset CLRB HDRFLG ; Say there is no header CALL PCBX ; Allocate the PCB ; 100$: TST (SP)+ ; Throw away TCB address RETURN ; .PAGE .SBTTL PCB ALLOCATE PARTITIONS CNTRL BLOCKS, HEADERS. ; ; ; DESCRIPTION: ; ALLOCATE ALL PARTITION CONTROL BLOCKS, AND ANY ASSOCIATED TASK ; HEADERS. ; ;Remarks: ; PCBs for main partitions are chained via P.LNK from $PARHD. ; PCBs for sub-partitions are chained via P.SUB from main partitions. ; PCBs are fixed length - P.LGTH bytes. ; ; This section also allocates the following areas:- ; ; Task Headers ; Task File Windows ; Task File Control Blocks ; Task File Window Locked Block Lists ; ; Note that this section does not handle the Attachment Descriptors pointed ; to by the PCB as they were already allocated with the TCBs. ; ; PCB: CALL CLRNS ;PREPARE GENERATE STATISTICS MOV @PARHD,R4 ;GET ADDRESS OF FIRST PARTITION. BEQ 80$ ; NONE ; 20$: CALL RELOC4 ; Relocate R4 BCS 80$ ; Give up if we can't MOV P.LNK(R4),-(SP) ;SAVE ADDRESS OF NEXT MAIN-PARTITION. MOV P.SUB(R4),-(SP) ;SAVE ADDRESS OF FIRST SUB-PARTITION. CLR R3 ; THE MOVB #1,HDRFLG ; Say there might be a header CALL PCBX ;ALLOCATE MAIN PARTITION. ; 40$: MOV (SP)+,R4 ;GET ADDRESS OF NEXT SUB-PARTITION. BEQ 60$ ;BRANCH IF NONE. CALL RELOC4 ; Relocate R4 BCS 60$ ; Give up if we can't MOV P.SUB(R4),-(SP) ;SAVE ADDRESS OF NEXT SUB-PARTITION. CLR R3 ; THE MOVB #1,HDRFLG ; Say there might be a header CALL PCBX ;ALLOCATE SUB-PARTITION. BR 40$ ;GO BACK FOR NEXT. ; 60$: MOV (SP)+,R4 ;GET ADDRESS OF NEXT MAIN-PARTITION. BNE 20$ ;GO BACK IF MORE. ; 80$: MOV #RLNPCB-1,R3 ; and the number to move CALL COPENT ; Copy the data entries over ADD #RLNPCB,LINCNT ; Count extra lines needed first MOV #REPPC1,R1 ; Get address of report skeleton CALL EDIT ; Edit and output it SUB #RLNPCB,LINCNT ; Recount extra lines needed first MOV #REPPC2,R1 ; and the second bit CALL EDIT1 ; MOV #REPTOT,R1 ; and the totals line CALL EDIT1 ; RETURN ; ; PCBX: ; Allocate a PCB, Header & Lists MOV P.NAM(R4),TCBNAM ; Initialise name to partition name MOV P.NAM+2(R4),TCBNAM+2 ; BIT #PS.COM!PS.DRV,P.STAT(R4) ; Common or Driver partition? BNE 10$ ; If NE yes - no taskname MOV P.TCB(R4),R1 ; Get TCB address BEQ 10$ ; If EQ no TCB => No Taskname ADD OFFDIF,R1 ; Offset it MOV T.NAM(R1),TCBNAM ; Store the taskname MOV T.NAM+2(R1),TCBNAM+2 ; BIT #TS.EXE!TS.OUT,T.STAT(R1) ; Task not executing and/or out of memory BEQ 10$ ; If EQ no - carry on BIS #PS.OUT,P.STAT(R4) ; Flag partition for no header ; 10$: MOV PLGTH,R5 ;ALLOCATE ASR R5 ; CALL ALOCT1 ; PCB. MOV #ARGBLK,R0 ; Set up line report MOV TCBNAM,(R0)+ ; Insert Task/Partition name MOV TCBNAM+2,(R0)+ ; MOV PLGTH,2(R0) ; Insert length of element MOV #G.PCB,R1 ; Get address of report line skeleton CALL LINREP ; Output the report line BIT #PS.COM!PS.DRV!PS.OUT,P.STAT(R4) ; Partition have a header? BNE 20$ ; If NE no header TSTB HDRFLG ; Header possible? BEQ 20$ ; IF EQ no - don't even look for it ADD PHDR,R4 ; MOV (R4),R4 ;GET ADDRESS OF ASSOCIATED HEADER. BEQ 20$ ;BRANCH IF NONE. CALL HDR ;ALLOCATE HEADER AND ASSOCIATED LISTS. ; 20$: RETURN ; ; ; Task Headers are variable length, but their length is stored at ; offset H.HDLN within the Task Header. ; At the end of each Task Header is the LUT table with two words for ; each LUN - it starts at offset H.LUN, and the number of LUNs is stored ; at H.NLUN within the Task Header. ; The second word of each pair is either zero, or contains the address of ; a File Window Block for the task. Note that this address might have ; bit 0 set to 1 (F11ACP interlocking purposes). ; HDR: ; Allocate the Header and its lists ADD OFFDIF,R4 ; Offset R4 to table address MOV H.HDLN(R4),R5 ;GET LENGTH OF HEADER ASR R5 ; IN WORDS. MOV #2,R3 ;ALLOCATE CALL ALOCT1 ; HEADER. MOV #ARGBLK,R0 ; Get address of argument block MOV TCBNAM,(R0)+ ; Insert TCB name MOV TCBNAM+2,(R0)+ ; MOV H.HDLN(R4),2(R0) ; Insert length MOV #G.HDR,R1 ; Get address of report skeleton CALL LINREP ; Output the line report ; 20$: MOV R4,R0 ;GET ADDRESS OF HEADER. MOV R0,R1 ;GET ADDRESS OF LUT ADD #H.LUN,R1 ; FOR FIRST LUN. MOV H.NLUN(R0),R0 ;GET NUMBER OF LUNS. BEQ 80$ ;BRANCH IF NONE. ; 40$: TST (R1)+ ;LOOP ON LUNS. IGNORE FIRST LUT ENTRY FOR LUN. MOV (R1)+,R4 ;GET ADDRESS OF WINDOW BLOCK. BEQ 60$ ;BRANCH IF NONE. CALL RELOC4 ; Relocate the address BCS 60$ ; If CS can't map it - give up MOV R0,-(SP) ; Save the important registers MOV R1,-(SP) ; MOV #4,R3 ; AND ALLOCATE CALL WNDX ; Allocate the window ; ; File Control Block. ; The FCB is pointed to by W.FCB in the window block. ; MOV W.FCB(R4),R4 ; Get the FCB address BEQ 55$ ; If EQ there isn't one CALL RELOC4 ; Relocate it BCS 55$ ; If CS no relocation - ignore it MOV #8.,R3 ; Set the NUMENT/SIZENT offset. CALL FCBX ; Allocate and report an FCB ; 55$: MOV (SP)+,R1 ; Restore the work registers MOV (SP)+,R0 ; ; 60$: DEC R0 ; Decrement LUN count BLE 80$ ; If none left give up JMP 40$ ; Else do next one ; 80$: RETURN ; .PAGE .ENABLE LSB .SBTTL DCB ALLOCATE DCB/DSP/UCB/SCB/VCB/FCB 'S ; ; DESCRIPTION: ; ALLOCATE ALL DCB'S AND THEIR ASSOCIATED LISTS, AND THEIR ASSOCIATED ; LISTS, AND... ; ; Remarks: ; DCBs are chained via D.LNK from $DEVHD. ; Each DCB is a fixed length, as called in the preface, apart for pseudo- ; devices (identified by bit DV.PSE in U.CW1 of UCB) which are D.UCBL+2 bytes ; ; This section also handles:- ; UCBs ; SCBs ; DDTs ; VCBs ; ICBs ; I/O Packets ; FCBs ; Window Blocks ; VSCBs (for ANSI Magtape) ; MVLBs (for ANSI Magtape) ; UVLBs (for ANSI Magtape) ; ; Note that the report might have slight granularity problems in this area. ; Every request for pool space is rounded up to the granularity boundary, and ; this is reflected in the line reports - however device structures will ; usually be allocated in blocks (e.g. all UCBs at once) which means that each ; individual UCB will not be rounded up. As this is not really a serious ; problem it has been ignored at this point. ; DCB: CALL CLRNS ;PREPARE GENERATE STATISTICS MOV @DEVHD,R4 ;GET ADDRESS OF FIRST DCB. ; 20$: ;LOOP ON DCB'S. CLRB SCBNUM ; Clear the SCB fields CLRB SCBERR ; CLR SCBADD ; CALL RELOC4 ; Relocate R4 MOV R4,-(SP) ; Save the relocated DCB address for now MOV D.UCB(R4),R4 ; Get the first UCB address CALL RELOC4 ; Relocate that MOV U.CW1(R4),CHWRD1 ; Store the first characteristics word MOV U.TSTA(R4),UTSTA ; Save first word of Unit Triple.. ;..Status Word (Full Dup TT only) MOVB U.STS(R4),USTS ; and the unit status MOVB U.CTL(R4),UCTL ; and the unit control byte MOV (SP)+,R4 ; Restore relocated DCB address CLR NUMUNT ; Initialise number of units for DCB MOVB D.UNIT+1(R4),NUMUNT ; Get highest unit number MOVB D.UNIT(R4),R0 ; Get lowest unit number SUB R0,NUMUNT ; Hence get number of units MOVB R0,DEVUNT ; Initialise the unit number DECB DEVUNT ; MOV D.NAM(R4),DEVNAM ; Save the Device Name MOV D.LNK(R4),-(SP) ;SAVE ADDRESS OF NEXT DCB. MOV D.UCB(R4),-(SP) ;SAVE ADDRESS AND SIZE MOV D.UCBL(R4),UCBLEN; OF FIRST UCB. ; MOV DLGTH,R5 ; Allocate BIT #DV.PSE,CHWRD1 ; A Pseudo-device? BEQ 25$ ; If EQ no - carry on MOV #D.UCBL+2,R5 ; Yes - only goes to D.UCBL ; 25$: MOV R5,ARGBLK+4 ; Save length for line report ASR R5 ; CLR R3 ; THE CALL ALOCT1 ; DCB BCS 30$ ; If CS not in DSR - omit the line report MOV #ARGBLK,R0 ; Else get address of argument block MOV #DEVNAM,(R0)+ ; Insert address of device name MOV #G.DCB,R1 ; Insert skeleton line CALL LINREP ; Output the line report ; 30$: ; ; Driver Dispatch Table. ; This is pointed to by D.DSP in the DCB. ; DDTs are fixed length - 8 bytes. ; Naturally they do not exist for pseudo-devices. ; They contain no further information on DSR usage. ; BIT #DV.PSE,CHWRD1 ; Pseudo-Device? BNE 60$ ; If NE yes - omit this bit MOV D.DSP(R4),R4 ;GET ADDRESS OF DRIVER DISPATCH TABLE. BEQ 60$ ;BRANCH IF NONE. CMP R4,#100000 ; In driver itself? BHIS 60$ ; if HIS yes - ignore it CMP R4,POOL ; Is it in pool anywhere? BLO 60$ ; If LO no - ignore it CALL RELOC4 ; Relocate R4 BCS 60$ ; If CS not relocatable - skip it MOV #8./2,R5 ;ALLOCATE MOV #2,R3 ; THE CALL ALOCT1 ; DDT. BCS 60$ ; If CS not in DSR - omit the line report MOV #ARGBLK,R0 ; Else get address of argument block MOV #DEVNAM,(R0)+ ; Insert address of device name MOV 8.,2(R0) ; Insert length MOV #G.DDT,R1 ; Insert skeleton line CALL LINREP ; Output the line report ; 60$: ;LOOP ON UCB'S ; ; Unit Control Blocks. ; The first UCB is pointed to by D.UCB in the DCB. All further ; UCBs for that DCB follow sequentially in memory. The number of UCBs ; is stored in the DCB (Highest unit number - Lowest unit number + 1) ; All UCBs for one DCB are of a fixed length, and that length is ; stored at offset D.UCBL in the DCB. Just to make life awkward the ; UCB itself can extend backwards in memory from the start address the ; DCB points to as follows:- ; Multi-User Systems, non-terminal devices - UCB starts 2 bytes early ; " " " , terminal devices - UCB starts 4 bytes early ; Systems with multiple CLIs, terminal devices - UCB starts 6 bytes early ; (Note: this does not apply to pseudo-devices.) ; The UCBs point to the VCBs and the SCBs. ; For terminals on systems with the Full Duplex Terminal Driver, the ; UCBs might also point to UCB extensions. Care must be taken of these ; as they will probably be in the TTDRV address, and so have addresses like ; 12nnnn which would get confused with F11ACP if we used RELOC4. ; MOV UCBLEN,R5 ;GET SIZE OF A UCB. ASR R5 ; Convert to words MOV (SP)+,R4 ;GET ADDRESS OF NEXT UCB TO PROCESS. BNE 65$ ; If NE we got one - process it JMP 200$ ; Else go for next DCB ; 65$: MOV R4,-(SP) ;SAVE ADDRESS OF ADD UCBLEN,(SP) ; NEXT UCB. CALL RELOC4 ; Relocate R4 INCB DEVUNT ; Set to next unit number CLR R0 ; Initialise amount to subtract BIT #DV.PSE,CHWRD1 ; Pseudo-Device? BNE 67$ ; If NE yes - omit this bit BIT #FE.MUP,@FMASK ; Multi-User Protection BEQ 66$ ; If EQ No - Carry On INC R0 ; One word to allow for BIT #DV.TTY,CHWRD1 ; Device a terminal? BEQ 66$ ; If EQ No - Carry On INC R0 ; Allow second word ; 66$: BIT #FE.CLI,@FMASK ; Multiple CLI support? BEQ 67$ ; If EQ no - carry on BIT #DV.TTY,CHWRD1 ; Yes - is device a terminal? BEQ 67$ ; If EQ no - carry on MOV #3,R0 ; Yes - 3 words to allocate no matter what ; 67$: ASL R0 ; Convert word count to byte count MOV R4,-(SP) ; Save start address of UCB SUB R0,R4 ; Subtract from address MOV #4,R3 ;ALLOCATE CALL ALOCT1 ; UCB. BCS 70$ ; If CS not in DSR - omit the line report MOV #ARGBLK,R0 ; Else get address of argument block MOV #DEVNAM,(R0)+ ; Insert address of device name MOV DEVUNT,(R0)+ ; Insert unit number MOV UCBLEN,2(R0) ; Insert length MOV #G.UCB,R1 ; Insert skeleton line CALL LINREP ; Output the line report ; 70$: BIT #FE.FDT,@FMASK ; Full Duplex Terminal Driver? BEQ 73$ ; If EQ no - no UCB extensions CMP DEVNAM,#"TT ; Is this a terminal? BNE 73$ ; If NE no - no UCB extensions MOV (SP),R4 ; Yes - get start address of UCB back MOV U.TUX(R4),R4 ; Get address of UCB extension BEQ 73$ ; If EQ zero - nothing there CMP R4,#120000 ; In TTDRV partition? BHIS 73$ ; If HIS yes - forget it CALL RELOC4 ; No - try to relocate it BCS 73$ ; If CS no chance, give up MOV #46/2,R5 ; Else allocate as small UCB BCS 73$ ; If CS not in pool, omit line report MOV #ARGBLK,R0 ; Else get address of argument block MOV #DEVNAM,(R0)+ ; Insert address of device name MOV DEVUNT,(R0)+ ; Insert unit number MOV #46,2(R0) ; Put the length in for the report MOV #G.UCB,R1 ; Pretend it's a UCB CALL LINREP ; Output the line report ; 73$: MOV (SP)+,R4 ; restore UCB start address MOV U.SCB(R4),-(SP) ;SAVE ADDRESS OF SCB. ; ; Volume Control Blocks. ; VCBs are pointed to by offset U.VCB in the UCB. Not all UCBs ; have VCBs. Firstly a UCB whose length is less than U.VCB will not have ; a VCB. Secondly it is assumed that UCBs have VCBs if, and only if, the ; devices are mountable (DV.MNT set in U.CW1). ; The size of a VCB is variable, depending on the type of device:- ; Files-11 (DV.F11) - V.LGTH bytes ; Comms (DV.COM) - V.CLEN bytes (+ Param Block of 26 bytes) ; Other - S.VSCB ; Files-11 VCBs point to the Window Block for the Index File and to an ; FCB list. ; ANSI VSCBs point to more VSCBs and to a Mounted Volume List and an ; Unmounted Volume List. ; CMP #U.VCB,UCBLEN ;BRANCH IF NO BGE SCBS ; VCB. BIT #DV.MNT,CHWRD1 ; Is Device Mountable? BEQ SCBS ; If EQ no - can't be a VCB MOV U.VCB(R4),R4 ;BRANCH IF NOT BEQ SCBS ; MOUNTED. CALL RELOC4 ; Relocate R4 BCS SCBS ; If CS not relocatable - skip it BIT #DV.F11,CHWRD1 ; Is it a Files-11 Device? BEQ VCB1 ; If EQ no - can't handle it MOV #V.LGTH/2,R5 ;ALLOCATE MOV #8.,R3 ; THE CALL ALOCT1 ; VCB. BCS 75$ ; If CS not in DSR - omit the line report MOV #ARGBLK,R0 ; Else get address of argument block MOV #DEVNAM,(R0)+ ; Insert address of device name MOV DEVUNT,(R0)+ ; Insert the unit MOV #V.LGTH,2(R0) ; Insert length MOV #G.VCB,R1 ; Insert skeleton line CALL LINREP ; Output the line report ; 75$: ; ; File Control Block. ; The first FCB is pointed to by V.FCB in the VCB, the rest via F.LINK. ; FCBs are fixed length - F.LGTH bytes. ; They contain the pointer to the Locked Block List for the file. ; MOV R4,-(SP) ; Save the VCB address ADD #V.FCB,R4 ; Get address of first address ; 80$: MOV (R4),R4 ; Get the address BEQ 90$ ; If EQ there isn't one CALL RELOC4 ; Relocate FCB address BCS 90$ ; If CS no relocation - ignore it MOV #12.,R3 ; Size the SIZENT/NUMENT offset MOV R4,-(SP) ; Save R4 CALL FCBX ; Allocate and report the FCB MOV (SP)+,R4 ; Restore R4 ADD #F.LINK,R4 ; Else link to the next one BR 80$ ; ; 90$: MOV (SP)+,R4 ; Restore the VCB address MOV V.IFWI(R4),R4 ; Get the Index File Window Block Address BEQ SCBS ; None - give up CALL RELOC4 ; Relocate the address BCS SCBS ; If CS can't relocate it - give up MOV #16.,R3 ; Set the SIZENT/NUMENT address CALL WNDX ; Allocate the window BR SCBS ; Skip over rest of VCB stuff ; ; Communications Channel Volume Control Blocks. ; Comms Channels are recognised by the bit setting DV.COM in U.CW1. ; Each mounted volume has a VCB and a Communications Parameter Block. ; Unfortunately the format of the VCB, and in particular the location of ; the address of the Comms Parameter Block are not known at the moment, so ; the best we can do is allocate the VCB and keep an eye out for undetermined ; DSR which is 26 bytes long. ; VCB1: BIT #DV.COM,CHWRD1 ; Communications Channel (or something) BEQ VCB2 ; If EQ no - must be ANSI magtape MOV #V.CLEN/2,R5 ;ALLOCATE MOV #8.,R3 ; THE CALL ALOCT1 ; VCB. BCS SCBS ; If CS not in DSR - omit the line report MOV #ARGBLK,R0 ; Else get address of argument block MOV #DEVNAM,(R0)+ ; Insert address of device name MOV DEVUNT,(R0)+ ; Insert the unit MOV #V.CLEN,2(R0) ; Insert length MOV #G.VCB,R1 ; Insert skeleton line CALL LINREP ; Output the line report ; ; ANSI Magtape Volume Set Control Blocks. ; Currently ANSI Magtapes are recognisable by being any mounted device ; that is neither a Files-11 device nor a Communications Channel! ; They are slightly odd in that a device might have many VCBs (here called ; VSCBs technically) which are linked via V.NXT. ; Each VSCB contains pointers to a Mounted Volume List and an unmounted ; Volume List. ; However the exact usage and linkage of these is slightly unclear at the ; moment so we will just allocate the VSCB and see what happens. ; VCB2: MOV #S.VSCB/2,R5 ;ALLOCATE MOV #8.,R3 ; THE CALL ALOCT1 ; VCB. BCS SCBS ; If CS not in DSR - omit the line report MOV #ARGBLK,R0 ; Else get address of argument block MOV #DEVNAM,(R0)+ ; Insert address of device name MOV DEVUNT,(R0)+ ; Insert the unit MOV #S.VSCB,2(R0) ; Insert length MOV #G.VCB,R1 ; Insert skeleton line CALL LINREP ; Output the line report ; SCBS: ; ; Status Control Blocks. ; SCBs are linked via U.SCB in the UCB. ; For a given SYSGEN SCBs are a fixed length, as defined in the Preface. ; In addition to that however, drivers supporting error logging or User Mode ; Diagnostics have three extra words preceding the SCB address as given ; in the UCB. It is not easy to determine which these are, but the ; method used here is as follows:- ; If the entry point $DVCER exists, then E$$DVC was defined ; If SP.LOG is set in S.PRI in the SCB, then the device supports error ; logging ; If DV.UMD is set in U.CW1 in the UCB, then D$$IAG was defined & the ; device supports UMDs. ; Also, devices that are Massbus devices (DV.MBC in U.CW1), or NPR ; devices (UC.NPR in U.CTL), or a KMC11 (??) require, on systems with ; extended memory, six extra words at the end. ; On top of all that (!!!) devices MT & XQ have an extra 8 words at the ; end of each SCB (God knows why!) ; ; SCBs point to any I/O packets outstanding for the device, and indirectly ; point to anu Interrupt Control Blocks in memory. They also point to ; Fork Queue Entries, but these are handled more logically elsewhere. ; MOV (SP)+,R4 ;GET SCB ADDRESS. BEQ 91$ ;BRANCH IF NONE. BIT #DV.PSE,CHWRD1 ; A Pseudo-Device? BNE 91$ ; If NE Yes - doesn't have an SCB CALL RELOC4 ; Relocate R4 BCS 91$ ; If CS can't relocate - ignore it CMP R4,SCBADD ; Same as the last one? BNE 92$ ; If NE no - carry on ; 91$: JMP 160$ ; Yes - ignore this SCB ; 92$: MOV R4,SCBADD ; No - store it INCB SCBNUM ; and count it MOV SLGTH,R5 ; Get length of SCB MOV R4,-(SP) ; Save SCB address BIT #DV.UMD,CHWRD1 ; User Mode Diagnostics? BNE 102$ ; If NE yes - must have extra words TST DVCER ; Does $DVCER exist? BEQ 104$ ; If EQ no - cannot have extra words BITB #SP.LOG,S.PRI(R4) ; This device support error logging? BEQ 104$ ; If EQ no - cannot have extra words MOVB #1,SCBERR ; Device supports error-logging ; 102$: ADD #6,R5 ; Supports error-logging - add six bytes SUB #6,R4 ; and knock it off the address ; 104$: BIT #FE.EXT,@FMASK ; Extended Memory BEQ 108$ ; If EQ no - no UMRs BITB #UC.NPR,UCTL ; An NPR device? BNE 106$ ; Yes - grab room for UMRs BITB #DV.MBC,CHWRD1 ; A massbus device? BEQ 108$ ; If EQ no - no UMRs ; 106$: ADD #12.,R5 ; Allocate room for UMRs ; 108$: CMP DEVNAM,#"MT ; MT Device? BEQ 110$ ; If EQ grab some more space CMP DEVNAM,#"XQ ; No - how about an XQ? BNE 112$ ; If NE no - carry on ; 110$: ADD #16.,R5 ; another 8 words ; 112$: MOV R5,ARGBLK+4 ; Store length in argument block ASR R5 ; MOV #6,R3 ; THE CALL ALOCT1 ; SCB. BCS 114$ ; If CS not in DSR - omit the line report MOV #ARGBLK,R0 ; Else get address of argument block MOV #DEVNAM,(R0)+ ; Insert address of device name MOV DEVUNT,(R0)+ ; Insert the unit MOV SLGTH,2(R0) ; Insert length MOV #G.SCB,R1 ; Insert skeleton line CALL LINREP ; Output the line report ; 114$: ; ; I/O Packets. ; If the unit is busy then the address of the current I/O packet is ; in S.PKT in the SCB. In either case a list of pending packets is started ; at S.LHD in the SCB, and linked via offset 0. ; Note that for the full-duplex terminal driver, the busy status is ; recorded not in U.STS, but in U.TSTA. If a terminal is active in ; full-duplex mode then the address of the other 'current' packet is in ; the UCB extension, which is probably in TTPAR, so we'll ignore it ; for now. ; I/O packets have a fixed length - I.LGTH bytes. ; MOV (SP)+,R4 ; Restore relocated SCB address MOV S.LHD(R4),-(SP) ;SAVE FIRST IN I/O LIST. BIT #FE.FDT,@FMASK ; Full Duplex TTDRV support? BEQ 116$ ; If EQ no - carry on CMP DEVNAM,#"TT ; This a terminal? BNE 116$ ; If NE no - carry on BIT #S1.IBY!S1.OBY,UTSTA ; Input or Output Busy? BEQ 120$ ; If EQ no - no packet in SCB BR 118$ ; Yes - try for packet in SCB ; 116$: BITB #US.BSY,USTS ; Was the unit busy? BEQ 120$ ; If EQ no - there can't have been a current pkt ; 118$: MOV S.PKT(R4),R4 ;GET ADDRESS OF CURRENT PACKET. BEQ 120$ ; If none - check I/O list CALL RELOC4 ; Else relocate it BCS 120$ ; If CS not relocatable - skip it BR 140$ ; and check it ; 120$: MOV (SP)+,R4 ;GET ADDRESS OF NEXT PACKET. BEQ 160$ ;BRANCH IF NO MORE. CALL RELOC4 ; Relocate R4 BCS 160$ ; If CS not relocatable - skip it MOV I.LNK(R4),-(SP) ;SAVE ADDRESS OF NEXT. ; 140$: MOV #I.LGTH/2,R5 ;ALLOCATE THE MOV #10.,R3 ; I/O CALL ALOCT1 ; PACKET. BCS 120$ ; If CS not in DSR - omit the line report MOV #ARGBLK,R0 ; Else get address of argument block MOV #DEVNAM,(R0)+ ; Insert address of device name MOV DEVUNT,(R0)+ ; and the unit MOV #I.LGTH,2(R0) ; Insert length MOV #G.IOP,R1 ; Insert skeleton line CALL LINREP ; Output the line report BR 120$ ;DO NEXT. ; 160$: DEC NUMUNT ; Any more units? BLT 170$ ; If LT no - do next ICBs JMP 60$ ;DO NEXT UCB. ; 170$: ; ; Interrupt Control Blocks. ; Loaded drivers have ICBs allocated in pool by LOA. The only way ; to find them is to look at the vector address associated with the SCB, ; and see if the ISR routine address given there is in pool. ; Full Duplex Drivers have two ICBs allocated. LOA determines whether a ; device is full-duplex by checking what entry points are defined - as that ; method is not available to us we must make do by check the vector address+4 ; (where the second interrupt would be) and if that also points to an address ; in pool we assume a Full Duplex device! ; Note that there is only one (pair of) ICBs per DCB, so we need only examine ; any given SCB. ; MOV SCBADD,R4 ; Get an SCB address BEQ 200$ ; If EQ there wasn't one - ignore ICBs MOVB S.VCT(R4),R4 ; Get the vector address ASL R4 ; Convert to real address ASL R4 ; Like so CALL RELOC4 ; Relocate the vector address BCS 200$ ; If CS we can't - give up MOV R4,SCBADD ; Save it in SCB address for now MOV (R4),R4 ; Get the address of the ISR CMP R4,POOL ; Is it in pool? BLO 200$ ; If LO no - we can ignore it CALL RELOC4 ; No - relocate it BCS 200$ ; If we can't - give up CALL ICBX ; Grab an ICB MOV SCBADD,R4 ; Get the vector address back ADD #4,R4 ; Up it to the other half MOV (R4),R4 ; Get (possibly) other ISR CMP R4,POOl ; In Pool? BLO 200$ ; If LO no - can't be full-duplex CALL RELOC4 ; Yes - Relocate it BCS 200$ ; Can't be full-duplex CALL ICBX ; Hope it's full-duplex - get other ICB ; 200$: TST (SP)+ ; Throw away UCB MOV (SP)+,R4 ;GO BACK FOR BEQ 210$ ; JMP 20$ ; ; 210$: MOV #RLNDCB-1,R3 ; Copy 10 data elements CALL COPENT ; ADD #RLNDCB,LINCNT ; Force page throw first if at all MOV #REPDC1,R1 ; Output first part of summary CALL EDIT ; SUB #RLNDCB,LINCNT ; Prevent intermediate page throw MOV #REPDC2,R1 ; Output second part CALL EDIT1 ; MOV #REPDC3,R1 ; Output third part CALL EDIT1 ; MOV #REPDC4,R1 ; Output third part CALL EDIT1 ; MOV #REPTOT,R1 ; Output totals CALL EDIT1 ; RETURN ; .DSABL LSB ; ; FCBs are fixed length - F.LGTH bytes. ; They contain the pointer to the Locked Block List for the file. ; FCBX: MOV #F.LGTH/2,R5 ; Get the length CALL ALOCT1 ; Allocate it BCS 10$ ; If CS not in DSR - omit line report MOV #ARGBLK,R0 ; Get argument block address MOV F.FNUM(R4),(R0)+ ; Insert the File ID MOV F.FSEQ(R4),(R0)+ ; MOV #F.LGTH,2(R0) ; and the length MOV #G.FCB,R1 ; and the skeleton line address CALL LINREP ; Output the line report ; ; Locked Block List. ; The first is linked from F.LKL and the rest from L.LNK in the one before ; LBLBs are fixed length - L2.LGT bytes. ; They contain the address of the first window block, which has ; probably already been found, but might not have been. ; ; 10$: ADD #F.LKL,R4 ; Offset R4 to the address of the first ; 20$: MOV (R4),R4 ; Get address of next BEQ 50$ ; If EQ none - give up CALL RELOC4 ; Relocate it BCS 50$ ; If CS we can't - give up ADD #2,R3 ; Reset SIZENT/NUMENT offset MOV #L2.LGT/2,R5 ; Get length in words CALL ALOCT1 ; Allocate it BCS 30$ ; If CS not in DSR - omit line report MOV #ARGBLK+4,R0 ; Reset address of argument block MOV #G.LBL,R1 ; Insert line skeleton address MOV #L2.LGT,2(R0) ; And in bytes CALL LINREP ; Output the line report ; 30$: SUB #2,R3 ; Reset SIZENT/NUMENT offset MOV R4,-(SP) ; Save relocated LBLB address MOV L.WI1(R4),R4 ; Get address of Window block - if any BEQ 40$ ; If EQ there isn't one CALL RELOC4 ; Relocate the address BCS 40$ ; If CS can't relocate it - give up ADD #4,R3 ; Reset SIZENT/NUMENT offset CALL WNDX ; Allocate the window SUB #4,R3 ; Reset SIZENT/NUMENT offset ; 40$: MOV (SP)+,R4 ; Restore LBLB address ADD #L.LNK,R4 ; Reset to address of next one BR 20$ ; and process it ; 50$: RETURN ; ; The Window Block consists of two parts. The fixed part has a fixed length ; of W.RTRV bytes. This is followed by a variable part consisting of ; retrieval pointers. Each of these currently (3.2) requires 6 bytes ; and the number of them is held at offset W.WISZ in the fixed part. ; The Window Block also contains a pointer to the file FCB and to the ; locked block list associated with it. ; ; WNDX: BIC #1,R4 ; Clear the Interlocking Bit MOVB W.WISZ(R4),R5 ; Get number of retrieval pointers MUL #RTVSZ,R5 ; Multiply by retrieval pointer size ADD #W.RTRV,R5 ; Add size of fixed bit MOV R5,-(SP) ; Save the size ASR R5 ; Convert to words CALL ALOCT1 ; IT. BCS 10$ ; If CS not in DSR - omit line report MOV #ARGBLK,R0 ; Get address of argument block CLR (R0)+ ; Initialise File ID to zero CLR (R0)+ ; MOV R4,-(SP) ; Save the window address MOV OFFDIF,-(SP) ; And the offset difference MOV W.FCB(R4),R4 ; Get the FCB address CALL RELOC4 ; Relocate it BCS 5$ ; If CS leave default file ID MOV F.FNUM(R4),ARGBLK ; Insert real File ID MOV F.FSEQ(R4),ARGBLK+2 ; ; 5$: MOV (SP)+,OFFDIF ; Restore the offset difference MOV (SP)+,R4 ; Restore the window address MOV (SP),2(R0) ; Insert length MOV #G.WND,R1 ; Get address of report skeleton CALL LINREP ; Output the report line ; 10$: TST (SP)+ ; Remove the window size RETURN ; ; ; ICBs are tricky bastards with no easy way of determining their length. ; There are two considerations that determine the length:- ; ; Whether the device supports error-logging ; Whether the device is a multi-controller device ; ; No Error-Logging, 1 SCB = 32 bytes ; No Error-Logging, n SCBs = 54 bytes ; Error Logging, n SCBs = 34 + (n-1)*12 bytes ; ; We set up the error logging flag back in the SCB section where we ; determined length of SCB. Currently this means that we assume that if ; error logging is not SYSGENed into a system, then 'non error-logging' ; ICBs will be generated for all devices - an assumption which might be ; false (the code in LOA is not too clear). ; ICBX: TSTB SCBERR ; Error Logging? BNE 10$ ; If NE yes - tricky stuff MOV #32,R5 ; No - set basic length DECB SCBNUM ; Multiple SCBs? BEQ 20$ ; If EQ no - OK as we are ADD #22,R5 ; Yes - add difference BR 20$ ; Branch to common code ; 10$: MOVB SCBNUM,R5 ; Get number of SCBs MUL #12,R5 ; Multiply by 12 ADD #22,R5 ; Add the fixed bit ; 20$: MOV R5,ARGBLK+4 ; Store the length ASR R5 ; Convert to words MOV #18.,R3 ; Set SIZENT/NUMENT offset CALL ALOCT1 ; Allocate it BCS 30$ ; If CS not in DSR (??) MOV #ARGBLK,R0 ; Get address of argument block MOV #DEVNAM,(R0)+ ; Insert the device name MOV #G.ICB,R1 ; Get address of skeleton line CALL LINREP ; Output the report line ; 30$: RETURN ; .PAGE .SBTTL MISC Allocate Miscellaneous Blocks ; ; DESCRIPTION: ; Allocate all the Miscellaneous bits we haven't managed elsewhere. ; MISC: ; ; Checkpoint PCBs. ; Checkpoint PCBs are linked from $CFLPT in an analogous manner to ; ordinary PCBs (q.v.) via P.MAIN & P.REL. ; Each Checkpoint PCB is fixed length - P.SIZE+2 bytes. ; They contain no further information on DSR usage. ; MOV OFFSET+16.,OFFDIF ; All must be in pool CALL CLRNS ;PREPARE GENERATE STATISTICS MOV @CFLPT,R4 ;GET ADDRESS OF FIRST PARTITION. BEQ 40$ ; NONE ; 10$: ADD OFFDIF,R4 ; Offset R4 to table address MOV P.LNK(R4),-(SP) ;SAVE ADDRESS OF NEXT MAIN-PARTITION. MOV P.SUB(R4),-(SP) ;SAVE ADDRESS OF FIRST SUB-PARTITION. CALL CPCBX ;ALLOCATE MAIN PARTITION. ; 20$: MOV (SP)+,R4 ;GET ADDRESS OF NEXT SUB-PARTITION. BEQ 30$ ;BRANCH IF NONE. ADD OFFDIF,R4 ; Offset R4 to table address MOV P.SUB(R4),-(SP) ;SAVE ADDRESS OF NEXT SUB-PARTITION. CALL CPCBX ;ALLOCATE SUB-PARTITION. BR 20$ ;GO BACK FOR NEXT. ; 30$: MOV (SP)+,R4 ;GET ADDRESS OF NEXT MAIN-PARTITION. BNE 10$ ;GO BACK IF MORE. ; 40$: ; ; Clock Queue Control Blocks. ; Clock Queue CBs are chained via C.LNK from $CLKHD. ; Each is a fixed length - C.LGTH bytes. ; They contain no further information on DSR usage. ; MOV CLKHD,R4 ;GET ADDRESS OF ADDRESS OF FIRST ENTRY. MOV #C.LGTH/2,R5 ;GET LENGTH (IN WORDS). MOV #2,R3 ;Get SIZENT/NUMENT offset MOV #ARGBLK,R0 ; Get address of argument block MOV #C.LGTH,2(R0) ; Insert size MOV #G.CLK,R1 ; Get address of report skeleton MOV #C.LNK,R2 ; Get offset to link word. CALL COMLNK ; Call the common linking routine ; ; Logical Assignment Control Blocks. ; LCBs are chained via L.LNK from $LOGHD. ; They are all a fixed length - L1.LGT bytes. ; They contain no further information on DSR usage. ; MOV LOGHD,R4 ;GET ADDRESS OF ADDRESS OF FIRST ENTRY. MOV #L1.LGT/2,R5 ;GET LENGTH (IN WORDS). MOV #4,R3 ;Get SIZENT/NUMENT offset MOV #ARGBLK,R0 ; Get address of argument block MOV #L1.LGT,2(R0) ; Insert size MOV #G.LCB,R1 ; Get address of report skeleton MOV #L.LNK,R2 ; Get the link word offset CALL COMLNK ; Call the common routine ; ; Group Global Event Flag Blocks. ; GGEFBs are linked via G.LNK from $GGEF. ; They will only exist if support was SYSGENed in (GGEF will be zero otherwise) ; They are a fixed length - G.EFLG+4 bytes. ; They contain no further information on DSR usage. ; MOV #G.EFLG+4,2(R0) ; Insert the length in bytes MOV #G.GEF,R1 ; Get the report line skeleton MOV #G.LNK,R2 ; Get the link word offset MOV #6,R3 ; Get the NUMENT/SIZENT offset MOV GGEF,R4 ; Get the address of $GGEF BEQ 50$ ; If EQ not supported - skip them MOV #/2,R5 ; Get length in words CALL COMLNK ; Call the common routine. ; 50$: ; ; Mounted Device List Blocks. ; Mounted Device List Blocks are chained via 0 from $MOULS. ; They are a fixed length - 8 bytes. ; They contain no further information on DSR usage. ; MOV #8.,2(R0) ; Insert the length in bytes MOV #G.MOU,R1 ; Get the report line skeleton CLR R2 ; Get the link word offset MOV #8.,R3 ; Get the NUMENT/SIZENT offset MOV MOULS,R4 ; Get the address of $MOULS MOV #4,R5 ; Get length in words CALL COMLNK ; Call the common routine. ; ; Fork Queue. ; Fork Queue Control Blocks are chained via 0 from $FRKHD. ; They are a fixed length - 8 bytes (10 if loadable drivers) ; They contain no further information on DSR uasge. ; MOV #8.,R5 ; Get the length in bytes BIT #FE.DRV,@FMASK ; Loadable Driver support included? BEQ 60$ ; If EQ no - size is OK ADD #2,R5 ; Yes - add another two bytes ; 60$: MOV R5,2(R0) ; Store the size in bytes MOV #G.FRK,R1 ; Get the report line skeleton CLR R2 ; Get the link word offset MOV #10.,R3 ; Get the NUMENT/SIZENT offset MOV FRKHD,R4 ; Get the address of $FRKHD ASR R5 ; Get length in words CALL COMLNK ; Call the common routine. ; ; MCR Command Lines Queue. ; Command Lines are chained via 0 from $MCRCB. ; They are a fixed length - 84 bytes ; They contain no further information on DSR usage. ; MOV #84.,2(R0) ; Insert the length in bytes MOV #G.MCR,R1 ; Get the report line skeleton CLR R2 ; Get the link word offset MOV #12.,R3 ; Get the NUMENT/SIZENT offset MOV MCRCB,R4 ; Get the address of $MCRCB MOV #42.,R5 ; Get length in words CALL COMLNK ; Call the common routine. ; ; Error Message Blocks. ; Error Messages are chained via -2 from $ERRHD. ; They are variable-length - the length held in E.SIZE in the EMB. ; They contain no further information on DSR usage. ; MOV ERRHD,R4 ; Get the address of $ERRHD BEQ 90$ ; If EQ not in system - ignore EMBs ADD #2,R4 ; Add 2 to align with future entries ; 70$: MOV -2(R4),R4 ; Get address of next one BEQ 90$ ; If EQ finished CALL RELOC4 ; Relocate it BCS 90$ ; IF CS can't - ignore it MOV E.SIZE(R4),R5 ; Get the EMB size MOV R5,ARGBLK+2 ; Save it ASR R5 ; Convert to words SUB #2,R4 ; Reset R4 MOV #14.,R3 ; Get the NUMENT/SIZENT offset CALL ALOCT1 ; Allocate it BCS 80$ ; If CS not in DSR - omit line report MOV #ARGBLK,R0 ; Set up argument block address MOV #G.ERR,R1 ; And report line skeleton CALL LINREP ; Do the line-report ; 80$: ADD #2,R4 ; Reset R4 BR 70$ ; and do the next one ; 90$: ; ; Mapping Assignment Blocks. ; These come in two queues, one via M.LNK from $UMRHD, and one ; via M.LNK from $UMRWT. They only exist in systems with extended memory. ; MABs are fixed length - M.LGTH bytes. ; They contain no further information on DSR usage. ; MOV #ARGBLK,R0 ; Get the argument block address MOV #M.LGTH,2(R0) ; Insert the length in bytes MOV #G.UMR,R1 ; Get the report line skeleton MOV #M.LNK,R2 ; Get the link word offset MOV #16.,R3 ; Get the NUMENT/SIZENT offset MOV UMRHD,R4 ; Get the address of $UMRHD BEQ 100$ ; If EQ none in system - omit them MOV #M.LGTH/2,R5 ; Get length in words CALL COMLNK ; Call the common routine. MOV UMRWT,R4 ; Get the address of $UMRWT CALL COMLNK ; and do that lot ; 100$: ; ; Output the report for the Miscellaneous data areas ; MOV #RLNMSC-1,R3 ; Nine types so far CALL COPENT ; Copy the data entries ADD #RLNMSC,LINCNT ; Add in the number of lines MOV #REPMS1,R1 ; Format and output the first part CALL EDIT ; SUB #RLNMSC,LINCNT ; Remove the number of lines MOV #REPMS2,R1 ; And the second bit CALL EDIT1 ; MOV #REPMS3,R1 ; And the third bit CALL EDIT1 ; MOV #REPTOT,R1 ; and the totals CALL EDIT1 ; RETURN ; ; CPCBX: MOV #/2,R5 ; Get size in words CLR R3 ; First entry CALL ALOCT1 ; Allocate it MOV #ARGBLK,R0 ; Get address of argument block MOV #,2(R0) ; Insert size MOV #G.CHK,R1 ; Get address of report skeleton CALL LINREP ; Edit and output it RETURN .PAGE .SBTTL ALOCATE ALOCATE BITS IN BITMAP. ; ; ; DESCRIPTION: ; THIS SUBROUTINE IS CALLED TO ALLOCATE BITS IN THE BITMAP. THE BITMAP ; COVERS THE FULL POSSIBLE 20K OF EXEC+DSR. THE MAIN CODE WILL ; FIRST CALL THIS TO ALLOCATE THE BITS PRECEEDING THE DSR (IE: THE ; EXEC CODE), AND THEN THE UNUSED BITS FOLLOWING THE DSR UP TO THE ; 20K LIMIT. THIS WILL LEAVE THE DSR. INDIVIDUAL SUBROUTINES WILL ; THEN CALL THIS SUBROUTINE TO ALLOCATE AREAS OF THE DSR UED FOR ; TABLES AND LISTS, AND THE FREE POOL. ; ; THE DSR IS ALLOCATED IN 4 BYTE/2 WORD MULTIPLES, SO THE CALLER'S ; SIZE HAS TO BE ADJUSTED. ; ; THIS SUBROUTINE WILL MAXIMIZE CORE TIME BY ALLOCATING CHUNKS OF ; 16 BITS (1 WORD) WHERE POSSIBLE. ; ; INPUT PARAMETERS: ; R3 = OFFSET OF "NUMENT"/"SIZENT" WORD TO BE ADJUSTED. ; R4 = ADDRESS IN THE EXEC+DSR TO BE ALLOCATED. ; R5 = NUMBER OF WORDS (BITS) TO BE ALLOCATED. ; ; COMPLETION CODES: ; "C" = 0 IF SUCCESSFUL. ; 1 IF MULTIPLE ALLOCATION. ; ; ; ALOCT1: CMP OFFDIF,OFFSET+16. ; In pool? BNE 10$ ; If NE no - don't allocate it SUB OFFDIF,R4 ; Yes - reset to reality CMP R4,POOL ; Sure it's in pool? BLO 5$ ; If LO no it isn't CALL ALOCATE ; Allocate it ADD OFFDIF,R4 ; Reset to table CLC ; Show it was in pool RETURN ; 5$: ADD OFFDIF,R4 ; Reset to table ; 10$: SEC RETURN ; ALOCATE: ; CALL $SAVAL ;SAVE ALL REGISTERS. ; INC NUMENT(R3) ;ADJUST CALLER'S COUNT OF ENTRIES IN DSR. ; TST R5 ;BRANCH IF NO BITS BEQ 100$ ; TO ALLOCATE. ; ; INC R5 ;ROUND-UP SIZE TO NEAREST BIC #1,R5 ; 4BYTE/2WORD VALUE. ; MOV R4,R1 ;GET ADDRESS TO ASR R1 ; BIT NO. (0+) BIC #100000,R1 ; IN THE BITMAP. CLR R0 ;SET R0 = WORD NO. (0+) IN BITMAP. DIV #16.,R0 ; R1 = BIT OFFSET (0+) IN WORD. ; ASL R0 ;GET ADDRESS IN BITMAP HOLDING ADD #BITMAP,R0 ; FIRST BIT TO ALLOCATE. ; MOV #040000,R2 ;GENERATE NEG R1 ; BIT INC R1 ; MASK. ASH R1,R2 ; ; ; ; 20$: ;ROUTINE TO ALLOCATE WHERE LESS THAN 16 BITS TO BE SET. BIT R2,(R0) ;BRANCH IF THE BIT IS BNE 25$ ; ALREADY SET. INC SIZENT(R3) ;ADJUST CALLERS STATISTICS, AND INC TOTALO ; TOTAL WORDS ALLOCATED. BIS R2,(R0) ;SET BIT. 25$: ASR R2 ;ADJUST MASK. BCS 30$ ;BRANCH IF NEXT BITMAP WORD IS REQUIRED. BIC #100000,R2 ;MAKE SURE TOP BIT IS OFF. SOB R5,20$ ;LOOP ON NO. BITS TO BE SET. ; BR 100$ ;JOB COMPLETE. ; 30$: DEC R5 ;ANOTHER BITMAP WORD HAS TO BE STARTED. ; ; ; 40$: ;ROUTINE TO ALLOCATE SLABS OF 16 BITS. ADD #2,R0 ;ADDRESS OF NEXT WORD IN BITMAP. CMP #16.,R5 ;BRANCH IF LESS THAN A WORD BGT 60$ ; OF BITS TO BE SET. TST (R0) ;BRANCH IF BITS BNE 60$ ; ALREADY SET. ADD #16.,SIZENT(R3) ;ADJUST CALLER'S STATISTICS, AND ADD #16.,TOTALO ; TOTAL WORDS IN DSR ALLOCATED. MOV #177777,(R0) ;SET BITS. SUB #16.,R5 ;ADJUST COUNT OF BITS STILL TO SET. BR 40$ ;GO BACK AND SET ANY MORE. ; 60$: TST R5 ;BRANCH IF NO MORE BEQ 100$ ; BITS TO BE SET. MOV #100000,R2 ;GO BACK AND FINISH BR 20$ ; OFF LAST WORD. ; 100$: RETURN ;JOB COMPLETE. .PAGE .SBTTL REPUNA REPORT 3, UNALLOCATED DSR. ; ; DESCRIPTION: ; REPORT ALL DSR THAT AS NOT BEEN ALLOCATED IN THE BIT MAP. ; ; REPUNA: ; INCB RPTFLG ; We don't want repeats for this one MOV #BITMAP,R5 ;GET ADDRESS OF BITMAP. MOV #100000,R4 ;GET MASK TO FIRST BIT. CLR R3 ;START ADDRESS OF EXEC. ; ; ; 20$: MOV #1,R2 ;FIND NEXT UNALLOCATED CALL FIND ; BIT IN BITMAP. BCS 60$ ;BRANCH IF NONE. ; MOV R3,R0 ;SAVE EXEC ADDRESS OF UNALLOCATED DSR WORD(S). ; CLR R2 ;COUNT NUMBER OF CALL FIND ; UNALLOCATED BITS. BCS 60$ ; Branch if none MOV R3,-(SP) ; Save R3 MOV R1,-(SP) ; And R1 MOV R0,-(SP) ; and R0 ; 30$: MOV R0,R3 ; Get start address of unallocated area ADD OFFSET+16.,R3 ; Relocate (must be in DSR) ; 35$: MOV R3,R0 ; Save the relocated address MOVB W.WISZ(R3),R3 ; Get window size (if it were a window) MUL #RTVSZ,R3 ; ADD #W.RTRV,R3 ; ADD #2,R3 ; Round to granularity border BIC #2,R3 ; ASR R3 ; Convert to words SUB R3,R1 ; Same as undetermined length? BEQ 40$ ; If EQ yes - output guess BLT 50$ ; If LT too much - give up trying ASL R3 ; Convert back to bytes ADD R0,R3 ; Might be another one - try again BR 35$ ; ; 40$: MOV #GUES,R0 ; Output Guess MOV #GUESL,R1 ; CALL PRINT ; ; 50$: MOV (SP)+,R0 ; Restore R0 MOV (SP)+,R1 ; Restore R1 MOV (SP)+,R3 ; Restore R3 ; MOV OFFSET+16.,OFFDIF ; Must be in Pool! CALL REPOR1 ;PRINT REPORT ON UNALLOCATED WORDS. BR 20$ ;GO BACK FOR MORE. ; 60$: ; RETURN ;AND RETURN. .PAGE .SBTTL OPEN OPEN OUTPUT FILES ; ; DESCRIPTION: ; ; OPEND - Open the Dump File ; OPENR - Close the Dump File and Open the Report File ; OPENR: CLOSE$S #DMPFDB ; Close the old file MOV #REPFDB,OUTFDB ; Get FDB address of report file BR OPEN ; Branch to common open ; OPEND: ; MOV #DMPFDB,OUTFDB ; Get FDB address of dump file ; OPEN: OPEN$W OUTFDB ;OPEN OUTPUT FILE. BCC 10$ ; MOVB F.ERR(R0),R1 ;GET ERROR CODE. FERR ERR,R1 ; ; 10$: CLR PAGCNT ; Initialise Page Count RETURN ; .PAGE .SBTTL FIND SEARCH BITMAP UNTIL STATE CHANGE FOUND. ; ; DESCRIPTION: ; FROM THE CURRENT POSITION IN THE BITMAP, LOCATE THE BIT THAT CHANGES ; STATE FROM THE REQUIRED STATE, COUNTING NUMBER OF TIMES CURRENT STATE ; IS FOUND. ; ; INPUT PARAMETERS: ; R5 = ADDRESS OF BITMAP WORD TO CONTINUE FROM. ; R4 = BIT MASK INTO R5. ; R3 = ADDRESS OF EXEC LOCATION REPRESENTED BY R4/R5 ; R2 = STATE TO BE SEARCHED UNTIL CHANGE FOUND (0 OR 1) ; ; OUTPUT PARAMETERS: ; R5 TO R3 = AS ABOVE, BUT POINTING TO BIT THAT CHANGED STATE. ; R1 = NUMBER OF TIMES STATE (IN R2) WAS FOUND. ; ; COMPLETION CODES: ; "C" = 0 IF OK, ; 1 IF BITMAP SEARCHED COMPLETELY. ; ; FIND: ; CLR R1 ;PREPARE TO COUNT NUMBER OF TIMES R2 STATE FOUND. ; ; 20$: CMP #K20*2,R3 ;BRANCH IF WHOLE OF BLOS 200$ ; BITMAP SEARCHED. ; CMP #100000,R4 ;BRANCH IF NOT TESTING BNE 80$ ; FIRST BIT IN WORD. ; ;FIRST BIT IN WORD. LETS TRY WHOLE WORD. TST R2 ;SPLIT INTO "0" OR BNE 40$ ; "1" FIND. TST (R5) ;"0", BRANCH IF WHOLE BEQ 60$ ; WORD IS "0", OR BR 80$ ; BRANCH IF NOT. 40$: CMP #177777,(R5) ;"1", BRANCH IF WHOLE BNE 80$ ; WORD IS NOT "1". 60$: ADD #16.,R1 ;WHOLE WORD = R2 STATE. ADJUST COUNT OF TIMES FOUND. ADD #16.*2,R3 ;ADJUST EXEC ADDRESS. ADD #2,R5 ;ADJUST BITMAP ADDRESS. BR 20$ ;GO BACK FOR NEXT WORD. ; 80$: ;TEST INDIVIDUAL BITS IN WORD. TST R2 ;SPLIT INTO "0" BNE 100$ ; OR "1" FIND. BIT R4,(R5) ;"0", BRANCH IF BIT BEQ 120$ ; IS "0", OR BR 200$ ; BRANCH IF NOT. 100$: BIT R4,(R5) ;"1", BRANCH IF STATE BEQ 200$ ; NOT FOUND. 120$: INC R1 ;INCREMENT COUNT. ADD #2,R3 ;ADJUST EXEC ADDRESS. ASR R4 ;ADJUST BITMAP MASK. BCS 140$ ;BRANCH IF NEW WORD IS REQUIRED. BIC #100000,R4 ;CLEAN OFF TOP BIT. BR 80$ ;CONTINUE TEST OF BITS IN THIS WORD. ; 140$: ADD #2,R5 ;NEW WORD REQUIRED. ADJUST BITMAP ADDRESS. MOV #100000,R4 ;RESET BIT MASK. BR 20$ ;GO BACK AND START SEARCH OF THE NEW WORD. ; ; ; ; 200$: TST R1 ;BRANCH (OK) IF STATE BNE 220$ ; WAS FOUND ONCE+. ; SEC ;MUST BE END OF BITMAP. ; 220$: RETURN ; .PAGE .SBTTL REPOR1 PRINT REPORT ON GROUP OF UNALLOCATED DSR BITS. ; ; DESCRIPTION: ; PRINT THE CONTENTS OF THIS CONTIGUOUS GROUP OF DSR WORDS THAT CANNOT ; BE ACCOUNTED FOR. ; ; INPUT PARAMETERS: ; R0 = START ADDRESS (EXEC) OF WORDS. ; R1 = NUMBER OF WORDS. ; ; COMPLETION CODES: ; "C" = 0 IF NO WORRIES, ; 1 IF AN ERROR OCCURED. ; ; REPOR1: TST R1 ; Any data? BNE 1$ ; If NE yes - carry on JMP 100$ ; No - exit ; 1$: CALL $SAVAL ;SAVE ALL REGISTERS. MOV R0,R2 ;GET FIRST ADDRESS FOR DUMP. MOV R1,R3 ;GET NUMBER OF WORDS TO DUMP. MOV #BLANKL,R0 ;PRINT A MOV #BLANKZ,R1 ; BLANK CALL PRINT ; LINE. MOV #-1,RPTCNT ; Check first time through ; ; 20$: ;LOOP TO PRINT EACH BATCH OF FOUR LOCATIONS MOV R2,-(SP) ; Save real pool address ADD OFFDIF,R2 ; Reset for internal use TSTB RPTFLG ; Do we want repeats? BNE 28$ ; If NE no - carry on CMP #-1,RPTCNT ; First time through? BEQ 28$ ; If eq yes - say so MOV #4,R1 ; check four locations CMP R3,R1 ; less than that left? BLT 26$ ; If LT yes - omit compare ; 22$: CMP (R2)+,-10.(R2) ; Same as last four? BNE 26$ ; If NE no - see if repeat output needed SOB R1,22$ ; Yes - check next one TST RPTCNT ; First duplicated line? BNE 25$ ; If NE no - carry on CMP R3,#8. ; Yes - less than two lines left BLT 26$ ; If LT yes - output normally MOV #4,R1 ; No - check next four words ; 24$: CMP -(R2),8.(R2) ; Same as next four words? BNE 26$ ; If NE no - ignore single line repeats SOB R1,24$ ; Keep checking ; 25$: INC RPTCNT ; all the same - count another one SUB #4,R3 ; Count the entries MOV (SP)+,R2 ; Restore R2 JMP 90$ ; and check next four ; 26$: TST RPTCNT ; any repeats to output? BEQ 28$ ; If eq no - carry on MOV RPTCNT,ARGBLK ; Yes - put count in argument block MOV #REPBUF,R0 ; Set up lines in REPBUF MOV #RPT,R1 ; MOV #ARGBLK,R2 ; CALL $EDMSG ; MOV #REPBUF,R0 ; Output it CALL PRINT ; ADD #2,LINCNT ; Count the extra lines ; 28$: MOV (SP),R2 ; Restore R2 MOV #ARGBLK,R0 ; Get address of argument block MOV R2,(R0)+ ; Insert the Address ADD OFFDIF,R2 ; Reset R2 again CLR RPTCNT ; MOV #8.,R1 ; Initialise argument block ; 30$: CLR (R0)+ ; SOB R1,30$ ; MOV #ARGBLK+2,R0 ; Reset argument block address MOV #4,R1 ; Copy in four values CMP R3,R1 ; Less than that left? BHIS 40$ ; If HIS OK - carry on MOV R3,R1 ; No - reset to number left BNE 40$ ; If NE some left - carry one MOV (SP)+,R2 ; Else clear stack JMP 95$ ; and exit ; 40$: MOV R1,16.(R0) ; Insert number of ASCII characters ASL 16.(R0) ; MOV R2,18.(R0) ; And their address ; 50$: MOV (R2),8.(R0) ; Insert word for RAD50 MOV (R2)+,(R0)+ ; and for Octal SOB R1,50$ ; Like so MOV #REPBUF,R0 ; Get starting address of output block MOV #DSRLST,R1 ; Address of format string MOV #ARGBLK,R2 ; Address of argument block CALL $EDMSG ; Set up the output string SUB #4,R3 ; Count four words BGE 70$ ; If GE there were at least four left NEG R3 ; Get number to blank out MUL #9.,R3 ; Multiply by 9 MOV #REPBUF+46.,R2 ; Calculate address to blank ; 60$: MOVB #' ,-(R2) ; Like so SOB R3,60$ ; ; 70$: MOV #REPBUF,R0 ;PRINT THAT CALL PRINT ; REPORT. MOV (SP)+,R2 ; Restore real pool address ; 90$: ADD #8.,R2 ; Update pool address TST R3 ; test count of remaining BGE 20$ ;GO BACK IF MORE. ; ; 95$: CLC ;OK. ; 100$: RETURN ; .PAGE .SBTTL REPMAP REPORT 2, DSR BITMAP ; ; DESCRIPTION: ; PRINT REPORT ON DSR BITMAP, SHOWING KNOWN AND UNKNOWN AREA. ; REPMAP: ; RETURN ; .PAGE .SBTTL LINREP Format and print a report line ; ; ; Input Parameters: ; R0 = address to store start/end address ; R1 = address of skeleton format string ; LINREP: MOV R4,(R0) ; Insert start address SUB OFFDIF,(R0) ; Reset it ADD (R0)+,(R0) ; Calculate end address DEC (R0) ; BIS #2,(R0) ; Round up to granularity boundary ; EDIT: MOV #ARGBLK,R2 ; ; EDIT1: MOV #REPBUF,R0 ; Edit the message CALL $EDMSG ; MOV #REPBUF,R0 ; Output it CALL PRINT ; RETURN .PAGE .SBTTL PRINT PRINT A LINE TO OUTPUT FILE. ; ; DESCRIPTION: ; WRITE THE LINE TO THE OUTPUT FILE. ; ; INPUT PARAMETERS: ; R0 = ADDRESS OF LINE TO BE PRINTED. ; R1 = BYTE SIZE OF LINE. ; PRINT: ; MOV R2,-(SP) ; Save R2 MOV R0,-(SP) ; Save R0 MOV R1,-(SP) ; Save R1 CMP LINCNT,#60. ; Time for a new page? BLT 10$ ; If LT no - carry on GTIM$S #RCVPKT ; Yes - get the time INC PAGCNT ; Count the Page MOV PAGCNT,RCVPKT+10. ; Put it in as argument MOV #3,LINCNT ; Initialise the line count MOV #OUTBLK,R0 ; Get address for output MOV #HDR1,R1 ; and address of format string MOV #RCVPKT,R2 ; and argument block CALL $EDMSG ; edit the message PUT$ OUTFDB,#OUTBLK,R1 ; and output it MOV #OUTBLK,R0 ; Get address for output MOV SHEAD,R1 ; and address of format string BEQ 10$ ; If eq none - omit it MOV #RCVPKT,R2 ; and argument block CALL $EDMSG ; edit the message ADD #2,LINCNT ; another two lines PUT$ OUTFDB,#OUTBLK,R1 ; and output it ; 10$: MOV (SP)+,R1 ; Restore R1 MOV (SP)+,R2 ; put R0 in R2 for now INC LINCNT ; Count the line PUT$ OUTFDB,R2,R1 ;PRINT LINE. BCC 40$ ;BRANCH IF OK. MOVB F.ERR(R0),R1 ;GET ERROR CODE. FERR ERR,R1 ; ; 40$: MOV (SP)+,R2 ; Restore real R2 RETURN ; .PAGE .SBTTL CLRNS INITIALIZE "NUMENT" AND "SIZENT" ; ; DESCRIPTION: ; CLEAR BOTH VARIABLES. ; ; CLRNS: ; MOV #NUMENT,R0 ;CLEAR MOV #SIZENT,R1 ; BOTH MOV #ENTNUM,R2 ; VARIABLES. 20$: CLR (R0)+ ; CLR (R1)+ ; SOB R2,20$ ; ; RETURN ; ; COPENT: MOV #NUMENT,R0 ; Get address of numbers of items MOV #SIZENT,R1 ; and address of sizes of items MOV #ARGBLK,R2 ; and somewhere to stuff it CLR R4 ; Initialise totals counter ; 30$: MOV (R0)+,(R2)+ ; Insert number of elements ADD (R1),R4 ; Increment total MOV (R1)+,(R2)+ ; Insert size of elements SOB R3,30$ ; and so on MOV R4,(R2)+ ; Insert total RETURN .PAGE .SBTTL COMLNK Allocate Ordinary Linked Lists ; ; This subroutine allocates and reports any general linked list that ; has fixed-length elements, none of which contain special information. ; ; Note that the only such-list which is not linked through the first word ; (the Attachment Descriptors) links to the next link word and not to the top ; of the next element. This has therefore been adopted as a general principle ; ; Inputs: ; R0 = Address of argument list set up for LINREP ; R1 = Address of line report skeleton for LINREP ; R2 = Offset from start of element to link word to next element ; R3 = SIZENT/NUMENT offset for ALOCATE ; R4 = Address of address of first element ; R5 = Size (in words) of each element ; ; Outputs: ; All registers except R4 are preserved ; COMLNK: MOV (R4),R4 ; Get address of next element BEQ 10$ ; If EQ no more - exit SUB R2,R4 ; Reset to start of element CALL RELOC4 ; relocate the address BCS 10$ ; If CS can't map it - end of list CALL ALOCT1 ; Allocate the space BCS 5$ ; If CS not in DSR - omit line report MOV 2(R0),-(SP) ; Save the length field MOV R0,-(SP) ; Save R0 for next time MOV R1,-(SP) ; Save R1 for next time MOV R2,-(SP) ; Save R2 for next time CALL LINREP ; Output the line report MOV (SP)+,R2 ; Restore R2 MOV (SP)+,R1 ; Restore R1 MOV (SP)+,R0 ; Restore R0 MOV (SP)+,2(R0) ; Restore the length field ; 5$: ADD R2,R4 ; Offset to address of address of next element BR COMLNK ; Process it ; 10$: RETURN ; .PAGE .SBTTL RELOC4 Relocate R4 to internal address ; RELOC4: MOV R0,-(SP) ; Save some registers MOV R1,-(SP) ; MOV R2,-(SP) ; MOV #OFFSET,R0 ; Get address of offsets MOV #4,R1 ; 4 to check ; 10$: CMP R4,(R0) ; In this range? BLO 20$ ; If LO error - not in any range CMP R4,2(R0) ; Sure it is? BLO 30$ ; If LO yes - take it ADD #6,R0 ; Set to next SOB R1,10$ ; and check it ; 20$: DIAG RNGE,R4,6(SP) ; Log a message SEC ; Set carry bit BR 40$ ; and return ; 30$: MOV 4(R0),OFFDIF ; Store the offset ADD OFFDIF,R4 ; Relocate R4 CLC ; Show success ; 40$: MOV (SP)+,R2 ; Restore registers MOV (SP)+,R1 ; MOV (SP)+,R0 ; RETURN .PAGE .SBTTL STBRTN Get Values for Exec Symbols ; ; This is a subroutine to determine various Executive addresses, which does ; not have to be rebuilt for each Executive (I hope!) ; ; STBRTN: MOV #SYMTAB,R4 ; Get address of RAD50 symbol table MOV #SYMNUM,R2 ; And the number of them OPEN$ #INPFDB ; Open the input file BCC 10$ ; If CC OK - carry on MOVB F.ERR(R0),R0 ; Sign-extend error code FERR OPNI,R0 ; Else log an error ; 10$: GET$ #INPFDB,#BUFF,#256. BCS 90$ ; If error exit CMP BUFF,#1 ; Right type? BNE 90$ ; If ne no - exit MOV #BUFF+2,R0 ; Look for symbol MOV #15.,R3 ; ; 20$: CMP (R4),(R0) ; This one BNE 30$ ; If ne no - try next CMP 2(R4),2(R0) ; Sure? BNE 30$ ; No - check next one MOV 6(R0),(R4)+ ; Yes - overwrite with address CLR (R4)+ ; and set to next symbol DEC R2 ; Count the one we had BEQ 40$ ; If EQ we've finished - return ; 30$: ADD #8.,R0 ; Set to next one SOB R3,20$ ; Keep trying BR 10$ ; Get next record ; 40$: CLOSE$ #INPFDB ; RETURN ; Return ; 90$: MOV R2,-(SP) ; Save R2 TST (R4) ; A Forced rewind? BEQ 95$ ; If EQ yes - omit error message DIAG NSYM,(R4),2(R4) ; Output error message ; 95$: MOV #INPFDB,R0 ; Rewind the file CLR R1 ; MOV #1,R2 ; CLR R3 ; CALL .POINT ; MOV (SP)+,R2 ; Restore R2 CLR (R4)+ ; Set the word to zero CLR (R4)+ ; DEC R2 ; Count the one we had BEQ 40$ ; If EQ we've finished - return BR 10$ ; Get the next record .PAGE .SBTTL SST SST Handling Routines ; ; This routine handles any SSTs by logging an error, closing the file ; and exiting. This should make it easy to track down the error. ; SSTFP: INC SSTNUM ; Floating Point SSTTE: INC SSTNUM ; TRAP SSTEM: INC SSTNUM ; Non-RSX EMT SSTIL: INC SSTNUM ; Reserved Instruction SSTIO: INC SSTNUM ; IOT SSTBE: INC SSTNUM ; BPT SSTMP: INC SSTNUM ; Memory Protect SSTOD: ; Odd Address Trap TST SSTNUM ; Have we been here before? BGE 20$ ; If GE no - carry on CMP SSTNUM,#-1000. ; Yes - twice? BLE 10$ ; If LE yes - don't even try to close the file MOV #-2000.,SSTNUM ; Stop second level of recursion CLOSE$ OUTFDB ; No - close the file ; 10$: EXIT$S ; Exit ; 20$: CMP SSTNUM,#1 ; Memory Protect? BNE 30$ ; If NE no - carry on ADD #6,SP ; Yes - chuck three words off the stack ; 30$: CMP SSTNUM,#5 ; TRAP or EMT? (ignore FP as impossible) BLT 40$ ; If LT no - carry on TST (SP)+ ; Yes - chuck a word off the stack ; 40$: MOV (SP)+,SIZENT ; Save the old PC TST (SP)+ ; Ignore the PS MOV SSTNUM,SIZENT+2 ; Save the SST number MOV #-100.,SSTNUM ; And stop recursion FERR SST,SIZENT+2,SIZENT,R0,R1,R2,R3,R4,R5,SP,(SP),OFFDIF .PAGE .SBTTL DIAG Error Routines ; FERR: CALL DIAG ; Output the Message CLOSE$ OUTFDB ; Close any files CLOSE$ #INPFDB ; EXIT$S ; Terminate the program ; DIAG: CALL OUT ; Output QIOW$S #IO.WLB,#ERRLUN,#1,,,,<#OUTBLK,R1,#40> ; Output to TI: RETURN ; Return ; OUT: MOV #OUTBLK,R0 ; Get Buffer for Output MOV #RCVPKT,R2 ; Get Address of any Parameters CALL $EDMSG ; Edit the Message RETURN .END DSRDMP ;