Google
 

Trailing-Edge - PDP-10 Archives - BB-L288A-RM - swskit-utilities/filadr.mac
There are 2 other files named filadr.mac in the archive. Click here to see a list.
	TITLE	FILADR	TYPES OUT ADDRESSES A FILE IS USING


;WRITTEN BY DAVID I. BELL AT DIGITAL IN MARLBORO.
;THIS PROGRAM WILL TYPE OUT THE ADDRESSES OF EACH PAGE OF A FILE
;WHICH IS IN USE, AND ALSO THE PAGES USED BY THE INDEX BLOCKS.
;THE PROGRAM CAN ALSO CORRELATE THE ADDRESSES WITH THE ONES
;RECORDED IN THE BAT BLOCKS.  IT ALSO CAN LIST THE ADDRESSES IN
;THE BAT BLOCKS ALONE.


	SEARCH	MACSYM,MONSYM	;GET SYMBOLS
	SALL			;NICE LOOKING MACROS



;ACCUMULATORS:

	F=0			;FLAGS
	T1=1			;TEMPORARY AC'S
	T2=2
	T3=3
	T4=4
	I=5			;AOBJN POINTER FOR SUPER INDEX BLOCK
	A=6			;ADDRESS OF AN INDEX BLOCK IN CORE
	U=7			;LOGICAL UNIT NUMBER IN A STRUCTURE
	X=10			;ONLY FOR LUUO'S USE
	P=17			;STACK




;DEFAULT PARAMETERS:


	TXTLEN==^D100		;SIZE OF COMMAND BUFFERS
	PDLSIZ==30		;SIZE OF PUSHDOWN STACK
	MXUNIT==^D20		;NUMBER OF UNITS WE CAN HANDLE
	STGADR==77,,-1		;MASK FOR DISK ADDRESS IN A WORD
	DSKBIT==10,,0		;BIT SOMETIMES INCLUDED IN DISK ADDRESSES
	PAGI=10000		;ADDRESS OF INDEX BLOCK
	PAGSI=11000		;ADDRESS OF SUPER INDEX BLOCK
	BAT==12000		;ADDRESS TO READ IN FIRST BAT BLOCK
	BAT2==12200		;ADDRESS TO READ IN SECOND BAT BLOCK
	DATA=12400		;FIRST FREE LOCATION
;FLAGS:


	FR.BB1==1		;PRIMARY BAT BLOCK IS BAD
	FR.BB2==2		;SECONDARY BAT BLOCK IS BAD
	FR.BBI==4		;BAT BLOCKS DO NOT AGREE WITH EACH OTHER
	FR.ADR==10		;ADDRESSES ARE TO BE TYPED FOR FILES



;MACROS AND OPDEFS:



	OPDEF	PJRST	[JRST]		;PUSHJ/POPJ
	OPDEF	TYPE	[1B8]		;LUUO TO DO A SOUT
	OPDEF	OCTOUT	[2B8]		;LUUO FOR OCTAL OUTPUT
	OPDEF	DECOUT	[4B8]		;LUUO FOR DECIMAL OUTPUT



	DEFINE	AA(NAME,DATA),<		;;MACRO FOR COMMAND TABLES
	XWD	[ASCIZ/NAME/],DATA
>



	DEFINE	TEXT(STRING),<		;;MACRO FOR ASCIZ TEXT
	XLIST
	ASCIZ	@STRING@
	LIST
>



	DEFINE	ERROR(TEXT),<		;;MACRO FOR ERRORS
	JRST	[HRROI	T1,[ASCIZ/
? TEXT/]
		PSOUT
		JRST	LOSFIN]
>
;DEFINITIONS ASSOCIATED WITH BAT BLOCKS:



;BLOCK NUMBERS:

	BATAD1==^D2		;UNIT ADDRESS OF PRIMARY BAT BLOCK
	BATAD2==^D11		;UNIT ADDRESS OF SECONDARY BAT BLOCK


;OFFSETS IN A BLOCK:

	BT.NAM==0		;NAME OF BLOCK - SIXBIT /BAT/
	BT.ADR==1		;<- FREE WORDS>,,ADDRESS OF FIRST PAIR
	BT.MAP==2		;DATA RECORDED BY MAPPING PROGRAMS
	BT.CNT==3		;NUMBER OF PAIRS ADDED BY MONITOR
	BT.FRE==4		;FIRST PAIR OF WORDS
	BT.COD==176		;SPECIAL CODE - 606060
	BT.BLK==177		;THIS BLOCK NUMBER - 2 OR 11


;FIELDS IN THE WORD BT.MAP:

	BT%NBB==777000,,0	;NUMBER OF BAD BLOCKS FOUND BY MAP PROGRAM
	BT%NBR==777,,0		;NUMBER OF BAD REGIONS FOUND BY PROGRAM


;FIELDS IN FIRST WORD OF EACH PAIR OF ERROR WORDS:

	BT%NEW==40000		;THIS IS A NEW FORMAT PAIR OF WORDS
	BT%CNT==777000,,0	;ONE LESS THAN THE NUMBER OF CONSEQUTIVE
				;BAD BLOCKS IN THIS REGION


;FIELDS IN SECOND WORD OF EACH PAIR OF ERROR WORDS:

	BT%VER==700000,,0	;VERSION NUMBER IF BT%NEW IS SET
	BT%ADR==777,,-1		;UNIT ADDRESS OF FIRST BAD BLOCK
				;IN THIS REGION
	BT%AD2==777777		;UNIT ADDRESS IF BT%NEW IS OFF


;OTHER DEFINITIONS:

	BT$HDR==6		;NUMBER OF WORDS USED IN HEADERS
	BT$COD==606060		;SPECIAL CODE IN WORD 176
	SUBTTL	COMMAND SCANNER AND INITIALIZATION




START:	MOVEI	F,FR.ADR	;SET TO TYPE ADDRESSES BY DEFAULT
	MOVE	T1,[PUSHJ P,LUUO]	;GET INSTRUCTION
	MOVEM	T1,.JB41##	;AND SET UP FOR LUUOS
	SETZM	WIDTH		;CLEAR WIDTH ARGUMENT
	MOVEI	T1,.FHSLF	;GET READY
	RPCAP			;READ MY CAPABILITIES
	TXNN	T3,SC%WHL+SC%OPR	;CAN I RUN THIS PROGRAM?
	JRST	NOPOWR		;NO, GO COMPLAIN


REEN:	RESET			;CLEAR EVERYTHING
	MOVE	P,[IOWD PDLSIZ,PDL]	;SET UP A STACK
	SETZM	JFN		;CLEAR INPUT JFN
	SETZM	JFNOUT		;CLEAR OUTPUT JFN ALSO


NEWCMD:	MOVEI	T1,CMDBLK	;POINT TO COMMAND BLOCK
	MOVEI	T2,[FLDDB. .CMINI]	;INITIALIZATION FUNCTION
	PUSHJ	P,COMMND	;GO DO IT
	MOVEM	P,SAVEP		;SAVE STACK FOR REPARSING


NEWPAR:	MOVE	P,SAVEP		;RESTORE THE STACK
	MOVEI	T1,CMDBLK	;POINT TO THE COMMAND BLOCK
	MOVEI	T2,[FLDDB. (.CMKEY,,CMDTAB)]	;POINT TO COMMAND TABLE
	PUSHJ	P,COMMND	;READ IT
	MOVE	T2,(T2)		;GET ADDRESS OF ROUTINE
	PUSHJ	P,(T2)		;CALL IT
	SKIPE	T1,JFN		;INPUT FILES STILL OPEN?
	RLJFN			;YES, CLOSE THEM
	SETZM	JFN		;AND CLEAR WORD
	JRST	NEWCMD		;AND GET A NEW COMMAND
;TABLE OF COMMANDS:



CMDTAB:	CMDLEN,,CMDLEN			;HEADER
	AA	ADDRESS,CMDADR		;ADDRESS COMMAND
	AA	BAT-BLOCKS,CMDBAT	;TYPE OUT THE BAT BLOCKS
	AA	EXIT,CMDXIT		;EXIT COMMAND
	AA	FILE,CMDFIL		;GIVE ADDRESSES OF FILE
	AA	HELP,CMDHLP		;TYPE HELP MESSAGE
	AA	WIDTH,CMDWID		;SET WIDTH OF OUTPUT

	CMDLEN==.-CMDTAB-1		;NUMBER OF COMMANDS
	SUBTTL	THE SIMPLE COMMANDS



;EXIT FROM PROGRAM.  "EXIT" COMMAND.


CMDXIT:	MOVEI	T2,[ASCIZ/FROM PROGRAM/]	;GET NOISE
	PUSHJ	P,NOISE		;EAT NOISE WORDS
	PUSHJ	P,CONFRM	;THEN CONFIRM THE COMMAND
	HALTF			;QUIT FOR NOW
	POPJ	P,		;RETURN FOR A NEW COMMAND




;SET THE WIDTH OF THE OUTPUT.  THE "WIDTH" COMMAND.



CMDWID:	MOVEI	T2,[ASCIZ/OF OUTPUT IS/]	;GET NOISE
	PUSHJ	P,NOISE		;DO NOISE
	MOVEI	T2,[FLDDB. (.CMKEY,,WIDTAB,,<DEFAULT>)]	;GET READY
	PUSHJ	P,COMMND	;READ KEYWORD
	MOVE	T4,(T2)		;GET VALUE
	PUSHJ	P,CONFRM	;CONFIRM THE LINE
	HRRZM	T4,WIDTH	;SAVE VALUE
	POPJ	P,		;AND RETURN



WIDTAB:	WIDLEN,,WIDLEN		;NUMBER OF ENTRIES
	AA	DEFAULT,0	;DEFAULT
	AA	NARROW,3	;NARROW
	AA	WIDE,7		;WIDE

	WIDLEN==.-WIDTAB-1	;NUMBER OF ENTRIES
;SET MODE OF OUTPUT, WITH OR WITHOUT THE ADDRESSES BEING TYPED.
;THE "ADDRESS" COMMAND.


CMDADR:	MOVEI	T2,[ASCIZ/LISTING MODE IS/]	;GET NOISE
	PUSHJ	P,NOISE		;PARSE IT
	MOVEI	T2,[FLDDB. (.CMKEY,,ADRTAB,,<ON>)]	;GET READY
	PUSHJ	P,COMMND	;READ KEYWORD
	MOVE	T4,(T2)		;SAVE ADDRESS OF INSTRUCTION
	PUSHJ	P,CONFRM	;COMFIRM THE LINE
	XCT	(T4)		;TURN FLAG ON OR OFF
	POPJ	P,		;AND RETURN



ADRTAB:	ADRLEN,,ADRLEN		;NUMBER OF ENTRIES
	AA	OFF,[ANDCMI F,FR.ADR]	;ADDRESS LISTING IS OFF
	AA	ON,[IORI F,FR.ADR]	;ADDRESS LISTING IS ON

	ADRLEN==.-ADRTAB-1	;NUMBER OF KEYWORDS





;THE "HELP" COMMAND.



CMDHLP:	PUSHJ	P,CONFRM	;CONFIRM THE LINE
	HRROI	T1,HLPTXT	;POINT TO HELP MESSAGE
	PSOUT			;TYPE IT
	POPJ	P,		;AND RETURN
HLPTXT:	TEXT	<
This program can either dump out the addresses of the disk which a
file is using, or dump out the addresses which are marked in the BAT
blocks of a structure.  Commands are:

  ADDRESS arg	Set whether or not to type the addresses of the used
		pages, or just plus signs.  The arg is one of ON or
		OFF.  The default is ON.

  BAT-BLOCKS str	Type out information about the BAT blocks on
		the indicated structure.  The disk addresses pointed
		to by the BAT blocks is also listed.

  EXIT		Leave the program

  FILE spec	Process the given file spec, making a list of the
		addresses the file is using.

  HELP		Type this message.

  WIDTH arg	Set how many addresses to print on a line.  The
		argument is one of WIDE, NARROW, or DEFAULT.


Notes:

1.	WHEEL or OPERATOR capability is required to run this program
	as it does DSKOPs to read the index blocks.

2.	All disk addresses will seem to be at least as large as the
	value 10,,000000.  This bit can be ignored, it is simply a
	flag meaning that the address is a disk address.

3.	Numbers in the output followed by a period are decimal numbers,
	all other numbers are octal.

4.	Any gaps in the output (such as non-printed sections or page
	numbers) indicate that an area exists which has no pages in use.

5.	Any asterisks indicate that the indicated page is recorded
	in the BAT blocks for that structure.

6.	Addresses in the BAT blocks are listed as A,B where A is the
	address of the start of a bad region, and B is the number
	of consequtive bad blocks.

7.	The headers for the BAT block typeout mean the following:
	UNIT	  The logical unit within the structure
	BLOCKS	  The number of blocks found to be bad on the unit
	REGIONS	  The number of regions which are bad.  This number is
		  how many entries are made in the BAT block
	COUNT	  The number of regions which were found bad by the
		  monitor.  This will not include regions originally
		  found by the mapping program

>
	SUBTTL	COMMAND TO PRINT OUT ADDRESSES A FILE USES



;THIS COMMAND DOES THE MAIN ACTION.  WE READ ALL OF THE
;INDEX BLOCKS OF THE FILE, AND OUTPUT THE DISK ADDRESSES OF
;EACH PAGE OF THE FILE, AND ALSO OF THE INDEX BLOCK.


CMDFIL:	MOVEI	T2,[ASCIZ/TO PROCESS IS/]	;GET NOISE
	PUSHJ	P,NOISE		;PARSE IT
	MOVX	T2,GJ%IFG+GJ%OLD	;GET FLAGS
	MOVEM	T2,JFNBLK	;AND SAVE THEM IN GTJFN BLOCK
	MOVEI	T2,[FLDDB. (.CMFIL)]	;SET UP
	PUSHJ	P,COMMND	;READ FILE SPEC
	MOVEM	T2,JFN		;SAVE THE JFN
	MOVEI	T2,[ASCIZ/OUTPUT TO/]	;GET NOISE
	PUSHJ	P,NOISE		;PARSE IT
	MOVEI	T2,[FLDDB. (.CMOFI,,,,<TTY:>)]	;GET READY
	PUSHJ	P,COMMND	;READ OUTPUT SPEC
	MOVEM	T2,JFNOUT	;AND SAVE OUTPUT JFN
	PUSHJ	P,CONFRM	;CONFIRM THE LINE
	PUSHJ	P,SETOUT	;SET UP THE OUTPUT JFN FOR WRITING
	SETOM	JFNBTS		;INITIALIZE GNJFN BITS


FILLOP:	PUSHJ	P,DOFILE	;GO PROCESS THIS FILE
	MOVE	T1,JFN		;GET JFN AND FLAG BITS
	GNJFN			;ADVANCE TO NEXT FILE
	  ERJMP	FILDON		;ERROR, GO SEE IF DONE
	MOVEM	T1,JFNBTS	;SAVE THE GNJFN FLAGS
	MOVE	T1,JFNOUT	;GET OUTPUT JFN
	MOVEI	T2,14		;GET A CONTROL-L
	BOUT			;AND OUTPUT IT
	JRST	FILLOP		;AND GO DO IT


FILDON:	CAIE	T1,GNJFX1	;ALL DONE?
	  JRST	LOSE		;NO, HE LOSES
	SETZM	JFN		;GNJFN CLEARED THE JFN
FILCLS:	MOVE	T1,JFNOUT	;GET OUTPUT JFN
	CLOSF			;CLOSE THE FILE
	  ERJMP	LOSE		;FAILED
	SETZM	JFNOUT		;CLEAR OUTPUT JFN
	HRROI	T1,CRLF		;GET READY
	PSOUT			;TYPE A CRLF TO SAY WE'RE DONE
	POPJ	P,		;AND RETURN
	SUBTTL	ROUTINE TO PROCESS A FILE




;HERE TO PROCESS A PARTICULAR FILE.



DOFILE:	PUSHJ	P,SETIN		;SET UP TO HANDLE THIS FILE
	MOVE	T1,JFNBTS	;GET BITS FROM GNJFN
	TLNE	T1,(GN%STR)	;DID STRUCTURE CHANGE?
	PUSHJ	P,DOBAT		;YES, INITIALIZE BATS FOR THIS STRUCTURE
	TYPE	[ASCIZ/
	Disk addresses for file /]	;OUTPUT STRING
	HRRZ	T2,JFN		;GET INPUT JFN
	MOVE	T3,[1B2+1B5+1B8+1B11+1B14+JS%PAF]	;GET FLAGS
	JFNS			;TYPE STRING
	TYPE	CRLF		;THEN TYPE A CRLF
	MOVE	T1,FDB+.FBCTL	;GET FLAG BITS FOR THIS FILE
	TXNE	T1,FB%LNG	;IS IT A LONG FILE?
	JRST	DOLONG		;YES, GO HANDLE IT
	MOVE	T1,FDB+.FBADR	;NO, GET INDEX BLOCK ADDRESS
	MOVEM	T1,PAGSI	;SAVE IN A FAKE SUPER INDEX BLOCK
	MOVSI	I,-1		;SET UP AOBJN WORD OF 1
	JRST	SECLOP		;AND JOIN LOOP FOR LONG FILE


DOLONG:	MOVE	T1,FDB+.FBADR	;GET ADDRESS OF SUPER INDEX BLOCK
	MOVEI	A,PAGSI		;AND ADDRESS WHERE IT IS READ TO
	PUSHJ	P,READ		;READ IT IN
	PUSHJ	P,SCAN		;GET INFORMATION ABOUT IT
	PUSHJ	P,CHKSUM	;AND ITS CHECKSUM
	MOVE	T1,JFNOUT	;GET OUTPUT JFN READY
	TYPE	[ASCIZ/
Super Index Block address: /]	;TYPE TEXT
	OCTOUT	FDB+.FBADR	;TYPE ADDRESS
	MOVE	T1,FDB+.FBADR	;GET ADDRESS AGAIN
	SETZ	T2,		;WANT NO TYPEOUT UNLESS IN BAT BLOCK
	PUSHJ	P,BADSRC	;LOOK FOR IT
	TYPE	[ASCIZ/    Sections used: /]	;TYPE MORE
	DECOUT	PAGTOT		;OUTPUT TOTAL NUMBER OF SECTIONS
	TYPE	CRLF		;AND THEN A CRLF
	AOSE	PAGCHK		;SEE IF HAS A CHECKSUM ERROR
	TYPE	[ASCIZ/Index block has a checksum error
/]				;YES, SAY SO
	AOS	ALLPAG		;ADD TO NUMBER OF PAGES TOTAL
	MOVSI	I,-1000		;SET UP AOBJN POINTER FOR WHOLE PAGE
;HERE TO LOOP OVER ALL WORDS IN A SUPER INDEX BLOCK, TO READ IN
;AND PROCESS EACH REGULAR INDEX BLOCK.


SECLOP:	MOVE	T1,PAGSI(I)	;GET NEXT POSSIBLE INDEX BLOCK ADDRESS
	AND	T1,[STGADR]	;IGNORE CHECKSUM PARTS
	JUMPE	T1,SECNXT	;IF NONE, JUST GO TO NEXT ONE
	MOVEM	T1,PAGIDX	;SAVE ADDRESS OF INDEX BLOCK
	AOS	ALLPAG		;ADD TO TOTAL NUMBER OF PAGES FOR FILE
	MOVEI	A,PAGI		;POINT TO AREA TO READ IT INTO
	PUSHJ	P,READ		;READ IT IN
	PUSHJ	P,SCAN		;GET INFORMATION
	PUSHJ	P,CHKSUM	;AND CHECKSUM
	PUSHJ	P,LIST		;THEN OUTPUT INFORMATION ON IT
	MOVE	T1,PAGTOT	;GET TOTAL PAGES DESCRIBED
	ADDM	T1,ALLPAG	;ADD TO GRAND TOTAL
	ADDM	T1,ALLDAT	;AND TO DATA PAGE TOTAL
SECNXT:	AOBJN	I,SECLOP	;LOOP OVER ALL SECTIONS



;HERE WHEN ALL DONE, TO OUTPUT TOTALS AND CLOSE FILES.


	MOVE	T1,JFNOUT	;GET READY FOR LAST BIT OF OUTPUT
	TYPE	[ASCIZ/
Total pages used: /]		;MORE TEXT
	DECOUT	ALLPAG		;OUTPUT NUMBER OF DATA PAGES
	TYPE	[ASCIZ/    Data pages: /]	;MORE
	DECOUT	ALLDAT		;OUTPUT NUMBER OF DATA PAGES
	TYPE	CRLF		;THEN TYPE A CRLF
	SKIPN	ALLBAD		;ANY BAD BLOCKS?
	POPJ	P,		;NO, RETURN
	TYPE	[ASCIZ/Pages listed in the BAT blocks (marked with "*"): /]
	DECOUT	ALLBAD		;OUTPUT NUMBER
	TYPE	CRLF		;ANOTHER CRLF
	POPJ	P,		;THEN RETURN
	SUBTTL	ROUTINE TO PRINT OUT THE ADDRESSES OF A PAGE TABLE




;CALLED TO PRINT THE ADDRESSES POINTED TO BY THE INDEX BLOCK WHOSE
;ADDRESS IS IN AC A.  ALSO PRINTED IS SOME HEADER INFORMATION OF USE.




LIST:	TYPE	[ASCIZ/
Section: /]			;TYPE SOME TEXT
	MOVEI	T3,(I)		;GET SECTION NUMBER READY
	OCTOUT	T3		;OUTPUT IT
	TYPE	[ASCIZ/     Index block address: /]	;MORE TEXT
	OCTOUT	PAGIDX		;OUTPUT PAGE NUMBER
	MOVE	T1,PAGIDX	;GET ADDRESS AGAIN
	SETZ	T2,		;NO OUTPUT IF NOT BAD
	PUSHJ	P,BADSRC	;LOOK FOR IT IN BAD BLOCKS
	TYPE	[ASCIZ/     Pages in use: /]	;TYPE MORE
	DECOUT	PAGTOT		;OUTPUT TOTAL NUMBER OF PAGES
	TYPE	CRLF		;OUTPUT A CRLF
	AOSE	PAGCHK		;SEE IF CHECKSUM WAS -1
	TYPE	[ASCIZ/Index block has a checksum error
/]				;IF NOT, TELL HIM
	SKIPGE	T2,PAGMIN	;ANY PAGES TO BE TYPED?
	POPJ	P,		;NO, THEN ARE ALL DONE
;HERE TO ACTUALLY LOOP OVER EACH WORD IN THE INDEX BLOCK:


LISTLP:	TDNE	T2,PAGMSK	;TIME FOR A NEW LINE?
	JRST	LISTPG		;NO, JUST GO TYPE THE PAGE NUMBER
	TYPE	CRLF		;START WITH A CRLF
	OCTOUT	3,PAGMIN	;PRINT THE PAGE NUMBER
	MOVEI	T2,"/"		;GET A SLASH
	BOUT			;PRINT THAT
	TRNN	F,FR.ADR	;TYPING ADDRESSES?
	TYPE	[ASCIZ/   /]	;NO, THEN SPACE OVER SOME
	MOVE	T2,PAGMIN	;GET PAGE NUMBER AGAIN

LISTPG:	ADDI	T2,(A)		;POINT INTO INDEX BLOCK
	MOVE	T4,(T2)		;GET WORD FROM INDEX BLOCK
	AND	T4,[STGADR]	;KEEP ONLY THE DISK ADDRESS
	JUMPE	T4,LISTNO	;JUMP IF THERE IS NO ADDRESS
	TRNN	F,FR.ADR	;TYPING ADDRESSES?
	JRST	LISTPL		;NO, GO DO OTHER WAY
	OCTOUT	^D11,T4		;YES, DO SO
	MOVE	T1,T4		;GET ADDRESS AGAIN
	MOVEI	T2," "		;GET A SPACE IN CASE IT ISN'T BAD
	PUSHJ	P,BADSRC	;LOOK FOR ADDRESS IN BAD BLOCK
	JRST	LISTDN		;AND CONTINUE

LISTPL:	MOVE	T1,T4		;GET ADDRESS OF PAGE
	MOVEI	T2,"+"		;GET A PLUS IN CASE IT IS GOOD PAGE
	PUSHJ	P,BADSRC	;LOOK FOR THE PAGE
	JRST	LISTDN		;AND CONTINUE

LISTNO:	TRNE	F,FR.ADR	;ARE WE TYPING ADDRESSES?
	TYPE	[ASCIZ/      --    /]	;YES, TYPE SOME DASHES
	MOVEI	T2,"-"		;GET A DASH READY
	TRNN	F,FR.ADR	;NOT GIVING THE ADDRESSES?
	BOUT			;YES, THEN OUTPUT IT


LISTDN:	AOS	T2,PAGMIN	;INCREMENT TO NEXT PAGE
	CAMG	T2,PAGMAX	;DID ALL WE SHOULD YET?
	JRST	LISTLP		;NO, GO DO MORE
	TYPE	CRLF		;FINISH WITH A CRLF
	POPJ	P,		;RETURN
	SUBTTL	COMMAND TO PRINT THE BAT BLOCKS




;THIS IS THE COMMAND TO LIST THE BAT BLOCKS.  THE ADDRESSES OF EACH
;REGION IS TYPED, ALONG WITH USEFUL STATISTICS.



CMDBAT:	MOVEI	T2,[ASCIZ/OF STRUCTURE/]	;GET READY
	PUSHJ	P,NOISE		;READ NOISE
	MOVEI	T2,[FLDDB. (.CMDEV,,,,<PS>)]	;WANT TO INPUT DEVICE
	PUSHJ	P,COMMND	;DO IT
	MOVEM	T2,DEVICE	;SAVE THE DEVICE DESIGNATOR
	MOVEI	T2,[ASCIZ/LISTED TO FILE/]	;GET READY
	PUSHJ	P,NOISE		;PARSE IT MORE
	MOVEI	T2,[FLDDB. (.CMOFI,,,,<TTY:>)]	;GET READY
	PUSHJ	P,COMMND	;READ OUTPUT SPEC
	MOVEM	T2,JFNOUT	;SAVE THE OUTPUT JFN
	PUSHJ	P,CONFRM	;THEN CONFIRM THE LINE
	MOVE	T1,DEVICE	;GET DEVICE DESIGNATOR
	DVCHR			;GET INFORMATION ABOUT IT
	  ERJMP	LOSE		;CAN'T
	LDB	T1,[POINTR T2,DV%TYP]	;GET DEVICE TYPE
	CAIE	T1,.DVDSK	;IS IT A DISK?
	  JRST	NOTDSK		;NO, COMPLAIN
	HRROI	T1,STR		;POINT TO STORAGE
	MOVE	T2,DEVICE	;GET DEVICE DESIGNATOR
	DEVST			;CONVERT IT TO A STRING
	  ERJMP	LOSE		;FAILED
	PUSHJ	P,SETOUT	;GET OUTPUT FILE READY TO WRITE
	PUSHJ	P,DOBAT		;READ IN ALL BAT BLOCK INFO
	TYPE	[ASCIZ/
BAT blocks for structure /]	;TYPE SOME TEXT
	TYPE	STR		;THEN THE STRUCTURE NAME
	TYPE	[ASCIZ/:
Units in structure: /]		;MORE
	DECOUT	PACKS		;OUTPUT IT
	TYPE	[ASCIZ/

Unit   Blocks   Regions   Count           Status

/]
	SETZ	U,		;GET SET FOR LOOP OVER ALL UNITS
;HERE FOR LOOP OVER ALL UNITS IN A STRUCTURE, LISTING THE INFORMATION
;WE KNOW FOR EACH UNIT.


UNITLP:	OCTOUT	2,U		;PRINT THE UNIT NUMBER
	DECOUT	^D9,UNITBB(U)	;TYPE THE NUMBER OF BAD BLOCKS
	DECOUT	^D8,UNITBR(U)	;AND THE NUMBER OF BAD REGIONS
	DECOUT	^D8,UNITCT(U)	;AND NUMBER OF MONITOR ADDED REGIONS
	TYPE	[ASCIZ/      /]	;THEN SPACE OVER
	MOVE	T1,UNITFL(U)	;GET THE FLAGS FOR THIS STRUCTURE
	PUSHJ	P,BATSTS	;TYPE THE STATUS
	TYPE	CRLF		;THEN A CRLF
	ADDI	U,1		;MOVE TO NEXT UNIT
	CAMGE	U,PACKS		;DONE WITH ALL UNITS YET?
	JRST	UNITLP		;NO, GO DO NEXT ONE
	MOVEI	I,DATA		;POINT TO FIRST PAIR OF WORDS
	CAML	I,BADPTR	;ANY ADDRESSES TO TYPE?
	  JRST	FILCLS		;NO, GO CLOSE FILE AND RETURN
	TYPE	[ASCIZ/
Addresses marked in the BAT blocks:
/]				;TYPE MORE TEXT
	SETOM	PAGMIN		;AND INITIALIZE A COUNTER
	MOVEI	T1,3		;GET MASK TO BE USED
	MOVEM	T1,PAGMSK	;SET FOR 4 COLUMNS OF OUTPUT


PARLOP:	AOS	T1,PAGMIN	;INCREMENT COUNTER
	TDNN	T1,PAGMSK	;IS IT TIME FOR A NEW LINE?
	TYPE	CRLF		;YES, DO A CRLF FIRST
	MOVX	T2,DSKBIT	;GET THE BIT READY
	IOR	T2,0(I)		;ADD IN THE DISK ADDRESS
	OCTOUT	^D12,T2		;THEN TYPE IT
	MOVEI	T2,","		;GET A COMMA
	BOUT			;TYPE IT
	MOVE	T2,1(I)		;GET SECOND ADDRESS
	SUB	T2,0(I)		;SUBTRACT FIRST ADDRESS
	ADDI	T2,1		;ADD ONE TO GET SIZE
	MOVE	T3,[3,,^D8]	;GET READY FOR OUTPUT IN COLUMN OF 3
	NOUT			;DO IT
	JFCL			;STUPID ERROR
	ADDI	I,2		;MOVE POINTER TO NEXT PAIR
	CAMGE	I,BADPTR	;STILL MORE TO TYPE?
	JRST	PARLOP		;YES, LOOP MORE
	TYPE	CRLF		;FINISH WITH A CRLF
	JRST	FILCLS		;THEN GO CLOSE FILE AND RETURN
	SUBTTL	ROUTINE TO SET UP INPUT FILE




;CALLED TO MAKE SURE THAT THE INPUT FILE IS A DISK FILE, AND
;TO OBTAIN THE INFORMATION THAT WE WILL NEED LATER.





SETIN:	HRRZ	T1,JFN		;GET JFN
	DVCHR			;READ STATUS BITS
	LDB	T1,[POINTR T2,DV%TYP]	;GET DEVICE TYPE
	CAIE	T1,.DVDSK	;MAKE SURE THIS IS A DISK
	  JRST	NOTDSK		;IF NOT, ERROR
	HRRZ	T1,JFN		;GET JFN
	MOVSI	T2,.FBLWR+1	;GET NUMBER OF FDB WORDS
	MOVEI	T3,FDB		;POINT TO STORAGE
	GTFDB			;READ THE FILE'S FDB
	  ERJMP	LOSE		;CAN'T, THEN BOMB
	HRROI	T1,STR		;POINT TO STORAGE
	HRRZ	T2,JFN		;GET JFN OF FILE
	MOVE	T3,[FLD (.JSAOF,JS%DEV)]	;AND FLAGS
	JFNS			;STORE DEVICE NAME
	SETZ	T2,		;GET READY
	IDPB	T2,T1		;MAKE SURE IS ASCIZ
	HRROI	T1,STR		;POINT TO IT AGAIN
	STDEV			;GET THE DEVICE DESIGNATOR
	  ERJMP	LOSE		;FAILED
	MOVEM	T2,DEVICE	;SAVE IT
	SETZM	ALLPAG		;CLEAR TOTAL NUMBER OF PAGES
	SETZM	ALLDAT		;AND TOTAL NUMBER OF DATA PAGES
	SETZM	ALLBAD		;AND NUMBER OF BAD PAGES
	POPJ	P,		;THEN RETURN
	SUBTTL	ROUTINE TO SET UP OUTPUT FILE



;CALLED TO OPEN THE OUTPUT FILE FOR WRITING, AND TO DECIDE ON THE
;NUMBER OF COLUMNS IN THE OUTPUT.  IF THERE IS NO JFN YET IN USE,
;THEN WE WILL USE THE DEVICE OF TTY:.




SETOUT:	MOVE	T1,JFNOUT	;GET OUTPUT JFN READY
	MOVX	T2,OF%WR+7B5	;SET UP BYTE SIZE AND WRITE ACCESS
	OPENF			;OPEN IT
	  ERJMP	LOSE		;FAILED
	MOVEI	T1,77		;GET VALUE READY IN CASE NO ADDRESS MODE
	TRNE	F,FR.ADR	;WANTS NO ADDRESSES?
	SKIPE	T1,WIDTH	;OR HE SPECIFIED A WIDTH?
	JRST	SETWID		;YES, GO STORE IT
	MOVE	T1,JFNOUT	;GET JFN AGAIN
	DVCHR			;READ STATUS OF DEVICE
	LDB	T1,[POINTR T2,DV%TYP]	;GET DEVICE TYPE
	CAIE	T1,.DVTTY	;IS IT A TTY?
	JRST	SETBIG		;NO, THEN USE WIDE FORMAT
	MOVE	T1,JFNOUT	;GET READY
	MOVEI	T2,.MORLW	;GET READY TO READ WIDTH
	MTOPR			;DO IT
	CAIGE	T3,^D100	;IS TERMINAL WIDE ENOUGH?
	SKIPA	T1,[3]		;NO, THEN USE NARROW FORMAT
SETBIG:	MOVEI	T1,7		;OTHERWISE USE WIDE FORMAT
SETWID:	MOVEM	T1,PAGMSK	;SAVE AS MASK TO USE IN OUTPUT ROUTINE
	POPJ	P,		;RETURN
	SUBTTL	LUUO HANDLER




;HERE ON AN LUUO, TO TYPE OUT EITHER A STRING OR A DECIMAL OR OCTAL
;NUMBER.  EACH OF THESE FUNCTIONS IS A DIFFERENT LUUO.  ALL OUTPUT
;GOES TO THE JFN JFNOUT.  ERRORS IN THE NUMBER OUTPUT ARE IGNORED.





LUUO:	MOVE	X,.JBUUO##	;GET THE UUO
	TLNN	X,(TYPE)	;IS IT THE TYPE LUUO?
	JRST	LUUO1		;NO, GO ON
	MOVE	T1,JFNOUT	;SET UP OUTPUT JFN
	HRROI	T2,(X)		;POINT TO THE TEXT
	SETZ	T3,		;WANT TO OUTPUT ALL OF IT
	SOUT			;DO SO
	POPJ	P,		;THEN RETURN


LUUO1:	TLNN	X,(OCTOUT)	;WANT TO OUTPUT OCTAL NUMBER?
	JRST	LUUO2		;NO, WANTS DECIMAL
	MOVE	T2,(X)		;GET NUMBER TO TYPE
	MOVE	T1,JFNOUT	;SET UP OUTPUT JFN
	LDB	T3,[POINT 4,X,12]	;GET COLUMN WIDTH
	MOVSI	T3,<(NO%LFL)>(T3)	;PUT IN PROPER PLACE
	IORI	T3,^D8		;AND INSERT RADIX
	NOUT			;TYPE IT
	JFCL			;STUPID ERROR
	POPJ	P,		;THEN RETURN


LUUO2:	MOVE	T2,(X)		;GET NUMBER TO TYPE
	MOVE	T1,JFNOUT	;GET OUTPUT JFN READY
	LDB	T3,[POINT 4,X,12]	;GET COLUMN WIDTH
	MOVSI	T3,<(NO%LFL)>(T3)	;PUT IN PROPER PLACE
	IORI	T3,^D10		;AND INSERT RADIX
	NOUT			;OUTPUT IT
	JFCL			;STUPID ERROR
	MOVEI	T2,"."		;GET A PERIOD
	BOUT			;OUTPUT IT TO INDICATE DECIMAL NUMBER
CPOPJ:	POPJ	P,		;THEN RETURN


CRLF:	BYTE 	(7)15,12	;CRLF TEXT
	SUBTTL	ROUTINE TO READ IN AN INDEX BLOCK




;SIMPLE SUBROUTINE TO READ AN INDEX BLOCK INTO THE GIVEN ADDRESS.
;THE DISK ADDRESS OF THE INDEX BLOCK IS IN AC T1, AND THE ADDRESS
;TO WRITE THE DATA IS IN AC A.  NO RETURN IF AN ERROR ENCOUNTERED.



READ:	AND	T1,[DOP%RA]	;CLEAR NON-ADDRESS PART
	IOR	T1,[<FLD (.DOPSR,DOP%AT)>!DOP%SN]	;SET UP REST
	MOVEI	T3,(A)		;MOVE ADDRESS TO RIGHT AC
	MOVEI	T2,1000		;READ IN A WHOLE PAGE, NO FLAGS SET
	MOVE	T4,DEVICE	;GET DEVICE DESIGNATOR
	DSKOP			;READ THE PAGE
	  ERJMP	LOSE		;CAN'T DO IT
	POPJ	P,		;ALL DONE
	SUBTTL	ROUTINE TO SCAN INDEX BLOCK TO FIND OUT INFORMATION



;THIS ROUTINE IS CALLED TO OBTAIN THE FIRST AND LAST PAGE NUMBER
;TO BE PRINTED FOR THIS INDEX BLOCK.  ALSO OBTAINED IS THE NUMBER
;OF PAGES WHICH ARE USED ACCORDING TO THE INDEX BLOCK.  ADDRESS
;OF THE INDEX BLOCK IS IN AC A.





SCAN:	SETZM	PAGTOT		;CLEAR NUMBER OF PAGES USED
	SETOM	PAGMIN		;AND INITIALIZE MINIMUM PAGE NUMBER
	MOVSI	T1,-1000	;WANT TO SCAN WHOLE PAGE
	HRLI	A,T1		;SET UP FOR INDIRECT ADDRESS
	MOVE	T2,[STGADR]	;GET MASK READY

SCANLP:	TDNN	T2,@A		;IS THIS PAGE USED?
	JRST	SCANNX		;NO, GO ON
	HRRZM	T1,PAGMAX	;YES, SAVE AS HIGHEST PAGE SO FAR
	SKIPGE	PAGMIN		;ALREADY FOUND LOWEST PAGE?
	HRRZM	T1,PAGMIN	;NO, THEN SAVE IT
	AOS	PAGTOT		;BUMP NUMBER OF PAGES TOTAL
SCANNX:	AOBJN	T1,SCANLP	;LOOP OVER ALL PAGES
	MOVE	T1,PAGMSK	;GET MASK USED FOR THIS WIDTH
	ANDCAM	T1,PAGMIN	;ROUND FIRST PAGE DOWN TO NICE VALUE
	IORM	T1,PAGMAX	;ROUND LAST PAGE UP TO NICE VALUE TOO
	POPJ	P,		;THEN RETURN
	SUBTTL	ROUTINE TO CHECKSUM AN INDEX BLOCK



;ROUTINE TO COMPUTE THE CHECKSUM OF AN INDEX BLOCK.  THE ADDRESS IN
;OUR CORE OF THE INDEX BLOCK IS SUPPLIED IN AC A.  AN INDEX BLOCK
;CONTAINS THE CHECKSUM IN THE FIRST 9 BITS OF THE FIRST 4 WORDS.
;THE RIGHT 24 BITS OF EACH WORD IS THE DISK ADDRESS FOR THAT PAGE.
;ANY REMAINING BITS ARE NOT USED, AND DO NOT TAKE PART IN THE CHECKSUM.
;A GOOD CHECKSUM HAS THE VALUE OF -1.  THE COMPUTED CHECKSUM IS
;SAVED IN LOCATION PAGCHK.





CHKSUM:	MOVSI	T2,-4		;GET READY FOR A LOOP
	HRRI	T2,(A)		;OVER THE FIRST FOUR WORDS
	MOVE	T3,[POINT 9,T1]	;POINT TO PLACE CHECKSUM WILL GO

CHKGET:	LDB	T4,[POINT 9,(T2),8]	;GET A BYTE OF THE CHECKSUM
	IDPB	T4,T3		;STORE IT
	AOBJN	T2,CHKGET	;DO FOR ALL FOUR WORDS
	SETCA	T1,		;COMPLEMENT THE CHECKSUM
	JCRY0	.+1		;CLEAR CARRY FLAG
	MOVSI	T2,-1000	;GET READY TO LOOP OVER WHOLE PAGE
	HRLI	A,T2		;SETUP INDEX FIELD

CHKWRD:	MOVE	T3,@A		;GET NEXT WORD OF PAGE
	AND	T3,[EXP STGADR]	;KEEP ONLY THE DISK ADDRESS PART
	SKIPN	T3		;IS THERE ANY ADDRESS?
	MOVEI	T3,(T2)		;NO, THEN USE THE OFFSET INTO THE PAGE
	ADD	T1,T3		;ADD RESULT INTO CHECKSUM
	JCRY0	[AOJA T1,.+1]	;IF OVERFLOW, WRAP AROUND
	AOBJN	T2,CHKWRD	;LOOP OVER ALL WORDS IN THE PAGE
	MOVEM	T1,PAGCHK	;SAVE THE CHECKSUM FOR LATER
	POPJ	P,		;RETURN
	SUBTTL	ROUTINE TO COLLECT ALL DATA ON BAD BLOCKS




;THIS ROUTINE DOES ALL GOOD THINGS TO COLLECT A LIST OF THE BAD
;BLOCKS OF A STRUCTURE.  IT ALSO COLLECTS THE INFORMATION FOR
;EACH UNIT IN A STRUCTURE.  BEFORE CALLING, PUT THE ASCIZ STRUCTURE
;NAME IN LOCATION STR.  RETURNS WILL ALL DATA GOTTEN, READY TO
;SEARCH FOR BAD BLOCKS.




DOBAT:	PUSHJ	P,STRFND	;LOOK FOR ALL UNITS IN STRUCTURE
	MOVEI	T1,DATA		;POINT TO STORAGE
	MOVEM	T1,BADPTR	;AND INITIALIZE POINTER
	SETZ	U,		;GET SET FOR LOOP THROUGH ALL UNITS


DOBATL:	PUSHJ	P,GETBAT	;READ IN BOTH BATS FOR UNIT
	  SKIPA			;BOTH WERE BAD, SKIP NEXT STEP
	PUSHJ	P,SAVBAD	;GET BAD BLOCKS SAVED IN CORE
	MOVE	T1,BAT+BT.CNT	;GET COUND OF REGIONS MONITOR FOUND
	MOVEM	T1,UNITCT(U)	;SAVE FOR LATER
	MOVEM	F,UNITFL(U)	;SAVE FLAGS FOR LATER TOO
	MOVE	T1,UNITSZ(U)	;GET SIZE OF THIS UNIT
	ADDM	T1,UNITOF	;ADD TO OFFSET IN ADDRESSES
	ADDI	U,1		;MOVE UP A UNIT
	CAMGE	U,PACKS		;LOOKED AT ALL UNITS YET?
	JRST	DOBATL		;NO, KEEP LOOPING
	POPJ	P,		;ALL DONE, RETURN
	SUBTTL	ROUTINE TO SEARCH FOR A BAD BLOCK



;THIS ROUTINE IS CALLED WITH THE ADDRESS OF A BLOCK IN T1, AND
;A CHARACTER TO BE OUTPUT (NULL IF NONE) IN T2.  THE ADDRESS
;GIVEN IS SEARCHED TO SEE IF IT IS LISTED IN THE BAT BLOCKS.
;IF NOT, THE GIVEN CHARACTER IS OUTPUT.  IF SO, AN ASTERISK IS
;OUTPUT AND THE COUNT ALLBAD IS BUMPED ONE.




BADSRC:	TLZ	T1,(DSKBIT)	;CLEAR BIT WHICH MIGHT CONFUSE US
	SKIPA	T3,[EXP	DATA]	;START SEARCH AT TOP

SRCLOP:	ADDI	T3,2		;MOVE TO NEXT PAIR OF WORDS
	CAML	T3,BADPTR	;RAN OUT OF BAD PAIRS?
	JRST	SRCOK		;YES, NOT A BAD BLOCK THEN
	CAML	T1,0(T3)	;LESS THAN FIRST OF PAIR?
	CAMLE	T1,1(T3)	;OR GREATER THAN SECOND OF PAIR?
	JRST	SRCLOP		;YES, NOT INCLUDED IN THIS PAIR
	AOS	ALLBAD		;IS A BAD BLOCK, INCREMENT COUNT
	MOVEI	T2,"*"		;CHANGE CHAR TO AN ASTERISK
SRCOK:	MOVE	T1,JFNOUT	;GET OUTPUT JFN READY
	SKIPE	T2		;SOMETHING TO OUTPUT?
	BOUT			;YES, DO IT
	POPJ	P,		;THEN RETURN
	SUBTTL	ROUTINE TO SAVE BAD BLOCKS IN CORE




;CALLED AFTER HAVING READ IN A BAT BLOCK, TO INTERPRET THE PAIRS OF
;WORDS IN THE BAT BLOCK, AND TO REMEMBER THE ADDRESSES OF THE BAD
;BLOCKS SO THEY CAN BE EASILY SEARCHED LATER.  THE PAIRS OF WORDS
;WE REMEMBER ARE STORE AT LOCATION POINTED TO BY BADPTR.  CALLED
;AFTER HAVING READ A BAT BLOCK INTO LOCATION BAT.




SAVBAD:	LDB	T1,[POINTR BAT+BT.MAP,BT%NBR]	;GET MAPPED REGIONS
	ADD	T1,BAT+BT.CNT	;ADD REGIONS MONITOR FOUND
	JUMPE	T1,CPOPJ	;IF NONE, NO ERRORS SO RETURN
	CAILE	T1,<200-BT$HDR>/2	;OVERFLOWED?
	MOVEI	T1,<200-BT$HDR>/2	;YES, MAKE MAXIMUM
	MOVNI	T1,(T1)		;MAKE NEGATIVE
	MOVSI	T1,(T1)		;AND MAKE INTO AOBJN POINTER
	HRR	T1,BAT+BT.ADR	;GET ADDRESS OF FIRST PAIR
	ADDI	T1,BAT		;RELOCATE TO DATA IN CORE
	MOVX	T4,BT%NEW	;GET BIT READY FOR USE


SAVLOP:	MOVE	T2,1(T1)	;GET ADDRESS OF A REGION
	ANDX	T2,BT%ADR	;ONLY KEEP THE ADDRESS
	TDNN	T4,0(T1)	;IS THIS OLD STYLE FORMAT?
	ANDX	T2,BT%AD2	;YES, ADDRESS FIELD IS SMALLER
	ADD	T2,UNITOF	;OFFSET ADDRESS BY PRECEEDING UNITS
	MOVEM	T2,@BADPTR	;SAVE THE FIRST ADDRESS
	AOS	BADPTR		;THEN INCREMENT POINTER
	LDB	T3,[POINTR <(T1)>,BT%CNT]	;GET COUNT-1 OF BAD BLOCKS
	ADD	T2,T3		;PRODUCE LAST BLOCK IN THE REGION
	MOVEM	T2,@BADPTR	;AND SAVE IT TOO
	AOS	BADPTR		;INCREMENT POINTER AGAIN
	ADDI	T3,1		;MAKE NUMBER OF BAD BLOCKS
	ADDM	T3,UNITBB(U)	;ADD TO TOTAL NUMBER OF BAD BLOCKS
	AOS	UNITBR(U)	;AND INCREMENT NUMBER OF BAD REGIONS
	ADDI	T1,1		;INCREMENT ADDRESS BY 1
	AOBJN	T1,SAVLOP	;AND CONTINUE WITH NEXT PAIR
	POPJ	P,		;ALL DONE
	SUBTTL	ROUTINE TO FIND ALL UNITS OF A STRUCTURE




;THIS ROUTINE IS CALLED TO COLLECT ALL THE INFORMATION NEEDED
;TO PROCESS EACH UNIT IN A STRUCTURE.  THE STRUCTURE NAME TO
;BE PROCESSED IS IN THE ADDRESS STR.  DATA IS RETURNED IN
;VARIOUS TABLES, AND THE CONSISTANCY OF THE STRUCTURE IS CHECKED.




STRFND:	MOVE	T1,[ZERUNT,,ZERUNT+1]	;GET READY FOR BIG BLT
	SETZM	ZERUNT		;TO CLEAR ALL UNIT DATA
	BLT	T1,ZEREND	;DO IT
	SETOM	MBLK+.MSRCH	;INITIALIZE MSTR BLOCK
	SETOM	MBLK+.MSRCT	;BY SETTING ONES TO UNITS
	SETOM	MBLK+.MSRUN	;CHANNELS AND CONTROLLERS


;HERE TO LOOK AT NEXT UNIT IN THE SYSTEM.  IF IT BELONGS TO THE
;DESIRED STRUCTURE, ADD IT TO OUR KNOWLEDGE.


STRNXT:	HRROI	T1,UNITNM	;GET POINTER TO NAME
	MOVEM	T1,MBLK+.MSRSA	;AND SAVE IT
	SETZM	UNITNM		;CLEAR NAME IN CASE NOT UPDATED
	SETZM	MBLK+.MSRSN	;CLEAR PHYSICAL NAME POINTER
	MOVX	T1,<.MSRBT+1,,.MSRNU>	;CODE FOR STATUS
	MOVEI	T2,MBLK		;PLACE TO STORE IT
	MSTR			;READ INFO ON NEXT UNIT
	  ERJMP	STRFIN		;ERROR, GO FINISH
	MOVE	T1,MBLK+.MSRST	;GET STATUS BITS FOR THIS DRIVE
	TXNE	T1,MS%MNT	;MAKE SURE IT IS IN A STRUCTURE
	TXNE	T1,MS%OFL	;AND THAT IT IS ON-LINE
	  JRST	STRNXT		;NO, THEN DON'T LOOK AT IT
	MOVE	T1,[POINT 7,UNITNM]	;GET POINTER TO UNIT ALIAS NAME
	MOVE	T2,[POINT 7,STR]	;AND DESIRED STRUCTURE
STRCMP:	ILDB	T3,T1		;GET NEXT CHAR OF STR UNIT IT IN
	ILDB	T4,T2		;AND NEXT CHAR OF WANTED STR
	CAME	T3,T4		;DO THEY MATCH?
	  JRST	STRNXT		;NO, DON'T WANT THIS DRIVE
	JUMPN	T3,STRCMP	;LOOP OVER ALL OF THE NAME
	HLRZ	T1,MBLK+.MSRNS	;GET LOGICAL UNIT NUMBER
	CAIL	T1,MXUNIT	;MAKE SURE NOT TOO BIG
	  ERROR	Logical unit number too large for tables
	SKIPE	UNITSZ(T1)	;MAKE SURE DON'T DUPLICATE ENTRIES
	  ERROR	Duplicate logical unit found in structure
	HRRZ	T2,MBLK+.MSRNS	;GET NUMBER OF PACKS
	SKIPE	PACKS		;IGNORE CHECK IF FIRST PACK
	CAMN	T2,PACKS	;SAME NUMBER OF PACKS AS LAST ONE?
	SKIPN	T2		;AND TOTAL PACKS AT LEAST 1?
	  ERROR	Units don't agree in number of packs in structure
	MOVEM	T2,PACKS	;ALL OK, SAVE NUMBER OF PACKS
	MOVE	T2,MBLK+.MSRCH	;GET CHANNEL NUMBER
	MOVEM	T2,UNITCH(T1)	;REMEMBER IT
	MOVE	T2,MBLK+.MSRUN	;GET UNIT NUMBER
	MOVEM	T2,UNITUN(T1)	;REMEMBER IT TOO
	SKIPN	T2,MBLK+.MSRSU	;GET NUMBER OF BLOCKS (SECTORS)
	  ERROR	Unit found with zero sectors
	MOVEM	T2,UNITSZ(T1)	;SAVE IT TOO
	JRST	STRNXT		;AND LOOK FOR NEXT UNIT




STRFIN:	MOVEI	T1,.FHSLF	;GET READY
	GETER			;GET THE MOST RECENT ERROR
	MOVEI	T1,(T2)		;KEEP ONLY THE ERROR HALF
	CAIE	T1,MSTX18	;FAIL BECAUSE NO MORE UNITS?
	  JRST	LOSE		;NO, OTHER ERROR.
	SKIPN	PACKS		;SEE IF ANY PACKS FOUND
	  ERROR	No units found for structure
	MOVSI	T1,-MXUNIT	;GET READY FOR LOOP OVER ALL UNITS
STRCNT:	SKIPE	UNITSZ(T1)	;SEE IF WE FOUND THIS LOGICAL UNIT
	AOBJN	T1,.-1		;YES, KEEP LOOKING
	MOVEI	T1,(T1)		;KEEP NUMBER OF UNITS FOUND
	CAME	T1,PACKS	;FOUND ALL OF THE UNITS?
	  ERROR	Structure is missing some units
	POPJ	P,		;ALL DONE, RETURN
	SUBTTL	ROUTINE TO READ IN THE BAT BLOCKS FOR A UNIT



;CALLED WITH THE LOGICAL UNIT NUMBER IN AC U, TO READ BOTH OF
;THE BAT BLOCKS INTO CORE AND VERIFY THAT THEY ARE OK.  STATUS OF THE
;UNIT'S BAT BLOCKS RETURNED IN F.  SKIP RETURN TAKEN IF AT LEAST ONE
;BAT BLOCK IS GOOD, WITH IT IN LOCATION BAT.  NONSKIP RETURN
;TAKEN IF BOTH BATS ARE BAD.




GETBAT:	ANDCMI	F,FR.BB1+FR.BB2+FR.BBI	;ASSUME BOTH BATS ARE OK
	MOVEI	T1,BATAD1	;GET ADDRESS OF PRIMARY BAT
	MOVEI	T2,BAT		;AND ADDRESS WHERE TO READ IT TO
	PUSHJ	P,REDBAT	;READ IT IN AND VERIFY IT
	  IORI	F,FR.BB1	;IS WRONG, REMEMBER THAT
	MOVEI	T1,BATAD2	;GET ADDRESS OF SECONDARY BAT BLOCK
	MOVEI	T2,BAT2		;AND ADDRESS TO READ IT INTO
	PUSHJ	P,REDBAT	;READ IT TOO
	  IORI	F,FR.BB2	;ERROR, REMEMBER IT
	XORI	F,FR.BB1+FR.BB2	;COMPLEMENT BITS FOR TEST
	TRCN	F,FR.BB1+FR.BB2	;FIX BITS AND SEE IF BOTH ARE BAD
	  JRST	BATZER		;YES, GO ZERO IT
	AOS	(P)		;AT LEAST ONE IS GOOD, SET FOR SKIP
	TRNE	F,FR.BB2	;IS SECOND BAT BLOCK BAD?
	  POPJ	P,		;YES, JUST RETURN
	TRNE	F,FR.BB1	;IS FIRST BAT BLOCK BAD?
	  JRST	BATCPY		;YES, COPY GOOD ONE INTO FIRST ONE
	MOVSI	T1,-177		;BOTH ARE GOOD, GET READY FOR LOOP
	MOVE	T2,BAT(T1)	;GET A WORD OF FIRST BAT BLOCK
	CAMN	T2,BAT2(T1)	;MATCH OTHER ONE?
	AOBJN	T1,.-2		;YES, KEEP LOOKING
	SKIPGE	T1		;ALL WORDS MATCH?
	IORI	F,FR.BBI	;NO, REMEMBER THAT THEY DIFFER
	POPJ	P,		;AND RETURN

BATZER:	SETZM	BAT		;BOTH ARE BAD, GET READY
	SKIPA	T1,[BAT,,BAT+1]	;TO ZERO THE JUNK
BATCPY:	MOVE	T1,[BAT2,,BAT]	;GET SET TO COPY FROM GOOD BLOCK
	BLT	T1,BAT+177	;DO THE WORK
	POPJ	P,		;THEN RETURN
	SUBTTL	ROUTINE TO READ IN A BAT BLOCK



;THIS ROUTINE TAKES THE BLOCK NUMBER OF A BAD BLOCK IN AC T1,
;AND THE ADDRESS IN CORE TO READ IT INTO IN AC T2, THE UNIT NUMBER
;OF THE DISK IN AC U.  SKIP RETURN TAKEN IF THE READ BAT LOOKS
;OK, ERROR RETURN TAKEN IF IT IS BAD.




REDBAT:	ANDX	T1,DOP%UA	;KEEP ONLY THE ADDRESS
	MOVE	T4,T1		;AND SAVE IT FOR LATER
	TXO	T1,<FLD .DOPPU,DOP%AT>	;PUT IN CODE FOR UNIT ADDRESSING
	MOVE	T3,UNITCH(U)	;GET CHANNEL NUMBER
	DPB	T3,[POINTR (T1,DOP%CN)]	;STORE IT
	MOVE	T3,UNITUN(U)	;GET UNIT NUMBER
	DPB	T3,[POINTR (T1,DOP%UN)]	;STORE IT TOO
	MOVEI	T3,(T2)		;POINT TO PLACE TO READ TO
	MOVEI	T2,200		;WANT TO READ 1 BLOCK
	DSKOP			;DO IT
	  ERJMP	LOSE		;BETTER NOT FAIL
	MOVS	T1,BT.NAM(T3)	;GET NAME OF THE BAT BLOCK
	CAIN	T1,'BAT'	;IS IT AS IT SHOULD BE?
	CAME	T4,BT.BLK(T3)	;AND IS THE BLOCK NUMBER CORRECT?
	  POPJ	P,		;NO, ERROR
	MOVE	T1,BT.COD(T3)	;GET THE SPECIAL CODE VALUE
	HRRZ	T2,BT.ADR(T3)	;AND ADDRESS OF FIRST PAIR OF WORDS
	CAIN	T1,BT$COD	;IS THE CODE CORRECT?
	CAIL	T2,200		;AND THE ADDRESS REASONABLE?
	  POPJ	P,		;NO, RETURN
	HLRE	T1,BT.ADR(T3)	;GET NUMBER OF FREE WORDS
	MOVN	T1,T1		;MAKE POSITIVE
	SKIPL	T1		;MAKE SURE IT IS REASONABLE
	CAILE	T1,200		;IS IT?
	  POPJ	P,		;NO, ERROR
	AOS	(P)		;BLOCK LOOKS OK, SET FOR SKIP
	POPJ	P,		;RETURN
	SUBTTL	ROUTINE TO TYPE STATUS OF THE BAT BLOCKS



;THIS ROUTINE IS USED TO LOOK AT THE STATUS BITS WE FOUND OUT ABOUT
;THE UNIT, AND TO GIVE A SHORT DESCRIPTION OF THE CONDITION OF THE
;BAT BLOCKS.  CALLED WITH THE FLAGS WE COMPUTED IN AC T1.




BATSTS:	MOVEI	T2,[ASCIZ/Both BAT blocks are correct/]	;GET DEFAULT
	TRNE	T1,FR.BBI	;ARE THEY INCONSISTANT?
	MOVEI	T2,[ASCIZ/BAT blocks differ from each other/]
	TRNE	T1,FR.BB1	;IS FIRST BAT BLOCK BAD?
	MOVEI	T2,[ASCIZ/Primary BAT block is bad/]
	TRNE	T1,FR.BB2	;IS SECONDARY BAT BLOCK BAD?
	MOVEI	T2,[ASCIZ/Secondary BAT block is bad/]
	XORI	T1,FR.BB1+FR.BB2 	;GET READY
	TRCN	T1,FR.BB1+FR.BB2	;BOTH BAD?
	MOVEI	T2,[ASCIZ/Both BAT blocks are bad/]
	TYPE	(T2)		;OUTPUT CORRECT STATUS MESSAGE
	POPJ	P,		;AND RETURN
	SUBTTL	ERROR HANDLING ROUTINE



;HERE ON ANY ERROR AT ALL.  WE CLOSE UP THE FILES IF THEY WERE
;OPEN, AND RESTART THE PROGRAM.



LOSE:	HRROI	T1,[ASCIZ/
? /]				;GET PRELIMINARY TEXT
	PSOUT			;TYPE IT
	MOVEI	T1,.PRIOU	;OUTPUT TO TERMINAL
	HRLOI	T2,.FHSLF	;LAST ERROR IN THIS FORK
	SETZ	T3,		;ALL OF THE TEXT
	ERSTR			;PRINT THE ERROR
	JFCL			;FAILED
	JFCL			;FAILED


LOSFIN:	HRROI	T1,[ASCIZ/

/]				;GET FINAL STRING
	PSOUT			;TYPE IT TOO
	MOVEI	T1,.PRIIN	;GET READY
	CFIBF			;CLEAR INPUT BUFFER
	JRST	REEN		;AND START OVER



NOTDSK:	HRROI	T1,[ASCIZ/
? Device must be a disk/]	;GET STRING
	PSOUT			;TYPE IT
	JRST	LOSFIN		;AND JOIN OTHER CODE



NOPOWR:	HRROI	T1,[ASCIZ/
? This program can not run without WHEEL or OPERATOR capabilities

/]				;GET STRING
	PSOUT			;OUTPUT IT
	HALTF			;QUIT
	JRST	.-1		;AND STAY THAT WAY
	SUBTTL	COMMAND JSYS SUBROUTINES



;ANY ERROR IN THESE ROUTINES RESTARTS THE PROGRAM.
;POINTER TO THE COMMAND BLOCK IS IN AC T1.



NOISE:	HRROM	T2,NOIBLK+.CMDAT	;SAVE AS DATA
	MOVEI	T2,NOIBLK	;POINT TO BLOCK
	JRST	COMMND		;AND GO DO COMND JSYS



CONFRM:	MOVEI	T2,[FLDDB. (.CMCFM)]	;GET CONFIRM FUNCTION
COMMND:	COMND			;PARSE THE FUNCTION
	  ERJMP	LOSE		;ERROR, GO COMPLAIN
	TXNE	T1,CM%NOP	;DID IT PARSE?
	  JRST	LOSE		;NO, COMPLAIN
	POPJ	P,		;YES, RETURN SUCCESSFULLY




NOIBLK:	FLDDB.	(.CMNOI)	;BLOCK FOR NOISE FUNCTION
	SUBTTL	THE DATA AREA



CMDBLK:	0,,NEWPAR		;ADDRESS OF REPARSE ROUTINE
	.PRIIN,,.PRIOU		;INPUT,,OUTPUT JFNS
	-1,,[ASCIZ/FILADR>/]	;CONTROL-R POINTER
	-1,,TXTBUF		;POINTER TO TEXT BUFFER
	-1,,TXTBUF		;POINTER TO CURRENT POSITION
	TXTLEN			;NUMBER OF CHARS IN BUFFER
	0			;NUMBER OF UNPARSED CHARACTERS
	-1,,ATMBUF		;POINTER TO ATOM BUFFER
	TXTLEN			;NUMBER OF CHARACTERS IN BUFFER
	EXP	JFNBLK		;POINTER TO GTJFN BLOCK

JFNBLK:	GJ%OLD			;FLAGS,,GENERATION NUMBER
	.PRIIN,,.PRIOU		;INPUT,,OUTPUT JFNS
	BLOCK	20		;NO DEFAULTS


	XLIST			;DUMP THE LITERALS
	LIT
	LIST
PDL:	BLOCK	PDLSIZ		;STACK ROOM
PAGMSK:	BLOCK	1		;MASK USED TO KNOW WHEN TO DO A CRLF
PAGCHK:	BLOCK	1		;CHECKSUM FOR AN INDEX BLOCK
PAGTOT:	BLOCK	1		;NUMBER OF PAGES AN INDEX BLOCK REPRESENTS
PAGIDX:	BLOCK	1		;ADDRESS ON DISK OF INDEX BLOCK
ALLPAG:	BLOCK	1		;TOTAL NUMBER OF PAGES USED IN FILE
ALLDAT:	BLOCK	1		;TOTAL NUMBER OF DATA PAGES IN FILE
ALLBAD:	BLOCK	1		;NUMBER OF BAD PAGES IN A FILE
PAGMIN:	BLOCK	1		;FIRST PAGE TO BE LISTED FOR AN INDEX BLOCK
PAGMAX:	BLOCK	1		;LAST PAGE TO BE LISTED
BADPTR:	BLOCK	1		;POINTER TO THE BAD BLOCK ADDRESSES

	ZERUNT==.		;FIRST LOCATION TO ZERO

UNITOF:	BLOCK	1		;ADDRESS OF START OF A UNIT
PACKS:	BLOCK	1		;NUMBER OF PACKS IN A STRUCTURE
MBLK:	BLOCK	.MSRBT+1	;STORAGE FOR MSTR JSYS
UNITBB:	BLOCK	MXUNIT		;NUMBER OF BAD BLOCKS FOUND IN A UNIT
UNITBR:	BLOCK	MXUNIT		;NUMBER OF BAD REGIONS FOUND IN A UNIT
UNITSZ:	BLOCK	MXUNIT		;NUMBER OF BLOCKS IN EACH UNIT
UNITCH:	BLOCK	MXUNIT		;CHANNEL NUMBER UNITS ARE ON
UNITUN:	BLOCK	MXUNIT		;UNIT NUMBER ON CHANNEL UNIT IS ON
UNITFL:	BLOCK	MXUNIT		;FLAGS CONCERNING BAT BLOCK
UNITCT:	BLOCK	MXUNIT		;NUMBER OF MONITOR ADDED PAIRS TO BATS

	ZEREND==.-1		;LAST LOCATION TO ZERO

WIDTH:	BLOCK	1		;THE WIDTH THAT WAS SPECIFIED
FDB:	BLOCK	.FBLWR+1	;STORAGE FOR FILE'S FDB
JFN:	BLOCK	1		;JFN OF FILE WE ARE READING
JFNOUT:	BLOCK	1		;OUTPUT JFN
JFNBTS:	BLOCK	1		;BITS RETURNED BY GNJFN
DEVICE:	BLOCK	1		;DEVICE DESIGNATOR FOR A STRUCTURE
STR:	BLOCK	10		;ASCIZ STRING FOR STRUCTURE NAME
UNITNM:	BLOCK	10		;ASCIZ STRING FOR UNIT'S STRUCTURE
SAVEP:	BLOCK	1		;STORAGE OF STACK
TXTBUF:	BLOCK	TXTLEN/5+1	;BUFFER FOR COMMAND JSYS
ATMBUF:	BLOCK	TXTLEN/5+1	;BUFFER FOR ATOM BUFFER



	END	START