TITLE KLEPTO - THE KLEPTOMANIAC (A FAST RIPOFF) SUBTTL DEFINITONS SEARCH MAC10,JOBDAT,UUOSYM,COMMOD TWOSEG 760000 ;MAKE ROOM FOR LARGE LOWSEG SALL ;SAVE THE FORESTS ;STEPHEN M. WOLFE ;MR1-2/S43 ;DIGITAL EQUIPMENT CO. ;TECHNICAL SUPPORT GROUP (HOSS) ;200 FOREST ST. ;MARLBORO, MA., 01752 ;(617) 467-5583 ;AC'S F=0 ;FLAGS T1=1 ;TEMPS T2=T1+1 T3=T2+1 T4=T3+1 P1=5 ;PRESERVED P2=P1+1 P3=P2+1 P4=P3+1 U=11 ;ADDR OF UDB TC=12 ;ADDR OF TCB FL=13 ;ADDR OF FIL DDB=14 ;ADDR OF DDB B=15 ;ADDR OF BUFFER P=17 ;PDL ;FLAGS F.DIR==1B35 ;RIB OF DIRECTORY F.PRM==1B34 ;PRIME RIB F.RIB==1B33 ;ALREADY STEPPED OVER RIB F.SUM==1B32 ;ALREADY DID CHECKSUM F.STR==1B31 ;STR DATA FROZEN F.HW==1B30 ;HIGH WATER F.VHW==1B29 ;VERY HIGH WATER (PANIC) F.P2==1B28 ;PASS 2 F.SAT==1B27 ;SAT.SYS F.TTY==1B26 ;OUTPUT TO PHYSICAL TTY F.702==1B25 ;7.02 MONITOR (OR LATER) F.SHC==1B24 ;SAT HAS CHANGED F.TTC==1B23 ;USE TTCALL F.LOK==1B22 ;I OWN THE INTERLOCK F.NOC==1B21 ;NO CTRL-C ALLOWED F.CC==1B20 ;CTRL-C WAS TYPED F.SIL==1B19 ;NO OUTPUT TO LOG FILE (TTCALL ONLY) F.ALL==1B18 ;WE ARE DOING ALL ;ASSEMBLY PARAMETERS PAGLSH==11 ;BITS PER PAGE PAGSIZ==1_PAGLSH ;WORDS PER PAGE IFNDEF BADDR, ;NUMBER OF BAD CFPS IT TAKES TO ;DECLARE THAT DIR IS CLOBBERED IFNDEF UPN, ;PAGES TO ALLOCATE AT A TIME NSTR==^D36 ;NUMBER OF STRS IFNDEF NSEC, ;SECONDS TO SLEEP IFNDEF MINVRT, ;MINIMUM AMOUNT OF SWAP SPACE IFNDEF DOWNN, ;NUMBER OF PAGES TO RELEASE PDLSIZ==200 ;SIZE OF PDL BLKSIZ==200 ;SIZE OF A DISK BLOCK FOOSIZ==33 ;SIZE OF SCRATCH SPACE NUNT==^D15 ;MAX UNITS IN A STR IFG <1_ACSUN1>-1-NUNT, IFNDEF NSLT, ;NUMBER OF COPIES OF KLEPTO IFNDEF NHCOR, ;NUMBER OF WORDS OF HISEG FREE CORE IFNDEF FTCIH, ;CODE IN HISEG ;THERE IS A BUG IN SETUWP ;WHICH LEAVES THE HISEG UNCACHED IFNDEF LPTWID, ;WIDTH OF LPT IFNDEF LNM, ;LOGICAL NAME IFNDEF MAXSAF, ;MAX SAFETY BLOCKS PER UNIT IFNDEF NDDBS, ;NUMBER OF DDBS IFNDEF NBLK, ;NUMBER OF BLOCKS TO READ AT ONCE IFNDEF NSKP, ;NUMBER OF BLOCKS WE ARE WILLING ; TO SKIP (CALIBRATED FOR AN RP06) IFNDEF DSKP, ;BPT ON AN RP06 IFNDEF FTDBUG, ;DEBUGGING CODE IFNDEF FTCHK, ;CODE TO CHECK TREE CONSISTENCY IFNDEF FTGCHK, ;CODE TO CHECK CONSISTENCY OF GARBAGE IFNDEF TREG, ;THRESHOLD FOR TYPING REGIONS IFNDEF RMAR, ;RIGHT MARGIN IFNDEF HWN, ;HIGH WATER NUMERATOR IFNDEF HWD, ;HIGH WATER DEMONINATOR IFNDEF VHWN, ;VERY HIGH WATER NUMERATOR IFNDEF VHWD, ;VERY HIGH WATER DEMONINATOR ;OPDEFS OPDEF PJRST[JRST] ;POPPING JRST DEFINE FALL(AA),>> ;CH'S TL==16 ;TEMP LOG TO==17 ;LOG FILE ;MONITOR SYMBOLS KONCPU==32 ;THE 7.01 VERSION OF THIS SYMBOL UNI2ND==72 ;THE 7.01 VERSION OF THIS SYMBOL ;ABBREVIATIONS: ;CC=CLUSTER COUNT ;CS=CHECK SUM ;CA=CLUSTER ADDRESS ;BN=BLOCK NUMBER (USUALLY RELATIVE TO STR) ;RTP=RETRIEVAL POINTER ;FORMAT OF TCB (TASK CONTROL BLOCK) TCBLNK==0 ;LH=BACKWARD, RH=FORWARD TCBSON==1 ;LH=LEFT SON, RH=RIGHT SON TCBRNT==2 ;LH=ADDR OF PARENT TCB TCBBAL==2 ;BALANCE FACTOR (HEIGHT OF LEFT SUBTREE ; MINUS HEIGHT OF RIGHT SUBTREE) TCSBAL==3 TCNBAL==^D20 BALMO==1 ;TOO RIGHT HEAVY BALM==2 ;RIGHT HEAVY (ACCEPTABLY SO) BALZ==3 ;PERFECTLY BALANCED BALP==4 ;LEFT HEAVY (ACCEPTABLY SO) BALPO==5 ;TOO LEFT HEAVY TCBGAR==2 ;SIZE (GC ONLY) TCSGAR==^D15 TCNGAR==^D35 TCMGAR==<1_TCSGAR>-1 TCBCOD==3 ;FUNCTION CODE TCSCOD==3 TCNCOD==2 TCBRBC==3 ;(RIB ONLY) COUNT OF RIBS TCSRBC==^D8 ;I.E. PRIME RIB IS NUMBER 0 TCNRBC==^D10 IFG DESRBC-TCSRBC, TCBCX==3 ;CHANNEL INDEX (OF DDB) TCSCX==4 ; THIS FIELD ONLY FILLED IN FOR TCNCX==^D14 ; ONE TCB PER BUFFER CXACT==<1_TCSCX>-1 ;TRUST ME, I'M ACTIVE IFG NDDBS-, TCBCOR==3 ;(EXTENDED RIB) FILE IS TCPCOR==1B15 ;CORRUPT, IT HAS FREE ;AND/OR MULTIPLY USED CLUSTERS TCBMBB==3 ;MIGHT BE BAD TCPMBB==1B16 ;THIS BLOCK IS SUSPECTED OF HAVING ;AN I/O ERROR TCBFIL==3 ;RH=ADDR OF FIL TCBBLK==4 ;BN RELATIVE TO STR TCBFLR==5 ;(EXTENDED RIB) CONTENTS OF RIBFLR TCBREL==5 ;(SUM+DIR) BN RELATIVE TO FILE TCBSUM==6 ;(SUM ONLY) CHECKSUM TCBSIZ==6 ;(EXTENDED RIB) RIBSIZ FROM PRIME RIB TCBLFT==7 ;(EXTENDED RIB) BLOCKS LEFT IN RIBALC TCBCST==10 ;(CORRUPT EXTENDED RIB) ; COPY OF F2CST AND M2CST ;FORMAT OF FIL (FILE BLOCK) FILNAM==0 ;FILE NAME FILEXT==1 ;LH=EXTENSION FILDAD==FILEXT ;RH=PARENT FIL (0 IF MFD) FILCFP==2 ;LH=CFP FOR THIS FILE ;USED IN CHECKING RIBUFD FILCNT==2 ;USE COUNT FISCNT==^D18 FINCNT==^D35 ;FORMAT OF A REG (REGION) REGNXT==0 ;RH=NEXT REGION REGLOW==1 ;LOWEST CLUSTER IN REGION REGHI==2 ;HIGHEST CLUSTER IN REGION ;FORMAT OF A CST (CLUSTER LIST HEADER) CSTREG==0 ;RH=ADDR OF 1ST REG CSTNUM==1 ;TOTAL CLUSTERS IN ALL REGIONS CSTCNT==2 ;TOTAL NUMBER OF REGIONS ;FORMAT OF A DDB DDBHDR==0 ;RING HEADER (3 WORDS) DDBLBN==3 ;LOW BN DDBHBN==4 ;HIGH BN DDBPUN==5 ;PHYS UNIT NAME CURRENTLY OPEN DDBBUF==6 ;ADDR OF BUFFER DDBCH==7 ;CHANNEL NUMBER DDBCX==10 ;CHANNEL INDEX (INTO USRJDA) DDBTCB==11 ;1ST TCB DDBDON==12 ;NON-0 IF I/O DONE DDBERR==13 ;NON-0 IF I/O ERROR ;FORMAT OF SNF SNFNXT==0 ;NEXT SNF ON SYSTEM SNFLNK==1 ;NEXT SNF THIS LIST SNFNAM==2 ;NAME OF STR SNFCHN==3 ;BIT MASK OF CHANNELS SNFVRT==4 ;PAGES OF SWAPPING SPACE (0 IF NOT ASL) ;FORMAT OF A CNF CNFNXT==0 ;ADDR OF NEXT CNF CNFNAM==1 ;PHYS NAME OF UNIT CNFALT==2 ;NAME OF ALTERNATE PORT CNFSTR==3 ;NAME OF STR CNFCHN==4 ;BIT MASK OF CHANNELS CNFVRT==5 ;PAGES OF SWAPPING SPACE (0 IF NOT ASL) ;LOG FILE LOGNXT==0 ;ADDR OF NEXT LOG LOGDEV==1 ;STR NAME FILE IS ON LOGNAM==2 ;FILENAME ;SIZES SIZFIL==3 ;SIZE OF FIL SIZDIR==6 ;SIZE OF DIR TCB SIZSUM==7 ;SIZE OF SUM TCB SIZRIB==5 ;SIZE OF PRIME RIB TCB SIZXRB==10 ;SIZE OF EXTENDED RIB TCB SIZCXR==SIZXRB+SCSTL ;SIZE OF CORRUPT EXTENDED RIB SIZREG==3 ;SIZE OF REG SIZCST==3 ;SIZE OF CST SIZDDB==14 ;SIZE OF DDB SIZGAR==3 ;SIZE OF SMALLEST BLOCK SIZCNF==6 ;SIZE OF CNF SIZLOG==3 ;SIZE OF LOG FILE SIZSNF==5 ;SIZE OF SNF SUBTTL EDIT HISTORY VWHO==0 ;DEC VMAJOR==1 VMINOR==0 VEDIT==1 ;6-8-84/SMW DEVELOPEMENT COMPLETED, ;COMMENCE EDIT HISTORY LOC .JBVER BYTE (3)VWHO(9)VMAJOR(6)VMINOR(18)VEDIT SUBTTL DATA AREAS RELOC 0 FAST: BLOCK 1 ;FIRST WORD IN CORE (UNUSED) CRSHAC: BLOCK 20 ;ACS SAVED BY DIE TDEV: BLOCK 3 ;OPEN BLOCK FOR TEMP LOG LDEV: BLOCK 3 ;OPEN BLOCK FOR LOG FILE LFIL: BLOCK .RBEXT+1 ;ENTER BLOCK FOR LOG FILE TFIL: BLOCK .RBEXT+1 ;LOOKUP/ENTER BLOCK FOR TEMP LOG PTH: BLOCK .PTMAX ;PATH OF LOG FILE PTHL==.-PTH SVWCNT: BLOCK 1 ;SAVED VALUE OF WRDCNT WRDCNT: BLOCK 1 ;WORDS ALLOCATED FREMEM: BLOCK 1 ;1ST FREE CORE BLOCK SSL: BLOCK NSTR*3+.FSDSO ;ARG BLOCK FOR CHANGING SSL FOO: BLOCK FOOSIZ ;SCRATCH SPACE SYSPPN: BLOCK 1 ;PPN OF SYS MFDPPN: BLOCK 1 ;PPN OF MFD FFAPPN: BLOCK 1 ;OPR PPN ROOT: BLOCK 1 ;ROOT NODE QTCB: BLOCK 1 ;TCB QUEUE DEV: BLOCK 3 ;OPEN BLOCK IBUF: BLOCK 3 ;RING HEADER FOR TEMP LOG OBUF: BLOCK 3 ;RING HEADER FOR LOG FILE SAVBUF: BLOCK 1 ;ADDR OF 1ST BUF FOR LOG FILE HW: BLOCK 1 ;HIGH WATER LEVEL VHW: BLOCK 1 ;VERY HIGH WATER LEVEL ZER:! ;ZERO AT BEGINNING OF STR LSTCST: BLOCK SIZCST ;LOST CLUSTERS FRECST: BLOCK SIZCST ;FREE CLUSTERS MULCST: BLOCK SIZCST ;MULTIPLY USED CLUSTERS BADCST: BLOCK SIZCST ;BAD CLUSTERS ;THIS LIST CONTAINS ONLY THOSE ;BAD BLOCKS WHICH WERE NOT ;INCLUDED IN BADBLK.SYS ZERL==.-ZER ;LENGTH SCST:! ;ZERO AT BEGINING OF PASS 2 RIB F2CST: BLOCK SIZCST ;FREE CLUSTERS THIS RIB M2CST: BLOCK SIZCST ;MULTIPLY USED CLUSTERS THIS RIB SCSTL==.-SCST ;LENGTH HPOS: BLOCK 1 ;HORIZONTAL POSITION OF CURSOR MARGIN: BLOCK 1 ;VALUE OF HPOS AT RIGHT MARGIN ACTCNT: BLOCK 1 ;NUMBER OF ACTIVE DDBS DDBS: BLOCK 1 ;NUMBER OF DDBS TOTAL DONCNT: BLOCK 1 ;USED BY FNDDON USRJDA: BLOCK NDDBS+1 ;ADDR OF DDB TBUDB: BLOCK NUNT ;ADDR OF UDB (NOT IN ORDER) DEFIN: BLOCK .FSNUN ;DEFINE A STR TABUDB: BLOCK NUNT ;ADDR OF UNIT DATA BLOCK DEFINL==.-DEFIN ;SIZE OF ARG BLOCK LOGSTR: BLOCK 1 ;STR LOG FILE IS ON OURCPU: BLOCK 1 ;CURRENT CPU (BIT MASK) OVERN: BLOCK 1 ;NUMBER OF BAD FREE CLUSTERS MYSGN: BLOCK 1 ;MY HISEG NUMBER MYSLT: BLOCK 1 ;MY SLOT NUMBER MYJOB: BLOCK 1 ;MY JOB NUMBER RUNSTR: BLOCK 1 ;STR PROGRAM WAS RUN FROM LOGS: BLOCK 1 ;ADDR OF 1ST LOG MONVER: BLOCK 1 ;MONITOR VERSION MYSNF: BLOCK 1 ;ADDR OF SNF WE ARE DOING PDL: BLOCK PDLSIZ ;PUSH DOWN LIST CMD: BLOCK 2 ;COMMAND LIST SAVPC: BLOCK 1 ;COPY OF .EROPC ;THESE LOCATIONS ARE USED AS LOCAL VARIABLES INSIDE DORIB DRPHY: BLOCK 1 ;BN RELATIVE TO STR DRBLK: BLOCK 1 ;BN RELATIVE TO STR (WORKING COPY) DRCA: BLOCK 1 ;CLUSTER ADDRESS DRCS: BLOCK 1 ;CHECKSUM DRCC: BLOCK 1 ;CLUSTER COUNT DRCNT: BLOCK 1 ;BLOCKS LEFT IN THIS CLUSTER DRLFT: BLOCK 1 ;BLOCKS LEFT TILL RIBALC RUNS OUT DRREL: BLOCK 1 ;BN RELATIVE TO FILE DRSIZ: BLOCK 1 ;RIBSIZ IN BLOCKS SUBTTL STRUCTURE DATA BLOCK DEFINE SE(AA),< IFN .-SDB-AA, BLOCK 1> SDB:! ALIAS: SE .FSSNM ;NAME STR MOUNTED AS NUN: SE .FSSNU ;NUMBER OF UNITS HLBN: SE .FSSHL ;HIGHEST LOGICAL BLOCK NUMBER SSIZ: SE .FSSSZ ;SUM OF UDBBPU SE .FSSRQ ;RESERVED QUOTA SE .FSSRF ;RESERVED QUOTA LEFT STAL: SE .FSSTL ;SUM OF UDBTAL SOVR: SE .FSSOD ;OVERDRAW SPT1: SE .FSSMP ;1ST RTP FOR MFD S1PT: SE .FSSML ;NON-0 IF MFD ONLY HAS 1 RTP SUN1: SE .FSSUN ;1ST UNIT FOR MFD STRY: SE .FSSTR ;RETRIES ON ERROR BIGBPU: SE .FSSBU ;BIGGEST UDBBPU BPSC: SE .FSSBC ;BLOCKS PER SUPER CLUSTER SCPU: SE .FSSSU ;SUPER CLUSTERS PER UNIT SE .FSSIG ;IGNORED CCBP: SE .FSSCC ;BP TO CLUSTER COUNT CSBP: SE .FSSCK ;BP TO CHECKSUM CABP: SE .FSSCA ;BP TO CLUSTER ADDRESS SPVS: SE .FSPVT ;NON-0 IF PRIVATE STR SPPN: SE .FSPPN ;OWNER PPN CRSBN: SE .FSSCR ;BN (REL TO STR) OF CRASH.EXE SK4C: SE .FSK4C ;K FOR CRASH SZSDB==.-SDB ;PORTION OF SDB PASSED TO STRUUO BPC: BLOCK 1 ;BLOCKS PER CLUSTER BPCS: BLOCK 1 ;BITS PER CHECKSUM MBPCS: BLOCK 1 ;MINUS BITS PER CHECKSUM BPLU: BLOCK 1 ;BLOCKS PER LARGEST UNIT HUN: BLOCK 1 ;HIGHEST UNIT NUMBER STRNAM: BLOCK 1 ;NAME OF STR (IN HOME BLOCKS) MFDBN: BLOCK 1 ;BN OF RIB OF MFD WL: BLOCK 1 ;SOME UNIT IN STR IS WRITE LOCKED SDL: BLOCK 1 ;POSITION IN SDL OR -1 PSSL: BLOCK 1 ;POSITION IN SSL OR 0 SSLSTS: BLOCK 1 ;STATUS OF THIS STR IN SSL SUBTTL UNIT DATA BLOCK ZZ==0 DEFINE ITM(AA),< AA==ZZ ZZ==ZZ+1> DEFINE ITEM(AA,BB),< IFN BB-ZZ, ITM AA> ;UNIT DATA BLOCK (UDB) ITEM UDBNAM,.FSUNM ;UNIT NAME ITEM UDBHID,.FSUID ;PACK SERIAL NUMBER (SIXBIT) ITEM UDBLOG,.FSULN ;LOGICAL UNIT NAME (E.G. DSKB0) ITEM UDBLUN,.FSULU ;LOGICAL UNIT NUMBER ITEM UDBAWL,.FSUDS ;STATUS (E.G. SOFWARE WRITE-LOCK) ITEM UDBGRP,.FSUGP ;BLOCKS TO TRY ALLOCATING ON OUTPUT ITEM UDBTAL,.FSUTL ;BLOCKS LEFT (MINUS SAFETY FACTOR) ITEM UDBBPC,.FSUBC ;BLOCKS PER CLUSTER ITEM UDBCPS,.FSUCS ;CLUSTERS PER SAT ITEM UDBWPS,.FSUWS ;WORDS PER SAT ITEM UDBSIC,.FSUSC ;SATS IN CORE ITEM UDBSPU,.FSUSU ;SATS PER UNIT ITEM UDBSPT,.FSUSP ;POINTER TO SPT ITEM UDBSLB,.FSUSB ;1ST BLOCK FOR SWAPPING ITEM UDBK4S,.FSUKS ;K FOR SWAPPING SZUDB==ZZ ;PORTION OF UDB PASSED TO STRUUO ITM UDBBLK ;BN WHERE UNIT START (RELATIVE TO STR) ITM UDBSSF ;ENTRIES IN SPT SO FAR ITM UDBBPU ;BLOCKS PER UNIT ITM UDBHLB ;HIGHEST LEGAL BLOCK ITM UDBCYL ;BLOCKS PER CYLINDER ITM UDBBPT ;BLOCKS PER TRACK ITM UDBPST ;POINTER TO TABLE OF POINTERS ;INDEX BY SAT NUMBER, TABLE GIVES ;POINTER TO SAT BLOCK ITM UDBHWP ;NON-0 IF HARDWARE WRITE PROTECT ITM UDBASL ;POSITION IN ASL OR -1 ITM UDBALT ;NAME OF ALTERNATE PORT ITM UDBCPU ;CPU SPECIFICATION (7.01 ONLY) ITM UDBSKP ;BLOCKS TO SKIP SIZUDB==ZZ ;SIZE OF UDB SUBTTL SHARED WRITEABLE HISEG RELOC ;TO HISEG JBTJOB: BLOCK NSLT ;TABLE OF JOB NUMBERS JBTCHN: BLOCK NSLT ;BIT MASK OF CHANNELS LOKJOB: 0 ;JOB THAT OWNS INTERLOCK ILOCK: -1 ;THE INTERLOCK BLST: BLOCK 1 ;LIST OF UNPROCESSED STRS ALST: BLOCK 1 ;LIST OF STRS ALREADY DONE SLST: BLOCK 1 ;LIST OF ALL STRS ON SYSTEM JBTLOG: BLOCK NSLT ;STR NAME LOG IS OPEN ON JBTSTR: BLOCK NSLT ;STR NAME IN PROGRESS CNTSLT: 0 ;NUMBER OF SLOTS IN USE CONFIG: BLOCK 1 ;POINTER TO LIST OF CNF'S CHNNAM: BLOCK ^D36+1 ;TABLE OF NAMES OF CHANNELS HFF: BLOCK 1 ;FIRST FREE ADDR IN HISEG HCOR: BLOCK NHCOR ;HISEG FREE CORE SUBTTL IMPURE DATA RELOC ;BACK TO LOWSEG IFN FTCIH,< LOW:! RELOC ;BACK TO HISEG HI: PHASE LOW > INTR: XWD 4,TRAP ;INTERRUPT BLOCK ER.ICC ;CTRL-C ONLY BLOCK 2 ;END OF IMPURE CODE IFN FTCIH,< DEPHASE LOWL==.-HI ;SIZE OF IMPURE DATA RELOC ;BACK TO LOWSEG BLOCK LOWL ;ALLOCATE SPACE RELOC ;BACK TO HISEG > SUBTTL BYTE POINTERS FIYCNT: POINT FISCNT,FILCNT(FL),FINCNT ;USE COUNT FIZCNT: POINT FISCNT,FILCNT(P3),FINCNT ;USE COUNT RIYRBA: POINT DESRBA,RIBXRA(B),DENRBA ;RIB ADDRESS RIYRBU: POINT DESRBU,RIBXRA(B),DENRBU ;RIB UNIT TCWCOD: POINT TCSCOD,TCBCOD(T1),TCNCOD ;FUNCTION CODE TCXCOD: POINT TCSCOD,TCBCOD(T2),TCNCOD ;FUNCTION CODE TCZCOD: POINT TCSCOD,TCBCOD(P2),TCNCOD ;FUNCTION CODE TCYCOD: POINT TCSCOD,TCBCOD(TC),TCNCOD ;FUNCTION CODE TCXRBC: POINT TCSRBC,TCBRBC(T2),TCNRBC ;RIB COUNT TCYRBC: POINT TCSRBC,TCBRBC(TC),TCNRBC ;RIB COUNT TCZRBC: POINT TCSRBC,TCBRBC(P2),TCNRBC ;RIB COUNT BAYNBB: POINT BASNBB,BAFNBB(P2),BANNBB ;NUMBER BAD BLOCKS IN REGION-1 BAYNBR: POINT BASNBR,BAFNBR(B),BANNBR ;NUMBER OF BAD REGIONS TCXBAL: POINT TCSBAL,TCBBAL(T1),TCNBAL ;BALANCE FACTOR TCZBAL: POINT TCSBAL,TCBBAL(T2),TCNBAL ;BALANCE FACTOR TCWBAL: POINT TCSBAL,TCBBAL(T3),TCNBAL ;BALANCE FACTOR TCVBAL: POINT TCSBAL,TCBBAL(T4),TCNBAL ;BALANCE FACTOR TCYCX: POINT TCSCX,TCBCX(TC),TCNCX ;CHANNEL INDEX TCXCX: POINT TCSCX,TCBCX(T1),TCNCX ;CHANNEL INDEX TCZCX: POINT TCSCX,TCBCX(T2),TCNCX ;CHANNEL INDEX DEYSIZ: PNTR @DDBBUF(DDB),BF.SIZ ;SIZE OF BUFFER TCXGAR: POINT TCSGAR,TCBGAR(T2),TCNGAR ;SIZE OF GARBAGE TCZGAR: POINT TCSGAR,TCBGAR(T4),TCNGAR ;SIZE OF GARBAGE TCWGAR: POINT TCSGAR,TCBGAR(T3),TCNGAR ;SIZE OF GARBAGE SPYCLA: POINT CLASIZ,(T2),CLAPOS ;CA PART OF SPT SPYTAL: POINT TALSIZ,(T2),TALPOS ;CC PART OF SPT SUBTTL INITIALIZATION KLEPTO: JFCL ;NO CCL RESET ;STOP I/O MOVE P,[IOWD PDLSIZ,PDL] ;SETUP PDL SETZ F, ;SETUP FLAGS IFN FTCIH,< MOVE T1,[XWD HI,LOW] ;COPY IMPURE DATA BLT T1,LOW+LOWL-1 > MOVEI T1,INTR ;CTRL-C TRAP HRRM T1,.JBINT SETZM WRDCNT ;NO CORE ALLOCATED YET SETZM FREMEM PUSHJ P,MAKDDB ;BUILD DDBS SETOM OURCPU ;ASSUME ALL CPUS MOVE T1,[%LDMFD] ;PPN OF MFD GETTAB T1, PUSHJ P,DIE MOVEM T1,MFDPPN MOVE T1,[%LDFFA] ;PPN OF OPR GETTAB T1, PUSHJ P,DIE MOVEM T1,FFAPPN HRROI T1,.GTPPN ;OUR PPN GETTAB T1, PUSHJ P,DIE CAME T1,FFAPPN ;ARE WE THE OPR? JRST NOTOPR ;NO MOVE T1,[%LDSYS] ;PPN OF SYS GETTAB T1, PUSHJ P,DIE MOVEM T1,SYSPPN PJOB T1, ;MY JOB NUMBER MOVEM T1,MYJOB HRROI T1,.GTSGN ;MY HISEG NUMBER GETTAB T1, PUSHJ P,DIE HRRZM T1,MYSGN SETZ T1, ;WRITE ENABLE THE HISEG SETUWP T1, PUSHJ P,DIE PUSHJ P,GETLOK ;GET INTERLOCK PUSHJ P,ALIVE ;MAKE SURE EVERYBODY ALIVE PUSHJ P,GETSLT ;GET A SLOT NUMBER PUSHJ P,LUNIT ;BUILD LIST OF UNITS PUSHJ P,BDALL ;BUILD LIST OF STRS PUSHJ P,GIVLOK ;GIVE UP INTERLOCK PUSHJ P,OPENLG ;OPEN DEVICE FOR LOG PUSHJ P,SWATER ;SET WATER LEVEL SETZM LOGS ;NO TMP LOGS YET MOVSI T1,LNM ;ALL? DEVNAM T1, JRST NOSTR CAMN T1,[SIXBIT /ALL/] JRST DOALL ;YES PUSHJ P,GETLOK ;GET INTERLOC PUSHJ P,PIKONE ;TELL THE WORLD WHICH STR JRST XIT PUSHJ P,PIKLOG ;PICK STR FOR LOG PUSHJ P,GIVLOK ;GIVE UP INTERLOCK PUSHJ P,DOSTR ;PROCESS THE STR PUSHJ P,GETLOK ;GET INTERLOCK BACK PUSHJ P,ALIVE ;CHECK IF EVERYBODY ALIVE PUSHJ P,DONSTR ;TELL THE WORLD WE ARE DONE JRST XIT ;EXIT ;HERE TO DO ALL THE STR'S ON THE SYSTEM DOALL: HRROI T1,.GTRDV ;GET STR RUN FROM GETTAB T1, PUSHJ P,DIE MOVEM T1,RUNSTR PUSHJ P,GETLOK ;GET INTERLOCK TRO F,F.ALL ;WE ARE DOINT ALL DOALL1: PUSHJ P,PIKSTR ;PICK A STR JRST XIT ;NONE PUSHJ P,PIKLOG ;PICK A STR FOR LOG FILE PUSHJ P,GIVLOK ;GIVE UP INTERLOCK PUSHJ P,GC ;COLLECT GARBAGE PUSHJ P,CDOWN ;GIVE CORE AWAY PUSHJ P,DOSTR ;PROCESS THE STR PUSHJ P,GETLOK ;GET INTERLOCK PUSHJ P,ALIVE ;SEE IF ANYBODY DIED PUSHJ P,DONSTR ;FLAG THAT STR IS DONE PUSHJ P,CPYLG ;COPY TMP LOG JFCL SETZM RUNSTR ;OK TO DO RUN STR NOW JRST DOALL1 ;LOOP ;HERE IF NOT OPR NOTOPR: OUTSTR [ASCIZ /Must be OPR /] EXIT ;HERE IF LOGICAL NAME ISN'T ASSIGNED NOSTR: OUTSTR [ASCIZ /STR isn't assigned /] PUSHJ P,GETLOK ;GET INTERLOCK XIT: PUSHJ P,CPYLG ;COPY TMP LOG JRST XIT2 ;DO IT LATER PUSHJ P,GIVSLT ;GIVE UP SLOT NUMBER PUSHJ P,GIVLOK ;GIVE UP INTERLOCK EXIT XIT2: PUSHJ P,SLEEPY ;SLEEP AWHILE JRST XIT SUBTTL MAINSTREAM ;ROUTINE TO PROCESS A STR DOSTR: MOVE T1,WRDCNT ;SAVE WORD COUNT MOVEM T1,SVWCNT PUSHJ P,BEGIN ;TELL WHICH STR WE ARE DOING MOVE T1,[XWD QTCB,QTCB] ;QUEUE IS INITIALY EMPTY MOVEM T1,QTCB SETZM ROOT SETZM ZER ;ZERO AT BEGINNING OF STR MOVE T1,[XWD ZER,ZER+1] BLT T1,ZER+ZERL-1 TRZ F,F.P2 ;PASS 1 PUSHJ P,PUNT ;COMPILE TABLE OF UNITS PUSHJ P,RDHOM ;READ HOME BLOCKS JRST BADHOM PUSHJ P,RSTR ;REMOVE STR JRST DOSTR1 PUSHJ P,BDMFD ;BUILD TCB FOR MFD DOPASS: HRRZ T1,QTCB ;CRANK UP I/O PUSHJ P,CRANK0 PUSHJ P,DIE HRRZ TC,QTCB ;1ST TCB LOOP: LDB T1,TCYCOD ;DISPATCH PUSHJ P,@FUNX(T1) PUSHJ P,SCHED ;PICK NEXT TCB SETZ T1, ;DONE WITH PASS 1 PUSH P,T1 ;SAVE ADDR OF NEXT TCB PUSHJ P,DECFIL ;DECREMENT USE COUNT ON FIL PUSHJ P,UNLINK ;UNLINK TCB FROM TREE PUSHJ P,UNLNK ;UNLINK TCB FROM QUEUE IFN FTCHK,< PUSHJ P,CHECK ;CHECK CONSISTENCY > PUSHJ P,GIVTCB ;RETURN TCB TO FREE LIST POP P,TC ;RESTORE ADDR OF NEXT TCB JUMPN TC,LOOP ;HERE WHEN DONE WITH A COMPLETE PASS OF THE STR TRNE F,F.P2 ;DONE WITH PASS 1 OR 2? JRST DONE2 ;PASS 2 ;HERE WHEN DONE WITH PASS ONE IFN FTDBUG,< HRRZ T1,QTCB ;FORGOT ANY TCBS? CAIE T1,QTCB PUSHJ P,DIE > PUSHJ P,DOSAT ;PROCESS SAT BLOCKS JRST DOSTR4 ;CAN'T FIND SATS PUSHJ P,CSTSO ;PRINT CST'S PUSHJ P,BADOVR ;OVERLAP OF FREE AND BAD MOVEM T1,OVERN PUSHJ P,DEBAD ;DEALLOCATE BAD REGIONS PUSHJ P,DELST ;DEALLOCATE LOST REGIONS PUSHJ P,DEFRE ;DEALLOCATE FREE REGIONS SKIPN T1,OVERN ;ANY OVERLAP? JRST NOVR ;NO MOVEI T2,[ASCIZ /All/] ;TOTAL OVERLAP? CAME T1,FRECST+CSTNUM MOVEI T2,[ASCIZ /Some/] ;NO, PARTIAL OVERLAP PUSHJ P,STRO MOVEI T2,[ASCIZ / free clusters are bad blocks/] PUSHJ P,STRDSP NOVR: MOVE T1,FRECST+CSTNUM ;FREE CLUSTERS SUB T1,OVERN ;MINUS BAD FREE ADD T1,MULCST+CSTNUM ;MULTIPLY USED CLUSTERS JUMPN T1,DOP2 ;GO IF NEED PASS TWO MOVEI T2,[ASCIZ /No need for pass two/] PUSHJ P,STRDSP JRST DONE2 ;DONE ;HERE TO START PASS TWO DOP2: MOVEI T2,MULCST ;MARK MULTIPLY USED CLUSTERS IN PUSHJ P,MARKC ; SAT SO THEY ARE EASY TO SPOT TRO F,F.P2 ;FLAG PASS TWO MOVEI T2,[ASCIZ /Begining pass two/] PUSHJ P,STRDSP PUSHJ P,BDMFD ;BUILD TCB FOR MFD JRST DOPASS DOSTR1: MOVEI T2,[ASCIZ /Cannot remove STR, aborting/] JRST DOSTR2 BADHOM: MOVEI T2,[ASCIZ /Error while reading home blocks, aborting/] DOSTR2: PUSHJ P,STRDSP JRST DOSTR4 ;HERE WHEN DONE WITH PASS TWO DONE2: PUSHJ P,DEMUL ;DEALLOCATE MULTIPLY USED REGIONS PUSHJ P,ASTR ;PUT STR BACK PUSHJ P,DOSTR3 DOSTR4: PUSHJ P,DESTR ;DEALLOCATE CORE MOVE T1,WRDCNT ;MISS SOMETHING? CAME T1,SVWCNT PUSHJ P,DIE ;BUG POPJ P, DOSTR3: MOVEI T2,[ASCIZ /Error while mounting STR/] STRDSP: PUSHJ P,STRO PJRST DSPACE SUBTTL SCHEDULER ;TC PASSES ADDR OF PREVIOUS TCB ;T1 RETURNS ADDR OF NEXT TCB ;NOSKIP IF QUEUE IS EMPTY SCHED: LDB T2,TCYCX ;FIND DDB MOVE DDB,USRJDA(T2) MOVE T1,TC ;START AT CURRENT TCB SCHED3: HRRZ T1,TCBLNK(T1) ;GET NEXT TCB CAIN T1,QTCB JRST SCHED0 MOVE T2,TCBBLK(T1) ;IS IT IN CACHE? CAMLE T2,DDBHBN(DDB) JRST SCHED0 ;NO PUSHJ P,FITP ;FIT IN CORE? JRST SCHED3 ;NO SCHED2: LDB T2,TCYCX ;COPY CHANNEL INDEX DPB T2,TCXCX JRST CPOPJ1 SCHED0: MOVE T1,TC ;BACK TO BEGINING SCHED4: HLRZ T1,TCBLNK(T1) ;GET PREVIOUS TCB CAIN T1,QTCB JRST SCHED1 MOVE T2,TCBBLK(T1) ;IS IT IN CACHE? CAMGE T2,DDBLBN(DDB) JRST SCHED1 ;NO PUSHJ P,FITP ;FIT IN CORE? JRST SCHED4 ;NO JRST SCHED2 ;DO IT ;HERE IF CURRENT DDB IS EXHAUSTED SCHED1: SOS ACTCNT ;ONE LESS USEFUL DDB MOVEI T1,CXACT ;MARK ACTIVE BEFORE INVALIDATE DPB T1,TCYCX SETOM DDBHBN(DDB) ;INVALIDATE CACHE PUSHJ P,CRANK ;CRANK UP SOME I/O POPJ P, ;NOTHING TO CRANK UP MOVE T1,DDBTCB(DDB) ;1ST TCB IN THAT DDB JRST CPOPJ1 ;ROUTINE TO CRANK UP I/O: ;START UP A TRANSFER ON THIS DDB, ;AND WAIT FOR I/O TO FINISH ON SOME (OTHER) DDB. ;DDB PASSES CURRENT DDB ;TC PASSES CURRENT TCB ;SKIP IF THERE IS INDEED STUFF TO DO CRANK: PUSHJ P,NEXT ;FIND A TCB TO START JRST CRANK1 ;NONE CRANK0: PUSH P,TC ;SAVE CURRENT TCB MOVE TC,T1 ;TCB TO START PUSHJ P,LODTCB ;START IT POP P,TC ;RESTORE CURRENT TCB MOVE T1,ACTCNT ;ALL DDBS ACTIVE? CAMN T1,DDBS JRST CRANK2 ;YES PUSHJ P,FNDIDL ;NO, FIND ONE THAT'S IDLE JRST CRANK ;START SOMETHING ON IT CRANK1: SETOM DDBHBN(DDB) ;INVALIDATE CACHE SKIPN ACTCNT ;ANY DDBS ACTIVE? POPJ P, ;NO CRANK2: PUSHJ P,FNDDON ;WAIT FOR SOME DDB TO FINISH JRST CPOPJ1 ;FIND AN IDLE DDB ;DDB RETURNS DDB FNDIDL: MOVEI T1,1 FNDID1: MOVE DDB,USRJDA(T1) SKIPL DDBHBN(DDB) AOJA T1,FNDID1 POPJ P, ;WAIT TILL SOME DDB FINISHES I/O ;DDB RETURNS DDB FNDDON: PUSHJ P,SAVE1 ;SAVE AC FNDDN1: MOVE P1,DDBS ;THIS MANY DDBS TO TEST FNDDN2: AOS T1,DONCNT ;NEXT DDB TO TEST IDIV T1,DDBS MOVE DDB,USRJDA+1(T2) SKIPGE DDBHBN(DDB) ;I/O ALREADY STARTED? JRST FNDDN3 ;NO SKIPN DDBDON(DDB) ;I/O ALREADY DONE? PUSHJ P,DOIN ;OR JUST FINISHED NOW? POPJ P, ;YES, A WINNER FNDDN3: SOJG P1,FNDDN2 ;TEST EACH DDB MOVE T1,[HB.RIO+HB.RWJ+^D1000] ;NONE DONE, SLEEP AWHILE HIBER T1, HALT JRST FNDDN1 ;TRY AGAIN ;ROUTINE TO FIND THE CX OF A TCB (IF ANY) ;T1 PASSES TCB ;T2 RETURNS CX ;CPOPJ IF I/O NOT IN PROGRESS ;CPOPJ1 IF FOUND FNDCX: MOVE T2,DDBS ;THIS MANY DDBS TO TEST MOVE T3,TCBBLK(T1) ;BN OF THIS TCB FNDCX1: MOVE T4,USRJDA(T2) ;ADDR OF DDB CAML T3,DDBLBN(T4) ;BN IN CACHE? CAMLE T3,DDBHBN(T4) SOJG T2,FNDCX1 ;NO, TEST NEXT DDB SKIPE T2 ;FOUND IT? AOS (P) ;YES, SKIP POPJ P, ;FIND NEXT TCB TO START I/O ON ;TC PASSES CURRENT TCB ;T1 RETURNS NEXT TCB ;CPOPJ1 IF OK ;CPOPJ IF NO TCB'S STARTABLE NEXT: PUSHJ P,SAVE2 ;SAVE AC PUSHJ P,TWATER ;TEST WATER LEVEL MOVE T2,TCBBLK(TC) ;FIND UDB IDIV T2,BPLU HRRZ U,TABUDB(T2) IDIV T3,UDBCYL(U) ;CYL NUMBER IMUL T3,UDBCYL(U) ;1ST BN THIS CYL ADD T3,UDBBLK(U) ;BN RELATIVE TO STR MOVE P1,T3 ;SAVE IT IN A SAFE PLACE MOVE P2,P1 ;1ST BN ON NEXT CYL ADD P2,UDBCYL(U) NEXT14: MOVE T1,TC ;FIND LAST TCB IN PREVIOUS CYL NEXT1: HLRZ T1,TCBLNK(T1) CAIN T1,QTCB JRST NEXT3 CAMG P1,TCBBLK(T1) JRST NEXT1 ;HERE TO FIND NEXT TCB THAT DOES NOT HAVE I/O ACTIVE NEXT3: HRRZ T1,TCBLNK(T1) ;STEP TO NEXT TCB CAIN T1,QTCB JRST NEXT10 ;NONE NEXT13: LDB T2,TCXCX ;GET CHANNEL INDEX CAIN T2,CXACT ;RESTARTING CURRENT DDB? JRST NEXT3 ;YES, PITCH IT JUMPN T2,NEXT4 ;I/O ACTIVE IF NON-0 PUSHJ P,FNDCX ;DON'T KNOW, SEARCH AND FIND OUT JRST NEXT6 ;NOT ACTIVE NEXT4: MOVE T2,USRJDA(T2) ;GET DDB ADDR MOVE T2,DDBHBN(T2) ;HIGHEST BN IN TRANSIT NEXT5: HRRZ T1,TCBLNK(T1) ;FIND 1ST TCB BEYOND THAT BN CAIN T1,QTCB JRST NEXT10 CAML T2,TCBBLK(T1) JRST NEXT5 JRST NEXT13 ;SEE IF IT'S ACTIVE ;HERE WITH T1=1ST TCB THAT DOES NOT HAVE I/O ACTIVE NEXT6: CAMG P2,TCBBLK(T1) ;SAME CYL? JRST NEXT7 ;NO PUSHJ P,FITP ;WILL TCB FIT IN CORE? JRST NEXT3 ;NO JRST CPOPJ1 ;YES, A WINNER ;HERE IF MUST MOVE HEADS IN ;HERE WITH T1=1ST TCB ON NEXT CYL NEXT7: SKIPN ACTCNT ;I/O ACTIVE ON THIS CYL? JRST NEXT9 ;NO, MOVE HEADS NOW POPJ P, ;YES, DON'T MOVE TILL I/O DONE NEXT8: HRRZ T1,TCBLNK(T1) CAIN T1,QTCB JRST NEXT11 ;HERE IF MUST MOVE HEADS, FIND ANY TCB THAT WILL FIT IN CORE NEXT9: PUSHJ P,FITP ;THIS ONE FIT? JRST NEXT8 ;NO JRST CPOPJ1 ;YES, A WINNER ;HERE IF MUST MOVE HEADS OUT ;HERE WITH T1=QTCB NEXT10: SKIPE ACTCNT ;I/O ACTIVE ON THIS CYL? POPJ P, ;YES, DON'T MOVE TILL I/O DONE ;HERE IF MUST MOVE HEADS, FIND ANY TCB THAT WILL FIT IN CORE NEXT11: HRRZ T1,TCBLNK(T1) ;STEP TO NEXT TCB CAMG P1,TCBBLK(T1) ;BACK TO ORIGINAL CYL? JRST NEXT15 ;YES, NOTHING WE CAN DO PUSHJ P,FITP ;THIS ONE FIT? JRST NEXT11 ;NO JRST CPOPJ1 ;YES, A WINNER ;HERE IF ABSOLUTELY NOTHING TO DO NEXT15: TRZN F,F.VHW ;IGNORE VHW (MAY GO VIRTUAL) TRZE F,F.HW ;DIDN'T WORK, TRY IGNORING HW JRST NEXT14 POPJ P, SUBTTL WATER LEVEL ;ROUTINE TO SET THE WATER LEVEL(S) ;BY "HIGH WATER" WE MEAN THAT WE'RE LOW ON CORE AND SHOULD ;TRY TO BE MORE CONSERVATIVE. SWATER: MOVE T2,[%NSCMX] ;GET CORMAX GETTAB T2, PUSHJ P,DIE HRROI T3,.GTCVL ;CURRENT PHYS LIMIT GETTAB T3, PUSHJ P,DIE ANDI T3,77777 LSH T3,PAGLSH CAMLE T2,T3 ;TAKE THE LOWER OF THE TWO MOVE T2,T3 HRRZ T3,.JBHRL ;HIGHEST ADDR IN HISEG CAMLE T2,T3 ;TAKE THE LOWER OF THE TWO MOVE T2,T3 HLRZ T3,.JBHRL ;MINUS SIZE OF HISEG SUB T2,T3 SUB T2,.JBFF ;MINUS STUFF ALREADY USED ADD T2,WRDCNT MOVE T1,T2 ;SAVE IT IMULI T2,HWN ;COMPUTE FRACTION IDIVI T2,HWD MOVEM T2,HW ;HIGH WATER IMULI T1,VHWN ;COMPUTE FRACTION IDIVI T1,VHWD MOVEM T1,VHW ;VERY HIGH WATER POPJ P, ;ROUTINE TO TEST THE WATER LEVEL AND SET THE BITS IN F TWATER: MOVE T1,WRDCNT ;HIGH WATER? CAMGE T1,HW TRZA F,F.HW+F.VHW ;NO TROA F,F.HW ;YES POPJ P, CAMGE T1,VHW ;VERY HIGH WATER? TRZA F,F.VHW ;NO TRO F,F.VHW ;YES POPJ P, ;ROUTINE TO TEST IF THERE'S ENOUGH CORE TO PROCESS A GIVEN TCB ;T1 PASSES ADDR OF TCB ;SKIP IF THERE'S ENOUGH CORE ;FNCSUM ALWAYS MAKES CORE SIZE SMALLER SO THEY'RE ALWAYS SAFE. ;FNCDIR ALWAYS MAKES YOU BIGGER SO NEVER DO THOSE IF YOU'RE LOW ON CORE. ;FNCRIB SOMETIMES MAKES YOU BIGGER AND SOMETIMES SMALLER, IT TAKES ;EXTENSIVE CHECKING. ;DIRECTORY RIBS ALWAYS MAKE YOU BIGGER. ;OTHER RIBS SOMETIMES MAKE YOU BIGGER AND SOMETIMES SMALLER, DEPENDING ;ON HOW MANY RTP'S HAVE TO BE CHECKSUMED. THERE'S NO WAY TO TELL ;WITHOUT ACTUALLY READING THE RIB. BUT MOST RIBS ONLY HAVE ONE RTP, ;AND WILL PROBABLY MAKE YOU SMALLER. WE TEND TO GIVE RIBS THE BENEFIT ;OF A DOUBT AND ASSUME THEY MAKE US SMALLER. IF, HOWEVER, WE'RE AT ;THE VERY HIGH WATER MARK, THEN BE VERY CONSERVATIVE AND DON'T PROCESS ;ANY RIBS. WE ASSUME THAT THE ONLY WAY TO GET TO THE VERY HIGH WATER MARK ;IS BY HAVING LOTS OF RIBS WITH LOTS OF RTP'S. THUS THERE MUST BE LOTS ;OF CHECKSUMS IN THE QUEUE. PROCESS ONLY THE CHECKSUMS. FITP: TRNN F,F.HW ;HIGH WATER MARK? JRST CPOPJ1 ;NO, IT'S SAFE LDB T2,TCWCOD ;YES, BETTER CHECK IT PJRST @FUNHW(T2) ;ROUTINE TO TEST IF THERE'S ENOUGH CORE TO PROCESS A RIB HWRIB: HRRZ T2,TCBFIL(T1) ;DIR? HLRZ T2,FILEXT(T2) CAIE T2,'SFD' CAIN T2,'UFD' POPJ P, ;YES, DON'T PROCESS TRNN F,F.VHW ;VERY HIGH WATER? AOS (P) ;NO, GIVE HIM BENEFIT OF DOUBT POPJ P, ;YES, DON'T PROCESS SUBTTL DISPATCH TABLES DEFINE FUNC,< XX FNCRIB,DORIB,SIZRIB,GIVRIB,HWRIB XX FNCDIR,DODIR,SIZDIR,GIVBLK,CPOPJ XX FNCSUM,DOSUM,SIZSUM,GIVBLK,CPOPJ1 > DEFINE XX(AA,BB,CC,DD,EE),< AA==.-FUNX BB > FUNX: FUNC DEFINE XX(AA,BB,CC,DD,EE), FUNSZ: FUNC DEFINE XX(AA,BB,CC,DD,EE),
FUNGV: FUNC DEFINE XX(AA,BB,CC,DD,EE), FUNHW: FUNC SUBTTL PROCESS A RIB DORIB: PUSHJ P,SAVE1 ;PRESERVE ACS TRZ F,F.DIR+F.RIB+F.PRM+F.SAT ;CLEAR FLAGS LDB T1,TCYRBC ;PRIME RIB? SKIPN T1 TRO F,F.PRM ;YES, LIGHT FLAG TRNN F,F.P2 ;WHICH PASS? JRST DORIB5 ;ONE SETZM SCST ;TWO, ZERO CST MOVE T1,[XWD SCST,SCST+1] BLT T1,SCST+SCSTL-1 MOVE T1,TCBCOR(TC) ;SAVED CST? TRNN F,F.PRM TLNN T1,(TCPCOR) JRST DORIB5 ;NO MOVEI T1,SCST ;YES, RESTORE IT HRLI T1,TCBCST(TC) BLT T1,SCST+SCSTL-1 DORIB5: PUSHJ P,REDTCB ;READ THE BLOCK JRST DORB10 ;I/O ERROR PUSHJ P,RBCK ;CHECK REASONABLENESS JRST DORB11 MOVE P1,RIBFIR(B) ;AOBJN TO RTP'S ADD P1,B HRRZ T1,FILDAD(FL) ;GO IN NOT MFD JUMPN T1,DORIB6 TRNN F,F.PRM ;GO UNLESS PRIME RIB JRST DORIB6 SETZM S1PT ;MFD ONLY HAS ONE RTP? SKIPN 2(P1) SETOM S1PT ;YES DORIB6: HLRZ T1,FILEXT(FL) ;DIRECTORY? CAIE T1,'UFD' CAIN T1,'SFD' TRO F,F.DIR ;YES, SET FLAG CAIN T1,'SYS' ;SET FLAG IF SAT.SYS TRO F,F.SAT MOVS T1,RIBNAM(B) MOVE T2,RIBPPN(B) CAIN T1,'SAT' CAME T2,SYSPPN TRZ F,F.SAT TRNN F,F.PRM ;PRIME RIB? SKIPA T1,TCBFLR(TC) ;NO, GET FLR FROM TCB MOVEI T1,1 ;YES, 1ST BLOCK MOVEM T1,DRREL ;STORE 1ST LOGICAL RECORD MOVE T1,RIBSIZ(B) ;SIZE OF FILE IN BLOCKS IDIVI T1,BLKSIZ SKIPE T2 ADDI T1,1 TRNN F,F.PRM ;PRIME RIB? MOVE T1,TCBSIZ(TC) ;NO, GET SIZE FROM TCB MOVEM T1,DRSIZ ;STORE SIZE TRNN F,F.PRM ;PRIME RIB? SKIPA T1,TCBLFT(TC) ;NO, GET LEFTOVER FROM TCB MOVE T1,RIBALC(B) ;YES, FROM RIB MOVEM T1,DRLFT ;STORE BLOCKS LEFT ;HERE TO PROCESS AN RTP DORIB1: SKIPN T1,(P1) ;PICK UP RTP JRST DORIB2 ;EOF LDB T2,CCBP ;GET CC JUMPN T2,DORIB3 ;UNIT OR GROUP? ;HERE FOR UNIT POINTER TRZ T1,RIPNUB ;GET RID OF NOISE BIT CAMLE T1,HUN ;IN RANGE? JRST DORB12 ;NO HRRZ U,TABUDB(T1) ;YES, POINT TO NEW UDB JRST DORIB4 ;HERE FOR GROUP POINTER DORIB3: MOVEM T2,DRCC ;STORE CC LDB T3,CSBP ;STORE CS MOVEM T3,DRCS LDB T4,CABP ;STORE CA MOVEM T4,DRCA ADD T2,T4 ;IN RANGE? IMUL T2,BPC SUBI T2,1 CAMLE T2,UDBHLB(U) JRST DORB12 ;NO PUSHJ P,DOGRP ;PROCESS THE GROUP ;HERE WHEN ALL DONE WITH RTP DORIB4: AOBJN P1,DORIB1 ;LOOP SKIPN DRLFT ;RIB EXACTLY FULL? JRST DORIB2 ;YES, FORCE EOF SKIPN RIBXRA(B) ;BETTER BE EXTENDED JRST DORB12 LDB P1,RIYRBU ;BN OF EXTENDED RIB IMUL P1,BPLU LDB T1,RIYRBA IMUL T1,BPC ADDB P1,T1 PUSHJ P,LEGALP ;IN RANGE? JRST DORB12 ;NO MOVE T2,F2CST+CSTCNT ;SET T2 NON-ZERO TO SAVE CST ADD T2,M2CST+CSTCNT TRNN F,F.P2 SETZ T2, MOVEI T1,SIZXRB ;ALLOCATE CORE SKIPE T2 MOVEI T1,SIZCXR PUSH P,T2 PUSHJ P,GETBLK MOVE T1,P1 ;LINK THE TCB PUSHJ P,LNKTCB MOVEI T1,FNCRIB ;FUNCTION CODE DPB T1,TCXCOD LDB T1,TCYRBC ;RIB COUNT ADDI T1,1 DPB T1,TCXRBC HRRM FL,TCBFIL(T2) ;ADDR OF FIL LDB T1,FIYCNT ;BUMP USE COUNT OF FIL ADDI T1,1 DPB T1,FIYCNT MOVE T1,DRREL ;BN RELATIVE TO FILE SUBI T1,1 ;ACCOUNT FOR SPARE RIB MOVEM T1,TCBFLR(T2) ;SHOULD BE 1ST LOGICAL RECORD MOVE T1,DRSIZ ;SIZE MOVEM T1,TCBSIZ(T2) MOVE T1,DRLFT ;BLOCKS LEFT MOVEM T1,TCBLFT(T2) MOVSI T1,(TCPCOR) ANDCAM T1,TCBCOR(T2) POP P,T3 JUMPE T3,CPOPJ ;GO IF NOT SAVING CST IORM T1,TCBCOR(T2) ;LIGHT FLAG MOVEI T1,TCBCST(T2) HRLI T1,SCST ;SAVE CST BLT T1,TCBCST+SCSTL-1(T2) POPJ P, ;HERE ON EOF DORIB2: SKIPE RIBXRA(B) ;SHOULDN'T BE EXTENDED PUSHJ P,DORB16 SKIPE DRLFT ;TEST RIBALC PUSHJ P,DORB13 MOVE T1,DRREL ;TEST RIBSIZ SUBI T1,2 CAMGE T1,DRSIZ PUSHJ P,DORB14 FALL DNRIB ;COMMON EXIT FOR DORIB DNRIB: TRNN F,F.P2 ;WHICH PASS? POPJ P, ;PASS 1 PUSHJ P,CSTTO ;PASS 2, TYPE CST'S MOVEI P1,F2CST ;DEALLOCATE FREE PUSHJ P,DECST MOVEI P1,M2CST ;DEALLOCATE MULTIPLE PJRST DECST DORB10: PUSHJ P,MRKIT ;NOT A LOST CLUSTER MOVEI T2,[ASCIZ /Error while reading RIB/] PUSHJ P,DORB15 PJRST DNRIB DORB12: PUSHJ P,DORB16 PJRST DNRIB DORB16: MOVEI T2,[ASCIZ /Bad pointer in RIB/] DORB15: PUSHJ P,STRO TRNE F,F.PRM ;GO IF PRIME RIB JRST DORB99 MOVEI T1," " PUSHJ P,CO LDB T1,TCYRBC PUSHJ P,OCTO DORB99: MOVEI T2,[ASCIZ / of /] PUSHJ P,STRO PUSHJ P,FILO PJRST DSPACE DORB11: PUSHJ P,MRKIT ;NOT A LOST CLUSTER MOVEI T2,[ASCIZ /RIB error on /] PUSHJ P,STRO PUSHJ P,FILO TRNE F,F.PRM ;GO IF PRIME RIB JRST DORB17 MOVEI T2,[ASCIZ / (RIB /] PUSHJ P,STRO LDB T1,TCYRBC PUSHJ P,OCTO MOVEI T1,")" PUSHJ P,CO DORB17: PUSHJ P,DSPACE JRST DNRIB DORB13: SKIPA T2,[SIXBIT /RIBALC/] DORB14: MOVE T2,[SIXBIT /RIBSIZ/] PUSHJ P,SIXO MOVEI T2,[ASCIZ / is wrong in /] PUSHJ P,STRO PUSHJ P,FILO PJRST DSPACE DIE: MOVEM 17,CRSHAC+17 ;SAVE THE ACS MOVEI 17,CRSHAC BLT 17,CRSHAC+16 MOVE 17,CRSHAC+17 PUSHJ P,GIVIF ;GIVE UP INTERLOCK HALT ;FATAL ERROR ;SUBROUTINE TO PROCESS A GROUP DOGRP: TRNE F,F.SAT ;SAT.SYS? PUSHJ P,SAVSAT ;YES, SAVE CA TRZ F,F.SUM ;HAVEN'T DONE CHECKSUM YET MOVE T2,DRCA ;BN RELATIVE TO STR IMUL T2,BPC ADD T2,UDBBLK(U) MOVEM T2,DRPHY MOVN T1,DRCC ;BUMP COUNT IMUL T1,BPC ADDM T1,DRLFT DOGRP1: MOVE T1,DRPHY ;LIGHT SAT BIT PUSHJ P,MARKIT PUSHJ P,DOCLT ;PROCESS THIS CLUSTER MOVE T1,BPC ;BUMP BN ADDM T1,DRPHY SOSE DRCC ;LOOP JRST DOGRP1 POPJ P, ;ROUTINE TO PROCESS ALL THE BLOCKS IN A CLUSTER DOCLT: MOVE T1,DRPHY ;WORKING COPY OF BN MOVEM T1,DRBLK MOVE T1,BPC ;SETUP LOOP MOVEM T1,DRCNT DOCLT1: TRON F,F.RIB ;STEPPED OVER THE RIB YET? JRST DOCLT2 ;NO, THIS IS IT MOVE T1,DRREL ;PAST EOF? CAMLE T1,DRSIZ JRST DOCLT4 ;YES, IGNORE IT TRNN F,F.DIR ;IS THIS A DIR? JRST DOCLT3 ;NO, WE'RE ONLY INTERESTED IN 1ST BLOCK PUSHJ P,BDDIR ;YES, BUILD A TCB TO READ THIS BLOCK AOS DRREL ;BUMP BN RELATIVE TO FILE DOCLT2: AOS DRBLK ;LOOP SOSE DRCNT JRST DOCLT1 POPJ P, DOCLT3: TRON F,F.SUM ;DONE CHECKSUM YET? PUSHJ P,BDSUM ;NO, DO IT NOW DOCLT4: MOVE T1,DRCNT ;DUMP BN RELATIVE TO FILE ADDM T1,DRREL POPJ P, ;ROUTINE TO BUILD A TCB FOR CHECKSUM BDSUM: MOVE T1,RIBSTS(B) ;ALWAYS BAD CHECKSUM? TRNN T1,RIPABC TRNE F,F.P2 ;OR PASS TWO? POPJ P, ;YES, DON'T BOTHER MOVEI T1,SIZSUM ;ALLOCATE CORE PUSHJ P,GETBLK MOVE T1,DRBLK ;LINK THE TCB PUSHJ P,LNKTCB MOVEI T1,FNCSUM ;FUNCTION CODE DPB T1,TCXCOD HRRM FL,TCBFIL(T2) ;ADDR OF FIL LDB T1,FIYCNT ;BUMP USE COUNT OF FIL ADDI T1,1 DPB T1,FIYCNT MOVE T1,DRREL ;BN RELATIVE TO FILE MOVEM T1,TCBREL(T2) MOVE T1,DRCS ;EXPECTED CHECKSUM MOVEM T1,TCBSUM(T2) POPJ P, ;ROUTINE TO BUILD A TCB FOR THE DATA BLOCK OF A DIRECTORY BDDIR: MOVEI T1,SIZDIR ;ALLOCATE CORE PUSHJ P,GETBLK MOVE T1,DRBLK ;LINK THE TCB PUSHJ P,LNKTCB MOVEI T1,FNCDIR ;FUNCTION CODE DPB T1,TCXCOD HRRM FL,TCBFIL(T2) ;ADDR OF FIL LDB T1,FIYCNT ;BUMP USE COUNT OF FIL ADDI T1,1 DPB T1,FIYCNT MOVE T1,DRREL ;BN RELATIVE TO FILE MOVEM T1,TCBREL(T2) POPJ P, SUBTTL READ A DIRECTORY BLOCK DODIR: PUSHJ P,SAVE3 ;SAVE ACS PUSHJ P,REDTCB ;READ THE BLOCK JRST IOERR ;I/O ERROR PUSHJ P,DRCK ;CHECK JRST DIRERR ;BAD DIRECTORY MOVE P1,B ;START WITH ENTRY ZERO DODIR1: SKIPN T2,(P1) ;EMPTY SLOT? JRST DODIR2 ;YES, IGNORE IT HLLZ T1,FILEXT(FL) ;MFD POINTS TO SELF HLR T1,FILCFP(FL) CAMN T1,1(P1) CAME T2,FILNAM(FL) JRST DODIR3 JRST DODIR2 DODIR3: MOVEI T1,SIZFIL ;BUILD A FIL PUSHJ P,GETBLK MOVE P3,T2 MOVE T1,(P1) ;STORE FILENAME IN FIL MOVEM T1,FILNAM(P3) HLLZ T1,1(P1) ;STORE EXTENSION IN FIL HLLM T1,FILEXT(P3) HRRM FL,FILDAD(P3) ;STORE ADDR OF PARENT FIL LDB T1,FIYCNT ;BUMP PARENT COUNT ADDI T1,1 DPB T1,FIYCNT MOVEI T1,1 ;SET FIL USE COUNT DPB T1,FIZCNT ;(TCB WILL POINT TO FIL) HRRZ T1,1(P1) ;STORE CFP IN FIL HRLM T1,FILCFP(P3) JUMPE T1,DODIR9 ;ZERO IS ILLEGAL IMUL T1,BPSC ;BN RELATIVE TO STR PUSHJ P,LEGALP ;LEGAL BN? JRST DODIR9 ;NO MOVEI T1,SIZRIB ;BUILD A TCB PUSHJ P,GETBLK MOVE P2,T2 HRRZ T1,1(P1) ;LINK IT IMUL T1,BPSC PUSHJ P,LNKTCB MOVEI T1,FNCRIB ;STORE FUNCTION IN TCB DPB T1,TCZCOD SETZ T1, ;PRIME RIB DPB T1,TCZRBC HRRM P3,TCBFIL(P2) ;STORE ADDR OF FIL IN TCB DODIR2: ADDI P1,2 ;LOOP CAIE P1,BLKSIZ(B) JRST DODIR1 PJRST TWATER ;WATER LEVEL HAS CHANGED SIGNIFICANTLY ;HERE IF BAD CFP DODIR9: MOVEI T2,[ASCIZ /Bad CFP for /] PUSHJ P,STRO PUSH P,FL MOVE FL,P3 PUSHJ P,FILO PUSHJ P,DECFIL POP P,FL PUSHJ P,DSPACE JRST DODIR2 ;ROUTINE TO CHECK IF DIRECTORY DATA BLOCK IS OK DRCK: MOVE P1,B ;START WITH ENTRY ZERO SETZ P2, ;NO BAD ONES YET DRCK1: SKIPN (P1) ;ZERO FILENAME? JRST DRCK3 ;YES, EMPTY SLOT HRRZ T1,1(P1) ;GET CFP JUMPE T1,DRCK2 ;ZERO IS ILLEGAL IMUL T1,BPSC ;CONVERT TO BN PUSHJ P,LEGALP ;LEGAL BN? JRST DRCK2 ;NO JRST DRCK4 ;YES ;HERE IF FILENAME IS ZERO DRCK3: SKIPE 1(P1) ;EXTENSION MUST BE ZERO TOO POPJ P, ;FAIL IMMEDIATELY JRST DRCK4 ;HERE IF CFP IS BAD DRCK2: ADDI P2,1 ;COUNT IT CAIN P2,BADDR ;REACH THRESHOLD? POPJ P, ;YES DRCK4: ADDI P1,2 ;LOOP CAIE P1,BLKSIZ(B) JRST DRCK1 JRST CPOPJ1 ;OK SUBTTL CONFIGURATION ;ROUTINE TO BUILD A LIST OF ALL THE STRUCTURES ON THE SYSTEM BDALL: PUSHJ P,SAVE2 MOVEI P1,CONFIG-CNFNXT ;PRESET PRED BDALL1: HRRZ P1,CNFNXT(P1) ;STEP TO NEXT CNF JUMPE P1,CPOPJ MOVE P2,CNFSTR(P1) ;NAME OF STR MOVEI T2,SLST-SNFNXT ;PRESET PRED BDALL2: HRRZ T2,SNFNXT(T2) ;STEP TO NEXT SNF JUMPE T2,BDALL3 CAMN P2,SNFNAM(T2) ;ALREADY KNOW ABOUT THAT ONE? JRST BDALL4 ;YES JRST BDALL2 ;NO BDALL3: MOVEI T1,SIZSNF ;ALLOCATE AN SNF PUSHJ P,GETHI MOVE T1,SLST ;LINK TO SLST MOVEM T1,SNFNXT(T2) MOVEM T2,SLST MOVE T1,BLST ;LINK TO BLST MOVEM T1,SNFLNK(T2) MOVEM T2,BLST MOVEM P2,SNFNAM(T2) ;SAVE STR NAME BDALL4: MOVEI T4,CONFIG-CNFNXT ;PRESET PRED SETZB T1,T3 BDALL5: HRRZ T4,CNFNXT(T4) ;STEP TO NEXT UNIT JUMPE T4,BDALL6 CAME P2,CNFSTR(T4) ;THIS STR? JRST BDALL5 ;NO IOR T1,CNFCHN(T4) ;CHAN MASK ADD T3,CNFVRT(T4) ;SWAPPING SPACE JRST BDALL5 BDALL6: MOVEM T1,SNFCHN(T2) ;CHANNEL MASK MOVEM T3,SNFVRT(T2) ;SWAPPING SPACE JRST BDALL1 ;NEXT UNIT ;ROUTINE TO BUILD THE UDBS FOR ALL THE UNITS IN A STR ;ALIAS PASSES THE NAME OF THE STR ;TBUDB RETURNS A LIST OF POINTERS TO UDBS ;HUN RETURNS HIGHEST UNIT NUMBER PUNT: PUSHJ P,SAVE1 ;SAVE P1 PUSHJ P,GETLOK MOVEI P1,CONFIG-CNFNXT ;START WITH 1ST UNIT ON SYSTEM SETZM NUN ;NO UNITS SO FAR SETZM WL ;NO UNITS WRITE LOCKED (YET) SETZM SSIZ ;SUM OF UDBBPU SETZM BIGBPU ;BIGGEST UDBBPU PUNT1: HRRZ P1,CNFNXT(P1) ;STEP TO NEXT CNF JUMPE P1,GIVLOK MOVE T1,CNFSTR(P1) ;OUR STR? CAME T1,ALIAS JRST PUNT1 ;NO MOVEI T1,SIZUDB ;BUILD A UDB PUSHJ P,GETZER MOVE U,T2 MOVE T1,CNFNAM(P1) ;UNIT NAME MOVEM T1,UDBNAM(U) MOVE T1,CNFALT(P1) ;ALTERNATE PORT MOVEM T1,UDBALT(U) AOS T3,NUN ;BUMP COUNT CAILE T3,NUNT ;TOO BIG? PUSHJ P,DIE ;YES SUBI T3,1 ;HIGHEST UNIT MOVEM T3,HUN MOVEM U,TBUDB(T3) PUSHJ P,MOVCPY ;SAVE CAPACITY JRST PUNT1 ;AND TRY NEXT UNIT ;ROUTINE TO COMPILE A LIST OF ALL THE UNITS ON THE SYSTEM LUNIT: PUSHJ P,SAVE2 ;SAVE AC SETZ P1, ;NONE SO FAR LUNIT1: SYSPHY P1, ;GET NAME OF NEXT UNIT ON SYSTEM PUSHJ P,DIE JUMPE P1,CPOPJ MOVEM P1,FOO+.DCNAM ;GET STATS MOVE T1,[XWD FOOSIZ,FOO] DSKCHR T1, PUSHJ P,DIE SKIPE FOO+.DCSNM ;IN A STR? TLNE T1,(DC.STS) ;AND UNIT OK? JRST LUNIT1 ;NO, SKIP IT MOVEI P2,CONFIG-CNFNXT ;SEE IF IT ALREADY EXISTS LUNIT2: HRRZ P2,CNFNXT(P2) JUMPE P2,LUNIT3 ;NO CAME P1,CNFNAM(P2) CAMN P1,CNFALT(P2) JRST LUNIT4 ;YES JRST LUNIT2 ;HERE IF UNIT DOES NOT YET EXIST LUNIT3: MOVEI T1,SIZCNF ;ALLOCATE A CNF PUSHJ P,GETHI MOVE P2,T2 ;PUT IT IN A SAFE PLACE MOVE T1,CONFIG ;LINK IT MOVEM T1,CNFNXT(P2) MOVEM P2,CONFIG SETZM CNFVRT(P2) ;NO SWAP SPACE YET ;HERE IF UNIT DOES EXIST, STORE NEW INFO LUNIT4: MOVEM P1,CNFNAM(P2) ;SAVE PHYS UNIT NAME MOVE T1,FOO+.DCSNM ;STR NAME MOVEM T1,CNFSTR(P2) MOVE T1,FOO+.DCK4S ;K FOR SWAPPING LSH T1,1 ;PAGES SKIPL FOO+.DCPAS ;IN ASL? MOVEM T1,CNFVRT(P2) ;YES, THESE PAGES COUNT MOVE T2,P1 ;CHANNEL MASK PUSHJ P,GETCHN MOVEM T1,CNFCHN(P2) MOVE T2,FOO+.DCALT ;ALTERNATE UNIT NAME MOVEM T2,CNFALT(P2) JUMPE T2,LUNIT1 ;LOOP PUSHJ P,GETCHN ;CHANNEL MASK OF ALTERNATE IORM T1,CNFCHN(P2) ;ADD IT IN JRST LUNIT1 ;LOOP ;ROUTINE TO ALLOCATE SOME CORE IN THE HISEG ;T1 PASSES SIZE (DESTROYED) ;T2 RETURNS ADDR ;NOTE THAT HISEG CORE IS NEVER RETURNED GETHI: MOVE T2,HFF ;FIRST FREE ADDB T1,HFF ;NEW FIRST FREE CAILE T1,HCOR+NHCOR PUSHJ P,DIE POPJ P, ;ROUTINE TO BUILD A BIT MASK FOR THE CHANNEL NUMBER ;T2 PASSES THE UNIT NAME ;T1 RETURNS BIT MASK ;THIS ROUTINE IS A HORRIBLE CROCK. WE REALLY OUGHT TO USE THE ;CHANNEL NUMBER RETURNED BY THE DSKCHR UUO, BUT THE INFORMATION ;RETURNED BY DSKCHR SIMPLY CAN'T BE TRUSTED. THERE ARE SIMPLY ;TOO MANY MONITOR BUGS INVOLVED. THE VALUE RETURNED BY DSKCHR IS ;A CHANNEL NUMBER PER CPU RATHER THAN SYSTEM WIDE. MOREOVER, ;PRE-703 MONITORS RETURN A BAD CHANNEL NUMBER FOR THE SECOND ;KDB OF A 16 DRIVE RP20 STRING. ;THE ALGORITHM USED HERE DOESN'T ALWAYS GENERATE PERFECT RESULTS, ;BUT IT'S USUALLY PRETTY GOOD. GETCHN: HLRZS T1,T2 ;BLOW THE UNIT NUMBER TRZ T1,77 ;IS IT AN RP20? CAIE T1,'RN ' JRST GTCHN1 ;NO MOVE T3,MONVER ;PRE-703? CAIL T3,70300 JRST GTCHN1 ;NO TRNN T2,1 ;ALTERNATE KDB? SUBI T2,1 ;YES, USE NAME OF PRIME KDB GTCHN1: SKIPN T3,CHNNAM ;SEARCH FOR KON NAME JRST GTCHN2 GTCHN3: CAMN T2,CHNNAM(T3) JRST GTCHN4 ;FOUND IT SOJN T3,GTCHN3 GTCHN2: AOS T3,CHNNAM ;NOT FOUND, ROOM FOR ANOTHER? CAILE T3,^D36 SOS T3,CHNNAM ;NOPE, BACK UP MOVEM T2,CHNNAM(T3) ;STORE CHANNEL NAME GTCHN4: MOVEI T1,1 ;BUILD A BIT MASK LSH T1,-1(T3) POPJ P, SUBTTL READ HOME BLOCKS ;ROUTINE TO READ THE HOME BLOCKS OF ALL THE UNITS ON A STR ;SKIP IF OK RDHOM: PUSHJ P,SAVE1 ;SAVE P1 SETZM TABUDB MOVE T1,[XWD TABUDB,TABUDB+1] BLT T1,TABUDB+NUNT-1 TRZ F,F.STR ;STR INFO ISN'T FROZEN YET MOVE P1,HUN ;SET UP LOOP RDHOM1: MOVE U,TBUDB(P1) ;GET ADDR OF UDB PUSHJ P,RDHM ;READ THE HOME BLOCK POPJ P, MOVE T1,HOMLUN(B) ;GET LOGICAL UNIT NUMBER SKIPE TABUDB(T1) ;ALREADY HAVE ONE OF THOSE? POPJ P, ;YES HRLI U,SZUDB ;SAVE ADDR OF UDB MOVEM U,TABUDB(T1) PUSHJ P,MOVSTR ;COPY STUFF TO STRUCTURE DATA BLOCK POPJ P, PUSHJ P,MOVUDB ;COPY STUFF TO UDB PUSHJ P,BLDSAT ;BUILD SAT TABLES SOJGE P1,RDHOM1 ;LOOP FOR EACH UNIT MOVE T1,MFDBN ;TEST IF BN IS LEGAL PUSHJ P,LEGALP POPJ P, MOVE T1,MFDBN IDIV T1,BPSC SKIPN T2 AOS (P) POPJ P, ;ROUTINE TO READ A HOME BLOCK ;U PASSES UDB ;SKIP IF OK RDHM: MOVEI T3,1 ;READ 1ST HOME BLOCK PUSHJ P,REDBLK JRST RDHM1 ;ERROR PUSHJ P,HMCK ;VALID HOME BLOCK? JRST RDHM1 ;NO JRST CPOPJ1 ;YES, WIN RDHM1: MOVEI T3,12 ;READ 2ND HOME BLOCK PUSHJ P,REDBLK POPJ P, PJRST HMCK ;AND CHECK IF VALID ;ROUTINE TO READ A BAT BLOCK ;U PASSES UDB ;SKIP IF OK RDBT: MOVEI T3,2 ;READ 1ST BAT BLOCK PUSHJ P,REDBLK JRST RDBT1 ;ERROR PUSHJ P,BTCK ;VALID BAT BLOCK? JRST RDBT1 ;NO JRST CPOPJ1 ;YES, WIN RDBT1: MOVEI T3,13 ;READ 2ND BAT BLOCK PUSHJ P,REDBLK POPJ P, FALL BTCK ;AND CHECK IF VALID ;ROUTINE TO TEST VALIDITY OF A BAT BLOCK ;SKIP IF OK BTCK: MOVS T1,BAFNAM(B) ;NAME MOVE T2,BAFCOD(B) ;UNLIKELY CODE CAIN T1,'BAT' CAIE T2,CODBAT POPJ P, HLRE T1,BAFFIR(B) ;USEABLE WORDS MOVNS T1 HRRZ T2,BAFFIR(B) ;1ST WORD ADD T2,T1 ;LAST WORD +1 LDB T3,BAYNBR ;REGIONS ADD T3,BAFCNT(B) LSH T3,1 ;TIMES WORDS PER ENTRY CAMG T3,T1 ;TOO MANY ENTRIES? CAILE T2,BAFCOD ;NOT ENOUGH SLOTS? POPJ P, JRST CPOPJ1 SUBTTL TCB I/O ;ROUTINE TO READ THE BLOCK POINTED TO BY A TCB ;TC PASSES ADDR OF TCB ;U RETURNS ADDR OF UDB ;FL RETURNS ADDR OF FIL ;SKIP IF OK REDTCB: HRRZ FL,TCBFIL(TC) ;LOAD ADDR OF FIL LDB T1,TCYCX ;FIND DDB IFN FTDBUG,< SKIPN T1 PUSHJ P,DIE > MOVE DDB,USRJDA(T1) MOVE T1,TCBBLK(TC) ;FIND UNIT IFN FTDBUG,< CAML T1,DDBLBN(DDB) CAMLE T1,DDBHBN(DDB) PUSHJ P,DIE > IDIV T1,BPLU HRRZ U,TABUDB(T1) SKIPE DDBERR(DDB) ;ERROR? POPJ P, ;YES MOVE B,TCBBLK(TC) ;ADDR OF BLOCK SUB B,DDBLBN(DDB) IMULI B,BLKSIZ ADD B,DDBBUF(DDB) ADDI B,2 JRST CPOPJ1 ;HERE TO LOAD A TCB INTO CACHE ;TC PASSES TCB ;DDB PASSES DDB ;WE WILL READ SEVERAL BLOCKS ALL AT ONCE ;FIND THE HIGHEST DO-ABLE BLOCK LODTCB: PUSHJ P,SAVE4 ;SAVE ACS MOVE P2,TCBBLK(TC) ;FIND UNIT IDIV P2,BPLU HRRZ U,TABUDB(P2) MOVE P2,TCBBLK(TC) ;GET BN BACK MOVE T1,TCBMBB(TC) ;SUSPECTED BAD? TLNE T1,(TCPMBB) JRST LDTCB9 ;YES, DO SINGLE BLOCK XFER MOVE P1,P3 ;BN RELATIVE TO UNIT IDIV P1,UDBCYL(U) ;CYL NUMBER ADDI P1,1 ;NEXT CYL IMUL P1,UDBCYL(U) ;1ST BN OF NEXT CYL ADD P1,UDBBLK(U) ;RELATIVE TO STR MOVE P4,TCBBLK(TC) ;1ST BN THAT WON'T FIT IN BUFFER ADDI P4,NBLK HRRZ T1,TC ;START WITH CURRENT TCB PUSHJ P,XTRAP ;WANT EXTRA BLOCK? TLO T1,(1B0) ;NO LDTCB2: MOVE P2,T1 ;SAVE LAST GOOD TCB LDTCB4: HRRZ T1,TCBLNK(T1) ;STEP TO NEXT TCB CAIN T1,QTCB ;IF END JRST LDTCB3 ;THEN DON'T DO IT CAMLE P1,TCBBLK(T1) ;SAME CYL? CAMG P4,TCBBLK(T1) ;AND FIT IN BUFFER? JRST LDTCB3 ;NO, DON'T DO IT LDB T2,TCXCX ;SEE IF I/O ALREADY ACTIVE JUMPN T2,LDTCB3 ;YES PUSHJ P,FNDCX ;DON'T KNOW, SEARCH AND FIND OUT SKIPA T3,TCBMBB(T1) ;NOT ACTIVE JRST LDTCB3 ;ACTIVE TLNE T3,(TCPMBB) ;SUSPECTED BAD? JRST LDTCB3 ;YES, DON'T DO IT PUSHJ P,FITP ;FIT IN CORE? JRST LDTCB4 ;NO MOVE T2,TCBBLK(P2) ;BN OF LAST GOOD TCB ADD T2,UDBSKP(U) ;1ST BN THAT WOULD SKIP TOO MUCH ADDI T2,2 SKIPL P2 ;WANT EXTRA BLOCK? ADDI T2,1 ;YES, ONE MORE CAMG T2,TCBBLK(T1) ;SKIP TOO MUCH? JRST LDTCB3 ;YES, DON'T DO IT PUSHJ P,XTRAP ;DOES CURRENT TCB WANT EXTRA? TLO T1,(1B0) ;NO MOVE T2,TCBBLK(T1) ;NEXT BN ADDI T2,1 TRNE F,F.702 ;7.02? CAME T2,P4 ;AND EXTRA WON'T FIT IN BUFFER? JRST LDTCB2 CAME T2,P1 ;AND EXTRA IS SAME CYL? SKIPGE T1 ;AND WE WANT EXTRA? JRST LDTCB2 FALL LDTCB3 ;YES, PUT THIS TCB IN NEXT XFER ; SO WE WON'T HAVE TO DO A ONE ; BLOCK XFER JUST TO PICK UP ; THE EXTRA ;HERE WITH P2=LAST GOOD TCB LDTCB3: MOVE T1,P2 ;LAST GOOD TCB MOVE P2,TCBBLK(T1) ;THIS BN SKIPGE T1 ;WANT EXTRA BLOCK? JRST LDTCB9 ;NO ADDI P2,1 ;NEXT BN CAMGE P2,P1 ;SAME CYL? CAML P2,P4 ;AND FIT IN BUFFER? SUBI P2,1 ;NO EXTRA ;HERE WITH P2=HIGHEST BN TO READ LDTCB9: MOVEM P2,DDBHBN(DDB) ;HIGH MOVE T1,TCBBLK(TC) ;LOW MOVEM T1,DDBLBN(DDB) SETZM DDBERR(DDB) ;NO ERRORS SO FAR SETZM DDBDON(DDB) ;NOT DONE YET SUB P2,TCBBLK(TC) ;NUMBER OF BLOCKS ADDI P2,1 IMULI P2,BLKSIZ ;NUMBER OF WORDS PUSHJ P,OPNUDB ;MAKE SURE UNIT IS OPEN PUSHJ P,DIE ;IT WENT AWAY MOVE T1,DDBCX(DDB) ;STORE CHANNEL INDEX DPB T1,TCYCX MOVEM TC,DDBTCB(DDB) ;STORE 1ST TCB AOS ACTCNT ;ANOTHER DDB ACTIVE MOVE T3,P3 ;POSITION PUSHJ P,SUSETI TRNE F,F.702 ;BIG BUFFERS? JRST LDTCB6 ;YES ;HERE IF 7.01 MOVE T4,DDBBUF(DDB) ;BUILD IOWD ADDI T4,1 MOVNS P2 HRL T4,P2 MOVEM T4,CMD LDTCB7: PUSHJ P,IOXCT ;READ IT IN CMD JRST DOIN1 PUSHJ P,SETDMP ;ERROR, CLEAR BIT MOVE T4,DDBBUF(DDB) ;BUILD SINGLE IOWD ADDI T4,1 HRLI T4,-BLKSIZ CAMN T4,CMD ;ALREADY SINGLE? JRST DOIN2 ;YES, HARD ERROR MOVEM T4,CMD PUSHJ P,SETMBB ;SET "MIGHT BE BAD" MOVE T4,DDBLBN(DDB) ;ONLY ONE BLOCK MOVEM T4,DDBHBN(DDB) MOVE T3,P3 ;RE-POSITION PUSHJ P,SUSETI JRST LDTCB7 ;TRY AGAIN ;HERE IF 7.02 LDTCB6: ADDI P2,1 ;STORE SIZE OF BUFFER DPB P2,DEYSIZ PUSHJ P,DOIN ;START I/O POPJ P, ;FINISHED POPJ P, ;NOT FINISHED ;ROUTINE DO NON-BLOCKING INPUT ;SKIP IF NOT DONE DOIN: PUSHJ P,IOXCT ;DO IT IN JRST DOIN1 PUSHJ P,IOXCT ;ERROR? STATO IO.ERR JRST CPOPJ1 ;NO, MERELY UNFINISHED PUSHJ P,SETBUF ;YES, CLEAR ERROR BIT LDB T1,DEYSIZ ;GET SIZE CAIN T1,BLKSIZ+1 ;ALREADY SINGLE? JRST DOIN2 ;YES, HARD ERROR MOVEI T1,BLKSIZ+1 ;NO, MAKE SINGLE DPB T1,DEYSIZ PUSHJ P,SETMBB ;SET "MIGHT BE BAD" MOVE T2,DDBLBN(DDB) ;RE-POSITION MOVEM T2,DDBHBN(DDB) IDIV T2,BPLU PUSHJ P,SUSETI JRST DOIN ;TRY AGAIN DOIN2: SETOM DDBERR(DDB) ;HARD ERROR DOIN1: SETOM DDBDON(DDB) ;IO DONE POPJ P, ;THIS ROUTINE IS CALLED WHENEVER THERE IS AN I/O ERROR. ;WE DON'T KNOW WHICH BLOCK IT IS THAT'S BAD, ;SO WE WILL LIGHT TCPMBB IN ALL THE TCB'S. ;THIS BIT WILL CAUSE EACH BLOCK TO BE READ SEPERATELY (WITHOUT ;TRYING TO XFER SEVERAL BLOCKS IN THE SAME BUFFER). ;THIS IS THE FASTEST ALGORITHM FOR FINDING THE BAD BLOCK. ;YES, IT'S EVEN FASTER THAN A BINARY SEARCH! ;IT TURNS OUT THAT THE LIMITING FACTOR ON HOW FAST YOU CAN SEARCH IS ;THE NUMBER OF TIMES THAT THE BAD BLOCK IS READ. EACH TIME THAT ;WE ATTEMPT TO READ THE BAD BLOCK, THE MONITOR WILL END UP DOING ;NUMEROUS RETRIES. THIS CAN TAKE UPWARDS OF 1/2 SEC EACH TIME! ;THUS THE GOAL IN DESIGNING THE SEARCH ALGORITHM IS THAT THE BAD ;BLOCK (WHEREVER IT MAY BE) SHOULD ONLY BE READ ONCE. SETMBB: MOVE T1,DDBTCB(DDB) ;1ST TCB IN XFER STMBB1: MOVSI T2,(TCPMBB) ;LIGHT THE BIT IORM T2,TCBMBB(T1) HRRZ T1,TCBLNK(T1) ;STEP TO NEXT TCB CAIN T1,QTCB POPJ P, MOVE T2,TCBBLK(T1) ;END OF XFER? CAMG T2,DDBHBN(DDB) JRST STMBB1 ;NO, LOOP POPJ P, ;YES ;ROUTINE TO DECIDE WHETHER TO READ AN EXTRA BLOCK ;T1 PASSES ADDR OF TCB ;SKIP IF SHOULD READ AN EXTRA BLOCK ;THIS DOES NOT IMPLY THAT THE EXTRA BLOCK WILL FIT IN THE BUFFER, ;IT MERELY IMPLIES THAT WE WOULD LIKE TO READ THE EXTRA BLOCK IF IT ;WILL, IN FACT, FIT. XTRAP: HRRZ T2,TCBLNK(T1) ;NEXT TCB CAIN T2,QTCB JRST XTRAP1 MOVE T3,TCBBLK(T1) ;NEXT BN ADDI T3,1 CAMN T3,TCBBLK(T2) ;CONSECUTIVE TCB'S? POPJ P, ;YES XTRAP1: LDB T2,TCWCOD ;RIB? CAIE T2,FNCRIB POPJ P, ;NO HRRZ T2,TCBFIL(T1) ;YES, RIB OF DIR? HLRZ T2,FILEXT(T2) CAIE T2,'SFD' CAIN T2,'UFD' JRST CPOPJ1 ;YES, READ XTRA TRNN F,F.P2 ;NOT DIR, IS IT PASS 2? AOS (P) ;PASS 1, READ XTRA POPJ P, ;PASS 2, NO XTRA SUBTTL I/O ;ROUTINE TO READ A DISK BLOCK (WITHOUT HAVING A TCB) ;U PASSES A POINTER TO THE UDB ;DDB PASSES A POINTER TO THE DDB ;T3 PASSES BN RELATIVE TO UNIT ;NOSKIP IF ERROR ;SKIP IF OK REDBLK: SETOM DDBHBN(DDB) ;INVALIDATE CACHE MOVE B,DDBBUF(DDB) ;ADDR OF BUFFER ADDI B,2 JUMPE T3,CPOPJ PUSHJ P,OPNUDB ;MAKE SURE UNIT IS OPEN POPJ P, PUSHJ P,CODMP ;SWITCH TO DUMP PUSHJ P,SUSETI ;POSITION MOVEI T1,-1(B) ;BUILD IOWD HRLI T1,-BLKSIZ MOVEM T1,CMD PUSHJ P,IOXCT ;READ IT IN CMD JRST CPOPJ1 ;WIN PJRST SETDMP ;CLEAR ERROR BIT ;ROUTINE TO WRITE A DISK BLOCK (WITHOUT HAVING A TCB) ;U PASSES A POINTER TO THE UDB ;DDB PASSES A POINTER TO THE DDB ;B PASSES A POINTER TO THE BUFFER ;T3 PASSES BN RELATIVE TO UNIT ;NOSKIP IF ERROR ;SKIP IF OK WRTBLK: JUMPE T3,CPOPJ PUSHJ P,OPNUDB ;MAKE SURE UNIT IS OPEN POPJ P, PUSHJ P,CODMP ;SWITCH TO DUMP PUSHJ P,SUSETO ;POSITION MOVEI T1,-1(B) ;BUILD IOWD HRLI T1,-BLKSIZ MOVEM T1,CMD PUSHJ P,IOXCT ;WRITE IT OUT CMD JRST CPOPJ1 ;WIN PJRST SETDMP ;CLEAR ERROR BIT ;ROUTINE TO EXECUTE AN IO INSTRUCTION ON THE RIGHT CHANNEL ;DDB PASSES DDB ;CLOBBERS T1 (ALL OTHER ACS PRESERVED) IOXCT: MOVE T1,DDBCH(DDB) ;GET CHANNEL NUMBER LSH T1,^D18+4+1 ;POSTION IT ADD T1,@(P) ;ADD REST OF INSTRUCTION AOS (P) ;SKIP OVER INSTRUCTION XCT T1 ;DO THE INSTRUCTION POPJ P, ;NOSKIP JRST CPOPJ1 ;SKIP ;ROUTINE TO OPEN THE UNIT ;U PASSES UDB ;DDB PASSES DDB OPNUDB: MOVE T1,UDBNAM(U) ;ALREADY OPEN? CAMN T1,DDBPUN(DDB) JRST CPOPJ1 ;YES MOVEM T1,DEV+.OPDEV ;NO, OPEN IT NOW MOVEI T1,.IODMP TRNE F,F.702 MOVE T1,[UU.AIO+UU.LBF+.IOBIN] MOVEM T1,DEV+.OPMOD MOVEI T1,DDBHDR(DDB) MOVEM T1,DEV+.OPBUF SETZM DDBPUN(DDB) PUSHJ P,IOXCT OPEN DEV POPJ P, MOVE T1,UDBNAM(U) MOVEM T1,DDBPUN(DDB) MOVE T1,DDBBUF(DDB) TLO T1,(BF.VBR) MOVEM T1,DDBHDR+.BFADR(DDB) ;UNDER 7.02 THERE DOES NOT APPEAR TO BE ANY ADVANTAGE TO SETTING CPU. ;USING QUEUED PROTOCOL IS ONLY GOING TO TAKE ONE TICK, AND GETTING THE ;REQUEST QUEUED A TICK FASTER WOULDN'T REALLY HELP. THE DRIVE WILL STILL ;BE BUSY DOING THE CURRENT TRANSFER FOR AT LEAST A TICK ANYWAY. ;THUS THERE IS NO ADVANTAGE TO SETTING CPU. IN FACT, IT'S ACTUALLY AN ;ADVANTAGE TO BE RUNNABLE ON LOTS OF CPU'S. THAT WAY, YOU'RE MORE LIKELY ;TO GET CPU TIME WHEN YOU NEED IT IN A HURRY. TRNE F,F.702 ;7.01? JRST CPOPJ1 ;NO ADVANTAGE MOVE T1,UDBCPU(U) ;CPU(S) THIS UNIT IS ON CAMN T1,OURCPU JRST CPOPJ1 ;YES MOVEM T1,OURCPU ;NO HRLI T1,.STCPU ;SET US THERE SETUUO T1, JFCL JRST CPOPJ1 ;PUT DDB INTO BUFFERED MODE SETBUF: PUSHJ P,IOXCT SETSTS .IOBIN POPJ P, ;PUT DDB INTO DUMP MODE SETDMP: PUSHJ P,IOXCT SETSTS .IODMP POPJ P, ;COROUTINE TO PUT DDB IN DUMP MODE CODMP: TRNN F,F.702 ;ALREADY IN DUMP MODE? POPJ P, ;YES PUSHJ P,SETDMP ;NO, SWITCH POP P,T1 ;PRUNE STACK PUSHJ P,@T1 ;CALL CALLER CAIA AOS (P) JRST SETBUF ;SWITCH BACK ;ROUTINE TO PERFORM A SUPER USETI ;THE SUSET UUO REALLY SUCKS. ;I PREFER A GOOD OLD USETI. ;BUT SOME PEOPLE PATCH SUPER USETI OUT OF THEIR MONITOR. ;T3 PASSES BN (RELATIVE TO UNIT) ;CLOBBERS T1 SUSETI: MOVE T1,DDBCH(DDB) ;GET CHANNEL NUMBER LSH T1,^D23 ;POSITION IT SUSET2: ADD T1,T3 ;BN SUSET. T1, PUSHJ P,DIE ;SERVES YOU RIGHT! POPJ P, ;ROUTINE TO PERFORM A SUPER USETO ;T3 PASSES BN (RELATIVE TO UNIT) ;CLOBBERS T1 SUSETO: MOVE T1,DDBCH(DDB) ;GET CHANNEL NUMBER LSH T1,^D23 ;POSITION IT TLO T1,(SU.SOT) ;OUTPUT JRST SUSET2 SUBTTL CHECK HOME BLOCKS ;ROUTINE TO TEST THE VALIDITY OF A HOME BLOCK ;SKIP IF HOME BLOCK IS OK HMCK: MOVS T1,HOMNAM(B) ;NAME MUST BE HOME MOVE T2,HOMCOD(B) ;MUST HAVE MAGIC NUMBER CAIN T1,'HOM' CAIE T2,CODHOM POPJ P, LDB T1,[POINT 6,HOMCLP(B),11];BITS PER CA LDB T2,[POINT 6,HOMCLP(B),5];CA BIT POSITION JUMPN T2,CPOPJ ;MUST BE ZERO LDB T2,[POINT 6,HOMCKP(B),11];BITS PER CS LDB T3,[POINT 6,HOMCKP(B),5];CS BIT POSITION CAIG T1,CLASIZ ;CA MUST FIT IN SPT CAME T1,T3 ;SIZE OF CA IS POSITION OF CS POPJ P, ADD T1,T2 ;COMBINED SIZE OF CA AND CS LDB T2,[POINT 6,HOMCNP(B),11];BITS PER CC LDB T3,[POINT 6,HOMCNP(B),5];CC BIT POSITION CAME T1,T3 ;SIZE OF CA+CS IS POSITION OF CC POPJ P, ADD T1,T2 ;COMBINED SIZE OF CA, CS, AND CC SKIPN HOMREF(B) ;CAN'T NEED REFRESHING CAIE T1,^D36 ;MUST FILL THE WORD EXACTLY POPJ P, SKIPL T1,HOMLUN(B) ;LOGICAL UNIT NUMBER CAMLE T1,HUN POPJ P, SUB T1,HUN ;NUMBER OF UNITS REMAINING SKIPN T2,HOMNXT(B) ;IS THIS SUPPOSED TO BE LAST UNIT? JUMPN T1,CPOPJ ;YES, BETTER BE NONE LEFT SKIPN T1 ;NONE LEFT? JUMPN T2,CPOPJ ;YES, IT'S SUPPOSED TO BE THE LAST SKIPLE T1,HOMBSC(B) ;BPSC MUST BE POSITIVE SKIPG T2,HOMBPC(B) ;BPC MUST BE POSITIVE POPJ P, IDIV T1,T2 ;BPC MUST DIVIDE BPSC JUMPN T2,CPOPJ SKIPLE T1,HOMSPU(B) ;SATS PER UNIT CAILE T1,^D100 ;BE REASONABLE POPJ P, SKIPLE T2,HOMSIC(B) ;SATS IN CORE CAMLE T2,T1 POPJ P, MOVE T1,BIGBPU ;BIGGEST UNIT IDIV T1,HOMBSC(B) ;SUPER CLUSTERS ON BIGGEST UNIT SKIPE T2 ADDI T1,1 CAMN T1,HOMSCU(B) SKIPN HOMSNM(B) ;MUST BE PART OF A STR POPJ P, SKIPE T1,HOMK4S(B) ;SWAP SPACE MUST FIT MOVE T1,HOMSLB(B) MOVE T2,HOMK4S(B) LSH T2,3 ADD T1,T2 CAMLE T1,UDBBPU(U) POPJ P, JRST CPOPJ1 SUBTTL MFD TCB ;ROUTINE TO BUILD A TCB FOR MFD ;SKIP IF OK BDMFD: MOVEI T1,SIZFIL ;ALLOCATE CORE FOR FIL PUSHJ P,GETBLK MOVE FL,T2 MOVE T1,MFDPPN ;FILENAME MOVEM T1,FILNAM(FL) MOVSI T1,'UFD' ;EXT MOVEM T1,FILEXT(FL) MOVE T1,MFDBN ;CFP IDIV T1,BPSC HRLZM T1,FILCFP(FL) MOVEI T1,1 ;USE COUNT DPB T1,FIYCNT MOVEI T1,SIZRIB ;ALLOCATE CORE FOR TCB PUSHJ P,GETBLK MOVE T1,MFDBN ;PUT TCB IN QUEUE PUSHJ P,LNKTCB MOVE TC,T2 MOVEI T1,FNCRIB ;FUNCTION CODE DPB T1,TCYCOD SETZ T1, ;PRIME RIB DPB T1,TCYRBC HRRM FL,TCBFIL(TC) ;ADDR OF FIL POPJ P, SUBTTL STORE HOME BLOCK INFO ;ROUTINE TO COPY INFO FROM HOME BLOCKS TO STR DATA BLOCK ;SKIP IF OK MOVSTR: MOVE T1,HOMSNM(B) ;STRUCTURE NAME TRNN F,F.STR MOVEM T1,STRNAM CAME T1,STRNAM POPJ P, MOVE T1,NUN ;HIGHEST LEGAL BN IMUL T1,BIGBPU SUBI T1,1 MOVEM T1,HLBN MOVEI T1,T1 ;BP TO CC HLL T1,HOMCNP(B) TLZ T1,77 TRNN F,F.STR MOVEM T1,CCBP CAME T1,CCBP POPJ P, HLL T1,HOMCKP(B) ;BP TO CS TLZ T1,77 TRNN F,F.STR MOVEM T1,CSBP CAME T1,CSBP POPJ P, LDB T2,[POINT 6,CSBP,11] ;BITS PER CHECKSUM MOVEM T2,BPCS MOVNS T2 HRRZM T2,MBPCS HLL T1,HOMCLP(B) ;BP TO CA TLZ T1,77 TRNN F,F.STR MOVEM T1,CABP CAME T1,CABP POPJ P, MOVE T1,HOMBPC(B) ;BLOCKS PER CLUSTER TRNN F,F.STR MOVEM T1,BPC CAME T1,BPC POPJ P, MOVE T1,HOMBSC(B) ;BLOCKS PER SUPER CLUSTER TRNN F,F.STR MOVEM T1,BPSC CAME T1,BPSC POPJ P, IMUL T1,HOMSCU(B) ;BLOCKS PER (LARGEST) UNIT TRNN F,F.STR MOVEM T1,BPLU CAME T1,BPLU POPJ P, MOVE T1,HOMPT1(B) ;BN FOR MFD TRNN F,F.STR MOVEM T1,SPT1 CAME T1,SPT1 POPJ P, LDB T2,CABP IMUL T2,BPC MOVE T1,HOMUN1(B) TRNN F,F.STR MOVEM T1,SUN1 CAME T1,SUN1 POPJ P, IMUL T1,BPLU ADD T1,T2 MOVEM T1,MFDBN MOVE T1,HOMOVR(B) ;OVERDRAW TRNN F,F.STR MOVEM T1,SOVR CAME T1,SOVR POPJ P, MOVEI T1,DSKTRY ;RETRIES ON ERROR MOVEM T1,STRY MOVE T1,HOMPVS(B) ;NON-0 IF PRIVATE STR ANDI T1,HOPPVS SKIPE T1 SETO T1, TRNN F,F.STR MOVEM T1,SPVS CAME T1,SPVS POPJ P, MOVE T1,HOMOPP(B) ;OWNER PPN TRNN F,F.STR MOVEM T1,SPPN CAME T1,SPPN POPJ P, MOVE T1,HOMCRS(B) ;BN (REL TO STR) OF CRASH.EXE TRNN F,F.STR MOVEM T1,CRSBN CAME T1,CRSBN POPJ P, MOVE T1,HOMSCU(B) ;SUPER CLUSTERS PER UNIT TRNN F,F.STR MOVEM T1,SCPU CAME T1,SCPU POPJ P, MOVE T1,HOMK4C(B) ;K FOR CRASH TRNN F,F.STR MOVEM T1,SK4C CAME T1,SK4C POPJ P, TRO F,F.STR ;STR DATA ACCEPTED JRST CPOPJ1 ;ROUTINE TO COPY INFO FROM HOME BLOCK TO UDB MOVUDB: MOVE T1,HOMLUN(B) ;LOGICAL UNIT NUMBER MOVEM T1,UDBLUN(U) IMUL T1,BPLU ;LOWEST BLOCK MOVEM T1,UDBBLK(U) MOVE T1,UDBBPU(U) ;HIGHEST LEGAL BLOCK IDIV T1,HOMBPC(B) IMUL T1,HOMBPC(B) SUBI T1,1 MOVEM T1,UDBHLB(U) MOVE T1,HOMSPU(B) ;SATS PER UNIT MOVEM T1,UDBSPU(U) MOVE T1,UDBBPU(U) ;CLUSTERS PER SAT IDIV T1,BPC SUBI T1,1 IDIV T1,UDBSPU(U) ADDI T1,1 MOVEM T1,UDBCPS(U) SUBI T1,1 ;WORDS PER SAT IDIVI T1,^D36 ADDI T1,1 MOVEM T1,UDBWPS(U) MOVE T1,HOMHID(B) ;PACK SERIAL NUMBER MOVEM T1,UDBHID(U) MOVE T1,HOMGRP(B) ;BLOCKS TO TRY ALLOCATE MOVEM T1,UDBGRP(U) MOVE T1,HOMBPC(B) ;BLOCKS PER CLUSTER MOVEM T1,UDBBPC(U) MOVE T1,HOMSIC(B) ;SATS IN CORE MOVEM T1,UDBSIC(U) MOVE T1,HOMSLB(B) ;1ST BLOCK FOR SWAPPING MOVEM T1,UDBSLB(U) MOVE T1,HOMK4S(B) ;K FOR SWAPPING MOVEM T1,UDBK4S(U) MOVSI T1,(FS.UWL) ;SOFTWARE WRITE LOCK AND T1,WL MOVEM T1,UDBAWL(U) MOVE T1,HOMLUN(B) ;LOGICAL UNIT NAME IDIVI T1,10 SKIPE T1 ADDI T1,'0' ADDI T2,'0' ROT T2,-6 SKIPE T1 LSHC T1,-6 MOVE T1,ALIAS MVUDB1: LSH T1,-6 TRNN T1,77 JRST MVUDB1 MVUDB2: LSHC T1,6 TLNN T1,770000 JRST MVUDB2 MOVEM T1,UDBLOG(U) POPJ P, ;ROUTINE TO SAVE CAPACITY MOVCPY: MOVE T1,UDBNAM(U) ;DO A DSKCHR MOVEM T1,FOO+.DCNAM MOVE T1,[XWD FOOSIZ,FOO] DSKCHR T1, PUSHJ P,DIE TLNE T1,(DC.AWL+DC.HWP) ;WRITE LOCK? SETOM WL ;YES SETZM UDBHWP(U) TLNE T1,(DC.HWP) ;HARDWARE WRITE PROTECT? SETOM UDBHWP(U) ;YES MOVE T1,FOO+.DCUSZ ;SAVE UNIT SIZE MOVEM T1,UDBBPU(U) ADDM T1,SSIZ ;SUM OF UDBBPU CAMLE T1,BIGBPU ;BIGGEST UDBBPU? MOVEM T1,BIGBPU ;YES LOAD T1,FOO+.DCUCH,DC.UCY ;BLOCKS PER CYLINDER MOVEM T1,UDBCYL(U) LOAD T1,FOO+.DCUCH,DC.UCT ;BLOCKS PER TRACK MOVEM T1,UDBBPT(U) IMULI T1,NSKP ;BLOCKS TO SKIP ADDI T1,DSKP/2 ;ROUND IDIVI T1,DSKP MOVEM T1,UDBSKP(U) MOVE T1,FOO+.DCPAS ;POSITION IN ASL MOVEM T1,UDBASL(U) MOVE T1,FOO+.DCPSD ;POSITION IN SDL MOVEM T1,SDL SKIPE T1,FOO+.DCALT ;DON'T OVERWRITE WITH ZERO MOVEM T1,UDBALT(U) ;SAVE ALTERNATE UNIT TRNN F,F.702 ;7.01? PUSHJ P,FNDCPU ;YES, FIND WHICH CPU POPJ P, ;ROUTINE TO FIND WHICH CPU(S) THE DISK IS ON. ;WE ONLY NEED THIS INFORMATION IN 7.01, BUT ;7.01 IS THE ONLY MONITOR WHERE DSKCHR DOESN'T ;RETURN THIS INFO. FNDCPU: SETOM UDBCPU(U) ;ASSUME ALL CPUS MOVE T1,[%LDUNI] ;ADDR OF 1ST UDB GETTAB T1, HALT FNCPU1: HLRZS T1 ;IN RH JUMPE T1,CPOPJ ;GIVE UP MOVEI T2,UNINAM(T1) ;GET NAME OF UNIT PEEK T2, CAME T2,UDBNAM(U) ;OURS? CAMN T2,UDBALT(U) JRST FNCPU2 ;YES MOVEI T1,UNISYS(T1) ;NO, GET ADDR OF NEXT UDB PEEK T1, JRST FNCPU1 ;LOOP FNCPU2: MOVEI T2,UNIKON(T1) ;ADDR OF KDB PEEK T2, MOVEI T2,KONCPU(T2) ;CPU WORD PEEK T2, LSH T2,-41 ;BIT MASK MOVEI T3,SP.CR0 LSH T3,(T2) MOVEM T3,UDBCPU(U) SKIPN UDBALT(U) ;2ND PORT? POPJ P, ;NO MOVEI T1,UNI2ND(T1) ;YES, GET ADDR OF 2ND UDB PEEK T1, MOVEI T2,UNINAM(T1) ;DOUBLE CHECK PEEK T2, CAME T2,UDBNAM(U) CAMN T2,UDBALT(U) CAIA POPJ P, MOVEI T1,UNIKON(T1) ;2ND KDB PEEK T1, MOVEI T1,KONCPU(T1) ;CPU WORD PEEK T1, LSH T1,-41 ;BIT MASK MOVEI T2,SP.CR0 LSH T2,(T1) IORM T2,UDBCPU(U) POPJ P, SUBTTL CHECK A RIB ;ROUTINE TO TEST FOR A VALID RIB ;NOSKIP IF RIB ERROR ;SKIP IF RIB IS OK RBCK: MOVE T1,TCBBLK(TC) ;BN MUST POINT TO SELF IDIV T1,BPLU MOVE T1,RIBCOD(B) ;MAGIC NUMBER MUST BE RIGHT CAIN T1,CODRIB CAME T2,RIBSLF(B) POPJ P, MOVE T1,FILNAM(FL) ;CHECK FILENAME AND EXT MOVE T2,FILEXT(FL) XOR T2,RIBEXT(B) CAMN T1,RIBNAM(B) TLNE T2,-1 POPJ P, HRRZ T2,RIBFIR(B) ;1ST RTP MUST BE IN RANGE CAIL T2,RIBTIM+1 CAILE T2,RIBCOD-1 POPJ P, HLRE T3,RIBFIR(B) ;LAST RTP MUST BE IN RANGE SUBM T2,T3 CAIL T3,1(T2) CAILE T3,RIBCOD POPJ P, LDB T3,TCYRBC ;GET RIB COUNT SKIPE T3 ;EXTENDED RIB? SKIPA T4,TCBFLR(TC) ;YES, GET 1ST LOGICAL RECORD MOVEI T4,1 ;NO, BLOCK ONE SUBI T4,1 ;LAST BLOCK IN PREVIOUS RIB CAME T4,RIBFLR(B) ;CHECK IT POPJ P, ADD T2,B ;GET 1ST RTP MOVE T1,(T2) MOVE T4,UDBLUN(U) ;IS IT UNIT POINTER? CAIN T1,RIPNUB(T4) AOSA T2 ;YES, POINT TO 1ST GROUP JUMPE T3,CPOPJ ;NO, ERROR UNLESS EXTENDED RIB MOVE T1,(T2) ;GET 1ST GROUP POINTER LDB T1,CABP ;GET CLUSTER ADDRESS IMUL T1,BPC ;MUST POINT TO SELF CAME T1,RIBSLF(B) POPJ P, MOVE T1,RIBUFD(B) ;CHECK UPWARD POINTER PUSHJ P,CTINT ;CONVERT TO INTERNAL FORMAT IDIV T1,BPSC JUMPN T2,CPOPJ HLRZ T3,FILCFP(FL) HRRZ T2,FILDAD(FL) SKIPE T2 HLRZ T3,FILCFP(T2) CAME T1,T3 POPJ P, MOVE T1,FL ;FIND UFD RBCK1: HRRZ T2,FILDAD(T1) SKIPE T2 MOVE T1,T2 HLRZ T2,FILEXT(T1) CAIE T2,'UFD' JRST RBCK1 MOVE T2,FILNAM(T1) CAMN T2,RIBPPN(B) AOS (P) POPJ P, SUBTTL CHECKSUMING ;READ A DATA BLOCK AND COMPUTE THE CHECKSUM DOSUM: PUSHJ P,REDTCB ;READ THE BLOCK JRST IOERR ;I/O ERROR MOVE T1,0(B) ;COMPUTE THE CHECKSUM PUSHJ P,FOLD CAMN T2,TCBSUM(TC) ;IS IT RIGHT? POPJ P, ;YES MOVEI T2,[ASCIZ /Checksum error on file /] PUSHJ P,STRO PUSHJ P,FILO ;TYPE FILESPEC PUSHJ P,CRLFO MOVEI T2,[ASCIZ /Block /] PUSHJ P,STRO MOVE T1,TCBREL(TC) PUSHJ P,OCTO MOVEI T2,[ASCIZ / relative to file, cluster /] PUSHJ P,STRO MOVE T1,TCBBLK(TC) IDIV T1,BPC PUSHJ P,OCTO PJRST DSPACE DIRERR: SKIPA T2,[[ASCIZ /Directory is overwritten with garbage /]] IOERR: MOVEI T2,[ASCIZ /Error while reading file /] PUSHJ P,STRO PUSHJ P,FILO ;TYPE FILESPEC PUSHJ P,CRLFO MOVEI T2,[ASCIZ /Block /] PUSHJ P,STRO MOVE T1,TCBREL(TC) PUSHJ P,OCTO MOVEI T2,[ASCIZ / relative to file, block /] PUSHJ P,STRO MOVE T1,TCBBLK(TC) PUSHJ P,BNO MOVEI T2,[ASCIZ / relative to STR/] PUSHJ P,STRO DSPACE: PUSHJ P,CRLFO TRNE F,F.TTY ;BREAK OUTPUT PUSHJ P,BUFO PJRST CRLFO ;ROUTINE TO COMPUTE FOLDED CHECKSUM ;T1 PASSES WORD TO BE FOLDED ;T2 RETURNS CHECKSUM FOLD: SETZ T2, LSHC T1,@MBPCS ROT T2,@BPCS JUMPE T1,CPOPJ ADD T1,T2 JRST FOLD SUBTTL CORE MANAGEMENT ;ROUTINE TO DECREMENT USE COUNT OF FIL DECFIL: LDB T1,FIYCNT ;DECREMENT COUNT SUBI T1,1 DPB T1,FIYCNT JUMPN T1,CPOPJ ;OTHER USERS, LEAVE ALONE PUSH P,FL ;LAST USER, SAVE ADDR HRRZ FL,FILDAD(FL) ;GET ADDR OF PARENT SKIPE FL ;MFD? PUSHJ P,DECFIL ;NO, DECREMENT PARENT'S COUNT POP P,FL ;RESTORE ADDR OF SON FALL GIVFIL ;RETURN SON TO FREE LIST ;ROUTINE TO GIVE A FIL BACK TO FREE CORE GIVFIL: MOVEI T1,SIZFIL MOVE T2,FL PJRST GIVBLK ;ROUTINE TO GIVE A TCB AWAY GIVTCB: LDB T3,TCYCOD ;GET FUNCTION CODE MOVE T1,FUNSZ(T3) ;SIZE MOVE T2,TC ;ADDR PJRST @FUNGV(T3) ;DISPATCH ;ROUTINE TO GIVE A RIB TCB AWAY GIVRIB: LDB T3,TCYRBC ;PRIME OR EXTENDED? JUMPE T3,GIVBLK MOVEI T1,SIZXRB ;EXTENDED MOVE T3,TCBCOR(TC) ;CORRUPT? TLNE T3,(TCPCOR) MOVEI T1,SIZCXR ;YES, CORRUPT EXTENDED RIB PJRST GIVBLK ;ROUTINE TO GET A BLOCK OF CORE AND ZERO IT ;T1 PASSES SIZE OF BLK (NOT PRESERVED) ;T2 RETURNS ADDR OF BLK GETZER: PUSHJ P,GETBLK ;ALLOCATE THE CORE SETZM (T2) ;ZERO 1ST WORD CAIN T1,1 ;ONLY ONE WORD? POPJ P, ;YES, ALL DONE HRLZI T3,0(T2) ;BLT THE REST HRRI T3,1(T2) ADDI T1,-1(T2) BLT T3,(T1) POPJ P, ;ROUTINE TO GET A CORE BLOCK ;T1 PASSES SIZE OF BLK (PRESERVED) ;T2 RETURNS ADDR OF BLK GETBLK: ADDM T1,WRDCNT ;BUMP COUNT PUSHJ P,TRYBLK ;ANY FREE BLOCKS? POPJ P, ;YES MOVE T2,.JBFF ;NO, ENOUGH CORE TO MAKE 1? ADD T2,T1 CAMG T2,.JBREL JRST GTBLK1 ;YES PUSHJ P,GC ;NO, GARBAGE COLLECT PUSHJ P,CDOWN ;CORE DOWN PUSHJ P,TRYBLK ;TRY AGAIN POPJ P, ;WIN MOVE T2,.JBFF ;STILL LOSE, GET MORE CORE ADD T2,T1 MOVE T3,T2 TRNN F,F.HW ADDI T3,*PAGSIZ CORE T3, PUSHJ P,DIE GTBLK1: EXCH T2,.JBFF ;T2=ADDR OF BLK POPJ P, ;ROUTINE TO CORE DOWN ;THIS ROUTINE MAY ONLY BE CALLED IMMEDIATELY AFTER GC ;PRESERVES T1 CDOWN: HRRZ T2,FREMEM ;LAST FREE NODE JUMPE T2,CPOPJ HLRZ T3,(T2) ;SIZE OF LAST NODE CAIGE T3,DOWNN*PAGSIZ ;BIG ENOUGH? POPJ P, ;NO ADD T3,T2 ;1ST ADDR BEYOND LAST NODE CAME T3,.JBFF ;LAST NODE IS AT VERY END? POPJ P, ;NO HRRZ T3,(T2) ;UNLINK LAST NODE HRRM T3,FREMEM MOVEM T2,.JBFF ;NEW VALUE OF 1ST FREE CORE T2, ;PITCH SOME CORE PUSHJ P,DIE ;MONITOR BUG? POPJ P, ;ROUTINE TO TRY TO FIND A FREE CORE BLK ;T1 PASSES SIZE OF BLK (PRESERVED) ;T2 RETURNS ADDR OF BLK ;SKIP IF FAIL TRYBLK: PUSHJ P,SAVE3 ;SAVE P1-P3 MOVEI P1,-1 ;FLAG NONE SO FAR MOVEI P2,FREMEM ;POINT TO 0TH FREE BLK TRYLOP: MOVE P3,P2 ;ADVANCE TO NEXT BLK HRRZ P2,(P3) JUMPE P2,TRY1 ;QUIT IF NO MORE BLKS HLRZ T4,(P2) ;GET SIZE OF BLK CAML T4,T1 ;BIG ENOUGH? CAML T4,P1 ;AND SMALLEST SO FAR? JRST TRYLOP ;NO SUB T4,T1 ;YES, COMPUTE SIZE OF LEFTOVER CAIGE T4,SIZGAR ;IS IT JUST A CRUMB? JUMPN T4,TRYLOP ;YES, DON'T LEAVE CRUMBS AROUND HLRZ P1,(P2) ;REMEMBER WHERE IT IS MOVE T3,P3 JUMPN T4,TRYLOP ;GO IF NOT PERFECT MATCH TRY1: CAIN P1,-1 ;QUIT IF NO WINNERS AT ALL JRST CPOPJ1 HRRZ T2,(T3) ;ADDR OF BEST CAMG P1,T1 ;TOO BIG? JRST TRYESY ;NO, JUST RIGHT MOVE P2,T2 ;COMPUTE ADDR OF LEFTOVER ADD P2,T1 SUB P1,T1 ;COMPUTE SIZE OF LEFTOVER HRL P1,(T2) ;SPLIT INTO TWO BLKS MOVSM P1,(P2) HRL P2,T1 MOVEM P2,(T2) TRYESY: HRRZ T4,(T2) ;UNLINK THE BLK HRRM T4,(T3) POPJ P, ;ROUTINE TO RETURN A BLOCK OF CORE TO FREE LIST ;T1 PASSES SIZE OF BLK ;T2 PASSES ADDR OF BLK GIVBLK: IFN FTGCHK,< CAIGE T1,SIZGAR PUSHJ P,DIE > HRRZ T3,FREMEM ;ADD TO HEAD OF LIST HRL T3,T1 MOVEM T3,(T2) MOVEM T2,FREMEM MOVNS T1 ;MAINTAIN COUNT ADDM T1,WRDCNT POPJ P, ;GARBAGE COLLECT ROUTINE ;COMBINES CONSECUTIVE FRAGMENTS ;T1 IS PRESERVED GC: PUSH P,T1 ;SAVE T1 PUSH P,QTCB ;SAVE THE TCB TREE PUSH P,ROOT MOVE T1,[XWD QTCB,QTCB] ;BUILD A NULL TREE MOVEM T1,QTCB SETZM ROOT GC1: HRRZ T2,FREMEM ;ADDR OF NEXT FREE NODE JUMPE T2,GC2 HRRZ T1,(T2) ;UNLINK IT FROM FREE LIST HRRM T1,FREMEM HLRZ T1,(T2) ;SIZE OF NODE PUSHJ P,LNKGAR ;LINK IT INTO THE TREE IFN FTGCHK,< PUSHJ P,CHECK ;CHECK CONSISTENCY > JRST GC1 ;LOOP GC2: HRRZ T2,QTCB ;ADDR OF NEXT NODE CAIN T2,QTCB ;QUIT IF LAST NODE JRST GC3 HRRZ T1,TCBLNK(T2) ;UNLINK IT FROM TREE HRRM T1,QTCB LDB T1,TCXGAR ;LINK IT TO FREE LIST HRL T1,FREMEM MOVSM T1,(T2) HRRM T2,FREMEM JRST GC2 ;LOOP GC3: POP P,ROOT ;RESTORE TCB TREE POP P,QTCB JRST TPOPJ ;RESTORE T1 ;ROUTINE TO LINK A FREE NODE INTO THE TREE ;USED ONLY FOR GC ;T1 PASSES SIZE OF BLK ;T2 PASSES ADDR OF BLK LNKGAR: IFN FTDBUG,< CAIGE T1,SIZGAR PUSHJ P,DIE > DPB T1,TCXGAR ;STORE SIZE SETZM TCBSON(T2) ;NO SONS MOVEI T4,BALZ ;WE ARE BALANCED DPB T4,TCZBAL SKIPN T4,ROOT ;1ST TIME? JRST LNKGR4 ;YES LNKGR1: MOVE T3,T4 ;ADVANCE TO NEXT NODE CAML T2,T3 ;TOO HIGH OR TOO LOW? JRST LNKGR2 ;TOO HIGH, GO RIGHT HLRZ T4,TCBSON(T3) ;TOO LOW, GET LEFT SON JUMPN T4,LNKGR1 ;AND LOOP LDB T4,TCXGAR ;JUST BEFORE PARENT? ADD T4,T2 CAME T4,T3 JRST LNKG10 ;NO LDB T4,TCXGAR ;YES, TOO BIG TO COMBINE? LDB T1,TCWGAR ADD T4,T1 CAIG T4,TCMGAR JRST LNKGR6 ;NO, GO COMBINE LNKG10: HLRZ T4,TCBLNK(T3) ;PRED CAIN T4,QTCB JRST LNKGR7 ;NO PRED LDB T1,TCZGAR ;JUST AFTER PRED? ADD T1,T4 CAME T1,T2 JRST LNKGR7 ;NO LDB T1,TCZGAR ;YES, TOO BIG TO COMBINE? LDB T4,TCXGAR ADD T1,T4 HLRZ T4,TCBLNK(T3) CAIG T1,TCMGAR JRST LNKGR8 ;NO, GO COMBINE LNKGR7: HRLM T2,TCBSON(T3) ;MAKE US THE LEFT SON HRLM T3,TCBRNT(T2) ;HERE WITH T4=PRED, T3=SUCC LNKGR3: HRRM T2,TCBLNK(T4) ;WE ARE SUCC OF PRED HRLM T2,TCBLNK(T3) ;WE ARE PRED OF SUCC HRL T3,T4 ;PRED,,SUCC MOVEM T3,TCBLNK(T2) PUSH P,T2 ;PRESERVE ADDR OF NODE PUSHJ P,ADDND1 ;ADD NODE TO BALANCE FACTOR T2POPJ: POP P,T2 POPJ P, LNKGR2: HRRZ T4,TCBSON(T3) ;GET RIGHT SON JUMPN T4,LNKGR1 ;AND LOOP LDB T4,TCWGAR ;JUST AFTER PARENT? ADD T4,T3 CAME T4,T2 JRST LNKG11 ;NO LDB T4,TCWGAR ;YES, TOO BIG TO COMBINE? LDB T1,TCXGAR ADD T4,T1 CAIG T4,TCMGAR JRST LNKGR5 ;NO, GO COMBINE LNKG11: HRRZ T4,TCBLNK(T3) ;GET SUCC LDB T1,TCXGAR ;JUST BEFORE SUCC? ADD T1,T2 CAME T1,T4 JRST LNKG12 ;NO LDB T1,TCZGAR ;YES, TOO BIG TO COMBINE? LDB T4,TCXGAR ADD T1,T4 HRRZ T4,TCBLNK(T3) CAIG T1,TCMGAR JRST LNKGR9 ;NO, GO COMBINE LNKG12: HRRM T2,TCBSON(T3) ;MAKE US THE RIGHT SON HRLM T3,TCBRNT(T2) EXCH T3,T4 ;OTHER WAY AROUND JRST LNKGR3 ;HERE TO INSERT THE VERY FIRST NODE LNKGR4: MOVEM T2,ROOT ;WE BECOME THE ROOT HRRZS TCBRNT(T2) ;NO PARENT MOVE T3,[XWD QTCB,QTCB] ;LINK US MOVEM T3,TCBLNK(T2) HRRZM T2,QTCB HRLM T2,QTCB POPJ P, ;HERE TO INSERT JUST AFTER T3 LNKGR5: MOVE T4,T3 ;HERE TO INSERT JUST AFTER T4 LNKGR8: LDB T1,TCXGAR ;TOTAL SIZE LDB T3,TCZGAR ADD T1,T3 DPB T1,TCZGAR HRRZ T2,TCBLNK(T4) ;NEXT ADD T1,T4 ;JUST BEFORE NEXT? CAME T1,T2 POPJ P, LDB T1,TCZGAR ;YES, TOO BIG TO COMBINE? LDB T3,TCXGAR ADD T1,T3 CAILE T1,TCMGAR POPJ P, ;YES, DON'T COMBINE ;HERE WHEN WE JUST INSERTED A NODE WHICH IS AN EXACT FIT ;FOR WHAT WAS MISSING BETWEEN TWO OTHER NODES. COMBINE INTO A SINGLE NODE. ;HERE WITH T4=LOW NODE, T2=HIGH NODE LNKGR0: PUSH P,T4 ;LOW NODE PUSH P,T2 ;HIGH NODE PUSH P,TC ;SAVE TC MOVE TC,T2 ;UNLINK HIGH NODE PUSHJ P,UNLINK PUSHJ P,UNLNK POP P,TC ;RESTORE TC POP P,T2 ;HIGH NODE POP P,T4 ;LOW NODE JRST LNKGR8 ;GO COMBINE ;HERE TO INSERT JUST BEFORE T3 LNKGR6: MOVE T4,T3 ;HERE TO INSERT JUST BEFORE T4 LNKGR9: HLRZ T1,TCBRNT(T4) ;COPY PARENT HRLM T1,TCBRNT(T2) SKIPN T1 MOVEI T1,ROOT-TCBSON HLRZ T3,TCBSON(T1) ;LEFT SON OF PARENT OR RIGHT? CAMN T3,T4 HRLM T2,TCBSON(T1) ;LEFT CAME T3,T4 HRRM T2,TCBSON(T1) ;RIGHT HLRZ T1,TCBLNK(T4) ;PRED HRRM T2,TCBLNK(T1) ;PRED HAS NEW SUCC HRRZ T1,TCBLNK(T4) ;SUCC HRLM T2,TCBLNK(T1) ;SUCC HAS NEW PRED HLRZ T1,TCBSON(T4) ;LEFT SON HAS NEW PARENT SKIPE T1 HRLM T2,TCBRNT(T1) HRRZ T1,TCBSON(T4) ;RIGHT SON HAS NEW PARENT SKIPE T1 HRLM T2,TCBRNT(T1) MOVE T1,TCBSON(T4) ;COPY SONS MOVEM T1,TCBSON(T2) MOVE T1,TCBLNK(T4) ;COPY LINKS MOVEM T1,TCBLNK(T2) LDB T1,TCVBAL ;COPY BALANCE FACTOR DPB T1,TCZBAL LDB T1,TCXGAR ;TOTAL SIZE LDB T3,TCZGAR ADD T1,T3 DPB T1,TCXGAR HLRZ T4,TCBLNK(T2) ;PRED CAIN T4,QTCB POPJ P, ;NO PRED LDB T1,TCZGAR ;JUST AFTER PRED? ADD T1,T4 CAME T1,T2 POPJ P, ;NO LDB T1,TCXGAR ;YES, TOO BIG TO COMBINE? LDB T3,TCZGAR ADD T1,T3 CAIG T1,TCMGAR JRST LNKGR0 ;NO, GO COMBINE POPJ P, ;YES, DON'T COMBINE ;ROUTINE TO INSERT A TCB INTO THE QUEUE ;T1 PASSES BN ;T2 PASSES ADDR OF TCB (PRESERVED) LNKTCB: MOVEM T1,TCBBLK(T2) ;STORE BN SETZB T4,TCBSON(T2) ;WE HAVE NO SONS DPB T4,TCZCX ;NOT YET LOADED INTO CACHE MOVSI T4,(TCPMBB) ;NOT BAD ANDCAM T4,TCBMBB(T2) MOVEI T4,BALZ ;WE ARE BALANCED DPB T4,TCZBAL SKIPN T4,ROOT ;1ST TIME? JRST LNKTC4 ;YES LNKTC1: MOVE T3,T4 ;ADVANCE TO NEXT NODE CAML T1,TCBBLK(T3) ;TOO HIGH OR TOO LOW? JRST LNKTC2 ;TOO HIGH, GO RIGHT HLRZ T4,TCBSON(T3) ;TOO LOW, GET LEFT SON JUMPN T4,LNKTC1 ;AND LOOP HRLM T2,TCBSON(T3) ;NONE, MAKE US THE LEFT SON HRLM T3,TCBRNT(T2) HLRZ T4,TCBLNK(T3) ;GET PRED ;HERE WITH T4=PRED, T3=SUCC LNKTC3: HRRM T2,TCBLNK(T4) ;WE ARE SUCC OF PRED HRLM T2,TCBLNK(T3) ;WE ARE PRED OF SUCC HRL T3,T4 ;PRED,,SUCC MOVEM T3,TCBLNK(T2) PUSH P,T2 ;PRESERVE ADDR OF NODE PUSHJ P,ADDND1 ;ADD NODE TO BALANCE FACTOR IFN FTCHK,< PUSHJ P,CHECK ;CHECK CONSISTENCY > JRST T2POPJ LNKTC2: HRRZ T4,TCBSON(T3) ;GET RIGHT SON JUMPN T4,LNKTC1 ;AND LOOP HRRM T2,TCBSON(T3) ;NONE, MAKE US THE RIGHT SON HRLM T3,TCBRNT(T2) LNKTC5: HRRZ T4,TCBLNK(T3) ;GET SUCC EXCH T3,T4 ;OTHER WAY AROUND JRST LNKTC3 LNKTC4: MOVEM T2,ROOT ;WE BECOME THE ROOT HRRZS TCBRNT(T2) ;NO PARENT HRRZ T3,QTCB ;LINK US JRST LNKTC5 ;ROUTINE TO UNLINK THE TCB FROM THE QUEUE UNLNK: HLRZ T1,TCBLNK(TC) ;UNLINK TCB FROM QUEUE HRRZ T2,TCBLNK(TC) HRRM T2,TCBLNK(T1) HRLM T1,TCBLNK(T2) POPJ P, ;ROUTINE TO UNLINK THE TCB FROM THE TREE UNLINK: HLRZ T1,TCBSON(TC) ;DO WE HAVE A LEFT SON? JUMPE T1,UNLNK6 ;NO, EASY HRRZ T1,TCBSON(TC) ;DO WE HAVE A RIGHT SON? JUMPE T1,UNLNK6 ;NO, EASY ;HERE WHEN WE HAVE BOTH LEFT AND RIGHT SONS MOVE T1,TC ;NODE TO MOVE OUT LDB T4,TCXBAL ;ITS BALANCE FACTOR HRRZ T2,TCBLNK(T1) ;NODE TO MOVE IN CAIL T4,BALZ HLRZ T2,TCBLNK(T1) IFN FTDBUG,< HLRZ T3,TCBSON(T2) ;LEFT CORNER CAN'T HAVE LEFT SON CAIL T4,BALZ HRRZ T3,TCBSON(T2) ;RIGHT CORNER CAN'T HAVE RIGHT SON SKIPE T3 PUSHJ P,DIE > PUSH P,T1 ;NODE TO MOVE OUT PUSH P,T2 ;NODE TO MOVE IN PUSHJ P,ORPHAN ;UNLINK CORNER NODE FROM ITS OLD POSITION POP P,T2 ;NODE TO MOVE IN POP P,T1 ;NODE TO MOVE OUT PJRST SWAP ;T2 NODE TAKES PLACE OF T1 NODE ;HERE WHEN WE DON'T HAVE BOTH SONS UNLNK6: MOVE T2,TC ;NODE TO UNLINK PJRST ORPHAN ;BLAST IT ;ROUTINE TO ADD A NODE TO THE BALANCE FACTOR ;T1 PASSES ADDR OF NODE JUST ADDED ADDNOD: MOVE T2,T1 ;WANT IT IN OTHER AC ;HERE WITH ADDR OF NODE IN T2 ADDND1: HLRZ T1,TCBRNT(T2) ;PARENT JUMPE T1,CPOPJ ;NOBODY TO ADD TO MOVEI T3,1 ;ASSUME LEFT SON HLRZ T4,TCBSON(T1) ;LEFT SON? CAME T4,T2 SETO T3, ;NO, RIGHT SON LDB T4,TCXBAL ;PARENT'S BALANCE FACTOR ADD T4,T3 ;UPDATE BALANCE FACTOR DPB T4,TCXBAL CAIL T4,BALM ;WITHIN TOLERANCE? CAILE T4,BALP PUSHJ P,REBAL ;NO, REBALANCE THE TREE CAIE T4,BALZ ;PERFECTLY BALANCED? JRST ADDNOD ;NO, ADJUST GRANDPA TOO POPJ P, ;YES ;ROUTINE TO SUBTRACT A NODE FROM THE BALANCE FACTOR ;T1 PASSES ADDR OF PARENT (OF NODE JUST DELETED) ;T3 PASSES DELTA FACTOR SUBNOD: LDB T4,TCXBAL ;GET PARENT'S BALANCE FACTOR ADD T4,T3 ;ADJUST BALANCE FACTOR DPB T4,TCXBAL CAIL T4,BALM ;WITHIN TOLERANCE? CAILE T4,BALP PUSHJ P,REBAL ;NO, REBALANCE THE TREE CAIE T4,BALZ ;PERFECTLY BALANCED? POPJ P, ;NO, ALL DONE MOVE T2,T1 ;YES, SAVE ADDR OF PARENT HLRZ T1,TCBRNT(T2) ;GET ADDR OF GRANDPA JUMPE T1,CPOPJ ;NONE MOVEI T3,1 ;ASSUME FATHER IS RIGHT SON OF GRANDPA HRRZ T4,TCBSON(T1) ;TRUE? CAME T4,T2 SETO T3, ;NO, LEFT SON JRST SUBNOD ;UPDATE GRANDPA'S BALANCE FACTOR ;ROUTINE TO REBALANCE THE TREE ;I.E. MAKE BALANCE FACTOR BETTER BY ROTATING THE ROOT NODE ;T1 PASSES ROOT OF UNBALANCED SUBTREE ;T4 PASSES BALANCE FACTOR OF ROOT ;T1 RETURNS NEW ROOT ;T4 RETURNS NEW BALANCE FACTOR OF NEW ROOT REBAL: PUSHJ P,SAVE2 ;SAVE ACS HLRZ P1,TCBRNT(T1) ;ORIGINAL PARENT OF ORIGINAL ROOT CAIL T4,BALZ ;RIGHT HEAVY OR LEFT HEAVY? JRST REBL ;LEFT HEAVY FALL REBR ;RIGHT HEAVY ;HERE IF RIGHT HEAVY REBR: HRRZ T2,TCBSON(T1) ;B IFN FTDBUG,< SKIPN T2 PUSHJ P,DIE > HLRZ T3,TCBSON(T2) ;Y OR C LDB T4,TCZBAL ;B BALANCE IFN FTDBUG,< CAIL T4,BALM CAILE T4,BALP PUSHJ P,DIE > CAIN T4,BALP JRST REBR3 MOVE P2,[EXP BALZ,BALM]-BALM(T4) DPB P2,TCXBAL MOVE P2,[EXP BALZ,BALP]-BALM(T4) DPB P2,TCZBAL HRRM T3,TCBSON(T1) SKIPE T3 HRLM T1,TCBRNT(T3) HRLM T1,TCBSON(T2) HRLM T2,TCBRNT(T1) JRST REBCM ;CASE R3 REBR3: IFN FTDBUG,< SKIPN T3 PUSHJ P,DIE > LDB T4,TCWBAL IFN FTDBUG,< CAIL T4,BALM CAILE T4,BALP PUSHJ P,DIE > MOVEI P2,BALZ DPB P2,TCWBAL MOVE P2,[EXP BALP,BALZ,BALZ]-BALM(T4) DPB P2,TCXBAL MOVE P2,[EXP BALZ,BALZ,BALM]-BALM(T4) DPB P2,TCZBAL HLRZ T4,TCBSON(T3) ;Y1 HRRM T4,TCBSON(T1) SKIPE T4 HRLM T1,TCBRNT(T4) HRRZ T4,TCBSON(T3) ;Y2 HRLM T4,TCBSON(T2) SKIPE T4 HRLM T2,TCBRNT(T4) HRLZM T1,TCBSON(T3) HRLM T3,TCBRNT(T1) HRRM T2,TCBSON(T3) HRLM T3,TCBRNT(T2) JRST REBCOM ;HERE IF LEFT HEAVY REBL: HLRZ T2,TCBSON(T1) ;B IFN FTDBUG,< SKIPN T2 PUSHJ P,DIE > HRRZ T3,TCBSON(T2) ;Y OR C LDB T4,TCZBAL ;B BALANCE IFN FTDBUG,< CAIL T4,BALM CAILE T4,BALP PUSHJ P,DIE > CAIN T4,BALM JRST REBL3 MOVE P2,[EXP BALP,BALZ]-BALZ(T4) DPB P2,TCXBAL MOVE P2,[EXP BALM,BALZ]-BALZ(T4) DPB P2,TCZBAL HRLM T3,TCBSON(T1) SKIPE T3 HRLM T1,TCBRNT(T3) HRRM T1,TCBSON(T2) HRLM T2,TCBRNT(T1) JRST REBCM ;CASE L3 REBL3: IFN FTDBUG,< SKIPN T3 PUSHJ P,DIE > LDB T4,TCWBAL IFN FTDBUG,< CAIL T4,BALM CAILE T4,BALP PUSHJ P,DIE > MOVEI P2,BALZ DPB P2,TCWBAL MOVE P2,[EXP BALZ,BALZ,BALM]-BALM(T4) DPB P2,TCXBAL MOVE P2,[EXP BALP,BALZ,BALZ]-BALM(T4) DPB P2,TCZBAL HLRZ T4,TCBSON(T3) ;Y2 HRRM T4,TCBSON(T2) SKIPE T4 HRLM T2,TCBRNT(T4) HRRZ T4,TCBSON(T3) ;Y1 HRLM T4,TCBSON(T1) SKIPE T4 HRLM T1,TCBRNT(T4) HRLZM T2,TCBSON(T3) HRLM T3,TCBRNT(T2) HRRM T1,TCBSON(T3) HRLM T3,TCBRNT(T1) FALL REBCOM ;COMMON EXIT FOR REBAL REBCOM: MOVE T2,T3 ;HERE WITH: ;T1=OLD ROOT ;T2=NEW ROOT ;P1=OLD PARENT OF OLD ROOT REBCM: HRLM P1,TCBRNT(T2) SKIPN P1 MOVEI P1,ROOT-TCBSON HRRZ T3,TCBSON(P1) CAMN T3,T1 HRRM T2,TCBSON(P1) CAME T3,T1 HRLM T2,TCBSON(P1) MOVE T1,T2 ;NEW ROOT LDB T4,TCXBAL ;NEW BALANCE OF NEW ROOT POPJ P, ;ROUTINE TO UNLINK A NODE FROM THE TREE ;THIS ROUTINE ONLY WORKS IF THE NODE DOESN'T HAVE BOTH SONS ;T2 PASSES NODE ORPHAN: HLRZ T1,TCBRNT(T2) ;GET PARENT HRRZ T3,TCBSON(T2) ;GET SON (IF ANY) SKIPN T3 HLRZ T3,TCBSON(T2) SKIPE T3 ;HAVE SON? HRLM T1,TCBRNT(T3) ;YES, SON GETS NEW PARENT SKIPN T1 ;DELETING THE ROOT? MOVEI T1,ROOT-TCBSON ;YES, FAKE PARENT HRRZ T4,TCBSON(T1) ;RIGHT SON OR LEFT SON? CAME T4,T2 JRST ORPHN1 ;LEFT HRRM T3,TCBSON(T1) ;RIGHT, PARENT GETS NEW SON MOVEI T3,1 ;DELTA BALANCE FACTOR HLRZ T1,TCBRNT(T2) ;GET PARENT BACK JUMPN T1,SUBNOD POPJ P, ;HERE IF THE NODE WE'RE DELETING IS A LEFT SON ORPHN1: IFN FTDBUG,< HLRZ T4,TCBSON(T1) ;DOUBLE CHECK CAME T4,T2 PUSHJ P,DIE > HRLM T3,TCBSON(T1) ;PARENT GETS NEW SON SETO T3, ;DELTA BALANCE FACTOR HLRZ T1,TCBRNT(T2) ;GET PARENT BACK JUMPN T1,SUBNOD POPJ P, ;T2 NODE TAKES T1 NODE'S PLACE ;PRESERVES T1 AND T2 SWAP: HRRZ T3,TCBSON(T1) ;COPY RIGHT SON (IF ANY) HRRM T3,TCBSON(T2) SKIPE T3 ;RIGHT SON EXIST? HRLM T2,TCBRNT(T3) ;YES, RIGHT SON GETS NEW PARENT HLRZ T3,TCBSON(T1) ;COPY LEFT SON (IF ANY) HRLM T3,TCBSON(T2) SKIPE T3 ;LEFT SON EXIST? HRLM T2,TCBRNT(T3) ;YES, LEFT SON GETS NEW PARENT LDB T3,TCXBAL ;COPY BALANCE FACTOR DPB T3,TCZBAL HLRZ T3,TCBRNT(T1) ;COPY PARENT HRLM T3,TCBRNT(T2) SKIPN T3 ;ROOT? MOVEI T3,ROOT-TCBSON ;YES, FAKE PARENT HRRZ T4,TCBSON(T3) ;ARE WE RIGHT SON? CAMN T4,T1 HRRM T2,TCBSON(T3) ;YES, UPDATE PARENT CAME T4,T1 ;ARE WE LEFT SON? HRLM T2,TCBSON(T3) ;YES, UPDATE PARENT POPJ P, IFN FTCHK,> IFN FTCHK!FTGCHK,< ;ROUTINE TO CHECK THE ENTIRE TREE FOR CONSISTENCY CHECK: SETZ T1, ;START AT ROOT SKIPE T2,ROOT PUSHJ P,CTREE HRRZ T1,QTCB ;DOES 1ST NODE POINT TO 2ND? HLRZ T1,TCBLNK(T1) CAIE T1,QTCB PUSHJ P,DIE ;NO POPJ P, ;ROUTINE TO CHECK A NODE FOR CONSISTENCY ;T2 PASSES NODE TO BE CHECKED ;T1 PASSES WHAT PARENT SHOULD BE ;T2 RETURNS HEIGHT OF TREE CTREE: HLRZ T3,TCBRNT(T2) ;CHECK PARENT CAME T3,T1 PUSHJ P,DIE MOVE T1,T2 ;SAVE ADDR OF ROOT HRRZ T2,TCBLNK(T1) ;NEXT NODE POINT BACK TO US? HLRZ T3,TCBLNK(T2) CAME T3,T1 PUSHJ P,DIE IFN FTCHK,< HRLOI T3,377777 ;ASSUME LAST NODE CAIE T2,QTCB ;TRUE? MOVE T3,TCBBLK(T2) ;NO, GET BN OF NEXT NODE CAMG T3,TCBBLK(T1) ;NEXT BN SHOULD BE GREATER > IFN FTGCHK,< CAIN T2,QTCB ;LAST NODE? MOVSI T2,1 ;YES, FAKE ADDR LDB T3,TCVGAR ;LAST ADDR IN THIS NODE ADD T3,T1 CAMGE T2,T3 ;NEXT NODE SHOULD BE GREATER ADDR > PUSHJ P,DIE HLRZ T2,TCBSON(T1) ;LEFT SUBTREE JUMPE T2,CTREE1 ;NONE IFN FTCHK,< MOVE T3,TCBBLK(T2) ;LEFT BN SHOULD BE LESS CAML T3,TCBBLK(T1) > IFN FTGCHK,< CAML T2,T1 ;LEFT SON SHOULD BE LOWER ADDR > PUSHJ P,DIE PUSH P,T1 ;SAVE ROOT PUSHJ P,CTREE ;CHECK LEFT SUBTREE POP P,T1 ;RESTORE ROOT CTREE1: PUSH P,T2 ;SAVE HEIGHT OF LEFT SUBTREE HRRZ T2,TCBSON(T1) ;RIGHT SUBTREE JUMPE T2,CTREE2 ;NONE IFN FTCHK,< MOVE T3,TCBBLK(T2) ;RIGHT BN SHOULD BE GREATER CAMG T3,TCBBLK(T1) > IFN FTGCHK,< CAMG T2,T1 ;RIGHT SON SHOULD BE HIGHER ADDR > PUSHJ P,DIE PUSH P,T1 ;SAVE ROOT PUSHJ P,CTREE ;CHECK RIGHT SUBTREE POP P,T1 ;RESTORE ROOT CTREE2: POP P,T3 ;RESTORE HEIGHT OF LEFT SUBTREE MOVEI T4,BALZ(T3) ;COMPUTE BALANCE FACTOR SUB T4,T2 CAIL T4,BALM ;IN RANGE? CAILE T4,BALP PUSHJ P,DIE LDB T1,TCXBAL ;MATCH EXPECTED? CAME T1,T4 PUSHJ P,DIE CAMGE T2,T3 ;HEIGHT OF THIS TREE IS GREATER OF MOVE T2,T3 ; HEIGHTS OF SUBTREES AOJA T2,CPOPJ ; PLUS ONE > SUBTTL BLOCK NUMBER ;ROUTINE TO TEST IF BN IS LEGAL ;T1 PASSES BN RELATIVE TO STR (DESTROYED) ;SKIP IF LEGAL LEGALP: IDIV T1,BPLU CAMLE T1,HUN POPJ P, HRRZ T1,TABUDB(T1) CAMG T2,UDBHLB(T1) AOS (P) POPJ P, ;ROUTINE TO CONVERT BN TO INTERNAL FORMAT CTINT: IDIV T1,BIGBPU IMUL T1,BPLU ADD T1,T2 POPJ P, ;ROUTINE TO CONVERT BN TO MONITOR FORMAT CTMON: IDIV T1,BPLU IMUL T1,BIGBPU ADD T1,T2 POPJ P, SUBTTL PRINTOUT ROUTINES ;ROUTINE TO PRINT A FILESPEC FILO: HLRZ T1,FILEXT(FL) ;A UFD? CAIN T1,'UFD' JRST FILO1 ;YES MOVE T2,FILNAM(FL) ;FILENAME PUSHJ P,SIXO JRST FILO2 FILO1: MOVEI T1,"[" PUSHJ P,CO PUSHJ P,PPNO ;PRINT PPN MOVEI T1,"]" PUSHJ P,CO FILO2: MOVEI T1,"." ;DOT PUSHJ P,CO HLLZ T2,FILEXT(FL) ;EXTENSION PUSHJ P,SIXO HRRZ T1,FILDAD(FL) ;QUIT IF MFD JUMPE T1,CPOPJ HRRZ T1,FILDAD(T1) ;OR UFD JUMPE T1,CPOPJ MOVEI T1,"[" ;BEGIN PATH PUSHJ P,CO PUSH P,FL HRRZ FL,FILDAD(FL) PUSHJ P,PTHO MOVEI T1,"]" ;END PATH PUSHJ P,CO FLPOPJ: POP P,FL POPJ P, ;ROUTINE TO PRINT THE PATH PTHO: PUSH P,FL ;SAVE CURRENT FILE HRRZ FL,FILDAD(FL) ;ADDR OF PARENT JUMPE FL,FLPOPJ ;QUIT IF NONE PUSHJ P,PTHO ;PRINT PARENT FIRST POP P,FL ;RESTORE SELF HLRZ T1,FILEXT(FL) ;SFD OR UFD? CAIN T1,'UFD' PJRST PPNO ;UFD MOVEI T1,"," ;SFD PUSHJ P,CO MOVE T2,FILNAM(FL) ;SFD NAME PJRST SIXO ;ROUTINE TO OUTPUT A PPN PPNO: HLRZ T1,FILNAM(FL) ;UFD, PRINT PROJECT PUSHJ P,OCTO MOVEI T1,"," PUSHJ P,CO HRRZ T1,FILNAM(FL) ;PRINT PROGRAMMER PJRST OCTO ;ROUTINE TO OUTPUT A BLOCK NUMBER (RELATIVE TO STR) BNO: PUSHJ P,CTMON ;CONVERT TO MONITOR FORMAT FALL OCTO ;ROUTINE TO OUTPUT AN OCTAL/DECIMAL NUMBER ;T1 PASSES THE NUMBER OCTO: SKIPA T3,[10] DECO: MOVEI T3,^D10 DECO1: IDIV T1,T3 HRLM T2,(P) SKIPE T1 PUSHJ P,DECO1 HLRZ T1,(P) ADDI T1,"0" JRST CO ;ROUTINE TO OUTPUT A CHAR ;T1 PASSES THE CHAR CO: CAIN T1,12 ;LINE FEED? SETZM HPOS ;YES, RESET POSITION AOS HPOS ;NO, COUNT HORIZONTAL POSITION TRNE F,F.TTC ;USE TTCALL? OUTCHR T1 ;YES TRNE F,F.SIL ;TTCALL ONLY? POPJ P, ;YES CO3: SOSGE OBUF+.BFCTR JRST CO2 IDPB T1,OBUF+.BFPTR POPJ P, CO2: PUSHJ P,BUFO JRST CO3 ;ROUTINE TO OUTPUT A BUFFER BUFO: OUT TO, POPJ P, PUSHJ P,DIE ;ROUTINE TO OUTPUT A SIXBIT NAME ;T2 PASSES THE NAME SIXO: LSHC T1,6 ANDI T1,77 ADDI T1,"A"-'A' PUSHJ P,CO JUMPN T2,SIXO POPJ P, ;ROUTINE TO OUTPUT A CRLF CRLFO: MOVEI T2,[BYTE (7)15,12] FALL STRO ;ROUTINE TO OUTPUT AN ASCIZ STRING ;T2 PASSES ADDR OF STRING STRO: HRLI T2,(POINT 7) STRO1: ILDB T1,T2 JUMPE T1,CPOPJ PUSHJ P,CO JRST STRO1 ;ROUTINE TO PRINT UNIT NAME UNITO: MOVE T2,UDBNAM(U) PUSHJ P,SIXO MOVEI T1,"(" PUSHJ P,CO MOVE T2,UDBLOG(U) PUSHJ P,SIXO MOVEI T1,")" PJRST CO ;ROUTINE TO TELL THE OPR WHICH STR WE ARE DOING BEGIN: PUSHJ P,ONTTC ;USE TTCALLS MOVEI T2,[ASCIZ /Beginning /] PUSHJ P,STRO MOVE T2,ALIAS PUSHJ P,SIXO PJRST DSPACE ;COROUTINE TO TURN ON TTCALLS ONTTC: TRNE F,F.TTY ;LOG DIRECTLY TO TTY? POPJ P, ;YES TRO F,F.TTC ;NO, DO THIS PART DIRECTLY POP P,T1 ;CALL THE CALLER PUSHJ P,@T1 TRZ F,F.TTC ;STOP TTCALLS POPJ P, ;COROUTINE TO ENTER TTCALL ONLY MODE ONSIL: SKIPN LOGSTR ;LOG FILE TO DISK? POPJ P, ;NO TRO F,F.TTC+F.SIL ;TTCALL ONLY POP P,T1 ;CALL THE CALLER PUSHJ P,@T1 TRZ F,F.TTC+F.SIL ;NORMAL OUTPUT POPJ P, SUBTTL ADD/REMOVE STR ;ROUTINE TO REMOVE A STR RSTR: PUSHJ P,RASL ;REMOVE FROM ASL JRST RSTR3 ;PUT OTHER UNITS BACK PUSHJ P,RSDL ;REMOVE FROM SDL JRST RSTR3 PUSHJ P,RSSL ;REMOVE FROM SSL JRST RSTR2 MOVEI T1,.FSREM ;FUNCTION CODE MOVEM T1,FOO+.FSFCN MOVE T1,ALIAS ;STR NAME MOVEM T1,FOO+.FSMNM MOVE T1,[XWD 2,FOO] ;REMOVE IT STRUUO T1, JRST RSTR0 JRST CPOPJ1 RSTR0: PUSHJ P,ASSL ;PUT BACK IN SSL JFCL RSTR2: PUSHJ P,ASDL ;PUT BACK IN SDL JFCL RSTR3: PUSHJ P,AASL ;PUT BACK IN ASL POPJ P, ;ROUTINE TO REMOVE STR FROM ASL (IF NECESSARY) RASL: MOVE T1,HUN ;HIGHEST UNIT NUMBER RASL2: HRRZ U,TABUDB(T1) ;ADDR OF UDB SKIPGE UDBASL(U) ;IN ASL? JRST RASL1 ;NO MOVEI T2,UDBNAM(U) ;REMOVE FROM ASL HRLI T2,.DUSWP DISK. T2, CAIA JRST RASL1 CAIE T2,DUOIP% ;MIGRATE ALREADY IN PROGRESS? POPJ P, PUSHJ P,SLPY ;SLEEP AWHILE JRST RASL2 ;TRY AGAIN RASL1: SOJGE T1,RASL2 ;LOOP FOR EACH UNIT JRST CPOPJ1 ;ROUTINE TO REMOVE STR FROM SDL (IF NECESSARY) RSDL: SKIPGE SDL ;IN SDL? JRST CPOPJ1 ;NO MOVE T1,[XWD .DURSD,ALIAS] ;YES, REMOVE IT DISK. T1, POPJ P, JRST CPOPJ1 ;ROUTINE TO REMOVE STR FROM SSL (IF NECESSARY) RSSL: SETZM FOO+.DFGJN ;SSL=JOB 0 SETOM FOO+.DFGNM ;1ST STR PLEASE SETZB T2,PSSL ;POSITION IN SSL MOVEI T3,SSL+.FSDSO ;ADDR TO STORE 1ST STR RSSL1: ADDI T2,1 ;BUMP POSITION MOVE T1,[XWD 5,FOO] ;GET NEXT STR GOBSTR T1, POPJ P, MOVE T1,FOO+.DFGNM CAME T1,ALIAS ;OUR STR? JRST RSSL2 ;NO MOVEM T2,PSSL ;YES, SAVE POSITION MOVE T1,FOO+.DFGST ;SAVE STATUS MOVEM T1,SSLSTS JRST RSSL1 ;LOOP RSSL2: JUMPE T1,RSSL3 ;GO IF END OF LIST MOVEM T1,.DFJNM(T3) ;COPY STR NAME MOVE T1,FOO+.DFGST ;AND STATUS MOVEM T1,.DFJST(T3) SETZM .DFJDR(T3) ADDI T3,3 ;BUMP ADDR JRST RSSL1 ;LOOP RSSL3: SKIPN PSSL ;IN SSL? JRST CPOPJ1 ;NO MOVEI T1,.FSDSL ;FUNCTION MOVEM T1,SSL+.FSFCN SETZM SSL+.FSDJN ;JOB 0 MOVEI T1,DF.SRM ;REMOVE MOVEM T1,SSL+.FSDFL MOVSI T1,-SSL(T3) ;DO IT HRRI T1,SSL STRUUO T1, POPJ P, JRST CPOPJ1 ;ROUTINE TO ADD A STR ASTR: MOVEI T1,.FSDEF ;FUNCTION MOVEM T1,DEFIN+.FSFCN MOVE T1,[XWD SZSDB,SDB] ;ADDR OF STR DATA BLOCK MOVEM T1,DEFIN+.FSNST MOVE T1,[XWD DEFINL,DEFIN] STRUUO T1, POPJ P, PUSHJ P,ASSL ;PUT BACK IN SSL JFCL PUSHJ P,ASDL ;PUT BACK IN SDL JFCL PUSHJ P,AASL ;PUT BACK IN ASL JRST CPOPJ1 ;ROUTINE TO ADD STR TO ASL AASL: MOVE T1,HUN ;HIGHEST UNIT NUMBER AASL1: HRRZ U,TABUDB(T1) ;ADDR OF UDB SKIPGE UDBASL(U) ;BELONGS IN ASL? JRST AASL2 ;NO MOVEI T2,UDBNAM(U) ;PUT UNIT IN ASL HRLI T2,.DUASW DISK. T2, JFCL AASL2: SOJGE T1,AASL1 ;LOOP FOR EACH UNIT POPJ P, ;ROUTINE TO ADD STR TO SDL ASDL: SKIPGE SDL ;BELONGS IN SDL? JRST CPOPJ1 ;NO MOVE T1,[XWD .DUASD,ALIAS] ;YES, PUT IT BACK DISK. T1, POPJ P, JRST CPOPJ1 ;ROUTINE TO ADD STR TO SSL ASSL: SKIPN PSSL ;BELONGS IN SSL? JRST CPOPJ1 ;NO SETZM FOO+.DFGJN ;SSL=JOB 0 SETOM FOO+.DFGNM ;1ST STR PLEASE SETZ T2, ;POSITION IN SSL MOVEI T3,SSL+.FSDSO ;ADDR TO STORE 1ST STR ASSL1: ADDI T2,1 ;BUMP POSITION CAME T2,PSSL ;NOW? JRST ASSL4 ;NO, NOT YET MOVE T1,ALIAS ;YES, COPY STR NAME MOVEM T1,.DFJNM(T3) MOVE T1,SSLSTS ;COPY STATUS MOVEM T1,.DFJST(T3) SETZM .DFJDR(T3) ADDI T3,3 ;BUMP ADDR ASSL4: MOVE T1,[XWD 5,FOO] ;GET NEXT STR GOBSTR T1, POPJ P, SKIPN T1,FOO+.DFGNM JRST ASSL3 ;GO IF END OF LIST MOVEM T1,.DFJNM(T3) ;COPY STR NAME MOVE T1,FOO+.DFGST ;AND STATUS MOVEM T1,.DFJST(T3) SETZM T1,.DFJDR(T3) ADDI T3,3 ;BUMP ADDR JRST ASSL1 ;LOOP ASSL3: MOVEI T1,.FSDSL ;FUNCTION MOVEM T1,SSL+.FSFCN SETZM SSL+.FSDJN ;JOB 0 MOVEI T1,DF.SRM ;REMOVE MOVEM T1,SSL+.FSDFL MOVSI T1,-SSL(T3) ;DO IT HRRI T1,SSL STRUUO T1, POPJ P, JRST CPOPJ1 SUBTTL LOG FILE ;ROUTINE TO OPEN THE DEVICE FOR THE LOG FILE OPENLG: MOVSI T1,'LPT' ;DEVICE NAME MOVE T2,T1 DEVTYP T1, ;IS IT SPOOLED? SETZ T1, TLNE T1,(TY.SPL) JRST OPNLG5 ;YES MOVE T1,T2 ;IS IT ASSIGNED? DEVCHR T1, TRNE T1,DV.ASC TLNN T1,(DV.AVL) OPNLG5: MOVSI T2,'TTY' ;NO, USE TTY MOVEM T2,LDEV+.OPDEV ;OPEN IT MOVEI T2,.IOASC MOVEM T2,LDEV+.OPMOD MOVSI T2,OBUF MOVEM T2,LDEV+.OPBUF OPEN TO,LDEV PUSHJ P,DIE OUTBUF TO, ;BUILD BUFFERS NOW MOVE T2,OBUF+.BFADR ;SAVE ADDR OF 1ST BUF MOVEM T2,SAVBUF MOVEI T2,LPTWID-RMAR ;SET MARGIN MOVEM T2,MARGIN MOVEI T1,TO ;GET DEVICE TYPE (TTY MIGHT BE LOGICAL) DEVCHR T1, TLNE T1,(DV.DSK) ;DISK? JRST OPNLG1 ;YES SETZM LOGSTR ;NO TLNN T1,(DV.TTY) ;TTY? POPJ P, ;NO TRO F,F.TTY ;YES MOVEI T1,TO ;GET UDX IONDX. T1, PUSHJ P,DIE MOVEM T1,FOO+.TOUDX MOVEI T1,.TOWID ;FUNCTION MOVEM T1,FOO+.TOFNC MOVE T1,[XWD 2,FOO] ;READ WIDTH OF TTY TRMOP. T1, MOVEI T1,LPTWID SUBI T1,RMAR ;BACK OFF MOVEM T1,MARGIN ;SET MARGIN POPJ P, ;HERE IF DISK OPNLG1: PUSHJ P,GETLOK ;GET INTERLOCK MOVE T1,LDEV+.OPDEV ;WHAT STR IS LOG? MOVEM T1,FOO+.DCNAM MOVE T1,[XWD FOOSIZ,FOO] DSKCHR T1, JRST OPNLG2 MOVE T1,FOO+.DCSNM JRST OPNLG4 ;HERE IF DSKCHR FAILED (STR WAS PROBABLY YANKED) OPNLG2: MOVE T1,LDEV+.OPDEV ;UN-DO LOGICAL NAME DEVNAM T1, SETO T1, PUSHJ P,INPROG ;IS IT IN PROGRESS? JRST OPNLG4 ;YES MOVE T1,SLST ;NO, I GUESS IT DOESN'T MATTER MOVE T1,SNFNAM(T1) OPNLG4: MOVEM T1,LOGSTR ;YES, THAT'S IT THEN PUSHJ P,GIVLOK ;GIVE UP INTERLOCK MOVE T1,LDEV+.OPDEV ;GET PATH MOVEM T1,PTH+.PTFCN MOVE T1,[XWD PTHL,PTH] PATH. T1, CAIA POPJ P, HRRE T1,.PTFRD ;GET DEFAULT PATH MOVEM T1,PTH+.PTFCN MOVE T1,[XWD PTHL,PTH] PATH. T1, PUSHJ P,DIE POPJ P, ;ROUTINE TO COPY TEMP LOGS BACK TO THE STR WHERE THEY BELONG ;CALL WITH INTERLOCK ;EXIT CPOPJ IF STILL MORE TO GO ;EXIT CPOPJ1 IF ALL DONE CPYLG: PUSHJ P,SAVE1 CPYLG0: SKIPN P1,LOGS ;ANY TO COPY? JRST CPOPJ1 ;NO MOVE T1,LOGSTR ;NAME OF LOG STR MOVEM T1,LDEV+.OPDEV TRNE F,F.ALL ;DOING ALL? JRST CPYLG6 ;YES, MUST WAIT FOR STR TO FINISH MOVE T2,CNTSLT ;WE AREN'T, BUT ARE WE THE ONLY ONE? CAIN T2,1 JRST CPYLG5 ;ONLY ONE, IT'LL NEVER FINISH CPYLG6: MOVEI T2,ALST-SNFLNK ;IS LOG STR DONE? CPYLG3: HRRZ T2,SNFLNK(T2) JUMPE T2,CPOPJ CAME T1,SNFNAM(T2) JRST CPYLG3 CPYLG5: MOVE T1,LOGDEV(P1) ;IS TMP STR AVAILABLE? MOVEM T1,TDEV+.OPDEV PUSHJ P,INPROG POPJ P, ;NO MOVE T2,MYSLT ;YES, LOCK IT DOWN MOVEM T1,JBTLOG(T2) PUSHJ P,GIVLOK ;GIVE AWAY INTERLOCK MOVEI T1,.IOBIN MOVEM T1,LDEV+.OPMOD MOVEM T1,TDEV+.OPMOD MOVSI T1,OBUF MOVEM T1,LDEV+.OPBUF MOVEI T1,.RBEXT MOVEM T1,LFIL+.RBCNT MOVEM T1,TFIL+.RBCNT MOVEI T1,PTH MOVEM T1,LFIL+.RBPPN MOVE T1,LOGNAM(P1) MOVEM T1,LFIL+.RBNAM MOVEM T1,TFIL+.RBNAM MOVSI T1,'LST' MOVEM T1,LFIL+.RBEXT MOVEI T1,IBUF MOVEM T1,TDEV+.OPBUF MOVE T1,FFAPPN MOVEM T1,TFIL+.RBPPN MOVSI T1,'TMP' MOVEM T1,TFIL+.RBEXT OPEN TL,TDEV ;OPEN TEMP ON ANOTHER CH JRST CPYLG4 LOOKUP TL,TFIL JRST CPYLG4 OPEN TO,LDEV ;RE-OPEN LOG FILE JRST CPYLG4 ENTER TO,LFIL JRST CPYLG4 MOVE T1,SAVBUF ;USE SAME BUFFERS MOVEM T1,OBUF+.BFADR MOVEI T2,TDEV ;COMPUTE SIZE OF BUFFERS DEVSIZ T2, PUSHJ P,DIE HLRZ T1,T2 IMULI T1,(T2) PUSHJ P,GETBLK ;ALLOCATE SPACE PUSH P,T1 ;SAVE SIZE PUSH P,T2 ;SAVE ADDR EXCH T2,.JBFF ;ALLOCATE BUFFERS INBUF TL, MOVEM T2,.JBFF CPYLG1: PUSHJ P,CI ;INPUT A CHAR FROM TEMP FILE JRST CPYLG2 ;EOF PUSHJ P,CO ;COPY TO LOG FILE JRST CPYLG1 CPYLG2: CLOSE TO, ;CLOSE THE LOG FILE STATZ TO,IO.ERR PUSHJ P,DIE SETZM FOO ;DELETE TEMP LOG RENAME TL,FOO JFCL RELEAS TL, POP P,T2 ;RESTORE ADDR POP P,T1 ;RESTORE SIZE PUSHJ P,GIVBLK ;GIVE BACK SPACE CPYLG4: PUSHJ P,GETLOK ;GET INTERLOCK MOVE T1,MYSLT ;FREE TMP STR SETZM JBTLOG(T1) MOVE T1,LOGNXT(P1) ;UNLINK LOG MOVEM T1,LOGS MOVEI T1,SIZLOG ;RETURN LOG MOVE T2,P1 PUSHJ P,GIVBLK JRST CPYLG0 ;DO ANOTHER LOG ;ROUTINE TO INPUT A CHAR FROM THE TEMP LOG ;T1 RETURNS THE CHAR CI: SOSGE IBUF+.BFCTR JRST CI2 ILDB T1,IBUF+.BFPTR JRST CPOPJ1 CI2: IN TL, JRST CI STATZ TL,IO.ERR PUSHJ P,DIE POPJ P, ;ROUTINE TO TEST IF STR IS IN PROGRESS ;T1 PASSES STR NAME ;NOSKIP IF IN PROGRESS ;SKIP IF NOT IN PROGRESS INPROG: PUSHJ P,SAVE1 MOVEI P1,NSLT-1 INPRG1: CAMN T1,JBTSTR(P1) POPJ P, SOJGE P1,INPRG1 JRST CPOPJ1 ;ROUTINE TO PICK A STR FOR THE LOG FILE (AND OPEN IT) ;YOU MUST HAVE THE INTERLOCK TO CALL THIS ROUTINE PIKLOG: PUSHJ P,SAVE1 PKLOGA: SKIPN T1,LOGSTR ;LOG ON DISK? POPJ P, ;NO MOVEI T2,.IOASC MOVEM T2,LDEV+.OPMOD MOVSI T2,OBUF MOVEM T2,LDEV+.OPBUF MOVEI T2,.RBEXT MOVEM T2,LFIL+.RBCNT MOVE T2,ALIAS MOVEM T2,LFIL+.RBNAM CAMN T1,ALIAS ;DOING LOG STR? JRST PKLOG2 ;YES, MUST USE TMP STR MOVE T3,ALIAS ;PROCESS STR AND LOG STR THE ONLY ONES? MOVEI T2,SLST-SNFNXT PKLOGC: HRRZ T2,SNFNXT(T2) JUMPE T2,PKLOGD ;YES, MUST GO ON ACTUAL STR CAME T3,SNFNAM(T2) CAMN T1,SNFNAM(T2) JRST PKLOGC TRNN F,F.ALL ;NO, DOING ALL? JRST PKLOGD ;NOT ALL, DON'T CARE IF DONE MOVEI T2,ALST-SNFLNK ;LOG STR PROCESSED YET? PKLOG1: HRRZ T2,SNFLNK(T2) JUMPE T2,PKLOG2 ;NO CAME T1,SNFNAM(T2) JRST PKLOG1 JRST PKLOG3 ;HERE TO PUT ON ACTUAL STR IF NOT IN PROGRESS PKLOGD: PUSHJ P,INPROG ;LOG STR IN PROGRESS? JRST PKLOG2 ;YES, PUT ON TMP STR (IF ONE EXISTS) ;HERE TO PUT LOG ON ACTUAL STR PKLOG3: MOVEM T1,LDEV+.OPDEV OPEN TO,LDEV JRST PKLOG2 MOVE T1,SAVBUF ;USE SAME BUFFERS MOVEM T1,OBUF+.BFADR MOVEI T1,PTH MOVEM T1,LFIL+.RBPPN MOVSI T1,'LST' MOVEM T1,LFIL+.RBEXT ENTER TO,LFIL JRST PKLOG2 JRST PKLOGB ;HERE TO PUT LOG FILE ON TMP STR ;TRY ALL STRS COMPLETED PKLOG2: MOVEI P1,ALST-SNFLNK PKLOG5: HRRZ P1,SNFLNK(P1) JUMPE P1,PKLOG4 MOVE T1,SNFNAM(P1) PUSHJ P,TRYLG JRST PKLOG9 ;WIN JRST PKLOG5 ;TRY WHAT WORKED FOR SOMEBODY ELSE PKLOG4: MOVEI P1,NSLT-1 PKLOG6: SKIPN T1,JBTLOG(P1) JRST PKLOG7 PUSHJ P,TRYLG JRST PKLOG9 PKLOG7: SOJGE P1,PKLOG6 ;TRY ANYTHING AT ALL MOVEI P1,BLST-SNFLNK PKLOG8: HRRZ P1,SNFLNK(P1) JUMPE P1,PKLOG0 MOVE T1,SNFNAM(P1) PUSHJ P,TRYLG JRST PKLOG9 JRST PKLOG8 ;HERE IF NO PLACE AT ALL TO PUT LOG ;WAIT FOR SOMETHING TO FINISH PKLOG0: PUSHJ P,SLEEPY ;SLEEP AWHILE JRST PKLOGA ;TRY AGAIN ;HERE WHEN WE SUCCESSFULLY CREATED A TMP LOG PKLOG9: MOVEI T1,SIZLOG ;ALLOCATE A LOG BLOCK PUSHJ P,GETBLK MOVE T1,ALIAS ;FILE NAME MOVEM T1,LOGNAM(T2) MOVE T1,LDEV+.OPDEV ;DEVICE MOVEM T1,LOGDEV(T2) MOVE T1,LOGS ;LINK IT MOVEM T1,LOGNXT(T2) MOVEM T2,LOGS PKLOGB: MOVE T1,MYSLT ;TELL THE WORLD MOVE T2,LDEV+.OPDEV MOVEM T2,JBTLOG(T1) POPJ P, ;ROUTINE TO ATTEMPT THE CREATION OF A TMP LOG ;T1 PASSES STR TO TRY FOR ;CPOPJ IF SUCCEED ;CPOPJ1 IF FAIL TRYLG: CAMN T1,LOGSTR ;PUTING TMP FILE ON ACTUAL STR? JRST CPOPJ1 ;YES, THAT'S SILLY MOVEM T1,LDEV+.OPDEV ;SAVE DEVICE NAME OPEN TO,LDEV JRST CPOPJ1 MOVE T3,SAVBUF ;USE SAME BUFFERS MOVEM T3,OBUF+.BFADR MOVE T3,FFAPPN ;ENTER TEMP FILE MOVEM T3,LFIL+.RBPPN MOVSI T3,'TMP' MOVEM T3,LFIL+.RBEXT ENTER TO,LFIL JRST CPOPJ1 POPJ P, ;ROUTINE TO SLEEP SLEEPY: PUSHJ P,GIVLOK ;GIVE UP INTERLOCK PUSHJ P,SLPY ;SLEEP AWHILE PJRST GETLOK ;GET INTERLOCK BACK ;SLEEP SLPY: MOVEI T1,NSEC ;SLEEP AWHILE SLEEP T1, POPJ P, SUBTTL BAT BLOCK ;ROUTINE TO PROCESS BAT BLOCK FOR A GIVEN UNIT DOBT: PUSHJ P,SAVE4 ;SAVE ACS PUSHJ P,RDBT ;READ BAT BLOCK JRST DOBT9 ;ERROR LDB P1,BAYNBR ;NUMBER OF BAD REGIONS ADD P1,BAFCNT(B) JUMPE P1,CPOPJ HRRZ P2,BAFFIR(B) ;OFFSET OF 1ST ENTRY ADD P2,B ;ADDR OF 1ST ENTRY DOBT2: LDB P3,BAYNBB ;NUMBER OF BAD BLOCKS ADDI P3,1 MOVE P4,BAFELB(P2) ;WORD CONTAINING BN MOVE T1,BAFNBB(P2) ;WORD CONTAINING BAPNTP TRNE T1,BAPNTP ;NEW ENTRY OR OLD? TLZA P4,BATMSK ;NEW TLZ P4,-1 ;OLD DOBT3: CAMLE P4,UDBHLB(U) ;LEGAL BN? JRST DOBT4 ;NO MOVE T1,UDBBLK(U) ;CONVERT TO BN RELATIVE TO STR ADD T1,P4 PUSH P,T1 PUSHJ P,SATBIT ;FIND SAT BIT POP P,T1 TDNE T2,(T3) ;ALREADY LIT? (I.E. IN BADBLK?) JRST DOBT5 ;YES, IGNORE IORM T2,(T3) ;NO, LIGHT IT NOW IDIV T1,BPC ;CONVERT BN TO CLUSTER MOVEI T2,BADCST ;ADD CLUSTER TO BAD LIST PUSHJ P,ADDLST DOBT5: ADDI P4,1 ;NEXT BN SOJG P3,DOBT3 ;LOOP FOR EACH BLOCK IN REGION DOBT4: ADDI P2,2 ;ADDR OF NEXT ENTRY SOJG P1,DOBT2 ;LOOP FOR EACH ENTRY POPJ P, ;HERE IF BAT BLOCK IS BAD DOBT9: MOVEI T2,[ASCIZ /Error while reading BAT blocks on /] PUSHJ P,STRO PUSHJ P,UNITO PJRST DSPACE ;ROUTINE TO COMPUTE THE AMOUNT OF OVERLAP BETWEEN THE BAD LIST ;AND THE FREE LIST ;T1 RETURNS THE NUMBER OF CLUSTERS OF OVERLAP BADOVR: SETZ T1, ;NONE SO FAR SKIPE FRECST+CSTCNT ;QUIT EARLY IF NONE AT ALL SKIPN BADCST+CSTCNT POPJ P, PUSHJ P,SAVE2 MOVEI P1,FRECST+CSTREG-REGNXT ;PRESET PRED MOVEI P2,BADCST+CSTREG-REGNXT HRRZ P1,REGNXT(P1) ;NEXT FREE REGION JUMPE P1,CPOPJ BDOVR1: HRRZ P2,REGNXT(P2) ;NEXT BAD REGION JUMPE P2,CPOPJ BDOVR2: MOVE T2,REGLOW(P1) ;DO THEY OVERLAP? CAMLE T2,REGHI(P2) JRST BDOVR1 ;NO, GET NEXT BAD REGION MOVE T3,REGHI(P1) CAML T3,REGLOW(P2) JRST BDOVR3 ;YES BDOVR4: HRRZ P1,REGNXT(P1) ;NO, GET NEXT FREE REGION JUMPN P1,BDOVR2 POPJ P, ;HERE WHEN THERE IS DEFINITELY SOME OVERLAP BDOVR3: CAMGE T2,REGLOW(P2) ;GET HIGHEST OF THE LOWS MOVE T2,REGLOW(P2) CAMLE T3,REGHI(P2) ;GET LOWEST OF THE HIGHS MOVE T3,REGHI(P2) SUBM T3,T2 ;BUMP COUNT ADDI T1,1(T2) CAMN T3,REGHI(P1) ;WHICH REGION ENDS FIRST? JRST BDOVR4 ;FREE JRST BDOVR1 ;BAD SUBTTL SAT BLOCKS ;ROUTINE TO ALLOCATE SPACE FOR SAT BLOCKS BLDSAT: PUSHJ P,SAVE3 ;SAVE ACS MOVE T1,UDBSPU(U) ;BUILD SPT PUSHJ P,GETZER HRL T2,UDBSPU(U) MOVEM T2,UDBSPT(U) SETOM UDBSSF(U) ;NO ENTRIES IN SPT YET MOVE T1,UDBSPU(U) ;BUILD PST PUSHJ P,GETBLK MOVEM T2,UDBPST(U) MOVE P1,UDBSPU(U) ;HIGHEST SAT NUMBER SUBI P1,1 MOVE T1,UDBBPU(U) ;NUMBER OF FULL CLUSTERS IDIV T1,BPC MOVE T2,P1 ;TOTAL BITS IN ALL BUT LAST SAT IMUL T2,UDBCPS(U) SUB T1,T2 ;NUMBER OF CLUSTERS IN LAST SAT SKIPA P2,T1 BLDST1: MOVE P2,UDBCPS(U) ;CLUSTERS PER SAT MOVE T1,UDBWPS(U) ;ALLOCATE SPACE FOR SAT PUSHJ P,GETZER MOVE P3,T2 ;PUT PNTR IN SAFE PLACE MOVE T1,P1 ;STORE IT ADD T1,UDBPST(U) MOVEM P3,(T1) MOVE T1,P2 ;CLUSTERS THIS SAT IDIVI T1,^D36 ;WORDS MOVEI T3,^D36 ;UNUSED BITS SUBM T3,T2 SETZ T3, ;BUILD MASK SETO T4, LSHC T3,(T2) HRLI P3,T1 ;INDEX REGISTER CAMGE T1,UDBWPS(U) ;IS LAST WORD COMPLETELY FULL? IORM T3,@P3 ;NO, MARK UNUSED BITS BLDST2: ADDI T1,1 ;POINT AT NEXT WORD CAML T1,UDBWPS(U) ;DONE? JRST BLDST3 ;YES SETOM @P3 ;NO, MARK ALL BITS JRST BLDST2 ;LOOP BLDST3: SOJGE P1,BLDST1 ;DO NEXT SAT POPJ P, ;ROUTINE TO STORE CA IN SPT SAVSAT: TRON F,F.RIB ;STEPPED OVER RIB YET? POPJ P, ;NO, STEP NOW AOS T2,UDBSSF(U) ;GOT THEM ALL? CAML T2,UDBSPU(U) POPJ P, ;YES ADD T2,UDBSPT(U) ;NEXT ADDR IN SPT MOVE T1,DRCA ;STORE CA DPB T1,SPYCLA POPJ P, ;ROUTINE TO READ THE SAT BLOCKS AND SEE IF THEY ARE RIGHT ;IN THIS ROUTINE: ;P1=ADDR WITHIN SAT BLOCK (AS READ FROM DISK) ;P2=SAT NUMBER ;P3=WORD NUMBER ;P4=ADDR WITHIN SAT BLOCK (AS COMPUTED) ;NOSKIP IF CAN'T FIND SATS DOSAT: PUSHJ P,SAVE4 ;SAVE ACS MOVE T1,HUN ;FOUND ALL SATS? DOSAT7: HRRZ U,TABUDB(T1) MOVE T2,UDBSSF(U) ADDI T2,1 CAMGE T2,UDBSPU(U) JRST DOSAT8 ;NO SOJGE T1,DOSAT7 SETZM STAL ;NUMBER FREE BLOCKS (STR WIDE) MOVE T1,HUN ;HIGHEST UNIT NUMBER DOSAT1: HRRZ U,TABUDB(T1) ;UNIT DATA BLOCK SKIPN UDBAWL(U) ;WRITE LOCKED? SKIPE UDBHWP(U) PUSHJ P,DOSTWL ;YES MOVE T1,UDBBPU(U) ;COMPUTE SAFETY FACTOR MOVE T2,UDBK4S(U) LSH T2,3 SUB T1,T2 IDIVI T1,UNVRSF CAILE T1,MAXSAF MOVEI T1,MAXSAF MOVNS T1 MOVEM T1,UDBTAL(U) ADDM T1,STAL ;BUMP STR WIDE COUNTER PUSHJ P,DOBT ;DO BAT BLOCKS MOVE P2,UDBSPU(U) ;HIGHEST SAT NUMBER SUBI P2,1 DOSAT2: MOVE T3,P2 ;ADDR OF SAT ADD T3,UDBPST(U) MOVE P4,(T3) TRZ F,F.SHC ;SAT IS OK SO FAR MOVE T2,P2 ;READ THE SAT BLOCK ADD T2,UDBSPT(U) SETZ T3, DPB T3,SPYTAL LDB T3,SPYCLA IMUL T3,BPC PUSHJ P,REDBLK PUSHJ P,DOSTRE ;ERROR SETZ P3, ;START WITH WORD 0 MOVE P1,B DOSAT4: MOVE T1,(P1) ;PICK UP A SAT WORD CAMN T1,(P4) ;RIGHT? JRST DOSAT5 ;YES TRO F,F.SHC ;MUST REWRITE SAT TDZ T1,(P4) ;DO LOST CLUSTERS MOVEI T2,LSTCST PUSHJ P,DOCST MOVE T1,(P4) ;DO FREE CLUSTERS TDZ T1,(P1) MOVEI T2,FRECST PUSHJ P,DOCST MOVE T2,(P4) ;GET FREE CLUSTERS BACK TDZ T2,(P1) SKIPA T1,(P4) ;FIX THE SAT WORD DOSAT5: TDZA T2,T2 MOVEM T1,(P1) MOVEM T2,(P4) ;SET SAT TO FREE CLUSTERS MOVE T2,(P1) ;COUNT FREE CLUSTERS PUSHJ P,CNTSAT MOVE T2,P2 ;BUMP COUNT IN SPT ADD T2,UDBSPT(U) LDB T3,SPYTAL ADD T3,T4 DPB T3,SPYTAL IMUL T4,BPC ;CONVERT CLUSTERS TO BLOCKS ADDM T4,UDBTAL(U) ;BUMP UNIT COUNT ADDM T4,STAL ;BUMP STR COUNT ADDI P3,1 ;LOOP FOR EACH WORD ADDI P1,1 CAME P3,UDBWPS(U) AOJA P4,DOSAT4 ;JFCL THIS LOCATION TO PREVENT SAT BLOCKS FROM BEING WRITTEN SATPAT: TRNN F,F.SHC ;REWRITE SAT? JRST DOSAT6 ;NO SKIPN UDBAWL(U) ;WRITE PROTECT? SKIPE UDBHWP(U) JRST DOSAT6 ;YES, DON'T TRY TO WRITE MOVE T2,P2 ;COMPUTE BN OF SAT ADD T2,UDBSPT(U) LDB T3,SPYCLA IMUL T3,BPC PUSHJ P,WRTBLK ;WRITE THE SAT PUSHJ P,DOSTWE ;ERROR DOSAT6: SOJGE P2,DOSAT2 ;LOOP FOR EACH SAT MOVE T1,UDBLUN(U) ;LOOP FOR EACH UNIT SOJGE T1,DOSAT1 JRST CPOPJ1 ;HERE IF CAN'T FIND ALL THE SATS DOSAT8: MOVEI T2,[ASCIZ /Can't find SAT.SYS SATs will not be processed STR will not be mounted/] PJRST STRDSP ;HERE IF ERROR WHILE READING SAT BLOCK ;B PASSES ADDR SAT WOULD HAVE BEEN READ INTO ;P4 PASSES ADDR OF SAT (AS COMPUTED) ;P2 PASSES SAT NUMBER DOSTRE: HRLZ T1,P4 ;COPY SAT BLOCK HRR T1,B MOVE T2,B ADD T2,UDBWPS(U) BLT T1,-1(T2) TRO F,F.SHC ;WRITE SAT MOVEI T2,[ASCIZ /read/] JRST DOSTER ;HERE IF ERROR WHILE WRITTING SAT BLOCK ;P2 PASSES SAT NUMBER DOSTWE: MOVEI T2,[ASCIZ /writt/] DOSTER: PUSH P,T2 ;SAVE READ/WRITE MOVEI T2,[ASCIZ /Error while /] PUSHJ P,STRO POP P,T2 PUSHJ P,STRO MOVEI T2,[ASCIZ /ing SAT block /] PUSHJ P,STRO MOVE T1,P2 PUSHJ P,OCTO MOVEI T2,[ASCIZ / on unit /] PUSHJ P,STRO PUSHJ P,UNITO PJRST DSPACE ;HERE IF UNIT IS WRITE LOCKED DOSTWL: PUSHJ P,UNITO MOVEI T2,[ASCIZ / is write locked and SATs will not be corrected/] PUSHJ P,STRO PJRST DSPACE ;ROUTINE TO COUNT THE NUMBER OF ZERO BITS IN A SAT WORD ;T2 PASSES THE CORRECTED VERSION OF THE SAT WORD ;T4 RETURNS THE COUNT CNTSAT: SETZ T4, ;COUNTER CNTST2: SETCMM T2 ;COMPLIMENT JFFO T2,CNTST3 ;COUNT LEADING "ONES" POPJ P, ;NO MORE CNTST3: SETZ T1, ;PURGE LEADING "ONES" ROTC T1,(T3) SETCMM T2 ;RETURN TO NORMAL SPACE TIME JFFO T2,CNTST4 ;COUNT ZEROES MOVEI T4,^D36 ;ALL ZEROES POPJ P, CNTST4: ADD T4,T3 ;ADD TO TOTAL SETO T1, ;PURGE ZEROES ROTC T1,(T3) JRST CNTST2 ;LOOP ;LIGHT A SAT BIT MRKIT: MOVE T1,TCBBLK(TC) ;BN OF RIB FALL MARKIT ;ROUTINE TO LIGHT A SAT BIT ;T1 PASSES BN MARKIT: PUSH P,T1 ;SAVE BN PUSHJ P,SATBIT ;FIND THE RIGHT BIT POP P,T1 ;RESTORE BN TRNE F,F.P2 ;PASS TWO? JRST MARKI2 ;YES TDNE T2,(T3) ;ALREADY ON? JRST ADDMUL ;YES IORM T2,(T3) ;NO, LIGHT IT NOW POPJ P, ;HERE IF PASS TWO MARKI2: TDNN T2,(T3) ;TARGET BN? POPJ P, ;NO IDIV T1,BPC ;CONVERT BN TO CLUSTER MOVEI T2,MULCST ;IS IT FREE OR MULTIPLE? PUSHJ P,FNDREG SKIPA T2,[F2CST] ;FREE MOVEI T2,M2CST ;MULTIPLY USED PJRST ADDLST ;ADD IT TO CLUSTER LIST ;ROUTINE TO FIND THE SAT BIT CORRESPONDING TO A GIVEN BN ;T1 PASSES BN (DESTROYED) ;T2 RETURNS BIT MASK ;T3 RETURNS WORD ADDR SATBIT: IDIV T1,BPLU ;UNIT AND OFFSET HRRZ T1,TABUDB(T1) ;UNIT DATA BLOCK IDIV T2,BPC ;CLUSTER IDIV T2,UDBCPS(T1) ;SAT AND OFFSET ADD T2,UDBPST(T1) ;ADDR OF PST ENTRY IDIVI T3,^D36 ;WORD AND BIT ADD T3,(T2) ;WORD ADDR MOVSI T2,(1B0) ;BUILD MASK MOVNS T4 LSH T2,(T4) POPJ P, ;SUBROUTINE TO FIND A REGION ;T1 PASSES CLUSTER NUMBER ;T2 PASSES CST ;T3 RETURNS REG ;SKIP IF FOUND FNDREG: MOVEI T3,CSTREG-REGNXT(T2) ;PRESET PRED FNDRG1: HRRZ T3,REGNXT(T3) ;STEP TO NEXT REGION JUMPE T3,CPOPJ ;QUIT IF NO MORE REGIONS CAMGE T1,REGLOW(T3) ;WITHIN REGION? POPJ P, CAMLE T1,REGHI(T3) JRST FNDRG1 ;NO, KEEP SEARCHING JRST CPOPJ1 ;YES, WIN ;SUBROUTINE TO MARK A CLUSTER LIST ;T2 PASSES CST MARKC: PUSHJ P,SAVE2 ;SAVE AC MOVEI P1,CSTREG-REGNXT(T2) ;PRESET PRED MARKC1: HRRZ P1,REGNXT(P1) ;STEP TO NEXT REGION JUMPE P1,CPOPJ ;QUIT IF NO MORE REGIONS MOVE P2,REGLOW(P1) ;1ST CLUSTER MARKC2: MOVE T1,P2 ;CONVERT CLUSTER TO BN IMUL T1,BPC PUSHJ P,SATBIT ;FIND CORRESPONDING BIT IORM T2,(T3) ;LIGHT BIT CAME P2,REGHI(P1) ;END OF REGION? AOJA P2,MARKC2 ;NO, NEXT CLUSTER JRST MARKC1 ;YES, NEXT REGION SUBTTL CLUSTER LIST ;ROUTINE TO ADD A BIT MASK TO THE CLUSTER LIST ;T1 PASSES THE BIT MASK ;T2 PASSES ADDR OF CST ;U PASSES UDB ;P2 PASSES SAT NUMBER ;P3 PASSES WORD NUMBER DOCST: JUMPE T1,CPOPJ ;NONE IS EASY PUSHJ P,SAVE4 ;SAVE ACS MOVE T3,UDBBLK(U) ;1ST CLUSTER ON UNIT IDIV T3,BPC MOVE P1,T3 IMUL P2,UDBCPS(U) ;1ST CLUSTER IN SAT ADD P1,P2 IMULI P3,^D36 ;1ST CLUSTER IN WORD ADD P1,P3 MOVE P2,T1 ;SAVE THE BITS MOVE P4,T2 ;ADDR OF CST DOCST1: JFFO P2,DOCST2 ;FIND FIRST ONE POPJ P, ;NO MORE ONES, ALL DONE DOCST2: ADD P1,P3 ;CLUSTER IN QUESTION MOVE T1,P1 ;ADD IT TO THE LIST MOVE T2,P4 PUSHJ P,ADDLST LSH P2,1(P3) ;SHIFT OUT THE ONE AOJA P1,DOCST1 ;AND LOOP ;ROUTINE TO ADD A MULTIPLY USED CLUSTER TO THE LIST ;T1 PASSES BN ADDMUL: IDIV T1,BPC ;CONVERT TO CLUSTER MOVEI T2,MULCST ;ADD IT FALL ADDLST ;ROUTINE TO ADD A CLUSTER TO THE LIST ;T1 PASSES CLUSTER NUMBER ;T2 PASSES ADDR OF CST (DESTROYED) ADDLST: PUSHJ P,SAVE4 ;SAVE ACS DMOVE P1,T1 ;COPY ARGS MOVEI P3,CSTREG-REGNXT(P2) ;PRESET PRED ADDLS1: MOVE P4,P3 ;SAVE AS PRED HRRZ P3,REGNXT(P4) ;STEP TO NEXT REGION JUMPE P3,ADDLS3 ;END OF LIST MOVE T1,REGLOW(P3) ;CLUSTER JUST BEFORE REGION SUBI T1,1 CAMGE P1,T1 ;FAR ENOUGH? JRST ADDLS3 ;NO, BUILD NEW REGION CAME P1,T1 ;JUST BEFORE? JRST ADDLS2 ;NO, CHECK IF INTERIOR MOVEM P1,REGLOW(P3) ;NEW LOWEST JRST ADDLS4 ADDLS2: MOVE T1,REGHI(P3) ;CLUSTER JUST PAST REGION ADDI T1,1 CAMLE P1,T1 ;BEYOND END? JRST ADDLS1 ;YES, TEST NEXT REGION CAME P1,T1 ;JUST PAST? POPJ P, ;NO, DUPLICATE CLUSTER MOVEM P1,REGHI(P3) ;NEW HIGHEST AOS CSTNUM(P2) ;ANOTHER CLUSTER HRRZ T2,REGNXT(P3) ;NEXT REGION BEYOND JUMPE T2,CPOPJ ADDI T1,1 ;NEXT CLUSTER BEYOND CAME T1,REGLOW(T2) ;ADJACENT? POPJ P, ;NO MOVE T3,REGHI(T2) ;YES, MERGE THE TWO REGIONS MOVEM T3,REGHI(P3) SOS CSTCNT(P2) ;ONE LESS REGION HRRZ T3,REGNXT(T2) ;UNLINK 2ND REGION HRRM T3,REGNXT(P3) MOVEI T1,SIZREG ;PITCH IT PJRST GIVBLK ;HERE TO BUILD A NEW REGION ADDLS3: MOVEI T1,SIZREG ;ALLOCATE CORE PUSHJ P,GETBLK MOVEM P1,REGLOW(T2) ;STORE BOUNDS MOVEM P1,REGHI(T2) MOVEM P3,REGNXT(T2) ;LINK IT HRRM T2,REGNXT(P4) AOS CSTCNT(P2) ;ANOTHER REGION ADDLS4: AOS CSTNUM(P2) ;ANOTHER CLUSTER POPJ P, ;ROUTINE TO PRINT CST'S (PASS ONE) CSTSO: MOVEI T1,[ASCIZ /lost/] MOVEI T2,[ASCIZ /marked in SAT but not in any file/] MOVEI T3,LSTCST PUSHJ P,CSTA MOVEI T1,[ASCIZ /free/] MOVEI T2,[ASCIZ /not marked in SAT but in some file/] MOVEI T3,FRECST PUSHJ P,CSTA MOVEI T1,[ASCIZ /multiply used/] MOVEI T2,[ASCIZ /belonging to more than one file/] MOVEI T3,MULCST PJRST CSTA ;ROUTINE TO PRINT CST'S (PASS TWO) CSTTO: MOVEI T1,[ASCIZ /free/] MOVEI T3,F2CST PUSHJ P,CSTO MOVEI T1,[ASCIZ /multiply used/] MOVEI T3,M2CST FALL CSTO ;ROUTINE TO PRINT A CST ;T1 PASSES CST NAME (SHORT FORM) ;T2 PASSES CST NAME (LONG FORM), USED ONLY IN PASS ONE ;T3 PASSES CST ;FL PASSES FIL, USED ONLY IN PASS TWO CSTO: SKIPN CSTCNT(T3) ;ANY? POPJ P, ;NO ;ENTER HERE TO ALWAYS PRINT CSTA: PUSHJ P,SAVE3 ;SAVE AC'S DMOVE P1,T1 MOVE P3,T3 MOVE T1,CSTNUM(P3) ;NUMBER OF CLUSTERS PUSHJ P,DECO MOVEI T1,40 PUSHJ P,CO MOVE T2,P1 ;SHORT NAME PUSHJ P,STRO MOVEI T2,[ASCIZ / cluster/] PUSHJ P,STRO MOVEI T1,"s" MOVE T2,CSTNUM(P3) CAIE T2,1 PUSHJ P,CO MOVEI T2,[ASCIZ / in /] PUSHJ P,STRO MOVE T1,CSTCNT(P3) ;NUMBER OF REGIONS PUSHJ P,DECO MOVEI T2,[ASCIZ / region/] PUSHJ P,STRO MOVEI T1,"s" MOVE T2,CSTCNT(P3) CAIE T2,1 PUSHJ P,CO MOVEI T1,40 PUSHJ P,CO TRNE F,F.P2 ;WHICH PASS? JRST CSTO9 ;PASS TWO MOVEI T1,"(" ;PASS ONE PUSHJ P,CO MOVE T2,P2 PUSHJ P,STRO MOVEI T1,")" PUSHJ P,CO JRST CSTO8 CSTO9: MOVEI T2,[ASCIZ /in file /] PUSHJ P,STRO PUSHJ P,FILO CSTO8: PUSHJ P,CRLFO SKIPN T1,CSTCNT(P3) ;OVER THRESHOLD? PJRST CRLFO CAILE T1,TREG TRNN F,F.TTY ;AND PHYS TTY? SKIPA P1,CSTREG(P3) ;NO, GET 1ST REG PJRST CRLFO ;YES CSTO1: MOVE T2,HPOS ;BEGINING OF LINE? MOVEI T1,"," CAIE T2,1 PUSHJ P,CO ;NO, PRINT A COMMA MOVE T1,REGLOW(P1) ;PRINT 1ST CLUSTER PUSHJ P,OCTO MOVE T1,REGLOW(P1) ;ONLY ONE CLUSTER? CAMN T1,REGHI(P1) JRST CSTO2 ;YES MOVEI T1,"-" ;NO, PRINT LAST CLUSTER PUSHJ P,CO MOVE T1,REGHI(P1) PUSHJ P,OCTO CSTO2: MOVE T1,HPOS ;PAST MARGIN? CAML T1,MARGIN PUSHJ P,CRLFO ;YES, NEWLINE HRRZ P1,REGNXT(P1) ;NEXT REGION JUMPN P1,CSTO1 ;LOOP PJRST DSPACE ;EXTRA CRLF SUBTTL ALLOCATE/DEALLOCATE ;ROUTINE TO DEALLOCATE BAD REGIONS DEBAD: PUSHJ P,SAVE1 MOVEI P1,BADCST PJRST DECST ;ROUTINE TO DEALLOCATE LOST REGIONS DELST: PUSHJ P,SAVE1 MOVEI P1,LSTCST PJRST DECST ;ROUTINE TO DEALLOCATE FREE REGIONS DEFRE: PUSHJ P,SAVE1 MOVEI P1,FRECST PJRST DECST ;ROUTINE TO DEALLOCATE MULTIPLY USED REGIONS DEMUL: PUSHJ P,SAVE1 MOVEI P1,MULCST FALL DECST ;ROUTINE TO DEALLOCATE ALL THE REGIONS IN A CLUSTER LIST ;P1 PASSES ADDR OF CLUSTER LIST DECST: HRRZ T2,CSTREG(P1) ;ADDR OF 1ST REGION JUMPE T2,CPOPJ HRRZ T3,REGNXT(T2) ;UNLINK IT HRRM T3,CSTREG(P1) MOVEI T1,SIZREG ;PITCH IT PUSHJ P,GIVBLK JRST DECST ;LOOP ;ROUTINE TO DEALLOCATE ALL THE UNITS IN A STR DESTR: PUSHJ P,SAVE3 ;SAVE ACS SKIPGE P2,HUN ;HIGHEST UNIT NUMBER POPJ P, DESTR1: SKIPN U,TBUDB(P2) ;UNIT DATA BLOCK JRST DESTR6 SKIPN P1,UDBPST(U) ;ADDR OF PST JRST DESTR5 MOVE P3,UDBSPU(U) ;SATS PER UNIT DESTR2: MOVE T2,(P1) ;ADDR OF SAT MOVE T1,UDBWPS(U) ;WORDS PER SAT PUSHJ P,GIVBLK ;DEALLOCATE CORE SOSE P3 ;LOOP FOR EACH SAT AOJA P1,DESTR2 MOVE T2,UDBPST(U) ;DEALLOCATE PST ITSELF MOVE T1,UDBSPU(U) PUSHJ P,GIVBLK DESTR5: MOVE T1,UDBSPU(U) ;DEALLOCATE SPT HRRZ T2,UDBSPT(U) SKIPE T2 PUSHJ P,GIVBLK MOVE T2,U ;DEALLOCATE UDB ITSELF MOVEI T1,SIZUDB PUSHJ P,GIVBLK DESTR6: SOJGE P2,DESTR1 ;LOOP FOR EACH UNIT POPJ P, ;ROUTINE TO BUILD THE DDBS MAKDDB: PUSHJ P,SAVE1 ;SAVE AC MOVE T1,[%CNDVN] ;MONITOR VERSION GETTAB T1, HALT HLRZM T1,MONVER MOVE T1,MONVER CAIL T1,70200 ;7.02 (OR LATER)? TRO F,F.702 ;YES MOVEI P1,1 ;1 DDB FOR 7.01 TRNE F,F.702 MOVEI P1,NDDBS ;MANY FOR 7.02 MOVEM P1,DDBS MKDDB1: MOVEI T1,SIZDDB ;ALLOCATE CORE FOR DDB PUSHJ P,GETBLK MOVE DDB,T2 MOVEM DDB,USRJDA(P1) MOVEI T1,NBLK*BLKSIZ+3 ;ALLOCATE CORE FOR BUFFER PUSHJ P,GETBLK ADDI T2,1 ;STEP OVER DEVIOS WORD MOVEM T2,DDBBUF(DDB) ;STORE IN DDB HRLI T2,NBLK*BLKSIZ+1 ;POINT BUFFER AT SELF MOVEM T2,(T2) SETOM DDBHBN(DDB) ;INVALIDATE CACHE SETZM DDBPUN(DDB) ;NO UNIT OPEN YET MOVEM P1,DDBCH(DDB) ;CHANNEL NUMBER MOVEM P1,DDBCX(DDB) ;CHANNEL INDEX (SAME FOR NOW) SOJG P1,MKDDB1 SETZM ACTCNT ;NO DDBS ACTIVE YET POPJ P, SUBTTL INTERLOCK ;ROUTINE TO GET THE INTERLOCK GTLOK1: MOVE T1,MYJOB ;RESTART? CAMN T1,LOKJOB JRST GTLOK2 ;YES TRZ F,F.NOC ;CTRL-C OK MOVEI T1,22 ;SLEEP AWHILE HIBER T1, PUSHJ P,DIE ;ENTER HERE GETLOK: IFN FTDBUG,< TRNE F,F.LOK PUSHJ P,DIE > TRO F,F.NOC ;NO CTRL-C AOSE ILOCK ;GOT IT? JRST GTLOK1 ;NO GTLOK2: TRO F,F.LOK ;YES MOVE T1,MYJOB ;WE GOT IT MOVEM T1,LOKJOB POPJ P, ;ROUTINE TO GIVE UP THE INTERLOCK GIVIF: TRNN F,F.LOK ;OWN IT? POPJ P, ;NO GIVLOK: IFN FTDBUG,< TRNN F,F.LOK PUSHJ P,DIE > SETZM LOKJOB ;NOBODY OWNS IT SETOM ILOCK ;GIVE IT AWAY TRZ F,F.LOK+F.NOC ;CTRL-C OK TRZE F,F.CC ;WAS CTRL-C TYPED? MONRT. ;YES, EXIT POPJ P, ;CONTINUE ;CTRL-C TRAP TRAP: MOVEM T1,SAVPC ;SAVE AN AC MOVE T1,INTR+.EROPC ;PICK UP PC SETZM INTR+.EROPC ;RE-ENABLE TRAP EXCH T1,SAVPC ;STORE PC TRNE F,F.NOC ;CTRL-C ALLOWED? TROA F,F.CC ;NO, SET FLAG MONRT. ;YES, EXIT JRSTF @SAVPC ;CONTINUE ;ROUTINE TO CHECK IF ALL THE OTHER JOBS ARE STILL ALIVE ALIVE: MOVEI T1,NSLT-1 ;START WITH HIGHEST SLOT ALIVE1: SKIPN JBTJOB(T1) ;SLOT IN USE? JRST ALIVE2 ;NO HRLZ T2,JBTJOB(T1) ;YES, GET HIS HISEG HRRI T2,.GTSGN GETTAB T2, PUSHJ P,DIE TLZ T2,-1 CAMN T2,MYSGN ;SAME AS OUR HISEG? JRST ALIVE2 ;YES, STILL ALIVE SETZM JBTSTR(T1) ;NO, DECLARE HIM DEAD SETZM JBTJOB(T1) SETZM JBTCHN(T1) SETZM JBTLOG(T1) SOS CNTSLT ALIVE2: SOJGE T1,ALIVE1 ;LOOP FOR EACH SLOT POPJ P, ;ROUTINE TO DEALLOCATE A SLOT GIVSLT: MOVE T1,MYSLT SETZM JBTJOB(T1) SOS CNTSLT POPJ P, ;ROUTINE TO ALLOCATE A SLOT NUMBER GETSLT: MOVEI T1,NSLT-1 ;START WITH HIGHEST SLOT GTSLT1: SKIPE T2,JBTJOB(T1) ;SLOT IN USE? CAME T2,MYJOB ;BY ME? SOJGE T1,GTSLT1 ;NO, TRY NEXT SLOT JUMPGE T1,GTSLT5 ;YES ;HERE IF WE DON'T ALREADY HAVE A SLOT, ;FIND AN EMPTY ONE MOVEI T1,NSLT-1 ;START WITH HIGHEST SLOT GTSLT3: SKIPN JBTJOB(T1) ;EMPTY? JRST GTSLT4 ;YES SOJGE T1,GTSLT3 ;NO, TRY NEXT PUSHJ P,DIE GTSLT4: AOSA T2,CNTSLT ;BUMP COUNT GTSLT5: MOVE T2,CNTSLT ;GET COUNT MOVEM T1,MYSLT ;SAVE SLOT NUMBER MOVE T3,MYJOB ;TELL OUR JOB NUMBER MOVEM T3,JBTJOB(T1) CAIE T2,1 ;ARE WE THE ONLY SLOT? POPJ P, ;NO FALL FIRSLT ;YES ;ROUTINE TO SET UP THE SHARED HISEG ;CALLED ONLY BY THE FIRST JOB FIRSLT: MOVEI T1,HCOR ;INITIALIZE FIRST FREE MOVEM T1,HFF SETZM SLST ;NO STRS YET SETZM BLST SETZM ALST SETZM CONFIG POPJ P, SUBTTL PICK A STR ;ROUTINE TO PICK A STR TO PROCESS ;RULES: ;TRY TO DO THE LOG STR EARLY (BUT DON'T DO IT FIRST). ;IF YOU DO THE LOG STR FIRST, YOU MIGHT BLOW AWAY ;THE JSL OF SOMEBODY WHO DID AN "ASSIGN DSK LPT". ;LET HIM RUN LONG ENOUGH TO FIGURE OUT WHAT HIS JSL IS. ;TRY NOT TO DO THE RUN STR FIRST, SOMEBODY MIGHT STILL BE ;LOADING THE EXE FILE AND WOULD GET A TRANSMISSION ERROR. ;DO NOT, UNDER ANY CIRCUMSTANCE, DO A STR THAT SOME OTHER JOB ;HAS A LOG FILE OPEN ON. ;TRY NOT TO DO A STR IF SOMEBODY ELSE IS ALREADY USING THAT CHANNEL. PIKSTR: PUSHJ P,SAVE4 SETZ P4, ;NOTHING GOOD YET SKIPN RUNSTR ;1ST TIME? SKIPN P1,LOGSTR ;LOG FILE TO DISK? JRST PKSTR2 ;NO MOVEI P2,BLST-SNFLNK ;LOG STR ALREADY STARTED? PKSTR1: HRRZ P2,SNFLNK(P2) JUMPE P2,PKSTR2 ;YES CAME P1,SNFNAM(P2) JRST PKSTR1 MOVEI P3,NSLT-1 ;NO, SOMEBODY HAS LOG FILE HERE? PKSTR0: CAMN P1,JBTLOG(P3) JRST PKSTR2 ;YES, DON'T DO IT SOJGE P3,PKSTR0 PUSHJ P,SWPOK ;OK TO REMOVE FROM ASL? JRST PKSTR2 ;NO MOVE P4,P2 ;WE CAN DO THIS STR MOVE P2,SNFCHN(P4) ;ANYBODY USING THIS CHAN? MOVEI P3,NSLT-1 PKSTRA: TDNE P2,JBTCHN(P3) JRST PKSTR2 ;YES, TRY TO FIND SOMETHING BETTER SOJGE P3,PKSTRA JRST PKSTR9 ;DO IT ;HERE IF CAN'T DO LOG STR 1ST PKSTR2: MOVEI P2,BLST-SNFLNK ;PRESET PRED PKSTR5: HRRZ P2,SNFLNK(P2) ;STEP TO NEXT STR JUMPE P2,PKSTR7 MOVE P1,SNFNAM(P2) MOVEI P3,NSLT-1 ;SOMEBODY HAS LOG FILE HERE? PKSTR6: CAMN P1,JBTLOG(P3) JRST PKSTR5 ;YES, DO NOT DO THIS STR SOJGE P3,PKSTR6 PUSHJ P,SWPOK ;OK TO REMOVE FROM ASL? JRST PKSTR5 ;NO MOVE P4,P2 ;NO, WE CAN DO THIS STR SKIPE RUNSTR ;1ST TIME? CAME P1,LOGSTR ;YES, DON'T DO LOG STR CAMN P1,RUNSTR ;IS IT THE RUN STR? JRST PKSTR5 ;YES, TRY TO FIND SOMETHING BETTER MOVE P1,SNFCHN(P2) ;SOMEBODY USING THIS CHANNEL? MOVEI P3,NSLT-1 PKSTR8: TDNE P1,JBTCHN(P3) JRST PKSTR5 ;YES, TRY TO FIND SOMETHING BETTER SOJGE P3,PKSTR8 JRST PKSTR9 ;NO, GOOD, DO IT NOW ;HERE WHEN THERE'S NOTHING REALLY GOOD TO DO ;DO ONE OF THE UNPLEASANT STRS PKSTR7: JUMPE P4,PKSTR3 ;GO IF NONE ;HERE WHEN WE FOUND A PERFECT STR PKSTR9: MOVE P1,SNFNAM(P4) ;GET STR NAME MOVEI P2,BLST-SNFLNK ;FIND PRED PKSTRB: CAMN P4,SNFLNK(P2) JRST PKSTR4 HRRZ P2,SNFLNK(P2) JRST PKSTRB PKSTR4: MOVE P3,SNFLNK(P4) ;UNLINK FROM BLST MOVEM P3,SNFLNK(P2) MOVEM P4,MYSNF ;SAVE ADDR OF SNF MOVEM P1,ALIAS ;STR NAME WE WILL DO MOVE P2,MYSLT ;TELL EVERYBODY IT'S OURS MOVEM P1,JBTSTR(P2) MOVE P1,SNFCHN(P4) ;TELL THEM WHAT CHANNEL MOVEM P1,JBTCHN(P2) JRST CPOPJ1 ;HERE IF THERE'S ABSOLUTELY NOTHING TO DO PKSTR3: MOVE T1,CNTSLT ;ARE WE THE ONLY ONE? CAIE T1,1 POPJ P, ;NO MOVEI P2,BLST-SNFLNK ;PRESET PRED PKSTRC: HRRZ P2,SNFLNK(P2) ;STEP TO NEXT STR JUMPE P2,CPOPJ PUSHJ P,SWPOK ;PARANOIA PUSHJ P,SWPBAD ;CAN'T REMOVE FROM ASL JRST PKSTRC ;ROUTINE TO TELL THE WORLD ABOUT THE ONE STR WE ARE DOING ;CALL WITH INTERLOCK PIKONE: PUSHJ P,SAVE4 MOVSI P1,LNM ;NAME STR MOUNTED AS MOVEM P1,FOO+.DCNAM MOVE P1,[XWD FOOSIZ,FOO] DSKCHR P1, PUSHJ P,DIE SKIPA P1,FOO+.DCSNM PKONE3: PUSHJ P,SLEEPY ;SLEEP AWHILE MOVEI P2,BLST-SNFLNK ;FIND OUR STR'S SLOT PKONE1: MOVE P4,P2 HRRZ P2,SNFLNK(P4) JUMPE P2,CPOPJ ;NOT FOUND CAME P1,SNFNAM(P2) JRST PKONE1 PUSHJ P,SWPOK ;OK TO REMOVE FROM ASL? JRST PKONE2 ;NO EXCH P2,P4 ;YES JRST PKSTR4 PKONE2: MOVE T1,CNTSLT ;ARE WE THE ONLY ONE? CAIE T1,1 JRST PKONE3 ;NO SWPBAD: PUSHJ P,ONSIL ;TTCALL ONLY MOVEI T2,[ASCIZ /Cannot process STR /] PUSHJ P,STRO MOVE T2,SNFNAM(P2) PUSHJ P,SIXO MOVEI T2,[ASCIZ / (not enough swapping space)/] PJRST STRDSP ;ROUTINE TO TEST IF IT'S OK TO REMOVE A STR FROM THE ASL ;P2 PASSES ADDR OF SNF ;SKIP IF OK SWPOK: SKIPN SNFVRT(P2) ;IN ASL? JRST CPOPJ1 ;NO, IT'S OK MOVE T1,[%SWVRT] ;NUMBER OF FREE PAGES OF SWAP SPACE GETTAB T1, PUSHJ P,DIE CAMG T1,SNFVRT(P2) ;REMOVING ALL FREE PAGES? POPJ P, ;YES, DON'T DO THAT ;HERE TO ADD UP ALL THE SWAPPING SPACE THAT'S LEFT SETZ T1, MOVEI T2,BLST-SNFLNK SWPOK1: HRRZ T2,SNFLNK(T2) JUMPE T2,SWPOK2 CAME T2,P2 ADD T1,SNFVRT(T2) JRST SWPOK1 SWPOK2: MOVEI T2,ALST-SNFLNK SWPOK3: HRRZ T2,SNFLNK(T2) JUMPE T2,SWPOK4 ADD T1,SNFVRT(T2) JRST SWPOK3 SWPOK4: CAIL T1,MINVRT ;BELOW TRESHHOLD? AOS (P) ;OK POPJ P, ;ROUTINE TO TELL THE WORLD WE ARE DONE WITH THE STR DONSTR: MOVE T2,MYSNF ;LINK IT TO ALST MOVE T3,ALST MOVEM T3,SNFLNK(T2) MOVEM T2,ALST MOVE T1,MYSLT ;CLEAR TABLES SETZM JBTSTR(T1) SETZM JBTLOG(T1) SETZM JBTCHN(T1) SKIPN LOGSTR POPJ P, CLOSE TO, STATZ TO,IO.ERR PUSHJ P,DIE POPJ P, SUBTTL SAVE AC SAVE1: EXCH P1,(P) HRLI P1,(P) PUSHJ P,CJRA SOS -1(P) JRST RET1 SAVE2: EXCH P1,(P) HRLI P1,(P) PUSH P,P2 PUSHJ P,CJRA SOS -2(P) JRST RET2 SAVE3: EXCH P1,(P) HRLI P1,(P) PUSH P,P2 PUSH P,P3 PUSHJ P,CJRA SOS -3(P) JRST RET3 SAVE4: EXCH P1,(P) HRLI P1,(P) PUSH P,P2 PUSH P,P3 PUSH P,P4 PUSHJ P,CJRA SOS -4(P) RET4: POP P,P4 RET3: POP P,P3 RET2: POP P,P2 RET1: POP P,P1 CPOPJ1: AOSA (P) ;SKIP RETURN TPOPJ: POP P,T1 ;RESTORE T1 CPOPJ: POPJ P, CJRA: JRA P1,(P1) END KLEPTO