ER[EXAM];

%	D I S K   D I A G N O S T I C

TO ASSEMBLE:	@MI@ EXAM.MC
LOAD:		EXAM
%
*
*
*	OUTGOING COMMAND BITS FROM MAXC TO DISK AND CONTROLLER
*
	INSERT[DBEG.MC];

	LVN[L20];

	TARGET[ILC];

	MP[UDSEL,13];	* DESELECT THE UNIT
	MP[RSC,7];	* RESET SECTOR CONDITION
	MP[RPDL,10];	* RESET PROCESSOR DATA LATE
	MP[RCDL,11];	* RESET CONTROLLER DATA LATE
	MP[RSO,12];	* RESET SECTOR OVERFLOW
	MP[I1EN,0];	* ENABLE SECTOR INTERRUPTS
	MP[I2EN,4];	* ENABLE TYPE 1 WORD INTERRUPTS
	MP[I3EN,5];	* ENABLE TYPE 2 WORD INTERRUPTS
	MP[I4EN,6];	* ENABLE TYPE 3 WORD INTERRUPTS
	MP[LCR,1];	* LOAD CYLINDER ADDRESS REGISTER
	MP[LHR,2];	* LOAD HEAD ADDRESS REGISTER
	MP[COM,3];	* INTERPRET THIS AS A COMMAND
	MP[WRGAT,20];	* TURN ON WRITING
	MP[RDGAT,21];	* TURN ON READING
	MP[ERGAT,24];	* TURN ON ERASING
	MP[SEEK,22];	* INITIATE SEEK TO C.A.R.
	MP[RHR,23];	* RESET HEAD ADDRESS REGISTER TO 0
	MP[HDS,25];	* ACTIVATE R/W HEAD IN H.A.R.
	MP[RESTOR,26];	* SEEK TO CYLINDER 0
	SP[RESET,RSC,RPDL,RCDL,RSO];  * RESETS CONTROLLER ERRORS
	PM[ALL1CYL,777 0000];
	F[HDADR,23,27];	* HEAD ADDRESS FIELD
	F[CYLADR,17,27];* CYLINDER ADDRESS FIELD
*
*	INCOMING STATUS FROM DISK AND CONTROLLER
*
	MP[IC,0];	* INDEX CONDITION
	MP[UUNS,1];	* UNIT UNSAFE
	MP[UOFF,2];	* UNIT OFF LINE
	MP[UNR,3];	* UNIT NOT READY (NORMALLY = SEEKING)
	MP[SKFAIL,4];	* SEEK HAS FAILED
	MP[URDONLY,5];	* UNIT CANNOT BE WRITTEN ON
	MP[CNR,6];	* CONTROLLER IS NOT READY
	MP[SC,7];	* SECTOR CONDITION
	MP[PDL,10];	* PROCESSOR DATA LATE CONDITION
	MP[CDL,11];	* CONTROLLER DATA LATE CONDITION
	MP[SO,12];	* SECTOR OVERFLOW CONDITION
*
*	SELECT THE PROPER DISK UNIT
*
	MC[UNIT];
	MC[DISCONN,UDSEL,RESET];
	MC[RESTORC,I1EN,RESET,COM,RESTOR];
	MC[IDLE,I1EN,RESET];
	MC[CURSEC];
	MC[ISTAT];
SELUNIT:Q←7S;
SU1:	KUNIT←Q;
	P←AQ;
	KSET←DISCONN,KNEWCOMM;
	P←P-1;
	Q←P,GOTO[SU1,ALU>=0];
	Q←3S;
	CURSEC←Q;
	KUNIT←UNIT;
	P←P;
	KSET←IDLE,KNEWCOMM;
	CALL[WAITRDY];
	KSET←RESTORC,KNEWCOMM;
	CALL[WAITRDY];
	KSET←IDLE,KNEWCOMM;
	ARM←2160S;
	RETURN;
*
*	WAIT UNTIL DISK UNIT AND CONTROLLER BOTH READY
*
	MC[ALLRDY,UOFF,SKFAIL,UNR,CNR];
WAITRDY:Q←ALLRDY;
	P←KSTAT;
	P←P AND Q; GOTO[.-2,ALU#0];
	RETURN;
*
*	INTERRUPT HANDLERS FOR SECTOR AND WORD INTERRUPTS
*
	IM[SILOC,5];
	SILOC[(YKPTR←KUNIT,CALL[SIHAND])];
	IM[WILOC,11];
	REPEAT[3,WILOC[(YKPTR←KUNIT,CALL[WIHAND])]];
	MC[SECRDY];
	MC[WDRDY];
	MC[RSCC,RSC,I1EN];
	MC[KDO];
	MC[KDOL];
	MC[KDI];
	MC[KDIL];
	MC[SIUNIT];
	MC[WIUNIT];
	MC[QAFT];
	MC[WDWRTN];
	MC[WDWRTNL];
	MC[I2ENWD,I1EN,I2EN];
	MC[OOPSMSK,BADUNIT,PDL,CDL,SO];
SIHAND:	QAFT←Q;
	P←UNIT;
	Q←KUNIT;
	P-Q, KCSET←RSCC;
	Q←1S, GOTO[SIEX,ALU#0];
	SECRDY←Q;
	Q←OOPSMSK;
	P←KSTAT;
	P←P AND Q;
	CALL[ANALYZE,ALU#0];
	SIUNIT←Y;
	P←CURSEC;
	Q←P+1, P←3S;
	P-Q, P←KSTAT;
	CURSEC←Q, PQ RCY [43], GOTO[ZEROSEC,ALU=0];
	Q←P;
	GOTO[SIEX,QEVEN];
	Q←2S;
	CURSEC←Q,GOTO[SIEX];
ZEROSEC:CURSEC←NULL;
SIEX:	Q←QAFT, RETURN, P←P1, IRET;
WIHAND:	P←AQ, Q←WDRDY;
	Q←1S, P←P, GOTO[.+2,QEVEN];
DATLAT:	BRKP[1];
	WDRDY←Q;
	WIUNIT←Y;
	KMDR←KDO;
	KMDRL←KDOL;
	Q←KWDATA;
	Q←KRDATA;
	KDI←Q;
	KDIL←KMDRL, Q←P;
	KCSET←I2ENWD;
	RETURN, P←P1, IRET;
*
*	WAIT FOR THE BEGINNING OF THE SELECTED SECTOR
*
	MC[SECTOR];
WAITSEC:SECRDY←NULL;
	KUNIT←7S;
WIX1:	P←SECRDY;
	P;
	GOTO[WIX1,ALU=0];
	SECRDY←NULL;
	Q←CURSEC;
	P←SECTOR;
	P-Q;
	GOTO[WIX1,ALU#0];
	KUNIT←UNIT,RETURN;
*
*	WAIT UNTIL READY FOR NEXT WORD. INTERRUPT 4 REQUEST MUST NOT
*	BE BACK-PANEL JUMPERED.
*
	SP[BADUNIT,UUNS,UOFF,UNR,SKFAIL,URDONLY];
	MC[WDW];
	MC[WDSCOPE];
WAITWD:	P←WDRDY;
	P;
	GOTO[WW0,ALU=0];
DATLAT1:BRKP[1],GOTO[WW0];
WW0:	Q←OOPSMSK,INHINT;
	P←KSTAT,INHINT;
	P AND Q;
	CALL[ANALYZE,ALU#0];
	P←WDRDY;
	P;
	P←NULL, GOTO[WW0,ALU=0];
	WDRDY←NULL,RETURN;
*
*	ANALYZE WHY WAITWD FAILED
*
	SV[CONDMSK,7777 7777 7777];
ANALYZE:Q←P AND Q, P←CONDMSK;
	P AND Q;
	GOTO[.+2,ALU=0];
STOP1:	BRKP[1], GOTO[PURIFY];
	AQ, RETURN;  * SET THE ALU OUTPUT NONZERO, REQUESTING RECOVERY
*
PURIFY:	IRET;
	P←P;
	KUNIT←UNIT;
	P←P;
	KSET←IDLE, KNEWCOMM;
	Q←3S;
	CURSEC←Q, GOTO[XFLP];
*
*	SEEK TO CYLINDER SPECIFIED IN CURCYL[17-27].
*
	MC[CURCYL,UZERO];
	MC[CYLCOM,UZERO];
	MC[SCRCOM,LCR,RESET,I1EN];
	MC[SEECOM,COM,RESET,SEEK,I1EN];
SEEKSUB:CALL[WAITRDY];
	Q←CURCYL;
	P←SCRCOM;
	Q← P OR Q;
	CYLCOM←Q;
	KSET←CYLCOM,KNEWCOMM;
	CALL[WAITRDY];
	KSET←SEECOM,KNEWCOMM;
	CALL[WAITRDY];
	RETURN;
*
*	SET HEAD REGISTER
*
	MC[RESETHD,RESET,COM,RHR,I1EN];
	MC[SETHD,LHR,I1EN];
	MC[SHCOM];
	MC[HEAD];
SETHDSUB:KSET←RESETHD,KNEWCOMM,CALL[WAITRDY];
	P←HEAD;
	Q←SETHD;
	Q←P OR Q;
	SHCOM←Q;
	KSET←SHCOM,KNEWCOMM,CALL[WAITRDY];
	RETURN;
*
*	ROUTINE TO SET UP PARAMETERS FOR BLOCKS OF WORDS TO BE
*	TRANSFERRED. DRIVEN BY A TABLE WITH THREE WORDS PER ENTRY.
*	FIRST, A CODE FOR THE ROUTINE TO BE USED. SECOND, A STARTING
*	ADDRESS IN A MEMORY. THIRD, THE LENGTH OF THE BLOCK.
*
	MC[ROUTINE];
	MC[WDSTOXF];
	MC[MEMAD];
	MC[WDTPTR];
	SV[WCONS,1234567];
	MC[RCONS];
	MC[CKSUM2];
*
	MC[DHDWD];
	MC[DUNBLK];
	MC[DUB1];
	MC[DUB2];
	MC[DUB3];
	MC[PREDAT];
	MC[PD1];
*
	SV[WDTB1,0];	SV[WDTB1A,IP[DHDWD]];	SV[WDTB1B,1];
	SV[WDTB2,1];	SV[WDTB2A,0];		SV[WDTB2B,1];
	SV[WDTB3,0];	SV[WDTB3A,IP[DUNBLK]];	SV[WDTB3B,4];
	SV[WDTB4,1];	SV[WDTB4A,0];		SV[WDTB4B,1];
	SV[WDTB5,0];	SV[WDTB5A,IP[PREDAT]];	SV[WDTB5B,2];
	SV[WDTB6,2];	SV[MMAD,0];		SV[WDTB6B,1000];
	SV[WDTB7,1];	SV[WDTB7A,0];		SV[WDTB7B,1];
*
	SV[@WDTAB,IP[WDTB1]];
TESTAD:	P←WDW;
	Q←P+1,P←WDSTOXF;
	WDW←Q;
TAD0:	Q←P-1;
	WDSTOXF←Q,RETURN[ALU>=0];
	Y←WDTPTR;
	Q←SY,INCY;
	ROUTINE←Q;
	Q←SY,INCY;
	MEMAD←Q;
	P←SY,INCY;
	WDTPTR←Y,GOTO[TAD0];
*
*	GET A WORD FOR THE DISK.
*
	MC[CKSUM];
FETIT:	CALL[TESTAD];
	P←ROUTINE;
	P←P;
	P←P-1,GOTO[SMF,ALU<=0];
	P←P-1,GOTO[CKSUMF,ALU<=0];
	P←P-1,GOTO[MMF,ALU<=0];
	P←P-1,GOTO[CONSF,ALU<=0];
ADF:	P←Q←MEMAD;
	Q←P+1,KDO←Q;
	MEMAD←Q;
	P←KDO;
	Q←17S;
	Q←P AND Q;
	KDOL←Q,GOTO[MMF1];
CONSF:	Q←WCONS;
	KDO←Q;
	KDOL←NULL,GOTO[MMF1];
MMF:	P←KREAD←MEMAD,CALL[ONEINST];
	KDO←KMDR;
	Q←P+1,KDOL←KMDRL;
	MEMAD←Q;
MMF1:	P←Q←CKSUM;
	P←PQ RCY [1],Q←KDO;
	P←P+Q,Q←KDOL;
	Q←P+Q;
	CKSUM←Q,RETURN;
SMF:	Y←MEMAD;
	Q←SY,INCY;
	KDO←Q;
	P←DHDWD;
	P-Q;
	GOTO[.+2,ALU=0];
NOTHD:	P←NULL;
	KDOL←NULL;
	MEMAD←Y,GOTO[MMF1];
CKSUMF:	Q←CKSUM;
	KDO←Q;
	CKSUM2←Q;
	Q←1S;
	KDOL←Q;
CKSMOK:	CKSUM←NULL;
TWOINST:P←P;
ONEINST:RETURN;
*
*	DISPOSE OF A WORD FROM THE DISK.
*
STORIT:	CALL[TESTAD];
	P←ROUTINE;
	P←P;
	P←P-1,GOTO[SMS,ALU<=0];
	P←P-1,GOTO[CKSUMS,ALU<=0];
	P←P-1,GOTO[MMS,ALU<=0];
	P←P-1,GOTO[CONSS,ALU<=0];
ADS:	P←Q←MEMAD;
	P←P+1;
	Q←P,P←MEMAD;
	MEMAD←Q;
	Q←KDI;
	P#Q;
	GOTO[DATERR,ALU#0];
	Q←KDIL;
	Q←P#Q,P←17S;
	P AND Q;
	GOTO[MMS1,ALU=0];
	GOTO[DATERR];
CONSS:	Q←KDI;
	P←WCONS;
	P#Q;
	RCONS←Q,GOTO[MMS1,ALU=0];
DATERR:	BRKP[1],GOTO[MMS1];
MMS:	KMDR←KDI;
	KMDRL←KDIL;
	P←KWRITE←MEMAD;
	Q←P+1;
	MEMAD←Q;
MMS1:	P←Q←CKSUM;
	P←PQ RCY [1],Q←KDI;
	P←P+Q,Q←KDIL;
	Q←P+Q;
	CKSUM←Q,RETURN;
SMS:	Y←MEMAD;
	Q←KDI;
	SY←Q,INCY;
	MEMAD←Y,GOTO[MMS1];
CKSUMS:	P←KDI;
	Q←CKSUM;
	P-Q;
	GOTO[CKSMOK,ALU=0];
CKSMERR:P←KSTAT;
	BRKP[1],GOTO[CKSMOK];
*
*	AFTER PAUSING FOR PAUS WORDS, READ A RECORD OF LREC WORDS, LEAVING
*	ITS LAST WORD IN KDI AND KDIL.
*
	MC[LREC];
	MC[PAUS];
	MC[WDSPAUSD];
	MC[WDSREAD];
	MC[HDSEL,COM,HDS,I1EN];
	MC[HDSELWI,COM,HDS,I1EN,I4EN];
	MC[READC,COM,RDGAT,HDS,I4EN,I1EN];
READREC:WDSPAUSD←NULL;
	WDRDY←NULL;
	KSET←HDSELWI;
	CALL[WW0];
RR1:	P←WDSPAUSD;
	Q←PAUS;
	P-Q;
	Q←P+1,GOTO[RR2,ALU>=0];
	WDSPAUSD←Q,CALL[WAITWD];
	GOTO[RR1];
RR2:	WDSREAD←NULL;
	KSET←READC;		* GIVE READ COMMAND
	P←NULL;		* LET ANY PENDING INTERRUPT HAPPEN
	P←NULL;
	P←NULL;
	P←NULL;
	WDRDY←NULL,CALL[WAITWD];	* CLEAR WORD READY FLAG AND WAIT
RDLP:	P←WDSREAD;
	Q←LREC;
	P-Q;
	Q←P+1,GOTO[TURNOFF,ALU>=0];
	WDSREAD←Q,CALL[WAITWD];
	CALL[STORIT];
	GOTO[RDLP];
*
*	WRITE A RECORD OF PAUS ZERO WORDS, ONE SYNC WORD, LREC DATA WORDS,
*	AND BETWEEN ONE AND TWO GARBAGE WORDS.
*
	MC[WDSWRT];
	SV[SYNC,17];
	MC[WRITC,COM,WRGAT,ERGAT,HDS,I4EN,I1EN];
	MC[ERASC,COM,ERGAT,HDS,I4EN,I1EN];
WRTREC:	WDSPAUSD←NULL;
	KDO←NULL;
	KDOL←NULL;
	WDRDY←NULL;
	KSET←WRITC;
	CALL[WW0];
WR1:	P←WDSPAUSD;
	Q←PAUS;
	P-Q;
	Q←P+1,GOTO[WR2,ALU>=0];
	WDSPAUSD←Q,CALL[WAITWD];
	GOTO[WR1];
WR2:	WDSWRT←NULL;
	Q←SYNC;
	KDO←Q;
	KDOL←Q,CALL[WAITWD];
WRTLP:	P←WDSWRT;
	Q←LREC;
	P-Q;
	Q←P+1,GOTO[WR3,ALU>=0];
	WDSWRT←Q;
	CALL[FETIT];
	CALL[WAITWD];
	GOTO[WRTLP];
WR3:	KDO←NULL;
	KDOL←NULL,CALL[WAITWD];
	CALL[WAITWD];
	CALL[WAITWD];
	CALL[WAITWD];
	KSET←ERASC,CALL[WAITWD];
	CALL[WAITWD];
	CALL[WAITWD];
TURNOFF:KSET←HDSEL;
	RETURN;
*
*	ISSUE COMMANDS CONTINUOUSLY TO THE DISK
*
COMCONT:CALL[SETUP],INHINT;
CC1:	KSET←HDSEL;
	GOTO[CC1];
*
*	SET UP THE PROCESSOR TO TAKE INTERRUPTS ON DISK CHANNELS 1 AND 4,
*	PROCESSOR CHANNELS ???. THEN SELECT THE UNIT.
*
SETUP:	ARM←0S,INHINT;
	SETF[100S],INHINT;
	IRET,INHINT;
	P←NULL,INHINT;
	CALL[SELUNIT];
	RETURN;
*
*	UNPACK THE HEAD, CYLINDER, AND SECTOR FROM THE DSKADR WORD.
*
	MC[DSKADR];
UNPK:	CALL[CKDSKAD];
	Q←DSKADR;
	P←77 0000S;
	Q←P AND Q;
	HEAD←Q;
	Q←DSKADR;
	P←7770S;
	P←Q←P AND Q;
	P←PQ RCY [33];
	Q←P;
	CURCYL←Q;
	Q←DSKADR;
	P←7S;
	Q←P AND Q;
	SECTOR←Q;
	RETURN;
*
*	READ THROUGH A SECTOR UNTIL REACHING WORD WDNO. THE RECORD FORMAT
*	OF THE SECTOR IS DETERMINED BY A TABLE FMTAB WITH TWO WORDS PER RECORD.
*	THE FIRST WORD GIVES THE NUMBER OF WORDS TO PAUSE BEFORE TRYING TO
*	READ THE RECORD. THE SECOND WORD GIVES THE LENGTH OF THE RECORD.
*
	SV[WDNO,0];
	SV[FULLSEC,1012];
	MC[WDSDONE];
	SV[FMTAB1,5];
	SV[FMTAB1A,2];
	SV[FMTAB2,3];
	SV[FMTAB2A,5];
	SV[FMTAB3,3];
	SV[FMTAB3A,1003];
	SV[FMTAB4,0];	*FOR FUTURE EXPANSION
	SV[FMTAB4A,0];
	SV[@FMTAB,IP[FMTAB1]];
	MC[HDSEL1,RESET,COM,HDS,I1EN];
	MC[FMTPTR];
	SV[PAUSDELT,3];
	SV[NREADRECS,3];
	MC[NRRNOW];
	MC[LSTAT];
XFSEC:	CALL[UNPK];
	CALL[SEEKSUB];
	CALL[SETHDSUB];
	CALL[WAITSEC];
XF0:	KSET←HDSEL1,KNEWCOMM;
	WDSDONE←NULL;
	Q←@FMTAB;
	FMTPTR←Q;
	WDSTOXF←NULL;
	Q←@WDTAB;
	WDTPTR←Q;
	CKSUM←NULL;
	NRRNOW←NULL;
	WDW←NULL;
XF1:	Y←FMTPTR;
	Q←SY,INCY;
	PAUS←Q;
	P←WDNO;
	Q←WDSDONE;
	P←P-Q;
	GOTO[QUIT,ALU<=0];
	Q←SY,INCY;
	P-Q;
	GOTO[.+2,ALU>=0];
	Q←P;
	LREC←Q;
	P←WDSDONE;
	Q←P+Q;
	WDSDONE←Q;
	FMTPTR←Y;
	P←NRRNOW;
	Q←P+1,P←NREADRECS;
	P-Q,NRRNOW←Q;
	GOTO[RDIT,ALU>=0];
	Q←PAUS;
	P←PAUSDELT;
	Q←P+Q;
	PAUS←Q,CALL[WRTREC];
	GOTO[XF1];
RDIT:	CALL[READREC];
	GOTO[XF1];
QUIT:	KSET←IDLE,KNEWCOMM;
	RETURN;
*
*	INCREMENT DISK ADDRESS AND CHECK FOR VALIDITY.
*
	SV[DAD1,1];
	SV[DAD1A,7];
	SV[DAD1B,2];
	SV[DAD1C,7777 7777 7770];
	SV[DAD2,1 0000];
	SV[DAD2A,77 0000];
	SV[DAD2B,23 0000];
	SV[DAD2C,7777 7700 7777];
	SV[DAD3,10];
	SV[DAD3A,7770]
	SV[DAD3B,6250];
	SV[DAD3C,7777 7777 0007];
	SV[@DAD,IP[DAD1]];
	MC[CARRY];
NXTDSKAD:Y←@DAD;
	X←2S;
	Q←1S;
	CARRY←Q;
NADLP:	P←SY,INCY;
	Q←CARRY;
	AQ;
	Q←DSKADR,GOTO[.+2,ALU<=0];
	Q←P+Q;
	DSKADR←Q;
	P←SY,INCY;
	Q←P AND Q;
	P←SY,INCY;
	P-Q;
	DECX,GOTO[INBNDS,ALU>=0];
	Q←CARRY;
	AQ;
	GOTO[BADADR,ALU<=0];
	P←DSKADR;
	Q←SY,INCY;
	Q←P AND Q;
	DSKADR←Q,GOTO[NADLP,X>=0];
INBNDS:	CARRY←NULL,INCY,GOTO[NADLP,X>=0];
	RETURN;
BADADR:	GOTO[.],BRKP[1];
*
CKDSKAD:Y←@DAD;
	X←2S;
	CARRY←NULL;
	GOTO[NADLP];
*
*	STORE THE RANDOM NUMBER GENERATOR PARAMETERS IN MAIN MEMORY
*	LOCATIONS RNM1 AND DOWNWARD.
*
	SV[RNM0,0];
	SV[RNM1,20];
	SV[RNM2,777];
	MC[CMAD];
RNS:	Q←RNM1;
	CMAD←Q;
	X←20S;
RNSLP:	RETURN[X<0];
	Q←LX;
	MDR←Q;
	P←WRITE←CMAD;
	Q←P-1;
	CMAD←Q,DECX,GOTO[RNSLP];
*
*	LOAD THE RANDOM NUMBER GENERATOR PARAMETERS FROM MAIN
*	MEMORY LOCATIONS RNM1 AND DOWNWARD.
*
RNL:	Q←RNM1;
	CMAD←Q;
	X←20S;
RNLLP:	RETURN[X<0];
	P←READ←CMAD;
	Q←P-1;
	CMAD←Q;
	P←MDR;
	LX←P,DECX,GOTO[RNLLP];
*
*	GENERATE THE NEXT RANDOM NUMBER; LEAVE IT IN Q. ASSUMES L
*	REGISTERS AND X ARE LEFT FROM LAST CALL.
*
NXTRN:	Q←L20,GOTO[.+2,X>=0];
	X←17S;
	P←LX;
	LX←Q←P+Q,DECX;
	L20←AQ,RETURN;
*
*	STORE RANDOM NUMBER GENERATOR PARAMETERS IN MAIN MEMORY AND THEN
*	FROM THOSE PARAMETERS GENERATE RANDOM WORDS INTO MAIN MEMORY WORDS
*	RNM1+1 THROUGH RNM2.
*
SRPG:	CALL[RNS];
	X←NULL;
	P←RNM1;
SRPGL:	Q←P+1,P←RNM2;
	P-Q,CMAD←Q;
	RETURN[ALU<0];
	CALL[NXTRN];
	MDR←Q,CALL[NXTRN];
	MDRL←Q;
	P←WRITE←CMAD,GOTO[SRPGL];
*
*	READ RANDOM NUMBER GENERATOR PARAMETERS FROM MAIN MEMORY AND THEN
*	CHECK THE MAIN MEMORY WORDS IN RNM1+1 TO RNM2 BY COMPARING THEM
*	WITH OUTPUT FROM THE RANDOM NUMBER GENERATOR.
*
	SV[ERRCNT,0];
CRPG:	X←20S;	* SAVE GENERATION PARAMETERS
	P←LX;
	RX←P,DECX;
	GOTO[.-2,X>=0];
	CALL[RNL];
	X←NULL;
	P←RNM1;
CRPGL:	Q←P+1,P←RNM2;
	P-Q,CMAD←Q;
	GOTO[RPRESTOR,ALU<0];
	READ←CMAD,CALL[NXTRN];
	P←MDR;
	P#Q;
	CALL[RDATERR,ALU#0];
	CALL[NXTRN];
	P←MDRL;
	Q←P#Q,P←17S;
	P AND Q;
	CALL[RDATERR,ALU#0];
	P←CMAD,GOTO[CRPGL];
*
RDATERR:P←ERRCNT,BRKP[1];
	Q←P+1;
	ERRCNT←Q;
	POP;
	POP;
	GOTO[DOSEC];
*
RPRESTOR:X←20S;	* RESTORE GENERATION PARAMETERS
	P←RX;
	LX←P,DECX;
	GOTO[.-2,X>=0];
	RETURN;
*
*	DUMP OR CHECK NSEC SECTORS OF RANDOM INFORMATION STARTING AT
*	DISK ADDRESS DSTRTAD.
*
	SV[NSEC,57450];
	SV[DSTRTAD,7775 0000 0000];
	MC[SECLFT];
	MC[PDSKADR];
	SV[DISTAB,2];
	SV[DISTAB1,0];
	SV[DISTAB2,7777 7777 7776];
	SV[@DISTAB,IP[DISTAB]];
	MC[RANAD];
RSTR:	CALL[SETUP],INHINT;
	RANAD←NULL;
	Q←3S,GOTO[DMPRCOM];
*
DMPR:	CALL[SETUP],INHINT;
	RANAD←NULL;
	Q←1S;
	L20←AQ,GOTO[DMPRCOM];
*
RSTRR:	CALL[SETUP],INHINT;
	Q←1S;
	RANAD←Q;
	Q←3S,GOTO[DMPRCOM];
*
DMPRCOM:NREADRECS←Q;
	Q←DSTRTAD;
	DSKADR←Q;
	Q←FULLSEC;
	WDNO←Q;
	P←NSEC;
	Q←P-1;
	SECLFT←Q;
	Q←RNM0;
	MMAD←Q;
DMPRLP:	Q←DSKADR;	* PERMUTE THE SECTORS ON A TRACK FOR FASTER
	PDSKADR←Q;	* ACCESS
	P←3S;
	Q←P AND Q,P←@DISTAB;
	Q←P+Q,P←DSKADR;
	Y←Q;
	Q←SY;
	Q←P+Q;
	DSKADR←Q;
	CALL[SRPG];
DOSEC:	CALL[XFSEC];
	CALL[CRPG];
	Q←DHDWD;
	P←DSKADR;
	P-Q;
	GOTO[.+2,ALU=0];
HDRERR2:BRKP[1],GOTO[.];
	Q←PDSKADR;
	DSKADR←Q;
	P←SECLFT;
	Q←P-1;
	SECLFT←Q,RETURN[ALU<0];
	P←RANAD;
	P;
	GOTO[.+3,ALU=0];
	CALL[GRANAD];
	GOTO[DMPRLP];
	CALL[NXTDSKAD];
	GOTO[DMPRLP];
*
*	GENERATE A RANDOM DISK ADDRESS.
*
	MC[MASK];
	MC[LIM];
	MC[LPCT];
GRANAD:	Y←@DAD;
	Q←2S;
	LPCT←Q;
GRANADLP:INCY;
	Q←SY,INCY;
	MASK←Q;
	Q←SY,INCY;
	LIM←Q;
GENIT:	CALL[NXTRN];
	P←MASK;
	Q←P AND Q,P←LIM;
	P-Q;
	GOTO[GENIT,ALU<0];
	LIM←Q;
	P←DSKADR;
	Q←SY,INCY;
	P←P AND Q,Q←LIM;
	Q←P OR Q;
	DSKADR←Q;
	P←LPCT;
	Q←P-1;
	LPCT←Q,GOTO[GRANADLP,ALU>=0];
	RETURN;
*
*	DUMP MAIN MEMORY ON THE DISK.
*
	SV[STRTLOC,0];
	SV[ENDLOC,37 7777];
DMPM:	CALL[SETUP],INHINT;
	Q←1S;
	NREADRECS←Q;
	GOTO[DRMEM];
*
RSTM:	CALL[SETUP],INHINT;
	Q←3S;
	NREADRECS←Q;
	GOTO[DRMEM];
*
DRMEM:	Q←DSTRTAD;
	DSKADR←Q;
	Q←FULLSEC;
	WDNO←Q;
	Q←STRTLOC;
	MMAD←Q;
RSTLP:	P←MMAD;
	Q←ENDLOC;
	P-Q;
	GOTO[.+2,ALU<=0];
	RETURN;
	Q←DSKADR;
	DHDWD←Q;
	CALL[XFSEC];
	P←DHDWD;
	Q←DSKADR;
	P-Q;
	GOTO[.+2,ALU=0];
HDRERR:	BRKP[1],GOTO[DRMEM];
	CALL[NXTDSKAD];
	P←MMAD;
	Q←1000S;
	Q←P+Q;
	MMAD←Q,GOTO[RSTLP];
*
*	WRITE ADDRESSES ON A PACK
*
	SV[PKNO,7775 0000 0000];
	MC[SECSLFT];
PKINIT:	CALL[SETUP],INHINT;
	NREADRECS←NULL;
PKCOM:	Q←2S;
	WDNO←Q;
	Q←7777 7700 0000S;
	P←PKNO;
	Q←P AND Q;
	DSKADR←Q;
	Q←57450S;	* NUMBER OF SECTORS PER PACK
	SECSLFT←Q;
PKLP:	P←SECSLFT;
	Q←P-1;
	SECSLFT←Q,GOTO[PKEXIT,ALU<0];
	Q←DSKADR;
	DHDWD←Q;
	CALL[XFSEC];
	P←DHDWD;
	Q←DSKADR;
	P-Q;
	GOTO[HDRERR,ALU#0];
	Q←DSKADR;
	P←PKNO;
	P←P#Q,Q←7777 7700 0000S;
	P←P AND Q;
	GOTO[CKR,ALU=0];
PKNOERR:BRKP[1],GOTO[.];
CKR:	CALL[NXTDSKAD];
	GOTO[PKLP];
PKEXIT:	RETURN,BRKP[1];
*
PKCK:	CALL[SETUP],INHINT;
	Q←1S;
	NREADRECS←Q,GOTO[PKCOM];
*
CKRST:	CALL[SETUP],INHINT;
	GOTO[CKR];
*
*	TRANSFER A SECTOR REPEATEDLY
*
XFRPT:	CALL[SETUP],INHINT;
XFLP:	CALL[CKDSKAD];
	CALL[UNPK];
	CALL[SEEKSUB];
	CALL[SETHDSUB];
	CALL[WAITSEC];
	CALL[XF0];
	GOTO[XFLP];
*
*	WRITE ADDRESSES IN MAIN MEMORY
*
	MC[CURLOC];
	SV[@CURLOC,IP[CURLOC]];
WMMAD:	Y←@CURLOC,CALL[SETUP],INHINT;
WMM1:	Q←STRTLOC;
	CURLOC←Q;
WMMLP:	Q←CURLOC;
	P←ENDLOC;
	P-Q;
	GOTO[.+2,ALU>=0];
****THIS CODE PROBABLY NEEDS MODIFICATION****
WMDONE:	BRKP[1],GOTO[.];
	Q←MDR←SY;
	P←MDR, CALL[PQCOMP];
	Q←MDRL←SY;
	P←AQ,Q←17S;
	Q←P AND Q;
	P←MDRL,CALL[PQCOMP];
	P←WRITE←CURLOC;
	P←P;
	P←P;	* MAKE THIS LOOP MORE THAN TWO MREFS LONG
	P←P;
	P←P;
	P←P;
	P←P;
	P←P;
	Q←P+1;
	CURLOC←Q,GOTO[WMMLP];
*
*	SET THE MAIN MEMORY TO ZEROS
*
	SV[ZERO,0];
	SV[@ZERO,IP[ZERO]];
ZMEM:	Y←@ZERO,CALL[SETUP],INHINT;
	GOTO[WMM1];
*
*	CHECK FOR CORRECT MEMORY CONTENTS
*
CKMMAD:	Q←STRTLOC,CALL[SETUP],INHINT;
	CURLOC←Q;
CKMLP:	Q←CURLOC;
	P←ENDLOC;
	P-Q;
	GOTO[.+2,ALU>=0];
CKMDONE:BRKP[1],GOTO[.];
	READ←CURLOC;
	P←CURLOC;
	Q←MDR;
	P#Q;
	GOTO[.+2,ALU=0];
CONBAD:	BRKP[1],GOTO[.];
	Q←17S;
	P←P AND Q;
	Q←MDRL;
	P#Q;
	GOTO[CONBAD,ALU#0];
	P←CURLOC;
	Q←P+1;
	CURLOC←Q,GOTO[CKMLP];
*
*	CALL THE MEMORY DUMP AND RESTORE ROUTINES
*
DMPMEM:	CALL[DMPM],INHINT;
	BRKP[1],GOTO[.-1];
*
RSTMEM:	CALL[RSTM],INHINT;
	BRKP[1],GOTO[.-1];
*
DMPRAN:	CALL[DMPR],INHINT;
	GOTO[.-1],BRKP[1];
*
RSTRAN:	CALL[RSTR],INHINT;
	GOTO[.-1],BRKP[1];
*
RSTRRAN:CALL[RSTRR],INHINT;
	BRKP[1],GOTO[.-1];