Google
 

Trailing-Edge - PDP-10 Archives - isi-saio_19830204 - isi-sa10/boot.mac
There are 59 other files named boot.mac in the archive. Click here to see a list.
;<ISI-SA10>BOOT.MAC.103	 3-Feb-83 13:59:30	Edit by ISI-SA10
;
;	SAIO Changes Copyright 1982, All Rights Reserved
;	University of Southern California
;
; <KOMPEL>BOOT.MAC.3,  1-Dec-82 00:14:42, Edit by KOMPEL
;#102 fix for tape errors
;#101 FIx for no dev
VERSION==5; <KOMPEL>BOOT.MAC.2, 23-Nov-82 15:13:56, Edit by KOMPEL
;#1 - #66 from old isi v4 boot
; UPD ID= 563, SNARK:<5.MONITOR>BOOT.MAC.15,  31-Mar-82 11:52:00 by LEACHE
;Update edit number for previous edit
; UPD ID= 551, SNARK:<5.MONITOR>BOOT.MAC.14,  18-Mar-82 15:46:21 by MILLER
;TCO 5.1762. Move code at start of FNDDEV to better place
; UPD ID= 366, SNARK:<5.MONITOR>BOOT.MAC.13,  16-Dec-81 16:06:16 by LEACHE
;Fix comment
; UPD ID= 86, SNARK:<5.MONITOR>BOOT.MAC.12,  31-Jul-81 09:58:22 by LEACHE
;Improve reporting of "structure not found" errors
; UPD ID= 33, SNARK:<5.MONITOR>BOOT.MAC.11,  15-Jul-81 08:14:26 by LEACHE
;More of previous edit
; UPD ID= 30, SNARK:<5.MONITOR>BOOT.MAC.10,  14-Jul-81 10:56:33 by LEACHE
;Remove all pretense of MTBOOT using a device name
; UPD ID= 2292, SNARK:<5.MONITOR>BOOT.MAC.9,   2-Jul-81 15:29:17 by LEACHE
;Correct debugging example
; UPD ID= 2291, SNARK:<5.MONITOR>BOOT.MAC.8,   2-Jul-81 14:13:56 by LEACHE
;Add /E switch (Load and go to location 141)
;Move KDDT to 500000 when debugging
; UPD ID= 2111, SNARK:<5.MONITOR>BOOT.MAC.7,  31-May-81 11:53:55 by LEACHE
;Shorten assembly error-messages
; UPD ID= 2110, SNARK:<5.MONITOR>BOOT.MAC.6,  31-May-81 11:43:46 by LEACHE
;Make error routine use STRNAM if CURNAM zero
;Force interactive mode on any error
; UPD ID= 2080, SNARK:<5.MONITOR>BOOT.MAC.5,  26-May-81 09:52:01 by LEACHE
;Display pass on swappable load
; UPD ID= 1979, SNARK:<5.MONITOR>BOOT.MAC.4,  12-May-81 13:18:14 by LEACHE
;Fix minor bug in MTBOOT
; UPD ID= 1970, SNARK:<5.MONITOR>BOOT.MAC.3,  10-May-81 10:28:19 by LEACHE
;Minor bug fix
; UPD ID= 1965, SNARK:<5.MONITOR>BOOT.MAC.2,   8-May-81 10:39:34 by LEACHE
;Rewrite error messages & error handling
; UPD ID= 1567, SNARK:<5.MONITOR>BOOT.MAC.14,  19-Feb-81 11:35:20 by LEACHE
;Bump maximum dumpable core to 3 meg
; UPD ID= 1566, SNARK:<5.MONITOR>BOOT.MAC.13,  18-Feb-81 09:30:23 by LEACHE
;Make BOOT complain if the dump file is too small
;Make /D & /S noops for MTBOOT
; UPD ID= 1518, SNARK:<5.MONITOR>BOOT.MAC.12,   4-Feb-81 21:04:23 by ZIMA
;Adjust comments on previous.
; UPD ID= 1517, SNARK:<5.MONITOR>BOOT.MAC.11,   4-Feb-81 17:40:44 by ZIMA
;TCO 5.1257 - Handle uninitialized memory for KS:
;  Put BLT of 20-23 under conditional for KL only
;  Do DBE scan for low 256K at GOTCOR
;  Do DBE scan for high memory at SETEP2
;Fixes problems including trashed ROOT-DIRECTORY on powerfail and SWPPTP
;BUGHLTs on reload.
; UPD ID= 1492, SNARK:<5.MONITOR>BOOT.MAC.10,  26-Jan-81 12:08:55 by LEACHE
;Increase code pages from 3 to 4
; Add /I switch (Information)
; Place following under control of feature test switch FT.RP2:
;	(1) symbols from RP20 microcode
;	(2) attempt/do not attempt to load DX20B's
; UPD ID= 1369, SNARK:<5.MONITOR>BOOT.MAC.9,  18-Dec-80 11:36:58 by LEACHE
;Fix bug that prevented all directory entries from being written to dump file
; Section-align directory entries for dump file
; Add symbols PHYPAG, PHYADR, NMEG.
; UPD ID= 1270, SNARK:<4.RP20-UTILITIES>BOOT.MAC.6,  13-Nov-80 10:45:09 by WACHS
;Add support for TM78/TU78, fix code for RP07, make the magtape stuff
; table driven
; UPD ID= 1251, SNARK:<5.MONITOR>BOOT.MAC.6,  10-Nov-80 11:44:52 by LEACHE
;Stop BOOT from writing DX20 microcode to dump file.  Add diagrams + comments
; Reload DX20 during auto-reload of monitor (currently for disk only)
; Display DX20 "type" during microcode load
; UPD ID= 732, SNARK:<5.MONITOR>BOOT.MAC.5,   5-Jul-80 22:15:17 by ZIMA
;TCO 5.1095 - FIX BOOT TO HANDLE UNINITIALIZED MEMORY INSTEAD OF HANGING.
; UPD ID= 657, SNARK:<5.MONITOR>BOOT.MAC.4,  16-Jun-80 17:22:54 by KONEN
;TCO 5.1063 -
;FIX BOOT TO LOOK AT APR SERIAL NUMBER ON HOME BLOCKS, BEFORE NAME 'PS'
; UPD ID= 553, SNARK:<5.MONITOR>BOOT.MAC.3,  24-May-80 21:27:04 by ZIMA
;TCO 5.1044 - FIX TYPO IN SETZM'ING 20-23.
;TCO 5.1045 - FIX TYPO IN MTBOOT PROMPT.
;TCO 5.1046 - INTERIM FIX FOR KS10 BOOT/MTBOOT HANGING, CLEAR KLINIK
; OUTPUT WORD DURING STARTUP.
; UPD ID= 547, SNARK:<5.MONITOR>BOOT.MAC.2,  21-May-80 16:18:11 by DBELL
;TCO 5.1043 - LOAD DX20 MICROCODE FOR RP20 DISKS
; UPD ID= 230, SNARK:<4.1.MONITOR>BOOT.MAC.63,  30-Jan-80 14:30:34 by ENGEL
;FIX NCSTPG FOR KS
; UPD ID= 229, SNARK:<4.1.MONITOR>BOOT.MAC.62,  30-Jan-80 08:12:35 by ENGEL
; UPD ID= 198, SNARK:<4.1.MONITOR>BOOT.MAC.61,  10-Jan-80 08:34:04 by ENGEL
;ADD <CR><LF> TO ERROR MESSAGES
;<4.MONITOR>BOOT.MAC.60, 18-Oct-79 16:57:29, EDIT BY DBELL
;TCO 4.2534 - DON'T LOAD DX20 MICROCODE IF DUMPING CORE OR AUTO-RELOADING
;<4.MONITOR>BOOT.MAC.59, 11-Oct-79 13:47:20, EDIT BY ENGEL
;MOVE PDL AWAY FROM LODTYP
;<4.MONITOR>BOOT.MAC.58,  5-Oct-79 16:55:50, EDIT BY ENGEL
;CHANGE EDDT TO KDDT IN LINK EXAMPLE
;<4.MONITOR>BOOT.MAC.55, 19-Jul-79 07:48:02, EDIT BY ENGEL
;<4.MONITOR>BOOT.MAC.54, 18-Jul-79 16:49:09, EDIT BY ENGEL
;ADD HELP TEXT TO DEBUGGING BOOT WITH EDDT
;<4.MONITOR>BOOT.MAC.53, 16-Jul-79 10:27:21, EDIT BY ENGEL
;ALLOW SYSTEM TO BOOT WHEN DX20 IS BAD
;<4.MONITOR>BOOT.MAC.52,  6-Jul-79 10:02:15, EDIT BY ENGEL
;<4.MONITOR>BOOT.MAC.51,  5-Jul-79 13:21:23, EDIT BY ENGEL
;FIX NCSTPG
;<4.MONITOR>BOOT.MAC.50,  2-Jul-79 09:04:45, EDIT BY ENGEL
;ADD HINTS FOR HOW TO DEBUG WITH EDDT
;<4.MONITOR>BOOT.MAC.49, 27-Jun-79 15:48:54, Edit by KONEN
;PRINT MTBOOT PROMPT
;<4.MONITOR>BOOT.MAC.48, 25-Jun-79 16:41:08, EDIT BY ENGEL
;DEFEND AGAINST MEMORY PARITY IN LOCATIONS 20-23
;<4.MONITOR>BOOT.MAC.47, 22-Jun-79 14:30:16, EDIT BY ENGEL
;ADD HIGH CORE SAVING AND RUBOUT CHANGES
;<4.MONITOR>BOOT.MAC.46, 10-Jun-79 14:44:37, Edit by MCLEAN
;<4.MONITOR>BOOT.MAC.45, 10-Jun-79 14:33:47, Edit by MCLEAN
;MOVE DECISION ON LOAD TYPE FOR BOOT OF SM FOR MORE ROOM
;<4.MONITOR>BOOT.MAC.44,  4-MAR-79 14:35:04, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.MONITOR>BOOT.MAC.43, 26-JAN-79 22:31:45, EDIT BY MCLEAN
;GET CORRECT NUMBER OF CYLS PER UNIT FOR RP07
;<4.MONITOR>BOOT.MAC.42, 26-JAN-79 22:25:14, EDIT BY MCLEAN
;ADD RP07
;<4.MONITOR>BOOT.MAC.41, 17-JAN-79 14:53:26, EDIT BY DBELL
;PUT IN THE SYMBOL A%VFST FOR THE FIRST ADDRESS OF BOOT, AND FIX
;TSTPAG AND SETLCV TO USE IT.
;<4.MONITOR>BOOT.MAC.40, 16-JAN-79 10:05:44, EDIT BY DBELL
;FIX TSTADR TO USE VFREE CORRECTLY.
;<4.MONITOR>BOOT.MAC.39, 15-JAN-79 10:34:32, EDIT BY DBELL
;TCO 4.2154 - MAKE THE UPPER LIMIT ON LOADING VARY ACCORDING TO .JBSYM,
; AND ADD THE /A SWITCH TO FORCE LOADING OF ALL OF A PROGRAM.  CLEAN UP
; THE PAGE DEFINITIONS.  EXTEND LOADING RANGE FROM 377 TO BOOT ITSELF.
;<4.MONITOR>BOOT.MAC.37,  7-NOV-78 18:12:26, EDIT BY MCLEAN
;FIX SAVING IF GT 512 K

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1981 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	TITLE BOOT - DISK AND TAPE BOOTSTRAP
	SUBTTL L.BOSACK 23-SEP-73 (OLD, OLD ORIGINAL)
	SALL
	SEARCH MONSYM,MACSYM,PHYPAR ;#8 Needed for sa10

V%WHO==6
V%MAJOR==10
V%MINOR==1
V%EDIT==101
	COMMENT \

   EEEEEEEEEEEEEEE   DDDDDDDDDDDD     DDDDDDDDDDDD    TTTTTTTTTTTTTTT
   EEEEEEEEEEEEEEE   DDDDDDDDDDDD     DDDDDDDDDDDD    TTTTTTTTTTTTTTT
   EEEEEEEEEEEEEEE   DDDDDDDDDDDD     DDDDDDDDDDDD    TTTTTTTTTTTTTTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEEEEEEEEEEEEEE   DDD         DDD  DDD         DDD       TTT
   EEEEEEEEEEEEEEE   DDD         DDD  DDD         DDD       TTT
   EEEEEEEEEEEEEEE   DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEE               DDD         DDD  DDD         DDD       TTT
   EEEEEEEEEEEEEEE   DDDDDDDDDDDD     DDDDDDDDDDDD          TTT
   EEEEEEEEEEEEEEE   DDDDDDDDDDDD     DDDDDDDDDDDD          TTT
   EEEEEEEEEEEEEEE   DDDDDDDDDDDD     DDDDDDDDDDDD          TTT



NOW THAT I HAVE YOUR ATTENTION, HERE ARE A FEW HINTS ON DEBUGGING BOOT 
WITH EDDT.  THE FIRST THING THAT NEEDS TO BE DONE IS TO CREATE AN .EXE FILE
WITH BOTH BOOT AND EDDT IN IT.  THIS CRITICAL STEP IS DONE WITH LINK
AND WOULD LOOK SOMETHING LIKE THE EXAMPLE BELOW. TO ASSEMBLE BOOT
WITH PROPER DEBUGGING INSTRUCTIONS FOLLOW THE INSTRUCTIONS AT SETPTB.
(IF YOU FAIL TO DO THIS, KDDT'S PAGES WILL NOT BE PLACED IN THE VITRUAL
MAP AND KDDT WILL HANG ONCE BOOT TURNS VIRTUAL MEMORY ON.)

NOW FOR HOW TO LINK IT:


@LINK
*/SET:.LOW.:40000		;BOOT CODE GOES HERE
*/SET:INCOD:500000		;KDDT GOES HERE
*BOOT,KDDT,DXMCA.RMC/G		(*BOOT,KDDT,DXMCA.RMC,DXMCE.RMC/G - TO INCLUDE
				 RP20 MICROCODE)

@SAVE BOOT.EXE

IF YOU GET A MESSAGE LIKE:
  
	?LNKPCL PROGRAM TOO COMPLEX TO LOAD, SAVING AS FILE DSK:005LNK.EXE

SIMPLY RENAME THAT FILE TO BOOT.EXE - THE FILE IS OK.

TO TEST THE EXE FILE:

@GET BOOT.EXE
@START 500000

-- YOU SHOULD NOW GET A DDT PROMPT

ENT=

-- YOU SHOULD NOW SEE THE VALUE OF THE SYMBOL DISPLAYED (40000)

IF EITHER OF THESE TESTS FAIL, YOU BLEW IT AND MUST START OVER.

THE .LOW. PSECT IS BOOT. PSECT INCOD IS KDDT.  THE ABOVE LINK COMMANDS LOAD 
KDDT AT 500000 AND BOOT AT 40000. DXMCA.RMC IS THE TU70 MICROCODE AND
NEEDS TO BE LINKED EVEN IF YOU HAVE NO TU70. DXMCE.RMC IS THE RP20 MICROCODE
AND ALSO HAS TO BE LOADED.

STEP NUMBER TWO IS TO GET THE SYSTEM TO THE POINT WHERE IT HAS TYPED "BOOT>"
AT YOU (I.E. KLI AND FRIENDS). ASSUMING YOU ARE USING DIRECTORY <ENGEL>
THE FOLLOWING IS A TYPICAL EXAMPLE OF HOW TO LOAD THE BOOT BEING DEBUGGED:

BOOT><ENGEL>BOOT.EXE/L
BOOT>/G500000
EDDT


NOW YOU ARE IN EDDT AND CAN ACCESS ANY OF BOOT'S SYMBOLS THAT OCCUR BEFORE
FNDDEV.  THERE ARE COUPLE OF TRICKY MANEUVERS TO GET TO FNDDEV.
ONCE AT FNDDEV YOU CAN USE ALL THE SYMBOLS AFTER FNDDEV.
THE FOLLOWING IS AN ATTEMPT TO STEP YOU THROUGH ALL OF THAT.
BUT FIRST, A FEW WORDS ABOUT THE GENERAL FLOW OF IT ALL.

BOOT DROPS IN TO WHEREVER YOU SET .LOW. (E.G. 40000).  AT GOTCOR IT
MOVES ITSELF + N PRECEDING LOW CORE PAGES TO HIGH CORE, WHILE MOVING
AN EQUIVALENT NUMBER OF HIGH CORE PAGES TO LOW CORE. THIS LITTLE
GOODY CAUSES ALL THE SYMBOLS TO POINT TO INCORRECT ADDRESSES,
FOR A SHORT TIME.  THE CODE THAT MOVES ALL THIS STUFF AROUND RUNS
IN THE ACS. BOOT ALSO BUILDS MAPS FOR THE ULTIMATE "CONO PAG,"
THAT STARTS THE MAPPING.  ONE OF THESE MAPS IS BUILT AT SETPTB.
THERE IS A COMMENT THERE ABOUT HOW TO ASSEMBLE BOOT
TO GET IT TO BUILD A 256K MAP (THEREBY MAPPING EDDT INTO THE
MAPPED BOOT SPACE).  ONCE BOOT HAS MAPPED ITSELF YOU CAN USE ALL THE
SYMBOLS PAST FNDDEV AND SET BREAKPOINTS AS FREELY AS YOU LIKE.
WHAT FOLLOWS IS A COOKBOOK APPROACH TO GETTING TO FNDDEV.


(WHEN WE LAST SAW THE COMPUTER IT HAD TYPED EDDT AT US. WE WILL CONTINUE FROM 
THERE.)
1.	SET A BREAKPOINT AT GOTCOR+7. THIS IS A JRST 1 TO THE CODE THAT MOVES BOOT
	TO HIGH CORE.

2.	TYPE ENT$G TO START BOOT.

3.	AT THE BREAKPOINT SET A NEW BREAKPOINT AT AC 7 (I.E. 7$B).

4.	TYPE $P

5.	YOU HAVE HIT THE SECOND BREAKPOINT. NOW SET THE THIRD.  SET THIS
	BREAKPOINT AT 773000+TOP2-ENT (I.E. 773000+TOP2-ENT$B).

6.	TYPE $P

7.	TYPE THREE (3) ALT X'S ($X) TO GET PAST THE CONO PAG, TO FNDDEV.
	IF THE KL GOES INTO LIMBO AFTER THE 1'ST $X, YOU PROBABLY FORGOT
	TO MAKE THE DEBUGGING CHANGE AT SETPTB.

8.	YOU ARE NOW AT FNDDEV. GET RID OF THE THREE BREAKPOINTS YOU SET.
	THIS STEP IS VERY IMPORTANT AS YOU HAVE SET A BREAKPOINT IN THE ACS.
	THUS, YOU HAVE TO TYPE 0$1B 0$2B 0$3B (OR $B TO REMOVE ALL BREAKPOINTS).

9.	FROM HERE ON IT IS JUST LIKE MONITOR DEBUGGING.  GOOD LUCK.
	0		*************************		*************************
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
	LODBAS:	      ##*#######################*##	SL	*************************
		      # *			* #		*BBBBBBBBBBBBBBBBBBBBBBB*
		      # *			* #		*BBBBBBBBBBBBBBBBBBBBBBB*
		      # *			* #		*BBBBBBBBBBBBBBBBBBBBBBB*
		      # +++++++++++++++++++++++++ #		*BBBBBBBBBBBBBBBBBBBBBBB*
		      # +     MOVEABLE CODE	+ #		*BBBBBBBBBBBBBBBBBBBBBBB*
		      # +			+ #		*BBBBBBBBBBBBBBBBBBBBBBB*
		      # +			+ #		*BBBBBBBBBBBBBBBBBBBBBBB*
	LODTOP:	      ##+#######################+##		*************************
	MCSPAG:		+      MOVING CODE	+ 		*			*
			+			+ 		*			*
			+++++++++++++++++++++++++ 		*			*
			+      MICRO CODE	+		*			*
			+			+		*			*
			+			+		*			*
			+			+		*			*
	MCEPAG:		+++++++++++++++++++++++++	EL	*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
	TOPBAS:	      %%*%%%%%%%%%%%%%%%%%%%%%%%*%%		*************************
		      % *			* %		*MMMMMMMMMMMMMMMMMMMMMMM*
		      % *			* %		*MMMMMMMMMMMMMMMMMMMMMMM*
		      % *			* %		*MMMMMMMMMMMMMMMMMMMMMMM*
		      % *			* %		*MMMMMMMMMMMMMMMMMMMMMMM*
		      % *			* %		*MMMMMMMMMMMMMMMMMMMMMMM*
		      % *			* %		*MMMMMMMMMMMMMMMMMMMMMMM*
		      % *			* %		*MMMMMMMMMMMMMMMMMMMMMMM*
	TOPTOP:	      %%*%%%%%%%%%%%%%%%%%%%%%%%*%%		*************************
			*     CORE > 256K	*		*			*
			*     (IF PRESENT)	*		*			*
			*			*		*			*
			*			*		*			*
			*************************		*************************

	LEGEND:		BOOT IN PHYSICAL MEMORY			MEMORY BEFORE PAGE MOVEMENT
			+ = BOOT DROP-IN WINDOW			B = PAGES OWNED BY BOOT
			# = SOURCE AREA				M = MONITOR PAGES
			% = TARGET AREA				SL = START LOST PAGES
								EL = END LOST PAGES
	0		*************************		*************************
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
	LODBAS:		*************************	SL	*************************
			*MMMMMMMMMMMMMMMMMMMMMMM*		*???????????????????????*
			*MMMMMMMMMMMMMMMMMMMMMMM*		*???????????????????????*
			*MMMMMMMMMMMMMMMMMMMMMMM*		*???????????????????????*
			*MMMMMMMMMMMMMMMMMMMMMMM*		*???????????????????????*
			*MMMMMMMMMMMMMMMMMMMMMMM*		*???????????????????????*
			*MMMMMMMMMMMMMMMMMMMMMMM*		*???????????????????????*
			*MMMMMMMMMMMMMMMMMMMMMMM*		*???????????????????????*
	LODTOP:		*************************		*???????????????????????*
	MCSPAG:		*			*		*???????????????????????*
			*			*		*???????????????????????*
			*			*		*???????????????????????*
			*			*		*???????????????????????*
			*			*		*???????????????????????*
			*			*		*???????????????????????*
			*			*		*???????????????????????*
	MCEPAG:		*			*	EL	*************************
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
	TOPBAS:		*************************		*			*
			*BBBBBBBBBBBBBBBBBBBBBBB*		*                       *
			*BBBBBBBBBBBBBBBBBBBBBBB*		*                       *
			*BBBBBBBBBBBBBBBBBBBBBBB*		*                       *
			*BBBBBBBBBBBBBBBBBBBBBBB*		*                       *
			*BBBBBBBBBBBBBBBBBBBBBBB*		*                       *
			*BBBBBBBBBBBBBBBBBBBBBBB*		*                       *
			*BBBBBBBBBBBBBBBBBBBBBBB*		*                       *
	TOPTOP:		*************************		*                       *
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*			*		*			*
			*************************		*************************

	LEGEND:		MEMORY AFTER PAGE MOVEMENT		ADDRESS SPACE OF DUMP
			B = PAGES OWNED BY BOOT			? = LOST PAGES (FILE HOLE)
			M = MONITOR PAGES			SL = START LOST PAGES
								EL = END LOST PAGES


\	;END COMMENT BLOCK



;ASSEMBLY PARAMETERS


IFNDEF PORG,<PORG==^D64*^D512>	;PHYSICAL ORIGIN OF CODE

IFNDEF FT.RH,<FT.RH==0>		;#8 SUPPORT FOR THE RH10 OR RH20
IFNDEF FT.RP,<FT.RP==0>		;SUPPORT FOR RP10 (0 IMPLIES RH20 OR RH10)
IFNDEF FT.SA,<FT.SA==0>		;SUPPORT FOR SA10 (DISKS UNLESS FT.MTA)
IFNDEF FT.MTA,<FT.MTA==0>	;MAG TAPE PART 2 IF NONZERO

IFE FT.RH+FT.RP+FT.SA,<FT.RH==1> ;DEFAULT TO RH10/RH20

IFNDEF FT.UDB,<FT.UDB==0>	;USER MODE DEBUG
IFNDEF FT.MTA,<FT.MTA==0>	;MAG TAPE PART 2 IF NONZERO
IFNDEF FT.EXE,<FT.EXE==1>	;LOAD EXE FORMAT FILES
IFNDEF FT.PRT,<FT.PRT==3>	;0 - JUST GLOBALS FOR SWPMON
				;1 = STANDALONE PART 1
				;2 = PART 2
				;3 = STANDALONE PART 1&2
IFN KLFLG,<			;ONLY ALLOW DX20 CODE IF KL10
IFNDEF FT.DX2,<FT.DX2==1>	;DX20/TU7X CODE IF NONZERO
IFNDEF FT.TM8,<FT.TM8==1>	;TM78/TU78 CODE IF NON-0
IFNDEF FT.RP2,<FT.RP2==0>	;RP20 CODE/MICROCODE IF NON-0
>				;END IFN KLFLG
IFE KLFLG,<
IFNDEF FT.DX2,<FT.DX2==0>	;DX20/TU7X CODE IF NONZERO
IFNDEF FT.TM8,<FT.TM8==0>	;TM78/TU78 CODE IF NON ZERO
>				;END IFE KLFLG

IFG <FT.RH+FT.RP+FT.SA>-1,<	;#8 test for too many channel types
	PRINTX ? Inconsistant Channel Definition
	EXP FT.RH,FT.RP,FT.SA	;#8 only one can be non-zero !
	END			;#8 Stop assembly
>				;#8 end of IFG <FT.RH+FT.RP+FT.SA>-1
;
; now flags combining channel and device type
;
FT.RD==FT.RH&<^-FT.MTA>		;#8 RH10/20 disks
FT.RT==FT.RH&FT.MTA		;#8 RH10/20 tapes
FT.SD==FT.SA&<^-FT.MTA>		;#8 SA10 disks
FT.ST==FT.SA&FT.MTA		;#8 SA10 tapes

IF1,<				;#8 Report assembly type
  IFN FT.RD,<PRINTX RPBOOT - Disk Bootstrap program for RH10/20
	PRGNAM=SIXBIT 'RPBOOT' >	;#8 .
  IFN FT.RP,<PRINTX BOOT - Disk Bootstrap program for RP10
	PRGNAM=SIXBIT 'RPBOOT' >	;#8 .

  IFN FT.SD,<PRINTX SDBOOT - Disk Bootstrap program for SA10 
	PRGNAM=SIXBIT 'SDBOOT' >;#8 .
  IFN FT.ST,<PRINTX STBOOT - Tape Bootstrap program for SA10
	PRGNAM=SIXBIT 'STBOOT' >	;#8 .

  IFN FT.RT,<			;#8 RH10/20 tapes
      IFE FT.DX2,<PRINTX MTBOOT - Tape Bootstrap program for RH10/20 without DX10
	PRGNAM=SIXBIT 'MTBOOT' >	;#8 .
      IFN FT.DX2,<PRINTX MTBOOT - Tape Bootstrap program for RH10/20 with DX10
	PRGNAM=SIXBIT 'MTBOOT' >	;#8 .
  >				;#8 end of IFN FT.RT
>				;#8 end of IF1
DEFINE PROMPT<[	PRGNAM		;#8 Define prompt string: program name
IFE VERSION-4,<	BYTE (6)36,'\'>	;#8 .GT. sign, end of string
IFE VERSION-5,<	BYTE (6)'5',36,'\'> ;#20 '5', .GT. sign, end of string
			]>	;#8 end of literal defining prompt string

;PROCESSOR (ETC.) BITS

AP.RES==1B19			;IOB RESET (SAME ON KI AND KL)
PGCLKE==1B18			;CACHE LOOK
PGCLDE==1B19			;CACHE LOAD
PGKLPG==1B21			;KL PAGE

AP.CLR==1B22
AP.SET==1B23
IFE SMFLG,<
AP.NXM==1B25
>
IFN SMFLG,<
AP.INE==1B25			;INTERRUPT 8080
AP.NXM==1B27
>
AP.RNX==AP.CLR!AP.NXM
IMMPTR==1B2!1B4!1B6		;IMMEDIATE PAGE POINTER.
				;1B2 = IMMEDIATE POINTER
				;1B4 = WRITEABLE
				;1B6 = CACHEABLE

;STATE TABLE DEFINATION
;
STTSIZ==^D25			;SIZE OF STATE TABLE
RH0==540
ICA==0				;INITIAL CHANNEL CONTROL WORD ADDRESS IN EPT

.RHRAE==1B24			;REGISTER ACCESS ERROR
.RHMBR==1B25			;MASSBUS RESET
.RHCTE==1B26			;CLEAR TRANSFER ERROR
.RHMBE==1B27			;MASSBUS ENABLE
.RHCLP==1B28			;RESET CLP
.RHAIE==1B30			;ATTENTION INTERRUPT ENABLE
.RHSTP==1B31			;STOP TRANSFER
.RHDON==1B32			;DONE
.RHSBR==70B5			;SBAR
.RHSTR==71B5			;STCR
.RHIVR==74B5			;INTERRUPT VECTOR REGISTER
.TMCSR==00B5			;CONTROL REG.
.TMRDF==71			;READ FORWARD AND GO
.TMBSF==33			;BACKSPACE BLOCK
.TMRWF==07			;REWIND
.TMDSR==01B5			;DEVICE STATUS REG
.TMERR==02B5			;ERROR REGISTER
TMSPIP==20000
TMSMOL==10000			;MEDIUM ON LINE(TELL YOU FORTUNE, 10KCS?)
TMSDRY==200			;DRIVE/FORMATTER READY
TMSIDB==10			;PE ID BURST SEEN
.TMATR==04B5			;ATTENTION SUMMARY REGISTER
.TMFCR==05B5			;FRAME COUNT REG.
.TMDTR==06B5			;DRIVE TYPE REG.
.TMTCR==11B5			;TAPE CONTROL REG.
TMCD8==1400			;800 BPI
TMCD16==2000			;1600 BPI
;DX20 ONLY
;
.DXATP==60			;DX20 DEVICE TYPE CODE FOR TAPES
.DXBTP==61			;DX20 DEVICE TYPE CODE FOR RP20 DISKS

.TDSTR==20B5			;DRIVE STATUS/STATUS INDEX
.TDDEB==1B25			;DEVICE END
.TDDNR==21B5			;DRIVE NUMBER, DRIVE MODE, DATA MODE
.TDMOD==1B23!14B27		;1600 BPI, CORE DUMP MODE
.TDTER==23B5			;TRACK IN ERROR, FLAGS
.TDE0R==26B5			;EXTENDED STATUS REG 0
.TDMNR==3B5			;MAINTENANCE REGISTER
.TDSCB==1B31			;SINGLE CYCLE THE DX20
.TDSTB==1B33			;START DX20
.TDSTR==20B5			;ENDING STATUS
.TDTCR==21B5			;CONTROL REGISTER
.TDFLR==23B5			;FLAGS
.TDAYR==24B5			;ASYNCHRONOUS STATUS
.TDE0R==26B5			;EXTENDED STATUS REGISTER 0
.TDE1R==27B5			;EXTENDED STATUS REGISTER 1
.TDIRR==30B5			;IR REGISTER
.TDPCR==31B5			;PC REGISTER
.TDICB==1B20			;ENABLE IR FROM CRAM
.TDCIB==1B21			;ENABLE CRAM FROM IR
.TDPEB==1B22			;ENABLE PC LOAD
.TDPIB==1B23			;ENABLE PC AUTO INCREMENT
.TDIBR==36B5			;IBUS AND BR REGISTER
.TDATB==1B20			;ATTENTION
.TDCEB==1B21			;COMPOSITE ERROR BIT
.TDMPR==1B23			;MICROPROCESSOR RUNNING BIT

.T8TYP==101			;TM78 DRIVE TYPE
.T7ICD==1B5		;INTERRUPT CODE (DATA XFER)
T7.ICD==77	;MASK FOR ALL INTERRUPT CODES
ICD.DN==1	;DONE, NO ERRORS
ICD.SR==21	;SHORT RECORD
ICD.EF==2	;END OF FILE
ICD.BT==3	;BOT
.T7FMT==2B5		;FORMAT
T7.SER==100000	;SUPPRESS ERROR RECOVERY (REPOSITIONING)
T7.CDP==30000	;CORE-DUMP
T7.1RC==4	;READ 1 RECORD
.T7BC==5B5		;BYTE COUNT
.T7SR==7B5		;STATUS REGISTER
T7.RDY==100000	;DRIVE IS READY
.T7ICN==13B5		;INTERRUPT CODE (NON DATA XFER)
.T7ND0==14B5		;NON-DATA-XFER COMMAND, DRIVE 0
.T7TMS==21B5		;TM STATUS
T7.TMR==1B20	;TM READY
T7.REW==7	;REWIND
T7.SNS==11	;SENSE
T7.BSR==23	;BACKSPACE RECORD
T7.RDF==71	;READ

LR==1B6				;LOAD REGISTER
GO==1B35			;GO BIT IN CONTROL REGISTER
RCLP==1B7			;RESET CLP (IN DATAO)
STLW==1B10			;STORE LOGOUT STATUS WORDS (IN DATAO)
; RP04 DEVICE REGISTERS

R4%CSR==00B5			;DEVICE CONTROL REGISTER
R4%DSR==01B5			;DEVICE STATUS REGISTER
	R4%ERR==1B20		;COMPOSITE ERROR BIT
	R4%DRY==1B28		;DRIVE READY FLAG
R4%ATN==04B5			;RP04 PSEUDO-ATTENTION REGISTER
R4%DST==05B5			;DESIRED SECTOR/TRACK REGISTER
R4%DTR==06B5			;DRIVE TYPE REGISTER
R4%DCA==12B5			;DESIRED CYLINDER REGISTER
RH%XFR==40B5			;RH INITIATE DATA TRANSFER REGISTER

R4%TYP==777B35			;DEVICE TYPE FIELD IN TYPE REGISTER
.R4TYP==20			;RP04 DEVICE TYPE CODE
.R5TYP==21			;RP05 DEVICE TYPE CODE
.R6TYP==22			;RP06 DEVICE TYPE CODE
.R7TYP==42			;RP07 DEVICE TYPE CODE
.R3TYP==24			;RM03 DEVICE TYPE CODE

R4%CSK==02B34			;RP04 SEEK FUNCTION
R4%CRC==03B34			;RE-CALIBRATE FUNCTION IN CONTROL REGISTER
R4%CDC==04B34			;RP04 DRIVE CLEAR FUNCTION
R4%RIP==10B34			;READ-IN PRESET FUNCTION
R4%CPA==11B34			;PACK ACKNOWLEDGE FUNCTION IN CONTROL REGISTER
R4%CWR==30B34			;RP04 WRITE FUNCTION
R4%CRD==34B34			;RP04 READ FUNCTION
RHERR==775120			;RH10 CONI ERROR BITS
NRETRY==5			;NUMBER OF TIMES TO RETRY
TIMOUT==^D50000			;COUNT FOR SOJG TIMEOUT

   IFE SMFLG,<
MAXCHN==7			;MAX # OF CHANNELS
   >
   IFN SMFLG,<
MAXCHN==2			;MAX # OF CHANNELS
   >
MAXDRV==7			;MAX NUMBER OF DRIVES/CHANNEL
; INDEX BLOCK ADDRESS DEFINITIONS

STGADM==<MASKB 12,35>		;MASK FOR STORAGE ADDRESS
MSKSTR IDXADR,,STGADM		;STORAGE ADDR MASK

; EXE FILE DEFINITIONS

.EXDIR==1776			;DIRECTORY BLOCK TYPE
.EXEND==1777			;END BLOCK TYPE
.EXENT==1775			;ENTRY BLOCK TYPE
.EXVER==1774			;VERSION BLOCK TYPE


; JOB DATA DEFINITIONS

.JBSYM==116			;SYMBOL TABLE POINTER


; STRUCTURE DEFINITIONS

DEFSTR (DIDIR,A%FP0,17,18)	;DIRECTORY BLOCK TYPE (=.EXDIR)
DEFSTR (DISIZ,A%FP0,35,18)	;SIZE OF DIRECTORY BLOCK

DEFSTR (DIFLG,0,8,9)		;FLAGS
   DEFSTR (DI%WRT,0,2,1)	;WRITE ACCESS ALLOWED BIT
DEFSTR (DIFIL,0,35,27)		;FILE PAGE NUMBER
DEFSTR (DIRPT,1,8,9)		;REPEAT COUNT
DEFSTR (DIPRO,1,35,27)		;PROCESS PAGE NUMBER

DEFSTR (VBTYP,0,17,18)		;ENTRY VECTOR BLOCK TYPE (=.EXENT)
DEFSTR (VBSIZ,0,35,18)		;SIZE OF ENTRY VECTOR BLOCK (=.VBSIZ)
DEFSTR (VBCNT,1,35,36)		;ENTRY VECTOR COUNT
DEFSTR (VBADR,2,35,36)		;ADDRESS OF ENTRY VECTOR

DEFSTR (EBTYP,0,17,18)		;BLOCK TYPE CODE FOR END BLOCK (=.EXEND)
DEFSTR (EBSIZ,0,35,18)		;SIZE OF END BLOCK

.DISIZ==2			;SIZE OF DESCRIPTORS
.EBSIZ==1			;SIZE OF END BLOCK
.VBSIZ==4			;SIZE OF ENTRY VECTOR BLOCK

; DEFAULT SIZE AND ADDRESS OF ENTRY VECTOR IN DUMP FILE

EVADR==140			;DEFAULT STARTING ADDRESS
EVLEN==1			;DEFAULT LENGTH OF VECTOR
;RH11 EXTERNAL PAGE DEFINITIONS

R0%CS1==1776700			;CONTROL AND STATUS 1
R0%WC==1776702			;WORD COUNT REGISTER
R0%BA==1776704			;UNIBUS ADDRESS REGISTER
R0%DA==1776706			;DESIRED SECTOR/TRACK ADDRESS REGISTER
R0%CS2==1776710			;CONTROL AND STATUS 2
R0%DS==1776712			;DRIVE STATUS REGISTER
R0%ER1==1776714			;ERROR REGISTER 1
R0%AS==1776716			;ATTENTION SUMMARY REGISTER
R0%DT==1776726			;DRIVE TYPE REGISTER
R0%SN==1776730			;SERIAL NUMBER REGISTER
R0%DC==1776734			;DESIRED CYLINDER REGISTER
R0%ER2==1776740			;ERROR REGISTER 2
R0%ER3==1776742			;ERROR REGISTER 3

;SECOND RH11 DEFINITONS
R1%CS1==3772440			;CONTROL AND STATUS 1
R1%WC==3772442			;WORD COUNT REGISTER
R1%BA==3772444			;UNIBUS ADDRESS REGISTER
R1%DA==3772446			;DESIRED SECTOR/TRACK ADDRESS REGISTER
R1%CS2==3772450			;CONTROL AND STATUS 2
R1%DS==3772452			;DRIVE STATUS REGISTER
R1%ER1==3772454			;ERROR REGISTER 1
R1%AS==3772456			;ATTENTION SUMMARY REGISTER
R1%DT==3772466			;DRIVE TYPE REGISTER
R1%SN==3772470
R1%DC=3772472			;DESIRED CYLINDER REGISTER
R1%ER2==3772474			;ERROR REGISTER 2
R1%ER3==3772476			;ERROR REGISTER 3
;
; DEVICE BIT DEFINITIONS FOR RH11

RH.NED==1B23			;NON EX DISK

RH1SC==100000			;SPECIAL CONDITIONS
RH1TRE==040000			;TRE ERROR
RH1RDY==000200			;READY
RH1IE==000100			;INTERRUPT ENABLE
RH1CLR==000040			;CLEAR CHANNEL

RPPGSZ==2000			;PAGE SIZE FOR 11 TRANSFER
UNBMP0==1763000			;ADDRESS OF UNIBUS MAP
UNBMP1==3763000			;UNIBUS MAP
UNVBIT==40000			;VALID BIT FOR UNIBUS
UN36B==100000			;36 BIT TRANSFER MODE


;
; TTY DEFINITIONS
;
CTYIRD=1B27			;INPUT READY
CTYIWD=32			;ADDRESS OF INPUT WORD
CTYORD=1B27			;OUTPUT READY
CTYOWD=33			;OUTPUT WORD
KLIOWD=35			;KLINIK OUTPUT WORD
RELWD=31			;RELOAD WORD
RLFLGS=1B34			;FLAGS THAT CAUSE RELOADS AND DUMPS
RSFLGS=1B32			;RESTART FLAG

CTIRDY=00200			;RECEIVE READY
CTORDY=100000			;TRANSMIT READY
CTYIST=760010			;STATUS REGISTER
CTIDAT=760012			;INPUT BUFFER
CTYLPR=760012			;LINE PARAMETER REGISTER
CTYTCR=760014			;TRANSMIT CONTROL
CTODAT=760016			;OUTPUT DATA BUFFER

CTYCLR=20			;RESET DZ11
CTYSCE=40			;ENABLE SCANNER
CTYBUD=17270			;9600 BAUD 1 STOP BIT
;MACRO TO PERFORM IO OPERATIONS - USE IS INDEPENDENT OF WHICH DISK

;MACRO DEFINITION FOR RP10

IFN FT.RP,<
DEFINE IOOP(OP,OPR)
<IFIDN <OP><CLEAR>,<
	CALL IOXCT
	DATAO DPC,[XWD 500000,776]
>				;END IFIDN CLEAR
IFIDN <OP><SKIPNOERR>,<
	CALL IOXCT
	CONSZ DPC,177720	;ANY ERROR?
>				;END IFIDN SKIPNOERR
IFIDN <OP><XCTOP>,<
	CALL IOXCT
	DATAO DPC,OPR		;EXECUTE OP
>				;END IFIDN XCTOP
IFIDN <OP><SKIPDONE>,<
	CALL IOXCT
	CONSO DPC,10		;SKIP IF DONE
>				;END IFIDN SKIPDONE
>				;END DEFINE IOOP
>				;END IFN FT.RP

; MACRO DEFINITION FOR RP04

IFN FT.RH,<
DEFINE IOOP(OP,OPR)
<IFIDN <OP><CLEAR>,<
	CALL IOXCT
	CONO .-.,2000
	CALL IOXCT
	CONO .-.,4600
>				;END IFIDN CLEAR
IFIDN <OP><SKIPNOERR>,<
	CALL IOXCT
	CONSZ .-.,RHERR		;RH ERROR BITS
>				;END IFIDN SKIPNOERR
IFIDN <OP><XCTOP>,<
	CALL IOXCT
	DATAO .-.,OPR		;EXECUTE OP
>				;END IFIDN XCTOP
IFIDN <OP><SKIPDONE>,<
	CALL IOXCT
	CONSO .-.,.RHDON	;SKIP IF DONE
>				;END IFIDN SKIPDONE
>				;END DEFINE IOOP
>				;#8 END IFN FT.RH
; MACRO TO SAVE AND RESTORE PI ASSIGNMENT

IFN FT.RP, <

DEFINE SAVPI(AC) <
	CONI DPC,AC
	ANDI AC,7
	PUSH P,AC
>				; END OF DEFINE SAVPI

DEFINE RESPI(AC) <
	POP P,AC
	CONO DPC,(AC)
>				; END OF DEFINE RESPI

>				; END OF IFN FT.RP


IFN FT.RH, <			;#8

DEFINE SAVPI(AC) <>

DEFINE RESPI(AC) <>

>				;#8 END OF IF FT.RH
IFN FT.SA,<			;#8 .

; default values

IFNDEF SSAN,<SSAN==2>		;#8 support 2 SA10's
IFNDEF SSANSC,<SSANSC==4>	;#8 4 subchannels per SA10

; Pointers


DEFSTR(DP%CYL,DPOSEK,31,16)	;Cylinder. 16 bits in 1st word of seek buffer
DEFSTR(DP%SRF,DPOSEK+1,15,16)	;Surface. 16 bits in 2nd word of seek buffer
DEFSTR(DP%REC,DPOSEK+1,23,8)	;Record. 8 bits in 2nd word of seek buffer
DEFSTR(DP%LRC,DPOSEK+1,25,2)	;Logical Record within physical record (SW) - 2
				; bits in 2nd word of seek buffer
DEFSTR(DP%SEC,DPOSEK+2,7,8)	;Sector. 8 bits (HW: 1/128 of track) - in
				; 3rd word of seek buffer (for convenience) 

MSKSTR(DP%CMD,DPOOPC,SC%CMD)	;Channel command
MSKSTR(DP%CCF,DPOOPC,SC%CCF)	;Channel command flags
MSKSTR(DP%DEV,DPOOPC,SC%DEV)	;Device address
MSKSTR(DP%LST,DPOADR,SC%LST)	;#8 "Last IOW" flag
MSKSTR(DP%CNT,DPOADR,SC%CNT)	;#8 count field
MSKSTR(DP%ADR,DPOADR,SC%ADR)	;#8 core address field

>				;#8 end of IFN FT.SA
;AC USAGE

F==0				;FLAGS
T1=1				;GP TEMP
T2=2				; ...
T3=3				; ...
T4=4				; ...
Q1=5				;GENERALLY HOLDS A SINGLE CHARACTER
Q2=6				;BYTE POINTER TO AN INPUT STRING
Q3=7				;BYTE POINTER TO AN OUTPUT STRING
P1=10				;OFTEN PRESERVED
P2=11				; ..
P3=12				;A NUMBER
P4=13				;DESTINATION POINTER (DISK ADDR, BYTE PTR)
P5=14				;DISK ADDRESS OR PARSER STATE
P6=15				;DEVICE TYPE INDEX
  TM.IDX==0			;TM02/TM03
  DA.IDX==1			;DX20 FOR TAPES
  T8.IDX==2			;TM78
  DB.IDX==3			;DX20 FOR RP20 DISKS
CX=16				;RETURN ADDRESS FOR VBOOT ENTRY FROM MONITOR
				; NO INTERNAL BOOT CODE MUST USE THIS AC!!!
P=17				;STACK POINTER

;BIT ALLOCATION IN F

F.WRIT==1B0			;WRITE FILE IF ON
F.PHYS==1B1			;PHYSICAL ADDRESSES IF ON, VIRTUAL IF OFF
F.CLR==1B2			;CLEAR CORE IF ON
F.STRT==1B3			;START AFTER LOAD IF ON
F.ACT==1B4			;SOME ACTION REQUEST IF ON
F.BACK==1B5			;BACKUP SCANNER IF ON
F.OUT==1B6			;THIS STATE HAS PRODUCED OUTPUT IF ON
F.DUMP==1B7			;DUMP VS SAVE IF ON
F.EDDT==1B8			;LOAD AND START AT LOCATION 141
F.ALL==1B9			;LOAD ALL PAGES FROM 0 TO VFREE
F.NCHL==1B10			;DON'T USE .JBSYM TO CHANGE PAGE LIMITS
F.INFO==1B11			;DISPLAY PROGRAM INFORMATION
F.TELL==1B12			;#12 Tell what disks are seen, from bit
F.DPER==1B16			;DUMP ERROR - FILE TOO SMALL
F.IOER==1B17			;IO ERROR DURING DUMP
;BITS PROVIDED BY KLINIT ON A SPECIAL LOAD CONDITION

F11.LD==1B0			;DO DEFAULT LOAD
F11.DM==1B1			;DO DUMP OF CORE

;START LOCATION FOR /E
ELOC==141

;FDB STRUCTURE DEFINITIONS

DEFSTR (FBEXL,.FBEXL,35,33)	;LINK TO NEXT EXTENSION FDB
DEFSTR (FBCTL,.FBCTL,35,36)	;CONTROL BITS FROM FDB
DEFSTR (FBADR,.FBADR,35,36)	;DISK ADDRESS OF INDEX BLOCK
DEFSTR (FBGEN,.FBGEN,17,18)	;GENERATION # OF FILE
DEFSTR (FBGNL,.FBGNL,35,33)	;LINK TO NEXT GENERATION
DEFSTR (FBNAM,.FBNAM,35,36)	;POINTER TO NAME STRING
DEFSTR (FBEXT,.FBEXT,35,36)	;POINTER TO EXTENSION STRING
DEFSTR (FBBYV,.FBBYV,35,36)	;POINTER TO PAGE COUNT WORD

	.SYMAD==0
	.SYMVL==1
DEFSTR (SYMET,.SYMAD,2,3)	;SYMBOL TABLE ENTRY TYPE
DEFSTR (SYMAD,.SYMAD,35,33)	;ADDRESS OF BLOCK IN DIR FOR THIS SYM
DEFSTR (SYMVL,.SYMVL,35,36)	;FIRST FIVE CHARS OF NAME
;PHYSICAL CORE PARAMETERS

	;HOW MANY MEGS CAN WE DUMP?
	;NMEG = INTEGRAL MEGS,,FRACTIONAL MEGS (# 1/4 MEGS)
	NMEG=3,,0
	IFN SMFLG,<NMEG=1,,0>
	NCSTPG==(<<<NMEG>&<-1,,0>>*4>+<<NMEG>&<0,,-1>>)
				;NUMBER OF CST PAGES - THIS DETERMINES THE
				; MAXIMUM AMOUNT OF CORE THAT CAN BE DUMPED
				;100 IS A SAFE NUMBER FOR ANY SIZE MACHINE.
				; 1 CST PAGE = 256K CORE = 1000^D8 PAGES
				; 4 CST PAGES = 1 MEG

	PHYPAG== <NCSTPG*1000>-1 ;HIGHEST PHYSICAL PAGE WE CAN DUMP
	PHYADR== PHYPAG*1000	;ADDRESS OF HIGHEST PHYSICAL PAGE WE CAN DUMP

;STORAGE ALLOCATION - *NOTE*  ADDRESSES USED ARE ALL VIRTUAL!
;		THE ORDER OF THESE CANNOT BE CHANGED INDISCRIMINATELY

	A%EDDT==5		;ADDRESS OF EDDT FOR DEBUGGING
	EDDTSZ==40		;NUMBER OF PAGES TO MAP FOR EDDT


;PAGES USED FOR BOOT.  ALLOCATION IS DONE UPWARD FROM VORG (HIGHER TO
; LOWER ADDRESSES).
;WHEN DONE, VFREE IS THE LAST FREE PAGE BEFORE BOOT BEGINS.


DEFINE PG(ADDR,SIZE<1>),<
VFREE==VFREE-<SIZE>		;;MOVE FREE PAGE DOWN BY REQUIRED PAGES
ADDR==<VFREE+1>_9		;;THEN DEFINE DESIRED ADDRESS
>

	VORG==777		;LAST PAGE USED BY BOOT
	VFREE==VORG		;INITIALIZE LAST FREE PAGE

PG	A%CODE,4		;FOUR CODE PAGES
PG	A%FP0			;FILE PAGE ZERO WINDOW
PG	A%XB			;INDEX BLOCK BUFFER
PG	A%SXB			;SUPER INDEX BLOCK BUFFER
PG	A%CST,NCSTPG		;CORE STATUS TABLE PAGES
PG	A%PTB			;PAGE TABLE PAGE
PG	A%EPT			;EXEC PROCESS TABLE
PG	A%DPG			;DIRECTORY HEADER PAGE
PG	A%DIR			;DIRECTORY DATA PAGE

	A%VFST==<VFREE+1>_9	;ADDRESS OF FIRST VBOOT PAGE
	A%VORG==VORG_9		;ADDRESS OF LAST VBOOT PAGE
	A%DATA==A%CODE		;LOCATION WHERE DATA GOES
	VFREE==VFREE		;FORCE VALUE OF VFREE INTO LISTING
DEFINE ALLOC(VAR,SIZ)
<VAR=A.DATA
IFNB <SIZ><A.DATA==A.DATA+SIZ>
IFB <SIZ><A.DATA==A.DATA+1>
>

	A.DATA==A%DATA		;INITIALIZE COUNTER


;NOTE -- DATA BETWEEN Z.STRT AND Z.END GETS ZEROED ON EACH COMMAND

Z.STRT==A.DATA
ALLOC(ISTRNG)			;INPUT STRING POINTER SAVE VARIABLE
ALLOC(START)			;STARTING ADDRESS

;DO NOT REORDER THE FOLLOWING WITHOUT CHANGING DEFAULT PROCESSING

DEFBEG==A.DATA			;BEGINNING OF DEFAULTED AREA
ALLOC(FILSTR)			;POINTER TO FILE NAME STRING
ALLOC(DIRSTR)			;POINTER TO DIRECTORY STRING
ALLOC(EXTSTR)			;POINTER TO FILE EXTENSION STRING
ALLOC(VERSTR)			;POINTER TO VERSION STRING
ALLOC(SWSTR)			;POINTER TO SWITCH STRING
ALLOC(UBSTR)			;POINTER TO UPPER BOUND STRING
ALLOC(LBSTR)			;POINTER TO LOWER BOUND STRING
DEFEND==A.DATA-1		;END OF DEFAULTED DATA AREA

;END OF DO NOT REORDER
ALLOC(D$FIL,8)			;STRING STORAGE FOR FILE NAME
ALLOC(D$DIR,8)			;STRING STORAGE FOR DIR NAME
ALLOC(D$EXT,8)			;STRING STORAGE FOR EXTENSION STRING
ALLOC(D$VER,2)			;STRING STORAGE FOR VERSION STRING
ALLOC(D$SW,2)			;STRING STORAGE FOR SWITCH STRING
ALLOC(D$ISTR,^D25)		;STRING STORAGE FOR INPUT STRING
ALLOC(D$UB,2)			;STRING STORAGE FOR UPPER BOUND STRING
ALLOC(D$LB,2)			;STRING STORAGE FOR LOWER BOUND STRING


ALLOC(VERNUM)			;VERSION NUMBER OF FILE
ALLOC(LWRLIM)			;LOWER PAGE LIMIT FOR GET/SAVE
ALLOC(UPRLIM)			;UPPER PAGE LIMIT FOR GET/SAVE
ALLOC(FNDSTR)			;STRING POINTER TO CURRENT NAME STRING

; DO NOT CHANGE THE ORDER OF THE FOLLOWING TWO WORDS

ALLOC(FNDSTE)			;STRING POINTER TO CURRENT EXT
ALLOC(FNDSTV)			;CURRENT VERSION NUMBER


; ***** NOTE WELL *****  FNDSTE MUST BE FOLLOWED IMMEDIATELY BY
;			 FNDSTV BECAUSE THEY ARE STORED USING A
;			 DMOVEM INSTRUCTION IN ROUTINE GETIDX !
;DISK DEPENDENT DATA

;DO NOT REORDER WITHOUT CHANGING SWPMON 

ALLOC(MAXUNI)			;LARGEST LOGICAL UNIT IN STR

;END OF DO NOT REORDER
ALLOC(FNDCMD)			;BYTE POINTER TO INITIAL TYPEIN
ALLOC(DEV)			;POINTER/ SIXBIT DEVICE NAME
Z.END==A.DATA-1

; FOLLOWING LOCATIONS NOT CLEARED ON EACH COMMAND

	DSKSIZ==^D8
ALLOC(FILPAG)			;PAGE # READ FROM FILE
ALLOC(STRNAM)			;SIXBIT NAME OF FS OR DEV (I.E. MT:)
ALLOC(CURNAM)			;STR NAME BOOT IS CURRENTLY LOOKING AT
ALLOC(DSKTYP)			;UNIT TYPE FOR DISK STRUCTURES
TAPTYP==DSKTYP			;UNIT TYPE FOR TAPES
ALLOC(NUMCYL)			;NUMBER OF CYLINDERS PER UNIT FOR THIS TYPE
ALLOC(DSKTAB,DSKSIZ)		;LOGICAL/PHYSICAL MAPPING
ALLOC(CURPAG)			;CURRENTLY MAPPED DIRECTORY PAGE
				; ** CAUTION: DO NO INITIALIZE TO 0 **
ALLOC(DIORG)			;HOLDS DISK INDEX ORIGIN
ALLOC(XBNUM)			;-1 FOR SHORT FILE, XB # OF MAPPED XB
				; IF THIS FILE IS A LONG FILE
ALLOC(MAXCOR)			;MAX CORE AVAILABLE
IFN FT.MTA,<ALLOC(DIRFLG)>	;NON-ZERO IF EXE DIRECTORY HAS BEEN READ
ALLOC(LODBAS)			;START OF SOURCE AREA (SEE DIAGRAMS)
ALLOC(LODTOP)			;END OF SOURCE AREA
ALLOC(TOPBAS)			;START OF TARGET AREA (SEE DIAGRAMS)
ALLOC(TOPTOP)			;END OF TARGET AREA
ALLOC(LODTYP)			;TYPE OF MONITOR LOAD: 0,DEFAULT - NO OPR COMMAND
ALLOC(MCSPAG)			;STARTING MICROCODE PAGE
				; THIS PAGE ALSO CONTAINS THE BOOT MOVING CODE
ALLOC(MCEPAG)			;ENDING MICROCODE PAGE
ALLOC(DXAMCV)			;WORD TO HOLD DXMCA MCODE VERSION
ALLOC(DXBMCV)			;WORD TO HOLD DXMCB MCODE VERSION
ALLOC(NOLDDX)			;NON-ZERO IF WE DON'T LOAD DX20 MICROCODE
ALLOC(PASS)			;INDICATES WHICH PASS OF UNIT-SEARCH CODE
ALLOC(MONLOD)			;0 = LOADING RESIDENT MONITOR
				;N = N'TH PASS LOADING SWAPABLE MONITOR
ALLOC(PFLAGS)			;PROGRAM FLAGS SAVE-WORD
ALLOC(DEXEPC)			;DUMP.EXE DISK PAGE COUNT
ALLOC(PGCNT)			;COUNT OF CORE PAGES WRITTEN TO DUMP.EXE
ALLOC(ZOOT,5)			;THIS IS TO PUT SOME SPACE BETWEEN THE PDL AND
				;LODTYP.  WITH ALL THE -N(P) ACCESS I SUSPECT
				;A BUG IN SOME OF THEM BUT CAN'T PROVE IT.
				; NON-0, PROMPT AND TAKE OPR COMMAND
PDLEN==20			;PUSH DOWN STACK SIZE
ALLOC(PDL,PDLEN)		;PUSH DOWN STACK
ALLOC (DTCNOW)			;ALLOCATE CONO WORD
IFN FT.RH,<			;#8 
ALLOC(PIA)			;RH20 PI ASSIGNMENT
ALLOC(INIVEC)			;RH20 INITIAL INT VECTOR REGISTER
;#100 ALLOC(APRSER)		;CPU SERIAL NUMBER
>				; END OF IFN FT.RH
ALLOC(APRSER)			;#100 CPU SERIAL NUMBER

ENTFLG==400000			;ENTRY IN USE FLAG IN  DSKTAB
ICCW==20
LCORAD==24			;LOWEST CORE ADDR DUMPED/LOADED
TIMLOC==23			;LOCATION OF TIME BASE
;.DMPUL==1000*NCSTPG-1		;UPPER PAGE LIMIT FOR DUMPING
N.BKPG==4

IFN FT.RP,<

N.SCL4==^D200			;NUMBER OF SECTORS PER CYLINDER
N.CLUN==^D400			;(RP03) NUMBER OF CYLINDERS PER UNIT

>				;END OF IFN FT.RP

IFN FT.RH!FT.SA,<		;#8 RH10/RH20 OR IBM TYPE DISKS

N.SCL3==^D148			;SECTORS PER CYL (RM03)
N.SCL4==^D380			;SECTORS PER CYL (RP04/RP05/RP06)
N.SCL7==^D1376			;SECTORS PER CYL RP07
N.CLP3==^D820			;CYLS PER UNI (RM03)
N.CLP4==^D400			;CYLS PER UNI (RP04/5)
N.CLP6==^D800			;CYLS PER UNI (RP06)
N.CLP7==^D629			;CYLS PER UNI (RP07)
N.STK3==^D30			;SECTORS PER TRACK (RM03)
N.STK7==^D43			;SECTORS PER TRACK (RP07)
N.STK4==^D20			;SECTORS PER TRACK (RP04)

>				;END IFN FT.RH!FT.SA
;GLOBALS FOR THE REST OF THE MONITOR

VBSTRT==:A%DIR			;START OF VBOOT PRIVATE AREA
VBEPT==:A%EPT			;WHERE VBOOT EXPECTS EPT TO BE MAPPED
VBEND==:A%VORG			;VBOOT ITSELF

VBDDAT==:DIORG			;START OF VBOOT DISK DATA AREA


BUTRXB==:151			;ROOT XB
BUTMUN==:152
BUTDRT==:153
BUTCMD==:163
BUTPGS==:202			;VBSTRT,,VBEND
BUTEPT==:203			;VBEPT
BUTPHY==:204			;# OF PAGES TO MAP,,# OF FIRST PHYSICAL PAGE
BUTVIR==:205			;VIRTUAL ADDRESS OF FIRST PAGE TO MAP

IFE FT.PRT,<END>		;END HERE IF SYMBOLS-ONLY ASSEMBLY
;LOCATIONS IN DIR AREA

DIRNUM==A%DIR+2			;DIR NUMBER
SYMBOT==A%DIR+3			;BOTTOM OF ST AREA
SYMTOP==A%DIR+4			;TOP OF ST AREA

HOMNAM==A%FP0+200+0		;SIXBIT /HOM/
HOMID==A%FP0+200+1		;PACK ID
HOMSNM==A%FP0+200+3		;STRUCTURE NAME
HOMLUN==A%FP0+200+4		;# UNI IN STR,,THIS UNI #
HOMRXB==A%FP0+200+10		;ROOT INDEX BLOCK
HOMSER==A%FP0+200+164		;APR SERIAL NUMBER
HOMCOD==A%FP0+200+176		;FUNNY CODE
CODHOM==707070			;TYPE CODE FOR HOME BLOCK

HOMNM2==A%FP0+200*^D<10-8>	;#13 WHERE 2ND HOME BLOCK IS IN BUFFER
				;#13 (BLOCK #10, PAGE STARTS ON BLK #8)

; EXEC PROCESS TABLE LOCATIONS

EPTEST==540			;INDEX TO EXEC SECTION TABLE
EPTATR==421			;INDEX TO ARITHMETIC TRAP INSTRUCTION
EPTPFW==503			;INDEX TO PAGE FAIL WORD
EPTSPT==760			;INDEX TO SPT (ONE WORD TABLE FOR VBOOT)

; OPDEF FOR STORING VALUES IN PAGER REGISTERS

OPDEF XCTU [XCT 4,0]		;PXCT DEFINITION
;OTHER OPDEFS

OPDEF CLRPT [701100,,0]		;CLEAR PAGING MEMORY

IFN SMFLG,<
OPDEF TIOE [710000,,0]
OPDEF TION [711000,,0]
OPDEF RDIO [712000,,0]
OPDEF WRIO [713000,,0]
OPDEF WRHSB [702700,,0]
OPDEF BSIO [714000,,0]
OPDEF BCIO [715000,,0]
OPDEF WRSPB [702400,,0]
OPDEF RDSPB [702000,,0]
OPDEF WRCSB [702440,,0]
OPDEF RDCSB [702040,,0]
OPDEF WRCSTM [702540,,0]
OPDEF RDCSTM [702140,,0]

>				;END IFN SMFLG


; PAGER REGISTERS

CSTMSK==0			;CST MASK, ANDED WITH CST ENTRY
CSTDTA==1			;CST DATA, IORED WITH CST ENTRY
CSTADR==2			;CST BASE ADDRESS
SPTADR==3			;SPT BASE ADDRESS

;KL-10 SPECIFIC UPT DEFINITIONS

UPTPFW==500			;PAGE FAIL ADDRESS
UPTPFO==502			;PAGE FAIL PC WORD

	;ERROR MESSAGE MACRO
	DEFINE $ERROR (CODE)
<	JRST [MOVEI Q2,CODE
	     JRST ERRTYP]
>
IFN FT.PRT&1,<

;  ***** MAIN ENTRY POINT AND INITIALIZATION  *****

;THE FRONT END AND BOOT:
;	1.	ON AN AUTO-RELOAD (ALIAS "SPECIAL" LOAD):
;		A.	FRONT END SETS IN AC0:
;			1.  1B0 - NO PROMPTING
;			2.  1B1 - DUMP
;			3.  B2-B35 - ZERO
;		B.	FRONT END STARTS BOOT AT ENT+1
;
;	2.	ON A DIALOG-LOAD (ALIAS "DEFAULT" LOAD, "MANUAL" LOAD, ETC):
;		A.	FRONT END DOES NOT TOUCH AC0
;		B.	FRONT END STARTS BOOT AT ENT



; SET UP RELOCATION CONSTANT IN ACCUMULATOR 16

ENT:
IFE SMFLG,<

	TDZA F,F		;DIALOGUE LOAD ALWAYS IF STARTED HERE
	JFCL			;SPECIAL LOAD. PRESERVE BITS


	CONI PAG,15		;GET CURRENT STATE OF PAGER
	ANDI 15,PGCLKE!PGCLDE	;CLEAR ALL BUT CACHE STRATEGY BITS
>				;END IFE SMFLG
IFN SMFLG,<
	MOVEI 15,PGKLPG		;SM10 REQUIRES KL PAGE FOR TRAPS
>				;END IFN SMFLG
	CONO APR,AP.RES		;IOB RESET - CLEAR I/O DEVICES
	CONO PAG,0(15)		;TURN OFF PAGING
	MOVSI 17,(<JRST (16)>)	;RETURN INST
	JSP 16,17		;GET CURRENT PC
	SUBI 16,.-ENT		;RETURN HERE 
				;16 NOW CONTAINS RUNTIME ORIGIN OF BOOT
	AND F,[F11.DM!F11.LD]-ENT(16) ;SAVE ONLY DEFINED BITS
	MOVEI T1,PAGTRP-ENT(16)	;THE PAGE FAULT HANDLER
	MOVEM T1,CODEND-ENT+EPTPFW(16) ;SET UP TEMPORARY EPT/UPT
	MOVEI T1,CODEND-ENT(16) ;GET LOCAL ADDRESS
	LSH T1,-11		;MAKE IT A PAGE NUMBER
	IOR 15,T1		;ADD PAGE NUMBER TO THE CACHE BITS
	CONO PAG,0(15)		;MAKE EBR POINT TO THAT PAGE
	TDO T1,[1B2+1B18]-ENT(16) ;AND SET UBR AND INHIBIT METER UPDATE
	DATAO PAG,T1		;MAKE UBR POINT TO ITS PAGE

; DETERMINE HIGHEST PHYSICAL CORE ADDRESS .LE. 256K

J1:	CONO APR,AP.RNX		;RESET NXM FLAG
	MOVEI P1,777000		;START AT PAGE 512
FNDCOR:	SKIP 20(P1)		;REFERENCE PAGE
TSTCOR:	CONSO APR,AP.NXM	;NXM?
	JRST GOTCOR-ENT(16)	;NO, NOW HAVE HIGEST ADDR
J2:	CONO APR,AP.RNX		;NXM - RESET
	SUBI P1,1000		;TRY NEXT LOWER PAGE
	JUMPN P1,FNDCOR-ENT(16)	;LOOP
	HALT .-ENT(16)		;INTERLEAVE PROBABLY BAD

; MOVE DISK SEARCH CODE TO TOP OF CORE WHILE MOVING TOP TO BOOTS OLD PLACE
;***NOTA BENE - P MUST REMAIN PRESERVED UNTIL FNDDEV!!

	;ARRIVE HERE WITH P1 CONTAINING HIGHEST CORE ADDR .LE. 256K
GOTCOR:
IFN SMFLG,<			;DBE SCAN FOR KS ONLY; -11 DOES KL
	MOVEI T1,20		;WHERE TO START TESTING CORE
DBESCN:	MOVE T2,0(T1)		;DO DBE SCAN TO INITIALIZE MEMORY
	MOVEM T2,0(T1)		;INCASE OF POWERFAIL (BLT WON'T WORK)
	CAIE T1,777(P1)		;LAST WORD? (AOBJN WON'T WORK)
	AOJA T1,DBESCN-ENT(16)	;NO, LOOP OVER ALL LOW CORE THERE
>				;END SMFLG CONDITIONAL
	HRRI P5,1		;PUT CODE IN T1
	HRLI P5,BOTMOV-ENT(16)	;GET BOOT MOVING CODE
	BLT P5,T1+MOVEND-BOTMOV	;MOVE MOVING CODE
	HRRZI P2,A%VFST-A%CODE+1000(16)	;WHERE WE START MOVING FROM
				;P2 POINTS TO SOURCE AREA (SEE DIAGRAMS)
	MOVEM P2,P		;SAVE OLD BASE
	MOVEI P1,A%VORG-777000(P1)	;#10 WHERE END OF PROGRAM WILL GO
	HRRZI P3,A%VFST-A%VORG(P1)	;WHERE WE ARE MOVING IT TO
				;P3 POINTS TO TARGET AREA (SEE DIAGRAMS)
	HRRZI P4,1000+A%VORG-A%VFST	;NUMBER OF WORDS TO MOVE (ROUND PAGES)
	JRST T1			;MOVE THE CODE

; CLEAR AND SET UP EXEC PAGE TABLE (EPT)

CORMVD:	HRRZI 16,A%CODE-1000-A%VORG(P1)	;COMPUTE NEW BASE
	MOVE P5,P1		;SAVE ADR OF HIGHEST PHYSICAL PAGE
	SUBI P1,A%VORG-A%EPT	;MOVE BASE TO START OF EPT
	MOVEI T1,1(P1)		;BUILD BLT POINTER
	HRL T1,P1		; ...
	SETZM 0(P1)		;CLR FIRST WORD
	BLT T1,777(P1)		;TO END OF EPT

	MOVSI T1,(<JFCL>)	;NO-OP ARITH TRAP INST
	MOVEM T1,421(P1)	;STORE IN EPT

	;THE NEXT PAGE FAULT HANDLER
	MOVEI T1,PFERR		;THE NEXT PAGE FAULT HANDLER
	MOVEM T1,EPTPFW(P1)	;TO THE EPT

	MOVE P2,P1		;COPY EPT BASE ADR
	LSH P2,-9		;GET PHYS PAGE #

; SET UP EXEC SECTION TABLE AND 1-WORD SPT IN EXEC PAGE TABLE

	MOVEI T1,A%PTB-A%EPT(P1) ;GET PHYSICAL ADDRESS OF PAGE TABLE
	LSH T1,-^D9		;CONVERT TO PAGE #
	MOVEM T1,EPTSPT(P1)	;SAVE 1-WORD SPT
	MOVX T1,1B1!1B4		;CODE=2, WRITE, SPT INDEX=0
	MOVEM T1,EPTEST(P1)	;SAVE SECTION PTR TO PAGE TABLE

; MOVE BASE POINTER TO PAGE TABLE PAGE

	ADDI P1,A%PTB-A%EPT	;CHANGE BASE TO PHYS ADDRESS OF A%PTB

; FORM AOBJN POINTER FOR LOOPING THROUGH PAGE TABLE

	MOVEI T2,A%DIR-A%PTB(P1) ;PHYSICAL ADDRESS IN RH OF T2
	LSH T2,-9		;CONVERT TO # OF DIRECTORY PAGE A%DIR
	HRLI T2,-< <VORG-A%DIR_-9>+1 > ;NUMBER OF PAGES TO MAP

; MAP PAGES USED BY VBOOT
	MOVEI T1,A%DIR_-9(P1)	;START MAPPING AT DIRECTORY AREA

	REPEAT 0,<
;EDDT NEEDS TO BE MAPPED WHEN BOOT GOES MAPPED.
;EDDT DOES NOT NORMALLY GET MAPPED INTO BOOT SPACE. IF YOU WANT TO DEBUG WITH
;EDDT AFTER BOOT GETS TO FNDDEV YOU NEED TO ADD THE FOLLOWING INSTRUCTIONS.
;THEY WILL CAUSE ALL OF THE FIRST 512 PHYSICAL PAGES TO APPEAR IN PAGE MAP
;**NOTA BENE - THE PATCH IS FOR SYSTEMS WITH 512K OR MORE ONLY.

	HRLZI T2,-1000		;DO THE WHOLE MAP PAGE
	MOVE T1,P1		;START AT LOCATION ZERO
>
	;HERE WE PUT THE N PAGES OF THE TARGET AREA (SEE DIAGRAMS)
	;IN THE PAGE MAP
SETPTB:	HRRZ T3,T2		;GET PHYSICAL ADR OF PAGE
	TXO T3,IMMPTR		;FORM AN IMMEDIATE POINTER
	MOVEM T3,(T1)		;STORE PAGE TABLE ENTRY
	ADDI T1,1		;POINT TO NEXT PAGE TABLE ENTRY
	AOBJN T2,SETPTB-ENT(16)	;GO MAP REMAINING PAGES

; SET UP CST ENTRIES FOR ALL PHYSICAL CORE NOW

	ADDI P1,A%CST-A%PTB	;CHANGE BASE POINTER TO CST PAGE
	MOVE T1,P1		;SET ALL SLOTS
	HRLI T1,-<NCSTPG*1000>	;ONE PAGE WORTH
	MOVX T3,1B5		;GET A NON-ZERO CST CODE FIELD
SETCST:	MOVEM T3,(T1)		;STORE A CST ENTRY
	AOBJN T1,SETCST-ENT(16)	;LOOP TILL ALL CST ENTRIES SET UP

	TLO P2,(1B2)		;LOAD UBR
	MOVE P3,P2		;SAVE PAGER WORD TO STORE LATER
	HRLI P2,500600		;SELECT BLOCK 6 AS PREVIOUS AC BLOCK
				; AND LOAD THE UBR
J3:	DATAO PAG,P2		; ...
IFN SMFLG,<
	HRRZI T1,A%EPT-A%CST+EPTSPT(P1) ;GET PHYS ADR OF SPT
	WRSPB T1		;SET UP SPB
	MOVEI T1,400		;SET UP HALT STATUS BLOCK
	WRHSB T1
	WRCSB P1		;SET UP CST
	WRCSTM [77B5]
>				;END IFN SMFLG
IFE SMFLG,<
	HRRZI T1,A%EPT-A%CST+EPTSPT(P1) ;GET PHYS ADR OF SPT
	XCTU [MOVEM T1,SPTADR]-ENT(16) ;STORE SPT BASE ADDRESS IN PAGER AC 3
	XCTU [MOVEM P1,CSTADR]-ENT(16) ;STORE CST BASE ADDRESS IN PAGER AC 2
	MOVX T1,77B5		;GET ONES FOR CST MASK FIELD
	XCTU [MOVEM T1,CSTMSK]-ENT(16) ;STORE CST MASK VALUE IN PAGER AC 0
>				;END IFE SMFLG
	TRO P2,1B22!1B21	;TRAP EN AND KL PAGING
	CONI PAG,T1		;GET PAGER BITS AGAIN
IFE SMFLG,<
	ANDI T1,PGCLKE!PGCLDE>	;ENABLE TOPS20 PAGING
   IFE SMFLG,<
	IOR P2,T1		;ADD IN CACHE BITS
   >
	DMOVE T1,[ CONO PAG,(P2) ;LOAD EBR
		   JRST FNDDEV ]-ENT(16) ;GO SET UP LOW CORE MAP
TOP2:	JRST T1			;AND TURN THE PAGING ON


	LIT

	IFGE .-ENT-141,<PRINTX NO ROOM FOR INITIAL UPT>
	BLOCK 1000-<.-ENT>	;RESERVE REST OF PAGE FOR THE EPT/UPT
	BLOCK A.DATA-A%DATA	;MAKE ROOM FOR ALLOCATED VARIABLES
CODE:
	PHASE A.DATA

IFE SMFLG,<
FNDDEV:	MOVEM F,LODTYP		;SAVE STARTING FLAGS FROM KLINIT
	TXNE F,F11.DM		;DUMPING?
	SETOM	NOLDDX		;YES, DON'T LOAD DX20 MICROCODE
	TXNE F,F11.LD		;AUTO-RELOADING?
	SETZM	NOLDDX		;YES, RELOAD DX20 EVEN IF DUMPING
>

IFN SMFLG,<
FNDDEV:
>
	MOVEM P,LODBAS		;SAVE START ADDRESS OF SOURCE AREA (SEE DIAGRAMS)
	MOVEI P,<1000+A%VORG-A%VFST>-1(P)	;SAVE END OF SOURCE AREA
	MOVEM P,LODTOP		;LAST ADDRESS MOVED
	HRRZI P,A%VFST-A%VORG(P5)	;TOP ADDRESS ROUNDED TO PAGES
	MOVEM P,TOPBAS		;SAVE START ADDRESS OF TARGET AREA (SEE DIAGRAM)
	MOVEI P5,777(P5)	;SET UP TOP OF SAVED FOR THE SAVE
	MOVEM P5,TOPTOP		;SAVE END OF TARGET AREA

IFN SMFLG,<
;INTERIM PROTECTION AGAINST CONFUSING THE FRONT END WITH KLINIK OUTPUT

	SETZM KLIOWD		;CLEAR THE KLINIK OUTPUT WORD
>

; CODE TO MAP LOW CORE USING KL STYLE PAGING

	MOVEI P1,A%PTB		;GET ADDRESS OF PAGE TABLE PAGE
	SETZB P2,P3		;P2=VIRTUAL, P3=PHYSICAL PAGE #

SETEPT:	CONO APR,AP.RNX		;RESET NXM FLAG
	MOVE T1,P3		;GET PHYSICAL PAGE NUMBER
	TXO T1,1B2!1B4		;CODE = 1, WRITE
	MOVEM T1,(P1)		;PUT ENTRY INTO PAGE TABLE
	MOVE T1,P2		;GET VIRTUAL PAGE #
	LSH T1,^D9		;CONVERT PAGE # TO ADDRESS
J4:	CLRPT 0(T1)		;CLEAR THE ENTRY FIRST
	SKIP 20(T1)		;TRY TO REFERENCE VIRTUAL PAGE
TSTMEM:	CONSZ APR,AP.NXM	;NXM OCCUR ?
	JRST SETEP1		;YES, TRY NEXT PHYSICAL PAGE
	ADDI P1,1		;NO, NEXT PAGE TABLE SLOT
	ADDI P2,1		;NEXT VIRTUAL PAGE #
	CAILE P2,VFREE		;MAP JUST UP TO OURSELF
	JRST SETEP2		;IF DONE, GO SET UP DTE20

SETEP1:	ADDI P3,1		;NEXT PHYSICAL PAGE #
	CAMG P3,[PHYPAG]	;DONE ALL OF CORE?

	JRST SETEPT		;NO, GO DO NEXT PAGE

IFE SMFLG,<
SETEP2:

; DEFEND AGAINST MEMORY PARITY ERRORS IN 20-23

	SETZM 20		;WIPE OUT PARITY ERRORS
	MOVE T1,[20,,21]	;ZERO WHOLE AREA
	BLT T1,23		;DO IT

	SETZM DTEFLG		;CLEAR DONE FLAG
	SETZM DTEMTI		;INITIALIZE INPUT READY FLAG
	MOVSI T1,-DTEN		;SCAN ALL AVAILABLE DTE'S
	MOVE T2,[CONSO DTE,DTEPRV] ;LOOK FOR MASTER
	MOVE T3,[CONSO DTE,PI0ENB+7] ;LOOK FOR ANY PI ASSIGNMENT
	MOVE Q1,[CONO DTE,0]	;PROTOTYPE CONO
SETEP3:	XCT T3			;A PI ASSIGNMENT UP?
	JRST [	HRRI Q1,PIENB+PI0ENB ;NO. TRY TO SET IT
		XCT Q1
		XCT T3		;NOW SET?
		JRST SETEP5	;NO. NON-EXISTANT DEVICE THEN
		TRZ Q1,PI0ENB	;YES. TURN IT OFF
		XCT Q1		;DO IT
		JRST .+1]	;AND PROCEED
	XCT T2			;THIS IT
	JRST [	MOVEI T1,0(T1)	;YES. GET DTE NUMBER
		LSH T1,^D26	;POSITION FOR CONO
		ADD T1,[CONO DTE,0(Q1)] ;PROTOTYPE WORD
		MOVEM T1,DTCNOW	;SAVE IT
		JRST SETEP4]	;DONE
SETEP5:	ADD T2,[4B11]		;NEXT DTE
	ADD T3,[4B11]
	ADD Q1,[4B11]		;ADJUST ALL I/O INSTRUCTIONS
	AOBJN T1,SETEP3		;NOPE. LOOK AT NEXT
	HALT .			;NOT THERE. CAN'T HAPPEN
SETEP4:	MOVEI Q1,.DTMMN		;MONITOR MODE ON
	MOVEM Q1,DTECMD		; STORE IN COMMAND
J5:	MOVEI Q1,TO11DB		;RING THE BELL
	XCT DTCNOW		;DO IT
J6:	SKIPN DTEFLG		;WAIT FOR COMPLETION
J7:	JRST .-1		; ...

>				;END IFE SMFLG
IFN SMFLG,<
SETEP2:
;MAP AND SCAN THE REST OF MEMORY TO BE SURE IT IS INITIALIZED

DBEPGA=1000			;USE PAGE ONE FOR MEM SCAN MAPPING

	MOVE T4,A%PTB+<DBEPGA/1000> ;PICK UP A MAP SLOT TO USE
	MOVEI P3,1000		;[137]START SCAN AT PAGE 1000
MAPDBE:	CONO APR,AP.RNX		;RESET NXM FLAG FOR TESTS
	MOVE T1,P3		;GET PHYSICAL MEMORY PAGE NUMBER
	TXO T1,1B2!1B4		;MAKE IMMEDIATE POINTER, WRITABLE
	MOVEM T1,A%PTB+<DBEPGA/1000> ;SET THE POINTER IN THE MAP
	CLRPT DBEPGA		;CLEAR THE PAGER
	SKIP DBEPGA		;REFERENCE THE PAGE
	CONSZ APR,AP.NXM	;NXM RESULT?
	 JRST MAPDB1		;YES, DON'T BOTHER WITH THE SCAN
	MOVE T1,[-1000,,DBEPGA]	;GET AOBJN POINTER TO PAGE
DBEMSC:	MOVE T2,0(T1)		;SCAN PAGE, CLEARING DBE/ECC ERRORS
	MOVEM T2,0(T1)		;(BLT DOESN'T WORK)
	AOBJN T1,DBEMSC		;LOOP FOR ALL OF PAGE
MAPDB1:	ADDI P3,1		;NEXT PAGE
	CAIGE P3,NCSTPG*1000	;DONE ALL POSSIBLE CORE?
	JRST MAPDBE		;NO, DO NEXT PAGE
	MOVEM T4,A%PTB+<DBEPGA/1000> ;RESTORE THE OLD MAP SLOT
	CLRPT DBEPGA		;AND CLEAR THE PAGER FOR IT AGAIN

	HRRZ F,RELWD		;GET RELOAD WORD
	MOVEM F,RELWD		;STOP KEEPALIVE IF UNDERWAY
	TRNE F,RLFLGS		;CHECK FOR RELOAD FLAGS
	MOVE F,[F11.DM!F11.LD]
	TRNE F,RSFLGS
	MOVE F,[F11.LD]
	MOVEM F,LODTYP
>				;END IFN SMFLG

	MOVEM P5,MAXCOR		;SAVE MAX CORE AVAILABLE
	SETOM CURPAG		;INITIALIZE CURRENTLY IN-CORE DIR PAGE
IFE SMFLG,<
IFN FT.DX2,<			;#100 .
	;HERE TO CALCULATE LENGTH OF THE DX20 MICROCODE
	MOVEI	T1,DXASA	;GET START OF FIRST MICROCODE MODULE
	TRO	T1,777		;GET PAGE ADDR + 777
	MOVEM	T1,MCSPAG	;SAVE STARTING MICROCODE PAGE
				; NOTE THAT THIS PAGE BEGINS WITH THE BOOT
				; MOVING CODE
	MOVEI	T1,DXASA	;GET START OF FIRST MICROCODE MODULE
	ADDI	T1,DXASZ+DXBSZ-1 ;ADD LENGTH OF EACH MICROCODE MODULE
	TRO	T1,777		;GET PAGE ADDR + 777
	MOVEM	T1,MCEPAG	;SAVE ENDING MICROCODE PAGE
	MOVE	T1,DXASA	;GET DXA MCODE VERSION
	MOVEM	T1,DXAMCV	;SAVE IT
	MOVE	T1,DXBSA	;GET DXB MCODE VERSION
	MOVEM	T1,DXBMCV	;SAVE IT
>				;#100 END OF IFN FT.DX2
>


	;DISPLAY PROGRAM VERSION
	CALL CRLF		;...
	MOVEI Q2,[ASCIZ/BOOT V/]
	CALL OUTSTR		;...
	CALL TYPBVR		;OUTPUT BOOT VERSION
GETCM1:	SETZM DSKTAB		;MAKE SURE THIS IS ZERO
	SETZM MONLOD		;INDICATE FIRST INVOCATION OF VBOOT
   IFN FT.MTA,<			;#8 FOR SA10
	MOVSI T1,'MT '		;MAGTAPE DEFAULT DEVICE
	SETZM DIRFLG		;NODIRECTORY YET
   >				;#8 END OF IFN FT.MTA
	IFE FT.MTA,<MOVSI T1,'PS '> ;DISK DEFAULT DEVICE
	MOVEM T1,STRNAM		;STORE THE DEFAULT NAME
	BLKI APR,T1		;GET CPU SERIAL NUMBER
   IFE SMFLG,< ANDI T1,7777>	;IF KL
   IFN SMFLG,<ANDI T1,77777>	;IF KS
	MOVEM T1,APRSER		;STORE SERIAL NUMBER
GETCOM:	SETZM CX		;INDICATES WE ARE ENTERING VBOOT FROM BOOT
	MOVE P,PDP		;SETUP PDL
	MOVE T1,[Z.STRT,,Z.STRT+1] ;CLEAR DATA AREA
	SETZM Z.STRT
	BLT T1,Z.END
	SETOM MAXUNI		;THIS MEANS WE HAVE NOT FOUND DEVICE, YET
	SKIPE LODTYP		;DIALOGUE LOAD?
	JRST GETCO1		;YES, DON'T PROMPT, DON'T TAKE OPR COMMAND
	CALL CRLF		;DO RETURN
	MOVEI T1,PROMPT		;GET PROGRAM NAME
	CALL OUTSIX		;OUTPUT IT IN SIXBIT


GETCO1:	CALL GETSTR		;GET COMMAND FROM OPERATOR
	MOVEM T1,FNDCMD		;SAVE COMMAND POINTER
	TXNE F,F.TELL		;?P
	JRST [	MOVEI T1,[SIXBIT 'CHN UNI TYP STR UNI/SIZ\'] ;YES
		CALL OUTSIX	;TYPE THE HEADER
		JRST DVX1]	;DO THE SCAN
	SETZ P2,		;WHERE TO FORM STRUCTURE NAME
	SKIPN T1,DEV		;DEVICE TYPED?
	JRST [	SKIPE DSKTAB	;NO. ALREADY HAVE A DEVICE?
		JRST FOUND	;YES. USE IT THEN
		JRST DVX1]	;NO. GO FIND THWE DEFAULT
	MOVE T2,[POINT 6,P2]	;PTR TO NAME
	MOVEI T3,6		;MAX # CHARS
DEVNAM:	ILDB T4,T1		;GET CHAR
	CAIN T4,":"		;END OF NAME?
	JRST DEVX		;YES - PUNT
	SUBI T4,40		;CONVERT TO SIXBIT
	IDPB T4,T2		;STORE CHR
	SOJG T3,DEVNAM		;LOOP
DEVX:	CAMN P2,STRNAM		;SAME STRUCTURE AS LAST TIME?
	SKIPN DSKTAB		;YES, FOUND DEVICES YET?
	SKIPA			;NO. MUST LOOK THEN
	JRST FOUND		;YES, GO DO COMMAND
	MOVEM P2,STRNAM		
DVX1:	MOVE T1,[DSKTAB,,DSKTAB+1] ;SET UP TO CLEAR DSKTAB
	SETZM DSKTAB		;CLEAR FIRST WORD OF TABLE
	BLT T1,DSKTAB+DSKSIZ-1	;CLEAR DISK TABLE
	SETZM PASS		;INDICATE PASS 1 OF UNIT-SEARCHING CODE
   IFN FT.MTA,<SETZM DIRFLG>	;MAKE IT READ DIRECTORY AGAIN
	SETZM DSKTYP		;INDICATE UNIT TYPE UNKNOWN


IFN FT.MTA, <
;REMOVE THIS CROCK

;THIS TEST IS INSERTED HERE TO MAKE DEFAULT AND SPECIAL LOADS FROM
; MAG TAPE WORK APPROXIMATELY THE SAME AS FOR DISK, AND TO PROVIDE
; FOR ANY POSSIBLE FUTURE CHANGE TO VBOOT WHEREIN A MAGTAPE DEVICE
; IDENTIFIER OTHER THAN "MT:" WILL BE ACCEPTED, AND ACTED UPON.
;	MOVSI T1,'MT '		;GET MAG TAPE DEVICE NAME
;	CAME T1,STRNAM		;CORRECT DEVICE ENTERED ?
;	JRST FDSK		;NO, GO ISSUE ERROR MESSAGE
;	JRST FTAP		;GO FIND READY TAPE DRIVE

	JRST FTAP		;GO FIND READY DRIVE
>				; END OF IFN FT.MTA
IFE FT.MTA, <
	JRST FDSK		;GO FIND STRUCTURE
>				; END OF IFE FT.MTA
;SUBROUTINE TO LOCATE UNIT CONTAINING STRUCTURE TO BOOT FROM
;ON A SPECIAL LOAD, WE CAN PASS THROUGH THIS CODE TWICE:
;1.	SEARCH FOR A PACK WHOSE APR SERIAL NUMBER MATCHES OUR CPU.
;	IF A MATCH IS FOUND, LOAD FROM THAT PACK.
;2.	IF #1 FAILS, SEARCH FOR STRUCTURE PS: AND LOAD FROM THAT PACK.
;
;	ON THE FIRST PASS, IF WE NOTICE WE HAVE A DX20, WE LOAD AND START IT.
;	EVERY CHANNEL AND UNIT ON THE SYSTEM IS CHECKED.

IFE FT.MTA, <

IFN FT.RH,<			;#8 

FDSK:	SETZB  P1,P2		;CHANNEL # HELD IN P1, UNIT IN P2
	SETZM DIORG		;INITIALIZE DIRECTORY ORIGIN
	MAP T1,A%FP0		;GET PHYS ADDR OF FP0

	TLZ T1,777760		;KEEP JUST THE ADDRESS BITS
	TLO T1,(<1B0+1B1+<1000B13>>) ;DATA XFR, LAST CCW, # OF WORDS
	MOVEM T1,ICCW		;STORE

FDSK1:
	MOVE T1,[1B1+ICCW]	;GET JUMP CCW
	MOVE T2,P1		;GET CHANNEL NUMBER
	LSH T2,2		;GET CHANNEL*4
	MOVEM T1,A%EPT+ICA(T2)	;STORE INITIAL CCW FOR RH20

	SETZM P2		;START AT UNIT 0
	CALL CHKCHN		;THIS CHANNEL EXIST ?
	 JRST FDSK2		;YES, GO CHECK ITS UNITS
	JRST FDSK4		;NO, GO TRY NEXT CHANNEL
FDSK2:	CALL CHKUNI		;THIS UNIT EXIST ?
	 JRST GOTDRV		;YES, GO SEE IF AN RP04
FDSK3:	AOS P2			;GET NEXT UNIT NUMBER
	CAIG P2,MAXDRV		;CHECKED ALL DRIVES YET ?
	JRST FDSK2		;NO GO CHECK NEXT DRIVE
FDSK4:	AOS P1			;YES, INCREMENT CHANNEL #
	CAIG P1,MAXCHN		;CHECKED ALL CHANNELS YET ?
	JRST FDSK1		;NO, GO DO NEXT CHANNEL
	JRST FDSK5		;YES, CHECK FOR ALL UNITS PRESENT

GOTDRV:	ANDI T2,R4%TYP		;KEEP JUST THE DEVICE TYPE CODE
IFN FT.DX2,<
	PUSH P,T2		;SAVE THIS AC
	SKIPN PASS		;SKIP IF NOT FIRST PASS
	CALL LODX20		;LOAD MICROCODE IF THIS IS A DX20
	POP P,T2		;RESTORE THE AC
>
	SKIPG T1,DSKTYP		;DISK TYPE KNOWN YET?
	JRST GOTDV3		;NO - SEE IF ANY OF ALLOWED TYPES
	CAIE T2,.DXATP		;#12 UNLESS THIS IS A DX20,...
	TXNN F,F.TELL		;#12 ... IF REPORTING ONLY, ACCEPT ANY DEVICE
	CAMN T2,T1		;YES - IS THIS UNIT SAME AS DESIRED?
	JRST GOTDV0		;YES - USE IT
	CAIN T1,.R4TYP		;IS DESIRED TYPE RP04?
	CAIE T2,.R5TYP		;YES - IS THIS UNIT AN RP05?
	JRST FDSK3		;NO TO EITHER QUESTION
IFN SMFLG,<
GOTDV0:	MOVEI T1,R4%CPA!GO	;PACK ACK
	WRIO T1,@RPCS1(P1)	;DO IT
	RDIO T1,@RPDS(P1)	;READ THE DEVICE STATUS REGISTER
>				; END IFN SMFLG

IFE SMFLG,<

GOTDV0:	MOVE T1,[R4%CSR!LR!R4%CPA!GO] ;PACK ACKNOWLEDGE, SETS VV BIT
	CALL RHWT1		;GO DO THE DATAO
	MOVSI T1,(.TMDSR)	;READ DEVICE STATUS REGISTER
	CALL RHRD1		;GET IT
>				; END IFE SMFLG
	TRNN T1,TMSMOL		;IS IT POWERED UP WITH A PACK ON-LINE?
	JRST FDSK3		;NO. FORGET IT
	MOVE T1,[A%FP0,,A%FP0+1] ;SET UP FOR BLT
	SETZM A%FP0		;CLEAR FIRST WORD OF DATA PAGE
	BLT T1,A%FP0+777	;ZERO DATA PAGE PRIOR TO READ
	CALL RD0		;GO READ PAGE 0
	CALL CHKHOM		;GO CHECK THE HOME BLOCK
	 JRST GOTDV2		;NO GOOD, TRY BACKUP HOME BLOCK
GOTDV1:	SKIPG T2,DSKTYP		;IS TYPE KNOWN YET?
	MOVNS T2,DSKTYP		;NO - MAKE THIS TYPE THE DESIRED TYPE
	MOVEI T1,N.CLP4		;COMPUTE NUMBER OF CYLINDERS PER UNIT
	CAIE T2,.R4TYP		;RP04?
	MOVEI T1,N.CLP6		;NO - ASSUME RP06
	CAIN T2,.R3TYP		;RM03?
	MOVEI T1,N.CLP3		;YES
	CAIN T2,.R7TYP		;RP07?
	MOVEI T1,N.CLP7		;YES
	MOVEM T1,NUMCYL		;SAVE RESULT
	JRST FDSK3		;OK, GO CHECK NEXT UNIT
GOTDV2:	CALL RD10		;GO READ BACKUP HOME BLOCK
	MOVE T1,[HOMNM2,,HOMNAM] ;#13 MOVE DATA TO WHERE THE CHKHOM
	BLT T1,HOMCOD		;  ROUTINE WANTS IT TO BE
	CALL CHKHOM		;GO CHECK THE BACKUP HOME BLOCK
	 JRST FDSK3		;ERROR
	JRST GOTDV1		;SETUP TYPE/SIZE IF NEEDED AND GO ON

;HERE IF DESIRED UNIT TYPE IS NOT KNOWN YET. CHECK TYPE AGAINST ALL
;KNOWN DISK TYPE UNITS.

GOTDV3:	CAIN T2,.R3TYP		;RM03?
	JRST GOTDV4		;YES
	CAIE T2,.R6TYP		;RP06?
	CAIN T2,.R4TYP		;OR RP04?
	JRST GOTDV4		;YES - SAVE TYPE NEGATED
	CAIN T2,.R7TYP		;RP07?
	JRST GOTDV4		;YES
	CAIE T2,.R5TYP		;RP05?
	JRST FDSK3		;NO - TRY FOR NEXT UNIT
	MOVEI T2,.R4TYP		;YES - MAKE IT LOOK LIKE RP04
GOTDV4:	MOVNM T2,DSKTYP		;SAVE NEGATED TYPE IN CASE HOME BLKS GOOD
	JRST GOTDV0		;AND TRY TO READ HOME BLOCKS

FDSK5:	TXZE F,F.TELL		;#12 JUST SURVEYING?
	JRST GETCM1		;#12 YES GET NEXT COMMAND
	SKIPL T1,MAXUNI		;NO - CHECK FOR FULL DECK
	JRST CHKSTR		;HAVE FOUND SOME UNITS
	SKIPE DEV		;HAVE WE CHECKED A STRUCTURE NAME?

	;STRUCTURE NOT FOUND - CHECK THE CONTEXT
	JRST	[SKIPE PASS	;PASS 1?
		$ERROR(STRNBS)	;NO - NO BOOTABLE STRUCTURE
		$ERROR(STRSNF)]	;YES - SPECIFIED OR DEFAULT STRUCTURE NOT FOUND
	SETOM DEV		;GO THRU DISKS A SECOND TIME -- FOR STR NAME
	SETOM PASS		;INDICATE 2'D PASS
	JRST FDSK
CHKSTR:	SKIPN DSKTAB(T1)	;ANY ID?
	 $ERROR (STRNID)	;NO STRUCTURE ID
	SOJGE T1,CHKSTR		;YES - LOOP FOR OTHER UNITS
	JRST FOUND		;PASS COMMAND TO VBOOT 

>				;END IFN FT.RH
IFN FT.RP,<
FDSK:	SETZB  P1,P2		;UNIT # HELD IN P1
	MAP T1,A%FP0		;GET PHYS ADDR OF FP0
	MOVEI T1,-1(T1)		;BUILD CCW
	HRLI T1,-1000		;...
	MOVEM T1,ICCW		;STORE
FDSK1:	MOVE T1,[600000,,0]	;RP10 SELECT OP
	DPB P1,[POINT 3,T1,5]	;INSERT UNIT
	DATAO DPC,T1		;SELECT UNIT
	DATAI DPC,T2		;GET STATUS
	TLNE T2,(1B13)		;DISK OFFLINE?
	TRNN T2,2000		;OR RP02?
	JRST FDSK2		;YES TO EITHER
	SETZM DIORG		;INITIALIZE DIRECTORY ORIGIN
	CALL RD0		;READ PAGE 0
	CALL CHKHOM		;SEE IF HOME BLOCK OK
	SKIPA			;ERROR TRY BACKUP
	JRST FDSK2		;MORE CHECKS LATER
	CALL RD10		;READ BACKUP BLOCK
	MOVE T1,[HOMNM2,,HOMNAM]	;#13 MOVE TO WHERE CHKHOM WANTS IT
	BLT T1,HOMCOD		; ...
	CALL CHKHOM		;SEE IF OK
	JFCL			;CLARIFY LATER
FDSK2:	AOS P1			;NEXT UNIT
	CAIGE P1,^D8		;ANY REMAINING?
	JRST FDSK1		;YES - LOOP
	MOVE T1,MAXUNI		;NO - CHECK FOR FULL DECK
CHKSTR:	SKIPN DSKTAB(T1)	;ANY ID?
	 $ERROR(STRNID)		;NO - DEFECTIVE STRUCTURE
	SOJGE T1,CHKSTR		;YES - LOOP FOR OTHER UNITS
	JRST FOUND		;PASS COMMAND TO VBOOT 

>				;END IFN FT.RP

>				; END OF IFE FT.MTA
IFE FT.MTA,<			;#8 .
IFN FT.SA,<			;#8 .
;#8 Note that this routine differs from the RP04/6 version in that it checks
;#8 to see if it has enough disks after processing each channel.

FDSK:	SETZB P1,P2		;#8 channel # in P1, unit in P2
	SETZM DIORG		;#8 initialize directory origin
	MAP P4,A%FP0		;#8 get physical address of FP0
	TLZ P4,777760		;#8 keep just the address bits
	MOVEM T1,ICCW		;#8 store IOW

FDSK1:	SETZ P2,		;#8 start at unit 0
	CALL CHKCHN		;#8 this channel exist?
	 JRST FDSK2		;#8 yes, go check its units
	JRST FDSK5		;#8 no, go try next channel
FDSK2:	CALL CHKUNI		;#8 this unit exist?
	 JRST GOTDRV		;#8 yes
FDSK3:	AOS P2			;#8 get next unit number
	CAIG P2,MAXDRV		;#8 checked all drives yet?
	JRST FDSK2		;#8 no, go check next drive
FDSK4:	SKIPGE T1,MAXUNI	;#101 yes, check for full structure
	JRST FDSK5		;#101 it's ok so go on
	TXNN F,F.TELL		;#12 no check if just surveying
CHKSTR:	SKIPN DSKTAB(T1)	;#8 any ID?
	JRST FDSK5		;#8 no, try another channel
	SOJGE T1,CHKSTR		;#8 yes, loop for other units
	JRST FOUND		;#8 pass command to VBOOT

FDSK5:	AOS P1			;#8 increment channel #
	CAIGE P1,SSAN*SSANSC	;#8 checked all channels yet?
	JRST FDSK1		;#8 no, go do next channel
	TXZE F,F.TELL		;#12 just surveying?
	JRST GETCM1		;#12 yes, go for next command
;START OF #101
	SKIPE DEV		;HAVE WE CHECKED A STRUCTURE NAME?

	;STRUCTURE NOT FOUND - CHECK THE CONTEXT
	JRST	[SKIPE PASS	;PASS 1?
		$ERROR(STRNBS)	;NO - NO BOOTABLE STRUCTURE
		$ERROR(STRSNF)]	;YES - SPECIFIED OR DEFAULT STRUCTURE NOT FOUND
	SETOM DEV		;GO THRU DISKS A SECOND TIME -- FOR STR NAME
	SETOM PASS		;INDICATE 2'D PASS
	JRST FDSK
;END OF #101
GOTDRV:				;#8 found a disk
	SKIPG T1,DSKTYP		;#8 disk type known yet?
	JRST GOTDV3		;#8 no, see if any of allowed types
	CAMN T2,T1		;#8 yes, is this unit same as desired?
	JRST GOTDV0		;#8 yes, use it
	TXNN F,F.TELL		;#12 no, just reporting?
	JRST FDSK3		;#8 no, try next

GOTDV0:	MOVE T1,[A%FP0,,A%FP0+1] ;#8 set up for BLT
	SETZM A%FP0		;#8 clear first word of data page
	BLT T1,A%FP0+777	;#8 zero data page prior to read
	CALL RD0		;#8 go read page 0
	CALL CHKHOM		;#8 go check the home block
	 JRST GOTDV2		;#8 no good, try backup home block
GOTDV1:	SKIPG T2,DSKTYP		;#8 is type known yet?
	MOVNS T2,DSKTYP		;#8 no, make this type the desired type
	MOVEI T1,N.CLP4		;#8 compute number of cylinders per unit
	CAIE T2,.R4TYP		;#8 mod I type?
	MOVEI T1,N.CLP6		;#8 no, assume mod II
	MOVEM T1,NUMCYL		;#8 save result
	JRST FDSK3		;#8 go check next unit

GOTDV2:	CALL RD10		;#8 go read backup home block
	MOVE T1,[HOMNM2,,HOMNAM] ;#13 move data to where the ...
	BLT T1,HOMCOD		;#8 ...  CHKHOM routine wants it to be
	CALL CHKHOM		;#8 go check the backup home block
	 JRST FDSK3		;#8 error
	JRST GOTDV1		;#8 setup type/size if needed and go on

;#8 Here if desired unit type is not known yet.  Check type against all
;#8  known disk type units.

GOTDV3:	CAIE T2,.R6TYP		;#8 mod II?
	CAIN T2,.R4TYP		;#8 or mod I?
	JRST GOTDV4		;#8 yes, save type negated
	JRST FDSK3		;#8 no, try for next unit

GOTDV4:	MOVNM T2,DSKTYP		;#8 save negated type in case home blocks good
	JRST GOTDV0		;#8 and try to read home blocks

>				;#8 end of IFN FT.SA
>				;#8 end of IFE FT.MTA
;SUBR TO CHECK IF A CHAN IS PRESENT
;RETURNS:	+1	CHANNEL EXISTS
;		+2	CHANNEL DOESN'T EXIST

IFN FT.RH, <
IFE SMFLG, <

CHKCHN:	MOVEI T1,.RHMBR		;RESET
	CALL RHCO1		;DO CONO
	MOVEI T1,.RHMBE		;ENABLE
	CALL RHCO1
	CALL RHCI1		;DO CONI
	TRNN T1,.RHMBE		;BIT COME BACK?
	RETSKP			;SKIP RETURN
	RET			;RETURN
>				; END IFE SMFLG

IFN SMFLG, <
CHKCHN:	CAIG P,MAXCHN		;ONLY ONE LEGAL FOR NOW
	RET
	RETSKP
>				; END IFN SMFLG

>				; END IFN FT.RH
IFN FT.RP,<
; ROUTINE FOR RH10 --
CHKCHN:	MOVX T1,R4%DTR		;GET DEVICE TYPE REGISTER #
	CALL RHRD1		;READ DEVICE 0 REGISTER
	TXNE T1,5000		;BUS TIMEOUT OR PARITY ?
	RETSKP			;YES, SKIP RETURN
	RET			;RETURN

>				; END OF IFN FT.RP
IFN FT.SA,<			;#8 .

;#8 CHKCHN - check to see if a channel is present
;#8  P1/ Subchannel number+ 4*<SA10 number>

CHKCHN:	MOVEI T1,SA%INI!SA%CME	;#8 clear the channel
	XCT SAXCNO(P1)		;#8 do the reset
	MOVEI T1,SSACHN		;#8 assign channel
	XCT SAXCNO(P1)		;#8 .
	XCT SAXCNI(P1)		;#8 read back
	TRNE T1,SA%PIA		;#8 test PI assignment
	RET			;#8 assignment made, say channel there
	RETSKP			;#8 say channel not there

>				;#8 end of IFN FT.SA
;SUBROUTINE TO SEE IF A UNIT EXISTS
;RETURNS:	+1	UNIT EXISTS
;			DEVICE BITS IN T2
;		+2	UNIT DOESN'T EXIST

IFE SMFLG,<
IFN FT.RH!FT.RP,<		;#8 ONLY FOR DEC DISKS
CHKUNI:	MOVSI T1,(.TMDTR)	;READ DRIVE TYPE REG
	CALL RHRD1		;...
	MOVE T2,T1		;COPY FOR RETURN
	CALL RHCI1		;SEE IF REG ACC ERR
	TRNN T1,.RHRAE		; ...
	CALLRET TELLCU		;#12 ALL IS WELL, TELL CHAN, UNIT IF "?"
	MOVEI T1,.RHRAE!.RHMBE	;CLEAR RAE, ENABLE
	CALL RHCO1		;DO CONO
	JRST RSKP		;LOSE
>				;#8 END OF IFN FT.RH!FT.RP

RHRD1:	TLZ T1,(LR)		;CLEAR LR BIT
RHWT1:	TSO T1,P2		;INSERT UNIT NUMBER
	CALL XIO1		;SET IOA
	DATAO .-.,T1		;SEND TO DEVICE
	CALL XIO1		;SET IOA
	DATAI .-.,T1		;READ REG
	RET

RHCI1:	CALL XIO1		;SET IOA
	CONI .-.,T1		;DO CONI
	RET

RHCO1:	CALL XIO1		; SET IOA
	CONO .-.,(T1)		;DO CONO
	RET

XIO1:	HRRI F,RH0_-2(P1)	;PRODUCE DEVICE CODE
IOXCT:	DPB F,[POINT 7,@(P),9]	;PLUG IOADDR
	RET			;EXECUTE INSTR

>				;END IFE SMFLG

IFN SMFLG,<

CHKUNI:	MOVEI T2,RH1CLR		;CHECK FOR NON EXIST DISK
	WRIO T2,@RPCS2(P1)
	WRIO P2,@RPCS2(P1)	;SELECT DISK
	RDIO T2,@RPCS1(P1)	;FORCE ERROR
	MOVEI T2,RH.NED		;CHECK FOR ERROR
	TIOE T2,@RPCS2(P1)	;CHECK STATUS
	RETSKP			;NO -- NO DISK HERE
	RDIO T2,@RPDT(P1)	;YES -- GET DRIVE TYPE
	CALLRET TELLCU		;#12 REPORT CHAN,UNIT IF "?"
>				; END IFN SMFLG


IFN FT.SA,<			;#8 .
IFE FT.MTA,<			;#8 .

;#8 CHKUNI - check to see if a unit exists
;#8  P1/ 4*<SA10 number>+ Subchannel number
;#8  P2/ unit number
;#8  P4/ buffer address
;#8  RETURNS +1: Success - unit exists
;#8   T2/ Device type (.R4TYP or .R6TYP)
;#8   P3-P4, T1-T4 destroyed
;#8  RETURNS +2: Failure - unit does not exist
;#8   P3-P4, T1-T4 destroyed

CHKUNI:	MOVEI T2,^D800		;#8 try to read from cyl not on mod I's
	MOVEI T3,0		;#8 sector 0 on that cylinder
	MOVEI P3,.ICRDC		;#8 operation is "read count"
	CALL CC1ST0		;#8 setup Channel Program
	CALL CC1SRC		;#8 set up Read Count program
	SETZ T2,		;#8 reset desired on channel
	CALL SAINGO		;#8 try the operation
	 JRST CHKUNX		;#8 unit not there
	MOVE T1,SAXBAS(P1)	;#8 get address of base
	MOVE T1,1(T1)		;#8 get status word
	TXNE T1,FLD(.S1ATN!.S1SMD!.S1CUE!.S1BSY!.S1UEX,S1%DVS) ;#8 unusual err?
	 JRST CHKUNX		;#8 yes
	SETZ P3,		;#8 show type not known yet
	TXNN T1,FLD(.S1UCK,S1%DVS) ;#8 unit check?
	MOVEI P3,.R6TYP		;#8 no, this must be a mod II
	MOVEI T1,CC1NCP+DPOSNP	;#8 get address of sense program
	SETO T2,		;#8 do not want reset (would clear sense)
	CALL SAINGO		;#8 do the sense
	 JRST CHKUNX		;#8 give up if sense fails
	HRRZ T2,CC1NCP+DPOSNP+1	;#8 get address of sense buffer
	MOVE T1,0(T2)		;#8 get 1st word of sense buffer
	TXNE T1,SN%CRJ		;#8 command reject?
	MOVEI P3,.R4TYP		;#8 yes, must be mod I
	JUMPE P3,CHKUNX		;#8 ignore if model not determined
	MOVE T2,P3		;#8 copy device code
	JRST CHKUNG		;#8 give "good" return

CHKUNX:	SETO T2,		;#8 set flag for not found
CHKUNG:				;#8 non-skip return means drive found
	JUMPL T2,RSKP		;#12 skip return means not found
	CALLRET TELLCU		;#12 report chan, unit if "/W"
>				;#8 end of IFE FT.MTA

IFN FT.MTA,<			;#8 .

;#8 CHKUNI - check to see if a unit exists
;#8  P1/ 4*<SA10 number>+ Subchannel number
;#8  P2/ unit number
;#8  RETURNS +1: Success - unit exists
;#8   P3-P4, T1-T4 destroyed
;#8  RETURNS +2: Failure - unit does not exist
;#8   P3-P4, T1-T4 destroyed

CHKUNI:	MOVEI T1,CMTNCP		;#8 NO-OP channel program
	MOVEI T2,.IDMTA(P2)	;#8 device address
	STOR T2,SC%DEV,(T1)	;#8 store device address in DCW
	SETZ T2,		;#8 start with a reset
	CALL SAINGO		;#8 try to do NOOP
	 RETSKP			;#8 signal no such unit
	MOVEI T1,CMTSCP		;#8 get sense CP
	MOVEI T2,.IDMTA(P2)	;#8 device address for this unit
	STOR T2,SC%DEV,(T1)	;#8 store device address in DCW
	SETO T2,		;#8 no reset this time
	CALL SAINGO		;#8 do sense
	 RETSKP			;#8 fail if sense does
	MOVE T1,CMTSB		;#8 get 1st 4 sense bytes
	TXNE T1,SN%CRJ!SN%IRQ!SN%BOP ;#8 bad stuff, or intervention required?
	RETSKP			;#8 yes, don't like the unit
	RET			;#8 otherwise say that unit is here
>				;#8 end of IFN FT.MTA

>				;#8 end of IFN FT.SA
TELLCU:				;#12 report Channel, Unit, type if "?"
	TXNN F,F.TELL		;#12 telling?
	RET			;#12 no, just return
	PUSH P,T2		;#12 save type
	CALL CRLF		;#12 output carriage return
	MOVE T2,P1		;#12 get channel
	CALL OCTOTS		;#12 output it, space
	MOVE T2,P2		;#12 get unit
	CALL OCTOTS		;#12 output unit, space
	POP P,T2		;#12 get back device type
	ANDI T2,R4%TYP		;#12 keep just the type code
	CALLRET OCTOTS		;#12 output type, space, return
IFN FT.MTA,<
FTAP:
IFN FT.DX2,<
	CALL LALLDX		;LOAD MICROCODE INTO ALL DX20S
>;END IFN FT.DX2
	SETZB P1,P2		;START AT CHAN 0, ADDR 0
GETTCH:	CALL CHKCHN		;DOES THIS CHANNEL EXIST?
	JRST GOTTCH		;YES - TRY UNITS
NXTTCH:	AOS P1			;NO  - NEXT CHANNEL
	CAIG P1,MAXCHN		;OUT OF CHANNELS
	JRST GETTCH		;NO - TRY THIS ONE
	 $ERROR (TAPNDR)	;NO READY DRIVE AVAILABLE

GOTTCH:	CALL CHKUNI		;GET DEV TYPE IN T2, IF EXTANT
	JRST GOTTUN		;EXISTS - GO CHECK TYPE
NXTTUN:	AOS P2			;NEXT CONTROLLER
	CAIG P2,7		;ANY MORE
	JRST GOTTCH		;YES - SEE IF THIS WINS
	SETZ P2,		;NO - TRY NEXT CHANNEL
	JRST NXTTCH		; ...

IFE FT.SA,<			;#8 NOT FOR SA10
GOTTUN:	ANDI T2,777		;ISOLATE CONTROLLER TYPE
	SETZ P3,		;START AT UNIT 0
IFN FT.DX2,<
	MOVEI P6,DA.IDX		;GET DEVICE INDEX FOR TAPE STYLE DX20
	CAIN T2,.DXATP		;IS THIS ONE?
	JRST GOTDX2		;YES, PROCESS IT
>
IFN FT.TM8,<
	CAIN T2,.T8TYP		;IS IT A TM78?
	JRST GOTTM8		;YES. SEE IF THIS IS THE UNIT
>
	MOVEI P6,TM.IDX		;TRY TM02/TM03
	CAIL T2,10		;SEE IF TM02
	CAIL T2,17		; ...
	SKIPA			;NOT A TM02
	JRST NXTTDR		;ITS A TM02
	CAIL T2,50		;SEE IF A TM03
	CAIL T2,57		; ...
	JRST NXTTUN		;NOT A TM03
NXTTDR:	MOVSI T1,(.TMTCR!LR)	;PREPARE TO SELECT UNIT
	IOR T1,P3		;INSERT UNIT NUMBER
IFE SMFLG,<

	CALL RHWT1		;INSERT KON, SEND TO CHN
	MOVSI T1,(.TMDSR)	;READ DEVICE STATUS
	CALL RHRD1		; ...
>				;END SMFLG
IFN SMFLG,<
	WRIO P2,@RPCS2(P1)	;WRITE UNIT
	WRIO T1,@RPDC(P1)	;SET SLAVE
	RDIO T1,@RPDS(P1)	;READ DRIVE STATUS
>				;END IFN SMFLG
	TRNE T1,TMSMOL		;DEVICE READY?
	JRST GOTTDR		;YES!!
	AOS P3			;NO - TRY NEXT DRIVE
	CAIG P3,7		;ANY MORE?
	JRST NXTTDR		;YES
	SETZ P3,		;NO - TRY NEXT KON
	JRST NXTTUN		; ...
IFN FT.TM8,<
GOTTM8:	MOVEI P6,T8.IDX		;SET FOR TM78
	MOVEI T1,T7.SNS_6	;DO A SENSE ON THIS SLAVE
	CALL T78.ND
	JUMPE T2,GOTM8A		;TIMED OUT IF 0 - TRY NEXT SLAVE
	MOVSI T1,(.T7SR)	;SLAVE IS THERE, SEE IF DRIVE IS OK
	CALL RHRD1
	TRNN T1,T7.RDY		;IS DRIVE READY?
	JRST GOTM8A		;NOPE. TRY NEXT
	MOVEI T1,T7.REW_6	;YES. REWIND IT
	CALL T78.ND
	JUMPE T2,GOTM8A		;LOSE IF WE TIMED OUT
T78.CK:	MOVEI T1,T7.SNS_6	;DO A SENSE
	CALL T78.ND
;THIS IS AN INCREDIBLE *****CROCK******  (CATCH 78) BUT:
;	THE ONLY WAY YOU CAN TELL IF A DRIVE IS REWINDING IS TO DO A SENSE
;	BUT YOU CAN'T DO A SENSE IF THE DRIVE IS REWINDING - THE CONTROL JUST STACKS IT
;	SO IF THE SENSE WE JUST DID TIMES OUT THE DRIVE IS REWINDING!
	JUMPE T2,T78.CK		;KEEP ON CHECKING IF WE TIMED OUT
	JRST GOTTD1		;ALL IS COOL. USE THIS SLAVE

GOTM8A:	CAIGE P3,3		;DONE WITH THIS UNIT (TM78)
	AOJA P3,GOTTM8		;NO, TRY NEXT SLAVE ON THIS TM78
	SETZ P3,		;YES, RESET SLAVE (UNIT) NUMBER
	JRST NXTTUN		;TRY NEXT TM78 ON THIS RH20

;ROUTINE TO DO A NON-DATA FUNCTION ON A TM78/TU78
;ENTER WITH T1=FUNCTION_6, P3=UNIT
T78.ND:	PUSH P,T1		;SAVE FUNCTION
	MOVEI T2,200000		;HOW LONG TO WAIT FOR TM78 TO BECOME READY
T78.N1:	MOVSI T1,(.T7TMS)	;READ THE TM78 STATUS REGISTER
	CALL RHRD1
	TRNN T1,T7.RDY		;IS IT WITH US?
	SOJG T2,T78.N1		;NO, TRY AGAIN
	POP P,T1		;RESTORE REAL FUNCTION
	JUMPE T2,R		;RETURN IF WE TIMED OUT
	ADDI T1,<(.T7ND0)>_-14(P3) ;POINT AT RIGHT REGISTER FOR THIS DRIVE
	ROT T1,-6		;BITS 0-5=REG, 33-35=FUNCTION
	TLO T1,(LR)		;WRITE THE REGISTER
	CALL RHWT1		;DO IT TO IT
	MOVEI T2,200000		;LOOP COUNT
T78.N2:	MOVSI T1,(.TMATR)	;WAIT FOR ATTENTION BIT TO COME UP
	CALL RHRD1		;WAIT FOR ATTENTION BIT TO COME UP
	TRNN T1,377		;ATTEN?
	SOJG T2,T78.N2		;NO, TRY AGAIN
	JUMPE T2,R		;GO AWAY IF WE TIMED OUT
	MOVE T2,T1		;SAVE FUNCTION
	MOVE T1,[.TMATR!LR!377]	;CLEAR THE ATTENTION BIT
	CALL RHWT1
	EXCH T1,T2		;RESTORE DATA, SET T2 POSITIVE
	RET			;AND GO AWAY
>
IFN FT.DX2,<

;FOUND A DX20, FIND A READY DRIVE

GOTDX2:	CALL STDX20		;START DX20 (MASSBUS RESET HALTS IT)
GTDX2A:	MOVE T1,P3		;GET DRIVE NUMBER
	TXO T1,<.TDDNR!LR>	;DRIVE NUMBER REG
	CALL RHWT1		;SELECT THIS DRIVE
	MOVE T1,[EXP .TMCSR!LR+.TMRWF]
	CALL RHWT1		;DO REWIND
	CALL DX2SWT		;SHORT WAIT
	JRST GTDX2B		;FAILED - DRIVE IS NOT READY
	MOVX T1,.TDSTR		;GET THE STATUS REGISTER
	CALL RHRD1		; ...
	TRNE T3,.TDDEB		;AT LOAD POINT YET?
	JRST GOTTD1		;YES
GTDX2C:	CALL DX2LWT		;NO, DO A LONG WAIT
	JRST GTDX2B		;ERROR, THIS DRIVE FAILS
	MOVX T1,.TDAYR		;GET ASYNCHRONOUS STATUS
	CALL RHRD1
	TXNN T1,.TDDEB		;DEVICE END?
	 $ERROR (TAPHTE)	;NO - HARD TAPE ERROR
	ANDI T1,377		;JUST THE DRIVE NUMBER
	CAMN T1,P3		;RIGHT DRIVE?
	JRST GOTTD1		;YES, GOOD DRIVE
	MOVX T1,.TDAYR		;NO, CLEAR ASYNCHRONOUS STATUS REG
	CALL RHWT1		; ...
	JRST GTDX2C		;AND WAIT SOME MORE

GTDX2B:	AOS P3			;TRY THE NEXT DRIVE
	CAIG P3,7		;MORE DRIVES ON THIS CONTROLLER?
	JRST GTDX2A		;YES
	JRST NXTTUN		;NO, TO THE NEXT CONTROLLER

;ROUTINE TO LOOK FOR AND LOAD MICROCODE INTO ALL
; DX20S ON THE SYSTEM
;
LALLDX:	SETZB P1,P2		;START WITH CHANNEL 0, ADDR 0
LALLD1:	CALL CHKCHN		;DOES THIS CHANNEL EXIST?
	 JRST LALLD3		;YES, SEE IF ANY DX20S OUT THERE
LALLD2:	ADDI P1,1		;NO, LOOK AT THE NEXT CHANNEL
	CAIG P1,MAXCHN		;LOOKED AT ALL THE CHANNELS?
	JRST LALLD1		;NO, LOOK AT NEXT CHANNEL
	RET			;ALL DONE
LALLD3:	CALL CHKUNI		;SEE WHAT EXISTS ON THIS CHANNEL
	 JRST LALLD5		;SOMETHING THERE, GO SEE IF DX20
LALLD4:	ADDI P2,1		;NEXT CONTROLLER
	CAIG P2,7		;LOOKED AT ALL CONTROLLERS?
	JRST LALLD3		;NO, LOOK AT NEXT ONE
	SETZ P2,		;CONTROLLER 0
	JRST LALLD2		;GO LOOK AT NEXT CHANNEL
LALLD5:	ANDI T2,777		;ISOLATE CONTROLLER TYPE
	CALL LODX20		;LOAD MICROCODE IF THIS IS A DX20
	JRST LALLD4		;GO LOOK AT NEXT CONTROLLER
>;END IFN FT.DX2

GOTTDR:	MOVE T1,[EXP .TMCSR!LR+.TMRWF]
IFE SMFLG,<
	CALL RHWT1		;DO REWIND
	MOVSI T2,10000		;WAIT COUNT
	CALL WTRDY1		;WAIT FOR READY
>
GOTTD1:	SETOM DIORG		;FLAG MAGTAPE
	MOVEM P6,TAPTYP		;SAVE TYPE TYPE FOR LATER
	SETZM MAXUNI		;HIGHEST NUMBERED UNIT
	MOVE T2,P1		;GET CHAN
	LSH T2,6		;SHIFT
	IOR T2,P2		;WITH KONTROLLER
	LSH T2,6		;AGAIN
	IOR T2,P3		;AND SUBUNIT
	TLO T2,(1B0)		;SET NEGATIVE
	MOVEM T2,DSKTAB		;STORE
	JRST FOUND		;WIN.


WTRDY:	MOVSI T2,5		;TIMEOUT COUNTER
WTRDY1:	MOVSI T1,(.TMDSR)	;WAIT FOR DRIVE READY
IFE SMFLG,<
	CALL RHRD1		; ...
>				;END IFE SMFLG
IFN SMFLG,<
	WRIO T1,@RPDS(P1)
>				;END IFN SMFLG
	TRNE T1,TMSPIP		; ...
	SOJG T2,WTRDY1		;TIMED LOOP
	PUSH P,T1		;SAVE STATUS REG
	MOVE T1,[EXP .TMATR!LR+377] ;RESET ALL ATTENTION FLAGS
IFE SMFLG,<
	CALL RHWT1		; ...
>				;END IFE SMFLG
IFN SMFLG,<
	WRIO T1,@RPAS(P1)	;WRITE ATTENTION SUMMARY
>				;END SMFLG
	POP P,T1		;RESTORE STATUS REG
	SKIPN T2
	 $ERROR (TAPHTE)	;HARD TAPE ERROR
	RET			;WIN

IFN FT.DX2,<

;DX20 WAIT ROUTINES

DX2LWT:	SKIPA T2,[10000,,0]	;LONG WAIT
DX2SWT:	MOVEI T2,2000		;SHORT WAIT
DX2WAT:	MOVX T1,.TMDSR		;GET THE STATUS REGISTER
	CALL RHRD1		; ...
	TXNN T1,.TDATB		;ATTENTION UP?
	SOJG T2,DX2WAT		;NO, WAIT
	PUSH P,T1		;SAVE THE STATUS
	MOVE T1,[EXP .TMATR!LR+377]
	CALL RHWT1		;TURN OFF ATTENTION
	POP P,T1		;GET BACK THE STATUS
	SKIPN T2
	  $ERROR (TAPHTE)	;HARD TAPE ERROR
	TXNN T1,.TDCEB		;ANY ERRORS?
	RETSKP			;NO, SKIP RETURN
	MOVX T1,<.TMERR!LR>	;YES, CLEAR THE ERROR REGISTER
	CALL RHWT1
	RET			;AND GIVE AN ERROR RETURN
>				;END IFN FT.DX2
>				;#8 END OF IFE FT.SA

IFN FT.SA,<			;#8 .
GOTTUN:				;#8 found a unit
	SETOM DIORG		;#8 flag magtape
	SETZM MAXUNI		;#8 highest numbered unit
	DPB P1,PCHAN		;#8 remember channel
	DPB P2,PUNIT		;#8 remember unit
	MOVSI T2,ENTFLG		;#8 entry-in-use flag
	IORM T2,DSKTAB		;#8 set entry-in-use flag
	JRST FOUND		;#8 proceed
>				;#8 end of IFN FT.SA

>				;END IFN FT.MTA
IFN FT.DX2,<


;ROUTINE TO CHECK FOR EITHER STYLE OF DX20, AND LOAD THE PROPER
;MICROCODE INTO IT.  CALLED WITH DEVICE TYPE IN T2.


	EXTERN	DXASA,DXASZ	;START ADDRESS AND SIZE OF TAPE MICROCODE

	IFN FT.RP2,
	<
	EXTERN	DXESA,DXESZ	;START ADDRESS AND SIZE OF RP20 MICROCODE
	>

	IFE FT.RP2,
	<
	DXESA=0			;PRESUMEABLY, WE HAVE NO RP20 MICROCODE,
	DXESZ=1			; SO DUMMY-UP THESE SYMBOLS
	>
	DXBSA=DXESA
	DXBSZ=DXESZ
	
COMMENT \
	NOTA BENE:

	INTERNAL PROGRAM MNEMONICS FOR MICROCODE ARE AS FOLLOWS:

	DXA...			TU7X MICROCODE
	DXB...			RP20 MICROCODE
	\

LODX20:	SKIPE NOLDDX		;ARE WE CONSIDERING LOADING A DX20?
	RET			;NO
	SETZ P6,		;ASSUME NOT A DX20
	CAIE T2,.DXATP		;TAPE STYLE DX20?
	JRST NCHK		;NO

	;HERE IF WE HAVE A TAPE DX20
	;"TEMPORARY" RESTRICTION
	MOVEI P6,DA.IDX		;YES, SET UP CODE
	MOVE	T1,LODTYP	;GET 11-SUPPLIED LOAD FLAGS
	TXNE	T1,F11.LD	;AUTO-RELOADING?
	RET			;YES - DON'T RELOAD ANY TAPE DX20'S
	
NCHK:	CAIN T2,.DXBTP		;DISK STYLE DX20?
	MOVEI P6,DB.IDX		;YES, SET UP OTHER CODE
	JUMPE P6,R		;RETURN IF NOT A DX20
IFE FT.RP2,
<	CAIN P6,DB.IDX		;DX20B?
	RET			;YES.  WE HAVE NO MICROCODE, SO RETURN.
>
	CALL TRYTYP		;TELL HIM WHAT WE ARE TRYING TO DO
	MOVEI T1,042562		;GET MAGIC CODE
				; FOR U-CODE CONSISTENCY CHECK (TAPE ONLY)
	CAIN P6,DA.IDX		;TAPE MICROCODE?
	MOVEM T1,DXASA+11	;YES, PUT INTO LOCATION 11 OF THE RAM
	MOVEI Q1,DXLDFT		;SET FUNCTION TABLE
	CALL LDX20		;LOAD THE RAMS
	MOVEI Q1,DXVRFT		;SET VERIFY FUNCTION TABLE
	CALL LDX20		;GO VERIFY THE WORKING MEMORY
	CALL STDX20		;START THE DX20


	MOVEI Q2,[ASCIZ \[OK]
\]
	CALL OUTSTR		;SAY WE DID IT
	RET
	;SUBROUTINE TO START THE DX20
STDX20:	MOVEI T1,1+.TDICB+.TDPIB+.TDPEB ;SET STARTING ADDRESS
	TXO T1,.TDPCR!LR	;INTO THE PC
	CALL RHWT1
	MOVEI T1,.TDSTB		;START THE DX20
	TXO T1,.TDMNR!LR
	CALLRET RHWT1


	;SUBROUTINE TO TELL HIM WE ARE ATTEMPTING TO START THE DX20
TRYTYP:	MOVEI Q2,[ASCIZ\[BOOT: STARTING\]
	CALL OUTSTR
	CALL TYPDX2		;TYPE OUT DX20 AND CHANNEL NUMBERS
	MOVEI Q2,[ASCIZ \MICROCODE V\]
	CALL OUTSTR		
	CAIN P6,DA.IDX		;DX20A?
	MOVE T1,DXAMCV		;YES
	CAIN P6,DB.IDX		;DX20B?
	MOVE T1,DXBMCV		;YES
	CALL TMCVER		;DISPLAY THE MICROCODE VERSION
	MOVEI Q2,[ASCIZ\] \]	;CLOSE THE EXPRESSION
	CALL OUTSTR
	RET
;LOAD FUNCTION TABLE

DXLDFT:	.TDPCR!LR+.TDCIB+.TDPEB ;PC BITS FOR CRAM LOADING
	RHWT1			;CRAM FUNCTION IS WRITE
	[			;WORKING MEMORY FUNCTION
		TRO T1,11400	;  SET INSTRUCTION TO MOVI TO BR WITH MA+
		CALLRET XI]	;  DO THE INSTRUCTION

;VERIFY FUNCTION TABLE

DXVRFT:	.TDPCR!LR+.TDICB+.TDPEB ;PC BITS FOR CRAM READING
	[			;CRAM VERIFY FUNCTION
		HRRZ T3,T1	;  SAVE THE EXPECTED VALUE
		CALL RHRD1	;  GET CRAM CONTENTS
		ANDI T1,177777	;  ONLY WANT 16 BITS
		CAIN T3,(T1)	;  VERIFY MATCH
		RET		;  MATCH, GOOD RETURN
		JRST NOVERC]	;  NO MATCH, TYPE ERROR 
	[			;WORKING MEMORY FUNCTION
		HRRZ T3,T1	;  SAVE THE EXPECTED VALUE
		MOVEI T1,043411	;  INSTRUCTION TO MOVE DATA TO BR
		CALL XI		;  EXECUTE IT
		MOVX T1,.TDIBR	;  GET THE BR
		CALL RHRD1	;  ...
		ANDI T1,377	;  ONLY THE BR
		CAIN T3,(T1)	;  MATCH?
		RET		;  YES, GOOD RETURN
		JRST NOVERW]	;  NO, COMPLAIN
;LOAD OR VERIFY DX20 MICRO CODE
;CALL WITH Q1 POINTING TO FUNCTION TABLE AND P6 CONTAINING DX20 TYPE


LDX20:	MOVSI T2,-DXASZ		;GET LENGTH OF TAPE MICROCODE
	CAIE P6,DA.IDX		;CORRECT?
	MOVSI T2,-DXBSZ		;NO, GET LENGTH OF RP20 MICROCODE INSTEAD
LDX20A:	CAIE P6,DA.IDX		;TAPE MICROCODE?
	SKIPA T1,DXBSA(T2)	;NO, GET CRAM WORD OF RP20 MICROCODE
	MOVE T1,DXASA(T2)	;YES, GET CRAM WORD OF TAPE MICROCODE
	JUMPL T1,LDX20B		;JUMP IF NO MORE CRAM DATA
	HRRZ T1,T2		;GET THE PC
	IOR T1,0(Q1)		;SET DESIRED PC BITS
	CALL RHWT1		;SET THE PC
	CAIE P6,DA.IDX		;TAPE MICROCODE?
	SKIPA T1,DXBSA(T2)	;NO, GET RP20 CRAM DATA
	MOVE T1,DXASA(T2)	;YES, GET CRAM DATA FOR TAPE
	ANDI T1,177777		;JUST THE LOW 16 BITS
	TXO T1,.TDIRR!LR	;INTO THE IR
	CALL @1(Q1)		;CALL THE PROCESSING ROUTINE
	AOBJN T2,LDX20A		;LOOP FOR MORE
LDX20B:	AOBJP T2,RSKP		;SKIP THE DELIMITER WORD
	MOVEI T1,.TDICB+.TDPEB	;SET PC BACK TO 0
	TXO T1,.TDPCR!LR	;PC REGISTER
	CALL RHWT1
	MOVX T1,.TDIRR		;GET CONTENTS OF LOCATION 0
	CALL RHRD1
	PUSH P,T1		;SAVE IT
	MOVEI T1,1000		;SET MEMORY ADDRESS TO 0
	CALL XI
	MOVEI T1,400
	CALL XI
LDX20C:	CAIE P6,DA.IDX		;TAPE MICROCODE?
	SKIPA T1,DXBSA(T2)	;NO, GET DATA FOR RP20
	MOVE T1,DXASA(T2)	;YES, GET DATA FOR TAPE
	ANDI T1,377		;ONLY 8 BITS OF DATA
	CALL @2(Q1)		;CALL PROCESSING ROUTINE
	AOBJN T2,LDX20C		;LOOP THROUGH THE WHOLE THING
	MOVEI T1,.TDPEB+.TDCIB	;BACK TO LOCATION 0 OF THE CRAM
	TXO T1,.TDPCR!LR
	CALL RHWT1
	POP P,T1		;GET BACK ITS ORIGINAL CONTENTS
	ANDI T1,177777		;ONLY 16 BITS
	TXO T1,.TDIRR!LR	;PUT IT BACK INTO THE CRAM
	CALLRET RHWT1
;MAKE DX20 EXECUTE INSTRUCTION IN T1

XI:	PUSH P,T1		;SAVE THE INSTRUCTION FOR A MOMENT
	MOVEI T1,.TDSCB		;PUT DX20 INTO SINGLE CYCLE
	TXO T1,.TDMNR!LR
	CALL RHWT1
	MOVEI T1,.TDPEB+.TDCIB	;SET PC 0
	TXO T1,.TDPCR!LR
	CALL RHWT1
	POP P,T1		;GET BACK THE INSTRUCTION
	TXO T1,.TDIRR!LR	;PUT INTO CRAM
	CALL RHWT1
	MOVEI T1,.TDICB+.TDPIB	;TURN ON THE CRAM
	TXO T1,.TDPCR!LR
	CALL RHWT1
	MOVEI T1,.TDSCB+.TDSTB	;CYCLE THE DX20
	TXO T1,.TDMNR!LR
	CALL RHWT1
	MOVX T1,.TDMNR!LR	;TURN SINGLE CYCLE OFF
	CALLRET RHWT1		;AND RETURN
;COMPLAIN ABOUT A VERIFY MISMATCH

NOVERC:	MOVEI Q2,[ASCIZ/CRAM VERIFY/]
	JRST NOVER

NOVERW:	MOVEI Q2,[ASCIZ/WORKING MEMORY VERIFY/]

NOVER:	PUSH P,T1		;SAVE A REGISTER
	MOVEI Q1,"?"		;TYPE A QM
	CALL TYO
	CALL OUTSTR		;OUTPUT DATA
	CALL CRLF		;NEXT LINE
	MOVEI Q2,[ASCIZ/GOOD /]
	CALL OUTSTR		;...
	MOVE Q2,T3		;FIRST WHAT IT SHOULD BE
	MOVEI Q1,40		;GET A SPACE
	CALL TYO		;OUTPUT IT
	CALL OUTOCT		;OUTPUT OCTAL DATA
	MOVEI Q2,[ASCIZ\ BAD\]	;OUTPUT HEADING
	CALL OUTSTR		;...
	MOVE Q2,(P)		;GET THE BAD DATA
	MOVEI Q1,40		;GET A SPACE
	CALL TYO		;OUTPUT IT
	CALL OUTOCT		;OUTPUT OCTAL DATA
	MOVEI Q2,[ASCIZ\ XOR\]	;OUTPUT HEADING
	CALL OUTSTR		;...
	POP P,Q2		;GET THE BAD DATA
	XOR Q2,T3		;GET THE XOR
	MOVEI Q1,40		;GET A SPACE
	CALL TYO		;OUTPUT IT
	CALL OUTOCT		;OUTPUT THE XOR VALUE IN Q2
	RET			;RETURN
	;PRINT CHANNEL #, DX20 TYPE AND #
	;CALL WITH :
	;	P1:		CHANNEL #
	;	P2:		DX20 #
	;	P6:		DX20 TYPE

TYPDX2:	PUSH P,Q2		;PRESERVE Q2
	MOVEI Q2,[ASCIZ \ CHN:\]
	CALL OUTSTR		;OUTPUT CHN:
	MOVE Q2,P1		;GET CHANNEL NUMBER
	CALL OUTOCT		;OUTPUT CHANNEL NUMBER
	CAIN P6,DA.IDX		;TAPE DX20
	MOVEI Q2,[ASCIZ \ DX20A:\] ;YES
	CAIN P6,DB.IDX		;DISK DX20?
	MOVEI Q2,[ASCIZ \ DX20B:\] ;YES
	CALL OUTSTR		;OUTPUT DX20:
	MOVE Q2,P2		;GET DX20 NUMBER
	CALL OUTOCT		;OUTPUT IT
	MOVEI Q1," "		;A SPACE
	POP P,Q2		;RESTORE Q2
	CALLRET TYO		;OUTPUT A SPACE AND RETURN
>;END IFN FT.DX2
	;PAGE FAULT HANDLER
PFERR:	AOS A%EPT+UPTPFO	;THE PC OF THE FAULT
	JRST @<A%EPT+UPTPFO>	;PROCEED


;	SUBROUTINE TO CHECK STRUCTURE NAME OF PACK ON CURRENT CHANNEL AND UNIT
;	RETURNS +1	NO MATCH
;		+2	MATCH
;	OR ERROR RETURN TO COMMAND PARSER

CHKHOM:	MOVE T1,HOMNAM		;CHECK BLOCK NAME
	CAME T1,[SIXBIT 'HOM']
	JRST BADHOM		;#12 BAD
	MOVE T1,HOMCOD		;CHECK BLOCK CODE
	CAIE T1,CODHOM		;...
	JRST BADHOM
	MOVE T1,HOMSNM		;#100 GET POINTER RIGHT
	TXNE F,F.TELL		;#100 SURVEYING?
	JRST HOMTEL		;#100 YES SO GO IT
	SKIPE DEV		;WAS DEVICE STRING TYPED AT CONSOLE
	JRST [MOVE T1,HOMSNM	;YES, FORGET LOOKING FOR SERIAL NUMBERS
		CAME T1,STRNAM	;CHECK STRUCTURE NAME
		RET		;NO MATCH
		JRST CHKHM1]	;MATCH, RECORD THIS
	MOVE T1,HOMSER		;GET APR SERIAL NUMBER
	CAME T1,APRSER		;IS IT A MATCH?
	RET			;NO
	MOVE T1,HOMSNM		;GET STRUCTURE NAME
	SKIPN CURNAM		;IS THIS THE FIRST TIME THRU?
	MOVEM T1,CURNAM		;YES, STORE NAME
	CAME T1,CURNAM		;ARE THE NAMES THE SAME
	RET			;NO
CHKHM1:	MOVE T1,HOMLUN		;GET LOGICAL UNIT
	SKIPE DSKTAB(T1)	;IS THERE ALREADY AN ENTRY?
	 $ERROR(STRMTO)		;YES - MORE THAN 1 BOOTABLE STRUCTURE
	HRRZM P2,DSKTAB(T1)	;STORE UNIT NUMBER
	MOVEI T2,ENTFLG(P1)	;GET CHANNEL & ENTRY-IN-USE FLAG
	HRLM T2,DSKTAB(T1)	;STORE CHANNEL NUMBER
	HLRZ T1,T1		;GET # UNI IN STR
	SOS T1
	SKIPGE MAXUNI		;ALREADY SET?
	MOVEM T1,MAXUNI		;NO - SET
	CAME T1,MAXUNI		;SAME AS OTHERS?
	 $ERROR (STRHOM)	;BAD HOME BLOCK
	MOVE T2,HOMRXB		;GET ROOT XB
	SKIPN DIORG		;ALREADY SET?
	MOVEM T2,DIORG		;YES - LET IT BE
	CAME T2,DIORG		;SAME AS OTHER
	 $ERROR (STRHOM)	;BAD HOME BLOCK


RSKP:
CPOPJ1:	AOS (P)			;SKIP RETURN

R:
CPOPJ:	RET
HOMTEL:	CALL SIXTYP		;#12 type structure name
	CALL SPACE		;#12 space
	HRRZ T2,HOMLUN		;#12 get number of this unit
	CALL OCTOUT		;#12 show it
	MOVEI Q1,"/"		;#12 separator
	CALL TYO		;#12 type it
	HLRZ T2,HOMLUN		;#12 get number of units in str
	CALL OCTOTS		;#12 type it, space
	RETSKP			;#12 return (good)

BADHOM:	MOVEI T1,[SIXBIT 'BADHB \'] ;#12 bad homeblock message
	TXNE F,F.TELL		;#12 reporting?
	CALL OUTSIX		;#12 yes, report error
	RET			;#12 return +1 for error 
;STRING READ FROM CONSOLE

GETSTR:	MOVE Q3,[POINT 7,D$ISTR] ;OUTPUT POINTER
	MOVE T1,Q3		;SAVE - THIS IS OUR VALUE
	SKIPE T2,LODTYP		;DIALOGUE LOAD? SKIP IF SO.
	JRST GETST1		;NO. GO PROCESS BITS

GET.W:	CALL TYI		;READ A CHARACTER
	CAIN Q1,"U"-100		;CONTROL-U?
	JRST [	MOVEI Q2,[ASCIZ/XXX/] ;YES - OUTPUT LINE DELETE PROMPT
		CALL OUTSTR
		JRST GETCOM]	;AND GET ANOTHER LINE
	CAIN Q1,177		;RUBOUT?
	JRST [	PUSH P,T1	;YES = START THE DELETE
		LDB Q1,Q3	;GET THE LAST CHARATER
		HRROI T1,-1	;BACKUP THE BYTE POINTER
		CAME Q3,[10700,,D$ISTR-1]	;HAVE WE?
		CAMN Q3,[POINT 7,D$ISTR]	;HAVE WE?
		JRST [	MOVEI Q1,7	;YES - RING THE BELL
			CALL TYO	;OUTPUT THE BELL
			POP P,T1
			JRST GET.W]	;GET NEXT CHARACTER
		ADJBP T1,Q3
		CALL TYO	;OUTPUT THE CHARACTER LAST TYPED
		MOVEI Q1,"\"	;AND THE BACK-SLASH
		CALL TYO	;TYPE IT
		MOVEM T1,Q3	;RESET BYTE POINTER
		POP P,T1
		JRST GET.W]	;GET NEXT CHARACTER
	CAIL Q1,140		;LOWER CASE?
	SUBI Q1,40		;YES, MAKE UPPER
	CAIN Q1,"?"		;#12 QM?
	TXOA F,F.TELL		;#12 YES, WANT SURVEY: SET FLAG AND FINISH
	CAIN Q1,15		;EOL?
	JRST GET.EL		;YES - FINISH OUT
	IDPB Q1,Q3		;STORE CHARACTER
	CAIE Q1,":"		;DEV NAME TERM?
	JRST GET.W		;NO - LOOP
	MOVEM T1,DEV		;YES - SET FLAG
	MOVE T1,Q3		;NEW COMMAND PTR
	JRST GET.W		;LOOP FOR MORE

GET.EL:	IDPB Q1,Q3		;STORE CR
	CALL CRLF		;ECHO CRLF
GET.E1:	SETZI T2,		;TERMINATING NULL
	IDPB T2,Q3		; STORE
	RET			;RETURN

SIXTYP:	MOVE Q2,T1		;COPY WORD
SIXTP1:	SETZ Q1,		;INIT Q1
	LSHC Q1,6		;PEEL OFF A CHR
	ADDI Q1,40		;CONVERT TO ASCII
	CALL TYO		;TYPE OUT
	JUMPN Q2,SIXTP1		;LOOP IF NOT BLANK
	RET

CRLF:	MOVEI Q1,15		;CR WITH PARITY
	CALL TYO		;TYPE OUT
	MOVEI Q1,12		;LF
	CALLRET TYO

OCTOTS:				;#12 output octal number (T2), then space
	CALL OCTOUT		;#12
;	CALLRET SPACE		;#12 output spacing, return

SPACE:	MOVEI T1,[SIXBIT '   \'] ;#12 output spacing
;	CALLRET OUTSIX		;#12 .

OUTSIX:				;#12 output SIXBIT string per T1
	HRLI T1,(POINT 6,)	;#12 make a byte pointer
OUTSX1:	ILDB Q1,T1		;#12 get a character
	MOVEI Q1,40(Q1)		;#12 convert to ASCII
	CAIN Q1,"\"		;#12 terminator?
	RET			;#12 yes, done
	CALL TYO		;#12 no, output character
	JRST OUTSX1		;#12 finish string

OCTOUT:				;#12 output octal
	PUSH P,T2		;#12 .
	PUSH P,T3		;#12 .
	CALL OCTOU1		;#12 do the output
	POP P,T3		;#12 restore ...
	POP P,T2		;#12 ... ACs
	RET			;#12 output digit

OCTOU1:	IDIVI T2,^D8		;#12 divide by 8
	JUMPE T2,OCTOU3		;#12 just about done if T2 0
	HRLM T3,0(P)		;#12 save digit
	CALL OCTOU1		;#12 recurse
	HLRZ T3,0(P)		;#12 get digit back
OCTOU3:	MOVEI Q1,"0"(T3)	;#12 ascii
	CALLRET TYO		;#12 output digit, return


;KLINIT HAS REQUESTED SPECIAL LOAD. PROCESS THE BITS

GETST1:	TXZE T2,F.TELL		;#14 AUTOMATIC TELL?
	 JRST [	MOVE T3,[BYTE (7) "?",0] ;#14 YES
		JRST GETST3]	;#14 DO IT
	TXZE T2,F11.DM		;WANT DUMP?
	JRST [	MOVE T3,[BYTE (7) "/","D",.CHCRT,0]
		JRST GETST3]
	TXZE T2,F11.LD		;WANT STANDARD LOAD?
	JRST [	MOVE T3,[BYTE (7) .CHCRT,0]
		JRST GETST3]
GETST3:	MOVEM T3,D$ISTR		;STASH THE STRING
	MOVEM T2,LODTYP		;STASH REMAINING FLAGS
	RET			;AND DONE

IFN FT.UDB,<

;USER MODE CONSOLE DRIVERS

TYO:	PUSH P,T1		;PRESERVE T1
	MOVE T1,Q1		;COPY CHAR
	PBOUT			;OUTPUT IT
	POP P,T1		;RESTORE T1
	RET

TYI:	PUSH P,T1		;SAVE T1
	PBIN			;READ A CHAR
	CAIN T1,37		;EOL?
	MOVEI T1,15		;YES - TURN TO CR
	MOVE Q1,T1		;RETURN IN STANDARD AC
	POP P,T1		;RESTORE T1
	RET
>				;END IFN FT.UDB

.DTTYO==10B27			;FUNCTION CODE FOR TYPE OUT, CHAR IN LOW BITS
.DTMMN==11B27			;FUNCTION CODE FOR MONITOR MODE ON

;EPT LOCS

DTEFLG=A%EPT+444		;OPERATION COMPLETE FLAG
DTEF11=A%EPT+450		;PDP11 TO PDP10 ARGUMENT
DTECMD=A%EPT+451		;-10 TO -11 COMMAND WORD
DTEOPR=A%EPT+453		;OPERATION IN PROGRESS FLAG
DTEMTD==A%EPT+455		;MONITOR OUTPUT DONE WHEN NONZERO
DTEMTI==A%EPT+456		;0 IF READY FOR ANOTHER CHAR FROM 11
DTEN==4				;NUMBER OF DTE'S

;DTE20 HARDWARE 

DTE==200			;DEVICE CODE
DTEPRV==1B20			;PRIVILEGED/RESTRICTED BIT IN CONI
PI0ENB==1B32			;ENABLE PI 0
PIENB==1B31			;SET PI ASSIGNMENT

TO11DB==1B22			;TO 11 DOORBELL

IFE FT.UDB,<
IFN KLFLG,<

IFE SMFLG,<
;KL10 CONSOLE ROUTINES


;TELETYPE INPUT

TYI:	SKIPN DTEMTI		;INPUT READY
	JRST TYI		;NO - LOOP
	MOVE Q1,DTEF11		;GET CHAR
	CALL TYO		;ECHO IT
	MOVE Q1,DTEF11		;GET CHAR AGAIN
	SETZM DTEMTI		;RESET INPUT DONE FLAG
	RET

;TELETYPE OUTPUT

TYO:	SETZM DTEMTD		;CLEAR OUTPUT DONE FLAG
	TRO Q1,.DTTYO		;LIGHT FUNCTION BI
	MOVEM Q1,DTECMD		;STORE FOR 11
	MOVEI Q1,TO11DB		;RING DOORBELL
	XCT DTCNOW		;DO IT
	SKIPN DTEMTD		;DONE YET?
	JRST .-1		;NO
	RET			;YES
>				; END IFE SMFLG
>				; END IFN KLFLG

IFN SMFLG,<
TYI:	MOVE Q1,CTYIWD		;CHECK FOR INPUT READY
	TRNN Q1,CTYIRD		;CHECK INPUT WORD
	JRST .-2		;NO INPUT YET
	SETZM CTYIWD		;CLEAR FLAGS
	CONO APR,AP.SET!AP.INE	;INTERRUPT 8080
TYO:	PUSH P,T1		;SAVE A REGISTER
	MOVE T1,CTYOWD		;CHECK FOR READY
	TRNE T1,CTYORD		;OUTPUT WORD
	JRST .-2		;NOT READY YET
	IORI Q1,CTYORD		;INSURE NOT READY FLAG SET
	MOVEM Q1,CTYOWD		;OUTPUT WORD
	ANDI Q1,177		;MASK TO USEFUL STUFF
	CONO APR,AP.SET!AP.INE	;INTERRUPT 8080
	POP P,T1		;RESTORE
	RET
>				; END IFN SMFLG
>				;END IFE FT.UDB
IFE FT.MTA, <

IFN FT.RP,<
RD0:	MOVSI T3,(700000,,0)	;RP10 RECAL OP
	DPB P1,[POINT 3,T3,5]	;STORE UNIT
	CALL DOOP		;DO OPERATION
	MOVEI T3,ICCW		;RP10 READ OP FOR PAGE 0
RD1A:	SETZM ICCW+1		;HALT CCW
	DPB P1,[POINT 3,T3,5]
	CALL DOOP
	RET

RD1:	MOVEI T3,4B23+ICCW	;READ COMMAND FOR PAGE 1
	JRST RD1A

RD10:	MOVEI T3,1B18+ICCW	;SECTOR 0, SURF 1
	JRST RD1A		;JOIN OTHER CODE

DOOP:	MOVEI T2,^D5		;RETRY COUNTER
DOOP1:	DATAO DPC,[500000,,776]	;CLEAR ATTN
	MOVEI T1,^D50000	;WAIT COUNT
	DATAO DPC,T3		;SEND OP
	CONSO DPC,10		;DONE?
	SOJG T1,.-1		;NO - WAIT
	JUMPLE T1,DOOP2		;ERROR - RETRY
	CONSO DPC,177720	;ERRORS?
	RET
DOOP2:	CONO DPC,175710		;CLEAR FLAGS
	SOJG T2,DOOP1		;RETRY IF NOT TOO MANY
	 $ERROR (DSKHDE)	;HARD DISK ERROR

>				;END IFN FT.RP


IFE SMFLG,<
IFN FT.RH!FT.RP,<

; ROUTINE TO READ PAGE CONTAINING BACKUP HOME BLOCK
;
; ACCEPTS IN P1/ CHANNEL NUMBER
;	     P2/ UNIT NUMBER
;		CALL RD10
; RETURNS +1 IF NO ERRORS, ELSE CAUSES DSKHDE ERROR RETURN

RD10:

IFN FT.RP,<
	SKIPA P4,[R4%DST!LR!0B27!^D10B35] ;DESIRED SECTOR AND TRACK
>				; END OF IFN FT.RP

IFN FT.RH, <
	SKIPA P4,[.RHSBR!LR!0B27!^D10B35] ;DESIRED SECTOR AND TRACK
>				; END OF IFN FT.RH

	;..
; ROUTINE TO READ PAGE 0
;
; ACCEPTS IN P1/ CHANNEL NUMBER
;	     P2/ UNIT NUMBER
;		CALL RD0
; RETURNS +1 IF NO ERRORS, ELSE CAUSES DSKHDE ERROR RETURN

RD0:IFN FT.RP, <
	MOVE P4,[R4%DST!LR!0]	;DESIRED SECTOR=0, TRACK=0
>				; END OF IFN FT.RP

IFN FT.RH, <
	MOVE P4,[.RHSBR!LR!0B27!0B35] ;RH20 XFR CONTROL REGISTER
>				; END OF IFN FT.RH
	MOVEI T3,NRETRY		;MAX TIMES TO RETRY THIS OPERATION
RD00:	MOVE T1,[R4%CSR!LR!R4%CRC!GO] ;RECALIBRATE FUNCTION
	CALL RHWT1		;GO RECALIBRATE DRIVE
RD0A:	MOVX T1,R4%DSR		;RP04 DEVICE STATUS REGISTER
	CALL RHRD1		;GET DRIVE STATUS
	TXNN T1,R4%DRY		;RECALIBRATE FINISHED ?
	JRST RD0A		;NO, GO WAIT TILL DONE
	MOVE T1,[R4%CSR!LR!R4%RIP!GO] ;READ-IN PRESET FUNCTION
	CALL RHWT1		;INITIALIZE DRIVE


READX:	SETZM ICCW+1		;CHANNEL HALT COMMAND
IFN FT.RP, <
	MOVE T4,[RH%XFR!LR!<ICCW_-1>B28!R4%CRD!GO] ;INITIATE TRANSFER REGISTER
>				; END OF IFN FT.RP

IFN FT.RH, <
	MOVE T4,[.RHSTR!LR!RCLP!STLW!R4%CRD!GO] ;RH20 XFR CONTROL REGISTER
	MOVNI T1,N.BKPG*1	;ONE PAGE
	DPB T1,[POINT 10,T4,29]	;ADD -BLOCK COUNT
>				; END OF IFN FT.RH
	;..
; ROUTINE TO DO A DATAO TO THE RP04

; ACCEPTS IN T4/	DATAO DATA
;	     P1/	CHANNEL NUMBER
;	     P2/	UNIT NUMBER
;	     P4/	POSITION SELECT WORD
; RETURNS + 1 IF NO ERRORS, ELSE CAUSES DSKHDE ERROR RETURN


DOOP0:	MOVE T1,P4		;GET POSITION SELECT WORD
	CALL RHWT1		;WRITE IT
	MOVE T1,T4		;GET TRANSFER WORD
	MOVEI T2,TIMOUT		;GET TIMEOUT COUNT
	CALL RHWT1		;GO DO THE DATAO
DOOP1:	CALL RHCI1		;GO GET CONI BITS
	TXNN T1,.RHDON		;OPERATION COMPLETE ?
	SOJG T2,DOOP1		;NO, LOOP TILL DONE
	MOVEI T1,.RHRAE!.RHCTE!.RHMBE!.RHDON
	CALL RHCO1		;CLEAR OUT CHANNEL GRACEFULLY
	JUMPLE T2,DOOP2		;OPERATION EVER FINISH ?
	MOVX T1,R4%DSR		;YES, SET UP TO GET DEVICE STATUS
	CALL RHRD1		;GO GET DEVICE STATUS
	TXNE T1,R4%ERR		;CHECK COMPOSITE ERROR INDICATOR
	JRST DOOP2		;THE CRUMMY DRIVE SCREWED UP
	CALL RHCI1		;GO GET CONI BITS
	TXNN T1,RHERR		;ANY ERRORS ?
	RET			;ALL DONE, RETURN

DOOP2:	MOVEI T1,.RHMBR+.RHMBE+.RHCTE+.RHSTP ;GET MASSBUS RESET AND ENABLE BITS
	CALL RHCO1		;DO CONO TO CHANNEL
	MOVEI T1,.RHMBE		;GET MASSBUS ENABLE
	CALL RHCO1		;ENABLE CHANNEL
	MOVE T1,[R4%ATN!LR!377]	;RP04 ATTENTION REGISTER
	CALL RHWT1		;CLEAR ATTENTION
	SOJG T3,RD00		;TRY IT ALL OVER AGAIN
	RET			;CATCH ERROR LATER
>				;#8 END OF IFN FT.RH!FT.RP
IFN FT.SA,<			;#8 .

; Routine to read page containing backup home block
;
; Accepts in P1/ Channel number
;	     P2/ Unit number
;		CALL RD10
; Returns +1 if no errors, else goes to DSKERR


RD10:	SKIPA P5,[^D10]		;#8 read block 10

; Routine to read page 0
;
; Accepts in P1/ Channel number
;	     P2/ Unit number
;		CALL RD0
; Returns +1 if no errors, else goes to DSKERR

RD0:	MOVEI P5,0		;#8 desired sector = 0
	MOVE T2,P5		;#8 copy sector number
	IDIVI T2,N.SCL4		;#8 break into Cyl, sector within Cyl
	MOVEI P3,.ICRDD		;#8 read
	CALL CC1ST0		;#8 set up the I/O
	CALL CC1GO		;#8 do the I/O
	 $ERROR(DSKHDE)		;#100 FIX NEW V5 ERROR MACRO
	RET			;#8 yes good

>				;#8 end of IFN FT.SA

>				;END IFE SMFLG

IFN SMFLG,<
RD10:	SKIPA P4,[^D10]		;READ BLOCK 10

RD0:	SETZ P4,		;READ BLOCK 0
	MOVEI T3,NRETRY		;SET UP RETRY
RD00:	MOVEI T1,R4%CRC!GO	;DO A DRIVE CLEAR
	WRIO T1,@RPCS1(P1)
	MOVEI T1,R4%DRY		;WAIT FOR READY
	TION T1,@RPDS(P1)
	JRST .-1
	MOVEI T1,R4%RIP!GO	;NO DO READIN PRESET
	WRIO T1,@RPCS1(P1)
	WRIO P4,@RPDA(P1)	;SET DISK ADDRESS
	MOVNI T1,RPPGSZ		;SET PAGE SIZE
	WRIO T1,@RPWC(P1)
	SETZ T1,0		;SET DEVICE CORE ADDRESS
	WRIO T1,@RPBA(P1)	;SET CORE ADDRESS
	MOVE T1,ICCW
	LSH T1,-9		;FIND PAGE ADDRESS
	ANDI T1,77777
	IORI T1,UNVBIT!UN36B	;SET UNIBUS VALID BIT
	WRIO T1,@UNBMAP(P1)	;SET MAP
	MOVEI T1,R4%CRD!GO	;DO THE READ
	WRIO T1,@RPCS1(P1)	;READ
	MOVEI T1,R4%DRY		;SET UP READY
	MOVEI T2,TIMOUT		;CHECK FOR TIMEOUT
DOOP1:	TION T1,@RPCS1(P1)	;WAIT FOR DONE
	SOJG T2,DOOP1
	RDIO T1,@RPCS1(P1)	;CHECK STATUS
	TRNE T1,R4%ERR		;ERROR?
	SOJG T3,RD00		;YES TRY AGAIN
	RET			;NO RETURN

>				;END IFN SM10
>				;END IFE FT.MTA

IFN SMFLG,<
;
;R11CHT:  THIS IS THE "CHANNEL" TABLE FOR THE RH11'S
; THERE SHOULD BE ONE ENTRY FOR EACH REGISTER OF EACH
; RH11.  EACH RH11 IS TO BE CONSIDERED A CHANNEL
; AND THIS TABLE IS USUALLY USED INDEXED.

RH11CH:
RPCS1:	R0%CS1			;STATUS 1
	R1%CS1
RPWC:	R0%WC			;WORD COUNT
	R1%WC
RPBA:	R0%BA			;BUS ADDRESS
	R1%BA
RPDA:	R0%DA			;DISK ADDRESS (SECTOR AND TRACK)
	R1%DA
RPCS2:	R0%CS2			;STATUS 2
	R1%CS2
RPDS:	R0%DS			;DRIVE STATUS
	R1%DS
RPER1:	R0%ER1			;ERROR REGISTER 1
	R1%ER1
RPAS:	R0%AS			;ATTENTION SUMMARY REGISTER
	R1%AS
RPDT:	R0%DT			;DRIVE TYPE REGISTER
	R1%DT
RPDC:	R0%DC			;DESIRED CYLINDER
	R1%DC
UNBMAP:	UNBMP0			;UNIBUS ADAPTER MAP ADDRESS
	UNBMP1
>				;END IFN SM10
IFN FT.SA,<			;#8 .
IFE FT.MTA,<			;#8 .

;CC1SRC - set up "Read Count" program
; T1/ channel program address
;	CALL CC1SRC
; RETURNS +1: Always
;  T3 destroyed

CC1SRC:				;#8 set up read count program
	MOVEI T3,.SCXCT!.SCILE!.SCBYT ;#8 eXiCuTe, Ignore Length Error, BYTe mode
	STOR T3,DP%CCF,(T1)	;#8 store flags
	MOVEI T3,-^D8		;#8 8 byte transfer only
	STOR T3,DP%CNT,(T1)	;#8 store count in CP
	RET

;DOIO - do an I/O operation
; F/  bit F.PHY determines if address in P4 is physical instead of virtual
; P3/ Command code
; P4/ Core address
; P5/ disk address
; Returns +1: Failure
;  RH(F), P2, T2-T4 destroyed
; Returns +2: Success
;  RH(F), P2, T2-T4 destroyed

DOIO:				;#8 do I/O
	PUSH P,P1		;#8 save P1
	CALL CC1SET		;#8 setup for the I/O
	CALL CC1GO		;#8 go do it 
	 CAIA			;#8 failed, do not skip
	AOS -1(P)		;#8 skip return for success
	POP P,P1		;#8 restore P1
	RET			;#8) return (+1 or +2)

;CC1SET - Setup for I/O operation
; F/  bit F.PHY determines if address in P4 is physical instead of virtual
; P3/ Command code
; P4/ Core address
; P5/ disk address
; Returns +1: always
;  T1/ Pointer to channel program (CC1NCP)
;  RH(F), P1-P2, T2-T4 destroyed

CC1SET:	MOVE T1,P5		;#8 get disk address ("sector")
	TLZ T1,777770		;#8 keep just the address bits
	IDIVI T1,N.SCL4		;#8 get Cylinder in T1, Sector in T2
	MOVE T3,T2		;#8 save sector within cyl
	IDIV T1,NUMCYL		;#8 get unit number in T1, CYL in T2
	HRRZ P2,DSKTAB(T1)	;#8 get Physical unit number
	HLRZ P1,DSKTAB(T1)	;#8 get channel #, entry-in-use flag
	TRZ P1,ENTFLG		;#8 keep just the channel number

;CC1ST0 - set up for I/O operation given unit, sector on unit
; F/  bit F.PHY determines if address in P4 is physical instead of virtual
; P1/ Channel number
; P2/ Unit number
; P3/ command code
; P4/ Core address
; T2/ Cylinder
; T3/ sector within cylinder
; RETURNS +1: always
;  RH(F), T1-T4 destroyed

CC1ST0:	CALL CC1GHA		;#8 get hardware format in T2, T3
	HRRI F,.IDDSK(P2)	;#8 get Device code
	MOVEI T1,CC1NCP		;#8 get address of channel program
	DMOVEM T2,DPOSEK(T1)	;#8 store seek arguments
	STOR F,SC%DEV,DPOC1(T1) ;#8 store device address
	STOR F,SC%DEV,DPOC2(T1) ;#8 store device address
	STOR F,SC%DEV,DPOC3(T1) ;#8 store device address
	STOR F,SC%DEV,DPOC4(T1) ;#8 store device address
	STOR F,SC%DEV,DPOC5(T1) ;#8 store device address
	STOR P3,DP%CMD,(T1)	;#8 store command code
	MOVEI T3,.SCXCT		;#8 normal channel flags
	STOR T3,DP%CCF,(T1)	;#8 store channel flags
	MOVEM T1,T3		;#8 save CP address
	CALL GETPHY		;#8 get physical address
	 $ERROR(MEMMRF)		;#100 FIX FOR V51
	EXCH T1,T3		;#8 exchange CP adr and data adr
	JUMPE T3,[		;#8 page 0?
		MOVX T3,<IOW LCORAD,0,CHN> ;#8 skip "lo core" if page 0
		MOVEM T3,DPOADR(T1) ;#8 store "SKIP" IOW
		MOVX T3,<IOW ^D512-LCORAD,LCORAD> ;#8 IOW to read rest of page
		MOVEM T3,DPOADR+1(T1) ;#8 store transfer IOW
		SETZM DPOADR+2(T1) ;#8 terminate channel program
		RET]		;#8 return
SSAPAG==SA0BAS&777000		;#8 page SA10 base registers are on
SSALEN==<SSAN*SSANSC*4>		;#8 length of SA10 base registers
	CAIN T3,SSAPAG		;#8 is this the page containing SA10 base?
	 JRST [			;#8 yes, don't clobber locations SA10 is using
		CAIE P3,.ICRDD	;#8 is this a read?
		JRST .+1	;#8 no, no need to worry
		 IFN SSAPAG-SA0BAS,< ;#8 if data before the base, read it in
		MOVX T3,<IOW SA0BAS-SSAPAG,SSAPAG,CHN> ;#8 .
		MOVEM T3,DPOADR(T1) ;#8 save IOW to read in beginning of page
		  IFN <SA0BAS+SSALEN>&777,< ;#8 .
		MOVX T3,<IOW SSALEN,0,CHN> ;#8 IOW to skip SA10 regs
		MOVEM T3,DPOADR+1(T1) ;#8 .
		MOVX T3,<IOW <^D512-SSALEN-<SA0BAS&777>>,SA0BAS+SSALEN> ;#8 .
		MOVEM T3,DPOADR+2(T1) ;#8 store IOW to read end of page
		SETZM DPOADR+3(T1) ;#8 terminate CP
		  >		;#8 end of IFN <SA0BAS+SSALEN>&777
		  IFE <SA0BAS+SSALEN>&777,< ;#8 .
		MOVX T3,<IOW SSALEN,0> ;#8 IOW to skip SA10 regs
		MOVEM T3,DPOADR+1(T1) ;#8 .
		SETZM DPOADR+2(T1) ;#8 terminate CP
		  >		;#8 end of IFE <SA0BAS+SSALEN>&777
		 >		;#8 end of IFN SSAPAG-SA0PAG
		 IFE SSAPAG-SA0BAS,<	;#8 if no data on page before the base 
		MOVX T3,<IOW SSALEN,0,CHN> ;#8 skip SA10 regs
		MOVEM T3,DPOADR(T1) ;#8 .
		MOVX T3,<IOW <^D512-SSALEN>,SA0BAS+SSALEN> ;#8 read rest of pg
		MOVEM T3,DPOADR+1(T1) ;#8 .
		SETZM DPOADR+2(T1) ;#8 terminate CP
		 >		;#8 end of IFE SSAPAG-SA0BAS
		RET ]		;#8 return
	TLO T3,(<IOW ^D512,0>)	;#8 form IOW
	MOVEM T3,DPOADR(T1)	;#8 store IOW
	SETZM DPOADR+1(T1)	;#8 terminate channel program
	RET			;#8 return

;CC1GHA - get HWFMT surface/record address
; T2/ Cylinder
; T3/ 'sector' within cylinder
; P3/ UDB
; RETURNS +1: always
;  T2/ HWFMT 1st word of seek: search address containing cylinder
;  T3/ HWFMT 2nd word of seek,search address containing surface, record,
;			quarter page within physical record
;  T4 destroyed

CC1GHA:	IDIVI T3,N.STK4		;#8 get surface, record
	LSH T2,<^D35-POS(DP%CYL)> ;#8 position cylinder for hardware
	LSH T3,<^D35-POS(DP%SRF)> ;#8 position surface
	DPB T4,[POINTR(T3,DP%REC!DP%LRC)] ;#8 insert record, logical record
	ADDI T3,FLD(1,DP%REC)	;#8 record numbers start with 1
;#8 Note that T3 will work as the 2nd word of seek/search arguments, and
;#8  if this is not a normal 1 page transfer, byte 3 contains which quarter
;#8  of the page to start with.
	RET			;#8 return

;CC1GOR - Start I/O on SA10 disks, doing System Reset first
; T1/ address of Channel program
; P1/ Channel
; RETURNS +1: I/O unsuccessful
;  T1-T4 destroyed
; RETURNS +2: I/O successful
;  T1-T4 destroyed

CC1GOR:	TDZA T2,T2		;signal SAINGO that reset is wanted
; ... 	

;CC1GO - Start I/O on SA10 disks
; T1/ address of Channel program
; P1/ Channel
; RETURNS +1: I/O unsuccessful
;  T1-T4 destroyed
; RETURNS +2: I/O successful
;  T1-T4 destroyed

CC1GO:	SETO T2,		;#8 do not do reset before I/O
	CALL SAINGO		;#8 do the I/O
	 CAIA			;#8 failed, more to do
	RETSKP			;#8 success
	MOVEI T1,CC1NCP+DPOSNP	;#8 get address of sense program
	HRRZ T2,1(T1)		;#8 get address of sense buffer
	SETOB T2,0(T2)		;#8 store invalid sense, request no reset
	CALL SAINGO		;#8 do the sense
	 JFCL			;#8 if sense fails ... ???
	RET			;#8 fail return

>				;#8 end of IFE FT.MTA
>				;#8 end of IFN FT.SA
IFN FT.SA,<			;#8 .
IFE FT.MTA,<			;#8 .	

;#8 Disk Channel Program (CP)

CC1NCP:				;#8 channel program
DPOC1==.-CC1NCP			;#8 command # 1
	DCW <XCT,CHN,BYT>,.ICSEK,.IDDSK ;#8 Seek cylinder
	IOW 6,CC1SK		;#8 arg to seek
DPOC2==.-CC1NCP			;#8 command # 2
	DCW <XCT,CHN,BYT>,.ICSSC,.IDDSK ;#8 Set sector
	IOW 1,CC1SK+2		;#8 sector number
DPOC3==.-CC1NCP			;#8 command # 3
	DCW <XCT,CHN,BYT,BOF>,.ICSIE,.IDDSK ;#8 Search ID equal
	IOW 5,CC1SK		;#8 arg to search
	TCH .-2			;#8 keep searching
DPOC4==.-CC1NCP			;#8 command # 4
DPOOPC==.-CC1NCP		;#8 offset to RD or WRT command
	DCW <XCT>,.-.,.IDDSK	;#8 Read data or write data
DPOADR==.-CC1NCP		;#8 offset to (1st) data address
	BLOCK 4			;#8 room for up to 3 IOW's + HLT **

DPOC5==.-CC1NCP			;#8 command # 5
DPOSNP==.-CC1NCP		;#8 offset to sense program
	DCW <XCT,BYT>,.ICSNS,.IDDSK ;#8 Sense command
	IOW ^D24,CC1SB		;#8 where to store sense bytes
	EXP 0			;#8 end of sense program

DPOSEK==:.-CC1NCP		;#8 ofset to seek buffer
CC1SK:	BLOCK 3			;#8 seek argument 
DPOLEN==.-CC1NCP		;#8 length of CP's

CC1SB:	BLOCK 6			;#8 sense buffer

>				;#8 end of IFE FT.MTA
IFN FT.MTA,<			;#8 .

; Magnetic tape Channel Programs (SA10)

CMTCP:				;#8 standard R/W Channel program for tape
	DCW <NMX,XCT,ILE,CHN>,.IC916,.IDMTA ;#8 set mode to 9-track, 1600-bpi
	DCW <XCT,CDM>,.-.,.IDMTA ;#8 read or write command (dec core dump mode)
CMTIOW: BLOCK 4			;#8 room for up to 3 IOWs + HLT

CMTRCP:				;#8 rewind channel program
	DCW <NMX,XCT,ILE>,.ICREW,.IDMTA ;#8 rewind
	HLT			;#8 that's all

CMTNCP:				;#8 NO-OP channel program
	DCW <NMX,XCT,ILE>,.ICNOP,.IDMTA	;#8 No-Op
	HLT

CMTBCP:				;#8 backspace block channel progarm
	DCW <NMX,XCT,ILE>,.ICBSB,.IDMTA	;#8 backspace block
	HLT			;#8 end of channel program

CMTSCP:				;#8 sense channel program
	DCW <XCT,BYT>,.ICSNS,.IDMTA ;#8 sense command
	IOW ^D24,CMTSB		;#8 count, address of sense buffer
	HLT			;#8 end of CP

CMTSB:	BLOCK 6			;#8 sense bytes (24 of them)
>				;#8 end of IFN FT.MTA

>				;#8 end of IFN FT.SA
IFN FT.SA,<			;#8 .

;SAINGO - Routine to start I/O 
; [Note: Caller must worry about caching of channel program and I/O area.]
; T1/ address of channel program 
; T2/ 0 = do reset (else don't)
; P1/ Channel number
;	CALL SAINGO
; RETURNS +1: I/O unsuccessful
;  T1-T4 destroyed
; RETURNS +2: I/O successful
;  T1-T4 destroyed

SAINGO:				;#8 .
	JUMPN T2,SAING1		;#8 Reset desired?
	PUSH P,T1		;#8 yes, save CP address
	MOVEI T1,SA%INI!SA%CME	;#8 reset SA10, clear errors
	XCT SAXCNO(P1)		;#8 do reset
	MOVEI T1,2000		;#8 some delay for the SA10 and channel
	SOJG T1,.		;#8 STALL
	POP P,T1		;#8 restore CP address
SAING1:	TLO T1,(TCH)		;#8 create transfer program
	MOVE T2,SAXBAS(P1)	;#8 get base address
	MOVEM T1,0(T2)		;#8 store TCH program at base
	MOVEI T3,4		;#8 Try up to 4 times
SAING2:	CALL SSAGO		;#8 start the I/O
	MOVEI T4,100000		;#8 lots of time to find the device
SAING3:	XCT SAXCNI(P1)		;#8 get current conditions
	TRNE T1,SA%MPE!SA%NXM	;#8 parity error or NXM?
	JRST SAING8		;#8 yes, return failure
	TDNN T1,SAXSTF(P1)	;#8 status flag present?
	SOJG T4,SAING3		;#8 no, go look again
	JUMPLE T4,SAING9	;#8 quit if it timed out
	DMOVE T1,1(T2)		;#8 get status words
	TXNE T1,FLD(.S1SER!.S1BIP!.S1CSE,S1%CHS) ;#8 test for errors meaning "not found"
	JRST SAING8		;#8 yes, indicate failure and quit
	TXNN T1,FLD(.S1BSY!.S1CUE,S1%DVS) ;#8 Test for transient condition
	JRST SAING9		;#8 no, done
	SOJG T3,SAING2		;#8 yes, try again if haven't tried too much
SAING8:	SETZ T4,		;#8 indicate failure
SAING9:	MOVEI T1,SA%CME!SA%CLR!FLD(.SASTS,SA%FCN)!SSACHN ;#8 clear status and errors
	XCT SAXCNO(P1)		;#8 do clears
	JUMPG T4,RSKP		;#8 good return
	MOVEI T1,SA%CLR!FLD(.SAGOF,SA%FCN)!SSACHN ;#8 clear go flag 
	XCT SAXCNO(P1)		;#8 .
	RET			;#8 "not found" return

;SSAGO - Start I/O on SA10 subchannel
; P1/ Channel number
;	CALL SSAGO
; RETURNS +1: Always
;  T1,T2 destroyed


SSAGO:	MOVE T2,SAXBAS(P1)	;#8 get base address
	SETOM 1(T2)		;#8 store phony status
	MOVEI T1,SA%SET!FLD(.SAGOF,SA%FCN)!SSACHN ;#8 request channel to do cmd
	XCT SAXCNO(P1)		;#8 go
	MOVEI T1,SA%CLR!FLD(.SASTS,SA%FCN)!SSACHN ;#8 clear status flag if set
	XCT SAXCNO(P1)		;#8 .
	RET			;#8 return
;#8 Constants indexed by SA10 Subchannel number
				
Define SAXX<			;;#8 macro to call SAC for each SA10
	..sa==-1
REPEAT SSAN,<
	SAC(\<..sa==..sa+1>)>
>				;;#8 end of SAXX definition

Define SAC(N)<			;;#8 Macro to call SASC for each subchannel
	..SC==-1
 REPEAT SSANSC,<
	SASC(\N,\<..SC==..SC+1>)>
>				;;#8 end of SAC definition


SAXBAS:				;#8 Base address for each SA10 Subchannel
DEFINE SASC(N,S)<EXP SA'N'BAS+S*4> ;#8 4 words per subchannel
	SAXX

SAXCNI:				;#8  CONI's for each subchannel
DEFINE SASC(N,S)<CONI SA'N,T1>
	SAXX

SAXCNO:				;#8  CONO's for each subchannel
DEFINE SASC(N,S)<CONO SA'N,FLD(S,SA%CHN)(T1)>
	SAXX

SAXDTI:				;#8  DATAI for each subchannel
DEFINE SASC(N,S)<DATAI SA'N,0(T2)>
	SAXX

SAXSTF:				;#8 Status flag for each subchannel
DEFINE SASC(N,S)<EXP FLD(.SACB'S,SA%SFN)>
	SAXX


;#8 End of constants indexed by SA10 Subchannel number

>				;#8 end of IFN FT.SA
; PUSH-DOWN POINTER

PDP:	IOWD PDLEN,PDL

FOUND:	MOVE T1,FNDCMD		;POINTER TO CMD
	CALL VBOOT1		;PERFORM COMMAND
VBTRET:	JUMPN CX,MRET2		;RETURN TO MONITOR?
	JRST GETCOM		;NO - GO ASK FOR NEXT COMMAND

	;ON ERROR, ARRIVE HERE WITH ERROR TYPE IN Q2
ERRTYP:	SETZM LODTYP		;FORCE INTERACTIVE MODE ON ERROR
	PUSH P,Q2		;SAVE Q2
	CALL CRLF		;OUTPUT CRLF
	MOVE Q2,ERRPFX		;GET THE PREFIX
	CALL OUTSTR		;OUTPUT IT
	MOVE Q2,(P)		;GET ERROR TYPE
	MOVE Q2,ERRTAB(Q2)	;GET POINTER TO MESSAGE
	CALL OUTSTR		;OUTPUT MESSAGE

	;DON'T TRY FOR STRUCTURE/FILENAMES IF MTBOOT
   IFE FT.MTA,<
	MOVE Q2,(P)		;GET ERROR SYMBOL
	CAILE Q2,ERRSTR		;TYPE STRUCTURE OR FILENAME?
	JRST TCR		;NO
TSTR:	MOVEI Q2,[ASCIZ/:  /]
	CALL OUTSTR		;TYPE COLON
	SKIPN Q2,CURNAM		;GET STRUCTURE NAME FROM CURNAM IF NON-ZERO
	MOVE Q2,STRNAM		;GET STRUCTURE NAME
	CALL TYPSTR		;TYPE IT
	POP P,Q2		;RESTORE ERROR SYMBOL	
	CAIG Q2,ERRFIL		;TYPE FILE NAME?
	CALL TYPFIL		;YES
>
TCR:	CALL CRLF		;OUTPUT CRLF
	JUMPN CX,MRET1		;RETURN TO MONITOR?
	JRST GETCM1		;NO, TRY FOR NEW COMMAND

MRET2:	AOS CX			;RETURN +2
MRET1:	MOVE CX-1,PFLAGS	;RETURN +1  - RESTORE FLAGS
	XJRSTF CX-1

;VBOOT
;ENTER HERE FOR YOUR FAVORITE BOOTSTRAP FUNCTION

;ARGUMENTS:
;	T1 - BYTE POINTER TO COMMAND STRING 

;
;CALL
;	;FIRST SETUP MAP FOR PAGES VORG-24 TO VORG + PROGRAM DATA
;	;ALSO SETUP DISK PARAMETERS IN DATA AREA
;	EXTERNAL:	JSP 16,VBOOT
;	INTERNAL:	PUSHJ P,VBOOT1

;RETURNS:	NO ERROR, NO START:	POPJ P, - TO VBTRET
;		ERROR:			JRST ERRTYP
;		START:			JRST @START
;
;	NOTE THAT VBOOT RUNS IN THE SECTION IT WAS CALLED FROM:
;
;	CALLER		SECTION
;	------		-------
;	BOOT		   0
;	TOPS20 V4	   0
;	TOPS20 V5	   1

;	BOOT MAY BE CALLED FROM SECTIONS 0 - 37
;	TO BE CALLED FROM A SECTION LARGER THAN 37 REQUIRES
;	A CHANGE IN THE MONITOR'S CALL TO BOOT


VBOOT::	XSFM PFLAGS		;SAVE FLAGS
	XMOVEI T4,VBTRET	;VBOOT IS ENTRY VECTOR FOR MONITOR ONLY -
	PUSH P,T4		; SET UP FOR POPJ RETURN TO FOUND: CODE
	TLZ CX,777740		;IN CASE WE WERE CALLED FROM SECTION ZERO,
				; TURN OFF ALL PC FLAGS (0-12)
	AOS MONLOD		;INDICATE ANOTHER INVOCATION OF VBOOT
VBOOT1:	JFCL			;VBOOT1 IS INTERNAL ENTRY VECTOR


IFE FT.RH,<			;#8 .
	SETZM F			;CLEAR FLAGS ONLY
>				; END OF IFE FT.RH
IFN FT.RH, <
	SETZM INIVEC		;INITIALIZE ORIGINAL REGISTER CONTENTS
	SETZB F,PIA		;CLEAR FLAGS AND RH20 PI ASSIGNMENT
	MOVE P6,TAPTYP		;PICK UP THE TAPE TYPE
>				; END OF IFN FT.RH
	MOVEM T1,ISTRNG		;T1 HAS STRING POINTER
	CALL PARSE		;PARSE STRING, SETUP ARG BLOCKS
	TLNE F,(F.INFO)		;ANY PASIVE FUNCTIONS?
	CALL INFO		;YES
	TLNN F,(F.ACT)		;ANY ACTIVE FUNCTIONS?
	JRST EXIT		;NO - EXIT
IFE FT.MTA,<
	CALL FNDIDX		;GET INDEX BLOCK OF DESIRED FILE
>				;END IFE FT.MTA
	JUMPGE F,LODRUN		;DUMP DESIRED (B0 OF F)
	CALL SAVE		;YES - DO DUMP
	RET

LODRUN:	MOVE T1,MONLOD		;GET VBOOT INVOCATION COUNT
	JUMPE T1,PASS0		;JUMP IF FIRST INVOCATION
	MOVEI Q2,[ASCIZ/[BOOT: LOADING SWAPPABLE MONITOR, PASS /]
	CALL OUTSTR
	MOVE Q2,MONLOD		;GET INVOCATION COUNT
	CALL OUTOCT		;OUTPUT IT
	MOVEI Q2,[ASCIZ/] /]	;CLOSE THE EXPRESSION
	CALL OUTSTR		;...
	JRST GETCAL
PASS0:	MOVEI Q2,[ASCIZ/[BOOT: LOADING RESIDENT MONITOR] /] 
	CALL OUTSTR

GETCAL:	CALL GET		;HERE IF LOAD OR RUN FUNCTIONS
	MOVEI Q2,[ASCIZ/[OK]
/]
	CALL OUTSTR

IFE SMFLG,<
	SETZM DTEMTI		;ZERO INPUT READY FLAG
	CALL SETLCV		;SETUP LOW CORE VARS
EXIT:	SETZM ICCW		;TEMP

IFN FT.RH,<
	CALL CHNRST		;RESTORE CHANNNEL
>				; END OF IFN FT.RH
>				; END OF IFE SMFLG
IFN SMFLG,<
	CALL SETLCV		;SET UP TEMP LOCORE VAR
EXIT:
>				; END OF IFN SMFLG
	TXNN F,F.EDDT		;START EDDT?
	JRST TSSTRT		;NO
	MOVEI T1,ELOC		;GET MONITOR START ADDR FOR EDDT
	HRRZM T1,START		;SAVE IT
	JRST DOSTRT		;GO DO IT
TSSTRT:	TLNE F,(F.STRT)		;SHOULD PROGRAM BE STARTED?
DOSTRT:	JRST @START		;YES - GO TO IT
	RET			;PRESUMED GOOD RETURN
SETLCV:	HRRZI T1,A%VORG		;GET ENDING PAGE ADDRESS
	HRLI T1,A%VFST		;GET STARTING PAGE ADDRESS
	MOVEM T1,BUTPGS		;SAVE ENDING PAGES IN COMMUNICATION AREA
	HRRZI T1,A%PTB		;GET ADDRESS OF EPT PAGE
	HRLI T1,A%EPT		;GET ADDRESS OF VBOOT EPT PAGE
	MOVEM T1,BUTEPT		;SAVE EPT PAGE ADDRESS FOR MONITOR
	MOVE T1,MAXCOR		;GET MAX CORE AVAILABLE
	MOVEI T1,A%XB-A%VORG(T1) ;GET PHYSICAL ADDRESS OF FIRST PAGE
	HRLI T1,-<<A%VORG-A%XB>_-9+1> ;GET # OF PAGES MONITOR MUST MAP
	MOVEM T1,BUTPHY		;SAVE MAPPING INFO FOR MONITOR
	MOVEI T1,A%XB		;GET FIRS VIRTUAL ADDRESS TO MAP
	MOVEM T1,BUTVIR		;SAVE VIRTUAL ADDRESS FROM MONITOR

	MOVE Q3,[POINT 7,BUTCMD] ;STORE FILESPEC
	MOVEI Q1,"<"		;DIR
	IDPB Q1,Q3		;STORE CHAR
	MOVE Q2,DIRSTR		;DIR STRING
	CALL CPYSTR		;COPY STRING
	MOVEI Q1,">"		;END OF DIR STRING
	IDPB Q1,Q3		;STORE CHAR
	MOVE Q2,FILSTR		;FILENAME STRING
	CALL CPYSTR		;COPY STRING
	MOVEI Q1,"."		;FOR EXT
	IDPB Q1,Q3		;STORE
	MOVE Q2,EXTSTR		;EXTENSION
	CALL CPYSTR		;COPY STRING
	SKIPN VERNUM		;VERSION SPECIFIED?
	JRST APPNUL		;NO - EXIT
	MOVEI Q1,"."		;YES- PUT VERSION OUT
	IDPB Q1,Q3		;STORE
	MOVE Q2,VERSTR		; ...
	CALL CPYSTR
	JRST APPNUL

CPYSTR:	ILDB Q1,Q2		;GET A CHAR
	JUMPE Q1,CPOPJ		;END OF STRING
	IDPB Q1,Q3		;OUTPUT A CHAR
	JRST CPYSTR
;THE COMMAND STRING PARSER

PARSE:	MOVE T1,[XWD DEFDAT,DEFBEG] ;SETUP BLT POINTER FOR DEFAULTS
	BLT T1,DEFEND		;COPY DEFAULTS
	TXZ F,F.EDDT		;RESET EDDT FLAG
	MOVE Q2,ISTRNG		;GET POINTER TO INPUT STRING
	MOVEI P5,ST.0		;INITIAL STATE
P.NXT:	CALL NXTSTA		;SETUP OUTPUTS THEN EVAL NXT STATE
	JUMPE P5,P.TRM		;TERMINAL STATE REACHED
	CAIN P5,777		;ERROR STATE
	  $ERROR (COMERR)	;COMMAND ERROR
	IORI P5,STPORG		;NO - RELOCATE STATE TABLE
	JRST P.NXT		;GO GET NEXT STATE

P.TRM:	MOVE Q2,VERSTR		;TERMINATION - GET VERSION AS #
	CALL DECIN		;CONVERT TO BINARY
	MOVEM P3,VERNUM		;SAVE VERSION

	TXNE F,F.DUMP		;DUMP WANTED?
	TXZ F,F.ALL!F.NCHL	;YES, CLEAR THESE FLAGS
	MOVE Q2,LBSTR		;GET POINTER TO LOWER BOUND
	TXNE F,F.ALL		;WANT TO USE ALL OF CORE?
	TDZA P3,P3		;YES, GET A 0
	CALL OCTIN		;NO, READ LOWER BOUND
	MOVEM P3,LWRLIM		;SAVE LOWER BOUND

	MOVE Q2,UBSTR		;GET POINTER TO UPPER BOUND
	TXNE F,F.ALL		;WANT ALL OF CORE?
	SKIPA P3,[VFREE]	;YES, GET HIGHEST PAGE BOOT CAN READ
	CALL OCTIN		;NO, READ IT
	MOVEM P3,UPRLIM		;SAVE UPPER BOUND

	MOVE Q2,SWSTR		;GET SWITCH STRING
	ILDB T1,Q2		;GET NEXT CHARACTER
	JUMPE T1,P.NOS		;NO SWITCHES - TEST START ADDR AND RETURN
	SETZI T2,		;CLEAR SWITCH INDEX
	MOVE T3,SWTAB		;GET POINTER TO SWITCHES
P.NXS:	ILDB T4,T3		;GET A LEGAL SWITCH
	SKIPN T4		;ZERO MEANS SWITCH LIST EXHAUSTED
	 $ERROR (COMUNS)	;UNKNOWN SWITCH
	CAME T1,T4		;TEST IF THIS IS A MATCH
	AOJA T2,P.NXS		;NO MATCH - LOOP
	XCT SWXTAB(T2)		;EXECUTE APPROPRIATE INSTRUCTION
	SKIPE D$UB		;UPPER BOUND SPECIFIED ?
	JRST P.SW2		;YES, USE SPECIFIED VALUE
	MOVE T1,[PHYPAG]	;GET HIGHEST PHYSICAL PAGE WE CAN DUMP

	TXNE F,F.DUMP		;DUMP REQUESTED ?
	MOVEM T1,UPRLIM		;YES, USE DEFAULT UPPER LIMIT FOR DUMP
P.SW2:	TLNN F,(F.WRIT)		;WRITING?
	JRST P.SA		;NO - CHECK STARTING ADDR
	DMOVE T1,DEF.WT		;LOAD BOTH FILENAME DEFAULTS
	CAMN T2,FILSTR		;NAME SPECIFIED?
	MOVEM T1,FILSTR		;NO - CHANGE DEFAULT

P.SA:	CALL OCTIN		;CONVERT STARTING ADDRESS
	CALLRET SETSA		;SET STARTING ADDR AND RETURN


SWTAB:	POINT 7,.+1		;POINTER TO SWITCH LIST
	ASCIZ 'MLRDSGAIE'

SWXTAB:	TLO F,(F.ACT)		;MERGE
	TLO F,(F.CLR!F.ACT)	;LOAD
	TLO F,(F.CLR!F.STRT!F.ACT) ;RUN
IFE FT.MTA,
<	TLO F,(F.WRIT!F.DUMP!F.ACT) ;DUMP
	TLO F,(F.WRIT!F.ACT)	;SAVE
>
IFN FT.MTA,
<	JFCL			;NOOP FOR DUMP
	JFCL			;NOOP FOR SAVE
>
	TLO F,(F.STRT)		;GO
	TLO F,(F.ALL!F.ACT!F.NCHL) ;ALL
	TLO F,(F.INFO)		;DISPLAY PROGRAM INFORMATION
	TLO F,(F.CLR!F.ACT!F.EDDT)  ;LOAD AND START AT LOCATION ELOC
;THE STATE MACHINE

NXTSTA:	MOVSI T4,(<POINT 18,0(P5)>) ;MAKE INPUT BYTE PTR
	ILDB P4,T4		;GET OUTPUT VALUE ADDRESS
	ILDB Q3,T4		;GET OUTPUT DATA ADDRESS
	HRLI Q3,(<POINT 7,0>)	; MAKE OUTPUT BYTE PTR
	MOVE T2,Q3		;SAVE FOR LATER (CAREFUL WITH T2)
	TLC T4,003300		;SWITCH TO 9 BIT BYTES

NXT.CH:	TLZN F,(F.BACK)		;TEST/CLEAR SCANNER BACKUP
	ILDB Q1,Q2		;GET NEXT CHAR
	SKIPN Q1
	 $ERROR(COMERR)		;COMMAND ERROR
	MOVE T3,T4		;COPY POINTER TO TRANSITION TABLE
NXT.NT:	ILDB T1,T3		;GET NEXT TRANSITION BYTE
	ANDI T1,177		;GET DATA ONLY
	JUMPE T1,NXT.EX		;SPECIAL BYTE - PROCESS IT
	CAMN Q1,T1		;TRANSITION CHARACTER?
	JRST NXT.EX		;YES - PROCESS
	ILDB T1,T3		;SKIP NEXT STATE
	JRST NXT.NT		;AND GET NEXT TRANSITION BYTE

NXT.EX:	LDB T1,T3		;GET FULL TRANSITION BYTE
	JUMPE T1,NXT.ST		;END OF TABLE - STORE CHAR
	ILDB P5,T3		;GET NEXT STATE
	CAIN P5,ST.6&777	;ACCUMULATING UPPER AND LOWER BOUNDS?
	TXO F,F.NCHL		;YES, DISABLE LIMIT CHANGING LATER
	LSH T1,-7		;GET FLAG BITS IN B34-35
	XCT NXXTAB(T1)		;EXECUTE INSTRUCTION CORRESPONDING
	TLZN F,(F.OUT)		;HAS STATE PRODUCED OUTPUT?
	RET			;NO - EXIT
	MOVEM T2,(P4)		;SAVE OUTPUT STRING
APPNUL:	SETZ T2,		;APPEND NULL
	IDPB T2,Q3		;...
	RET

NXT.ST:	IDPB Q1,Q3		;STORE OUTPUT CHAR
	TLO F,(F.OUT)		;INDICATE STATE DID SOMETHING
	JRST NXT.CH		;AND PROCESS NEXT CHARACTER

;STATE TABLE FLAG ACTION TABLE


NXXTAB:	JFCL			;NO FLAGS
	TLO F,(F.BACK)		;(200)SCANNER BACKUP
	TLO F,(F.OUT)		;(400)FORCE OUTPUT
				;(600)CURRENTLY UNUSED
;THIS BLOCK OF DEFAULT VALUES IS COPIED INTO THE DATA AREA
;STARTING AT DIRSTR ENDING AT DEFEND

DEF.WT:	POINT 7,[ASCIZ 'DUMP']	;DEFAULT FILSTR IF WRITING
DEFDAT:
DEF.FN:	POINT 7,[ASCIZ 'MONITR'] ;DEFAULT FILSTR
	POINT 7,[ASCIZ 'SYSTEM'] ;DEFAULT DIRSTR
	POINT 7,[ASCIZ 'EXE']	;DEFAULT EXTSTR
ZERO:	Z			;DEFAULT VERSTR
	Z			;DEFAULT SWSTR
	POINT 7,[ASCIZ '340']	;DEFAULT UBSTR
				;DEFAULT LBSTR

;NOTE: A LDB ON A BYTE POINTER WITH 0 S FIELD PRODUCES A ZERO BYTE!

IFN <<.&777000>-<<.+STTSIZ>&777000>>,< ;CHECK TO SEE IF STATE PAGE TABLE CROSSES A PAGE
FILLER=<<<.&777000>+1000>-.>&777
	BLOCK	FILLER		;FORCE STATE TABLE TO PAGE BOUNDARY
>

;STATE TRANSITION TABLES:

; THESE TABLES PARSE A FILESPEC OF THE FORM
;	<DIRECTORY>FILE.EXTENSION;VERSION/SWITCHSTARTADDR(LB,UB)

; FORMAT:
;	XWD OUTPUT POINTER LOCATION,DATA AREA FOR CHARACTERS OUTPUT FROM THIS STATE
;	A STRING OF 9 BIT BYTES CONSISTING OF A CHARACTER+FLAGS WHICH
;	  WILL CAUSE A STATE TRANSITION FOLLOWED BY THE LOW 9
;	  BITS OF THE TRANSITION TABLE FOR THE NEXT STATE.
;FLAGS:	200 = BACKUP SCANNER, 400=FORCE OUTPUT  EVEN IF NULL

STPORG=.&777000			;PAGE OFFSET TO STATE TABLES

;STATE 0 - INITIAL P5, MAKES TRANSITION TO NEXT STATE BASED ON FIRST CHARACTER.

ST.0:	XWD 0,0			;NO OUTPUT, NO DATA AREA
	BYTE (9)"<",ST.1,".",ST.3,".",ST.4,"/",ST.5,15,0,200,ST.2

;STATE 1 - ACCUMULATE DIRECTORY STRING.

ST.1:	XWD DIRSTR,D$DIR	;POINTER=DIRSTR, DATA=D$DIR
	BYTE (9)">",ST.2,15,0,0

;STATE 2 - ACCUMULATE FILE NAME STRING

ST.2:	XWD FILSTR,D$FIL	;POINTER=FILSTR,DATA=D$FIL
	BYTE (9)".",ST.3,".",ST.4,"/",ST.5,15,0,0

;STATE 3 - ACCUMULATE EXTENSION STRING

ST.3:	XWD EXTSTR,D$EXT	;POINTER=EXTSTR,DATA=D$EXT
	BYTE (9)"."+400,ST.4,"/"+400,ST.5,15+400,0,0

;STATE 4 - ACCUMULATE VERSION STRING

ST.4:	XWD VERSTR,D$VER
	BYTE (9)"/",ST.5,15,0,0

;STATE 5 - ACCUMULATE SWITCH STRING

ST.5:	XWD SWSTR,D$SW
	BYTE (9)15,0,"(",ST.6,0

;STATE 6 - ACCUMULATE LOWER PAGE BOUND STRING

ST.6:	XWD LBSTR,D$LB
	BYTE (9)")",0,",",ST.7,15,0,0

;STATE 7 ACCUMULATE UPPER BOUND STRING

ST.7:	XWD UBSTR,D$UB
	BYTE (9)")",0,15,0

IFN <<.-ST.0>-STTSIZ>,<PRINTX ?STATE TABLE SIZE DOES NOT AGREE WITH STTSIZ>
IFN <STPORG-<.&777000>>,<PRINTX ?STATE TABLE MUST FIT ON SINGLE PAGE>
;NUMBER INPUT SUBROUTINES

DECIN:	MOVEI T2,^D10		;SET RADIX DECIMAL
	JRST RADIN		;CONVERT
OCTIN:	MOVEI T2,^D8		;OCTAL RADIX
RADIN:	SETZI P3,		;ZERO RESULT
RAD.NX:	ILDB T1,Q2		;GET NEXT CHARACTER
	JUMPE T1,CPOPJ		;END OF STRING - RETURN OK
	CAIG T1,57(T2)		;CHECK TO BE SURE
	CAIGE T1,"0"		;THAT IT IS LEGAL
	  $ERROR (COMINV)	;INVALID NUMERIC VALUE
	IMUL P3,T2		;IS OK - CONVERT
	ADDI P3,-60(T1)		;ADD TO RESULT
	JRST RAD.NX

;STARTING ADDRESS SETUP/TEST SUBROUTINES

SETSA:
	HRRZM P3,START		;NO, STORE START ADDR FROM EXE FILE
	SKIPN START		;NON ZERO?
	TLZ F,(F.STRT)		;NO - CLEAR F.STRT
	RET
	;INFO SUBROUTINE

	;DISPLAY PROGRAM VERSION
INFO:	MOVEI Q2,[ASCIZ/
      BOOT VERSION:       /]    ;OUTPUT TEXT
	CALL OUTSTR		;...
	CALL TYPBVR		;OUTPUT BOOT VERSION
IFE SMFLG,
<
	;DISPLAY MICROCODE VERSION
	MOVEI Q2,[ASCIZ/      MICROCODE VERSION:  /] ;OUTPUT TEXT
	CALL OUTSTR		;...
	
	MOVEI Q2,[ASCIZ/DX20A: /] ;OUTPUT STRING
	CALL OUTSTR		;...
	MOVE T1,DXAMCV		;GET DXA MCODE VERSION
	CALL TMCVER		;GO DISPLAY VERSION INFO
IFN FT.RP2,
 <	MOVEI Q2,[ASCIZ/    DX20B: /] ;OUTPUT STRING
	CALL OUTSTR		;...
	MOVE T1,DXBMCV		;GET DXB MCODE VERSION
	CALL TMCVER		;GO DISPLAY VERSION INFO
 >
>

INFRET:	CALL CRLF		;OUTPUT CRLF
	RET



	;SUBROUTINE TO DISPLAY MICROCODE VERSION
	;CALL WITH MICROCODE VERSION WORD IN T1

DEFSTR(ED.NUM,T1,^D35,^D10)	;FIELD FOR EDIT NUMBER IN T1
DEFSTR(VR.NUM,T1,^D25,^D6)	;FIELD FOR VERSION NUMBER IN T1

TMCVER:	PUSH P,T1		;SAVE VERSION NUMBER
	LOAD Q2,VR.NUM		;GET THE VERSION NUMBER
	CALL OUTOCT		;DISPLAY IT
	MOVEI Q1,"("		;DISPLAY LEFT PAREN
	CALL TYO		;...
	POP P,T1		;RESTORE VERSION NUMBER
	LOAD Q2,ED.NUM		;GET EDIT NUMBER
	CALL OUTOCT		;DISPLAY IT
	MOVEI Q1,")"		;DISPLAY RIGHT PAREN
	CALL TYO		;...
	RET

	;SUBROUTINE TO OUTPUT BOOT VERSION
TYPBVR:	MOVEI Q2,V%MAJOR	;OUTPUT MAJOR VERSION
	CALL OUTOCT		;...
	MOVEI Q1,"."		;OUTPUT A PERIOD
	CALL TYO		;...
	MOVEI	Q2,V%MINOR	;OUTPUT MINOR VERSION
	CALL OUTOCT		;...
	MOVEI Q1,"("		;OUTPUT A LEFT PAREN
	CALL TYO		;...
	MOVEI Q2,V%EDIT		;OUTPUT EDIT NUMBER
	CALL OUTOCT		;...
	MOVEI Q2,[ASCIZ/)
/]				;OUTPUT RIGHT PAREN + CRLF
	CALL OUTSTR		;...
	RET
	;SUBROUTINE TO OUTPUT ASCIZ STRING
	;CALL WITH STRING ADDR IN Q2

OUTSTR:	HRLI Q2,(POINT 7,)	;MAKE ADDRESS INTO BYTE POINTER
OUTST1:	ILDB Q1,Q2		;PICK UP A CHARACTER
	JUMPE Q1,R		;IF DONE, RETURN
	CALL TYO		;OTHERWISE, TYPE IT
	JRST OUTST1		;AND LOOP FOR MORE


	;SUBROUTINE TO OUTPUT OCTAL VALUES
	;CALL WITH BINARY IN Q2
	;ENTRY VECTORS:
	;	OUTOCN:		;ALLOW LEADING ZEROES
	;	OUTOCT:		;SUPRESS LEADING ZEROES

OUTOCN:	SETOM Q3		;ALLOW LEADING ZEROES
	SKIPA
OUTOCT: SETZM Q3		;SUPRESS LEADING ZEROES
	PUSH P,Q3		;CREATE A TEMPORARY FLAG
	MOVE Q3,[POINT 3,Q2-1,35] ;USE TO FETCH 3-BIT OCTAL VALUE
	JUMPN Q2,GETDG1		;BYPASS LOOP-EXIT CODE FIRST TIME THROUGH
	ILDB Q1,Q3		;HERE IF HE GAVE US A ZERO
	JRST OUTASC		;TYPE A "0"
				; INSURES WE GET A ZERO EVEN IF SUPPRESSING


GETDIG:	TLNN Q3,770000		;TIME TO LEAVE?
	JRST OCTRET		;YES
GETDG1:	ILDB Q1,Q3		;GET A PACKED OCTAL VALUE
	SKIPN (P)		;NON-ZERO DIGIT SEEN YET?
	JUMPE Q1,GETDIG		;NO, IF THIS DIGIT IS ZERO, TRY AGAIN
	SETOM (P)		;INDICATE WE HAVE SEEN A NON-ZERO DIGIT
OUTASC:	ADDI Q1,60		;CONVERT TO ASCII
	CALL TYO		;OUTPUT IT
	JRST GETDIG		;GET ANOTHER DIGIT

OCTRET:	ADJSP P,-1		;RELEASE TEMPORARY STORAGE FOR FLAG
	POPJ P,			;RETURN
	;SUBROUTINE TO TYPE OUT STRUCTURE NAME
	;CALL WITH STRUCTURE NAME IN Q2
TYPSTR:	MOVE T1,[-6,,0]
	SETZM Q1		;INIT SHIFT AC
TYPST1:	LSHC Q1,6		;SHIFT A SIXBIT CHAR TO Q1
	ADDI Q1,40		;CONVERT TO ASCII
	CALL TYO 		;TYPE IT
	SKIPE Q2		;EXIT IF Q2 ZERO
	AOBJN T1,TYPST1		;BACK FOR MORE
STRRET:	MOVEI Q1,":"		;ADD A COLON
	CALL TYO
	RET

	;SUBROUTINE TO TYPE OUT FILENAME
TYPFIL:	MOVEI Q1,"<"		;OUTPUT LEFT ANGLE
	CALL TYO
	MOVE Q2,DIRSTR		;TYPE DIRECTORY
	CALL OUTSTR
	MOVEI Q1,">"		;OUTPUT RIGHT ANGLE
	CALL TYO
	MOVE Q2,FILSTR		;TYPE FILE NAME
	CALL OUTSTR
	MOVEI Q1,"."		;OUTPUT PERIOD
	CALL TYO
	MOVE Q2,EXTSTR		;TYPE FILE EXTENSION
	CALL OUTSTR
	RET
IFE FT.MTA,<
MAPDIR:	MOVEI P4,A%DIR		;GET ADDRESS FOR DIRECTORY HEADER
	MOVE P5,A%XB		;GET DISK ADDRESS FOR FIRST PAGE OF DIR
	JRST RDPGRT		;READ HEADER PAGE OF DIRECTORY

;MAP THE DIRECTORY INTO VIRTUAL ADDR DIR AND ABOVE

FNDIDX:	MOVE P5,DIORG		;GET ADDRESS
	MOVEI P4,A%XB		;INDEX BLOCK BUFFER
	CALL REDPAG		;READ ROOT-DIR XB
	 $ERROR (IOER10)	;ERROR READING PAGE
	CALL MAPDIR		;MAP IN ROOT DIR HEADER PAGE
	MOVE T1,DIRSTR		;GET POINTER TO DIR STRING
	MOVE T2,[POINT 7,[ASCIZ/DIRECTORY/]]
	MOVEI T3,0		;GET HIGHEST VERSION #
	CALL GETIDX		;GET INDEX BLOCK OF DIR FILE
	CALL MAPDIR		;MAP IN THE DIRECTORY
	MOVE T1,FILSTR		;GET POINTER TO NAME STRING
	MOVE T2,EXTSTR		;AND POINTER TO EXTENSION STRING
	MOVE T3,VERNUM		;GET DESIRED VERSION #
				;FALL INTO GETIDX
	;..

>				;END IFE FT.MTA
IFE FT.MTA,<
;HERE TO GET THE INDEX BLOCK FOR THE FILE

GETIDX:	MOVEM T1,FNDSTR		;SAVE NAME STRING
	DMOVEM T2,FNDSTE	;SAVE EXTENSION STRING POINTER
				; AND SAVE VERSION NUMBER
	CALL FIND		;RETURN FDB OFFSET IN P1
GX.NE:	MOVE Q2,FNDSTE		;COMPARE WITH NEXT EXTENSION
	CALL GETPAG		;MAP IN PAGE CONTAINING FDB
				; RETURN WITH MAPPED ADDR IN T1
	LOAD Q3,FBEXT,(T1)	;GET ADR OF EXT STRING BLOCK
	HRLI Q3,(POINT 7,0)	;SET IT UP AS A STRING POINTER
	ADDI Q3,1		;POINT TO STRING
	CALL STRCMP		;COMPARE STRINGS
	CAIA
	JRST GX.NV		;FOUND EXTENSION MATCH - LOOK AT VERSION
	CALL GETPAG		;MAP IN PAGE CONTAINING FDB
	LOAD P1,FBEXL,(T1)	;STEP TO NEXT FDB IN THIS CHAIN
	JUMPN P1,GX.NE		;BACK IF STILL MORE
	 $ERROR (FILFNF)	;FILE NOT FOUND

GX.NV:	CALL GETPAG		;MAP IN PAGE CONTAINING FDB
	LOAD T1,FBGEN,(T1)	;GET GENERATION NUMBER
	SKIPE FNDSTV		;IS MOST RECENT VER WANTED?
	CAMN T1,FNDSTV		;IS IT WHAT WE WANT?
	JRST GX.DON		;YES - EXIT
GX.NV1:	CALL GETPAG		;MAP IN PAGE CONTAINING THE FDB
	LOAD P1,FBGNL,(T1)	;STEP TO FDB OF NEXT GENERATION
	SKIPN P1
	  $ERROR (FILFNF)	;File not found
	JRST GX.NV		;TRY AGAIN

GX.DON:	CALL GETPAG		;MAP IN PAGE CONTAINING FDB
	LOAD T2,FBCTL,(T1)	;GET CONTROL BITS
	TXNE T2,FB%DEL!FB%NXF	;DOES IT EXIST?
	JRST GX.NV1		;NO. GO GET ANOTHER THEN
	MOVE T4,@FNDSTR		;GET 1'ST 5 CHARS OF FILE NAME
	CAME T4,[BYTE (7) "D","U","M","P"] ;IS IT THE DUMP FILE?
	JRST NOTDMP		;NO
	MOVE T4,@FNDSTE		;GET EXTENSION
	CAME T4,[BYTE (7) "E", "X", "E"] ;CORRECT EXTENSION?
	JRST NOTDMP		;NO
	LOAD T4,FBBYV,(T1)	;YES, GET PAGE COUNT
	HRRZM T4,DEXEPC		;REMEMBER IT
NOTDMP:	SETOM XBNUM		;INITIALIZE XB NUMBER TO SHORT FILE
	LOAD P5,FBADR,(T1)	;GET ADR OF INDEX BLOCK
	TXNN T2,FB%LNG		;LONG FILE?
	JRST GX.DN1		;NO, JUST READ IN INDEX BLOCK 0
	MOVEI P4,A%SXB		;LONG FILE, READ IN THE SUPER INDEX BLOCK
	CALL REDPAG		;  INTO A%SXB
	 $ERROR (IOER2)		;ERROR READING PAGE
	LOAD P5,IDXADR,A%SXB+0	;GET ADR OF FIRST INDEX BLOCK
	SKIPN P5		;IF NO PAGE 0, FORMAT ERROR
	 $ERROR (FILNEF)	
	SETZM XBNUM		;MARK THAT INDEX BLOCK 0 IS MAPPED
GX.DN1:	MOVEI P4,A%XB		;READ INTO XB AREA
RDPGRT:	CALL REDPAG		;READ THE PAGE
	 $ERROR (IOER3)		;ERROR READING PAGE
	RET


; ROUTINE TO MAP A PAGE OF THE DIRECTORY

; ACCEPTS IN P1/ ADDRESS TO MAP
;			CALL GETPAG
; RETURNS +1 WITH T1/ MAPPED ADDRESS

GETPAG:	HRRZ T1,P1		;GET ADDRESS DESIRED FROM FILE
	LSH T1,-^D9		;CONVERT ADDRESS TO PAGE NUMBER
	MOVE P5,A%XB(T1)	;GET DISK ADDRESS OF FILE PAGE
	MOVEI P4,A%DPG		;GET ADDRESS OF DIRECTORY DATA PAGE
	CAMN P5,CURPAG		;DESIRED PAGE ALREADY IN CORE ?
	JRST GETPG1		;YES, DO NOT NEED TO READ AGAIN
	CALL REDPAG		;NO, READ THE PAGE
	 $ERROR (IOER4)		;CAN'T READ DIRECTORY PAGE
GETPG1:	LDB T1,[POINT 9,P1,35]	;GET LOW ORDER BITS OF ORIGINAL ADDRESS
	IORI T1,A%DPG		;ADD ADDRESS OF DIRECTORY DATA PAGE
	MOVEM P5,CURPAG		;UPDATE CURRENTLY IN-CORE PAGE
	RET			;RETURN
>				;END IFE FT.MTA
IFE FT.MTA,<
;SUBROUTINE TO DO A PRIMARY NAME SEARCH IN A DIRECTORY
; CALL WITH BYTE POINTER TO FILENAME IN FNDSTR
; RETURN WITH OFFSET TO FDB FOR THAT FILE IN P1

FIND:	MOVE T1,SYMBOT		;START OF ST AREA
	SUB T1,SYMTOP		;GET -LENGTH
	MOVE P1,SYMBOT		;BUILD A
	ADDI P1,2		;RELOCATE
	HRLI P1,2(T1)		;AOBJN POINTER

FND.NF:	MOVE Q2,FNDSTR		;FILE NAME
	CALL GETPAG		;MAP IN PAGE CONTAINING S.T. ENTRY
	LOAD Q3,SYMET,(T1)	;GET SYMBOL TYPE
	SKIPE Q3
	 $ERROR(FILFNF)		;FILE NOT FOUND
	LOAD Q3,SYMVL,(T1)	;GET FIRST FIVE CHARS OF NAME
	CAME Q3,@FNDSTR		;IS THIS A MATCH AGAINST STRING?
	JRST FND.NM		;NO, NO NEED TO COMPARE NAME STRING
	LOAD Q3,SYMAD,(T1)	;GET FDB ADDRESS
	PUSH P,P1		;SAVE POINTER INTO SYMBOL TABLE
	MOVE P1,Q3		;GET ADDRESS OF FDB
	CALL GETPAG		;MAP IN PAGE CONTAINING FDB
	POP P,P1		;RESTORE SYMBOL TABLE POINTER
	LOAD Q3,FBNAM,(T1)	;GET ADDRESS OF NAME STRING BLOCK
	HRLI Q3,(POINT 7,0)	;SET UP STRING POINTER
	ADDI Q3,1		;POINT TO STRING
	CALL STRCMP		;COMPARE STRINGS
FND.NM:	 JRST [	ADD P1,[1,,1]	;NO MATCH, STEP OVER SYMBOL VALUE
		AOBJN P1,FND.NF
		$ERROR (FILFNF)]	;NO MORE NAMES, ERROR
	CALL GETPAG		;MAP IN PAGE CONTAINING S.T. ENTRY
	HRRZ P1,(T1)		;GET FIRST FILE FDB
	RET

;STRING COMPARE SUBROUTINE

STRCMP:	PUSH P,P1		;SAVE P1
	MOVE P1,Q3		;COPY ADDRESS OF STRING IN FILE
	CALL GETPAG		;MAP PAGE CONTAINING STRING BLOCK
	POP P,P1		;RESTORE P1
	HRR Q3,T1		;INSERT MAPPED ADDRESS TO STRING
STRCM1:	ILDB T1,Q2		;GET 1ST BYTE
	ILDB T2,Q3		;GET 2ND BYTE
	CAME T1,T2		;EQUAL?
	RET			;NO - LOSE
	JUMPN T1,STRCM1		;YES -END OF STRING?
>				;END IFE FT.MTA
	RETSKP			;SKIP RETURN
;IO SUBROUTINES
IFN FT.RP, <
REDPAG:	TDZA P3,P3		;READ
WRTPAG:	MOVEI P3,1		;WRITE
>				; END OF IFN FT.RP
IFE SMFLG, <

IFN FT.SA,<			;#8 .

IFE FT.MTA,<			;#8 .
REDPAG:	SKIPA P3,[.ICRDD]	;#8 Read Disk command
WRTPAG:	MOVEI P3,.ICWRD		;#8 Write Disk command
>				;#8 end of IFE FT.MTA

IFN FT.MTA,<			;#8 .
REDPAG:	SKIPA P3,[.ICRDT]	;#8 Read Tape command
WRTPAG:	MOVEI P3,.ICWRT		;#8 Write Tape command
>				;#8 end of IFN FT.MTA
>				;#8 end of IFN FT.SA

IFN FT.RH, <			;#8 .

REDPAG:	SKIPA T1,[.RHSTR!LR!RCLP!STLW!<-4&1777>B29!R4%CRD!GO] ;RH20 READ DATAO
WRTPAG:	MOVE T1,[.RHSTR!LR!<-4&1777>B29!RCLP!STLW!R4%CWR!GO] ;RH20 WRITE DATAO
>				;#8 end OF IFN FT.RH



	AOS FILPAG		;INCREMENT FILE PAGE #
	PUSH P,P2		;SAVE COUNTER
	MOVEI P2,5		;RETRY COUNT
IFN FT.MTA, <
	MOVEI P2,^D100		;RETRY COUNT FOR MAGTAPE
	JRST MRETRY		;YES, GO DO TAPIO
>				; END OF IFN FT.MTA

IFE FT.MTA, <
IFN FT.RP!FT.RH,<		;#8.
DRETRY:	CALL IOSET		;SETUP CHANNEL, DO SEEK
	 SOJG P2,DRETRY		;TRY SEEK ET AL AGAIN
	SKIPN P2
	$ERROR (IOER5)		;RETRY ERROR
	CALL DOIO		;START IO AND WAIT
   IFN FT.RH,<CALL CHNRST>	;IF RH'S, RESTOE CHANNEL
	EXCH T1,T4		;GET BACK ORIGINAL COMMAND
	JUMPG T4,RWSXIT		;IF NO ERRORS, EXIT SUCCESSFULLY
	SOJG P2,DRETRY		;GO RETRY TIL COUNT EXHAUSTED
	JRST RWFXIT		;OPERATION FAILED
>				;#8 end of IFN FT.RP!FT.RH
IFN FT.SA,<			;#8 .
	MOVE P6,P2		;#8 move counter to free P2
DRETRY:	CALL DOIO		;#8 do the I/O
	 JRST [	SOJG P6,DRETRY	;#8 try again on error, for a while
		JRST RWFXIT]	;#8 quit after too many errors

>				;#8 end of IFN FT.SA
>				; END OF IFE FT.MTA


IFN FT.MTA,<
MRETRY:	CALL TAPIO		;DO IO
	JRST RWSXIT		;WIN
	SOSG P2			;DO RETRY?
	  $ERROR (TAPHTE)	;NO - HARD TAPE ERROR
	CALL BSPACE		;YES - BACKSPACE
	JRST MRETRY		;LOOP
>				;END IFN FT.MTA
RWSXIT:	AOS -1(P)		;SKIP RETURN
RWFXIT:	POP P,P2		;RESTORE P2
	RET			;RETURN
IFN FT.RH!FT.RP,<		;#8 .
;DISK IO SUBROUTINES - DISK DEPENDENT PARTS.

DOIO:	SAVPI T2		;SAVE PI ASSIGNMENT
	IOOP(CLEAR)		;CLEAR CONTROLLER/UNIT
	MOVSI T1,2		;DELAY COUNT
	IOOP(XCTOP,T4)		;EXECUTE OPERATION
WAIT:	IOOP(SKIPDONE)		;SKIP IF DONE
	SOJG T1,WAIT		;LOOP
	RESPI T2		;RESTORE PI ASSIGNMENT
	JUMPLE T1,CPOPJ		;RETURN IF TIMEOUT
	IOOP(SKIPNOERR)		;SKIP IF NO ERRORS
	SETOI T1,		;YES - SET T1 MINUS AS FLAG
	RET			;RETURN
>				; END OF IFN FT.RH!FT.RP

;THIS RANDOM INSTRUCTION FROM PARSE IS HERE TO SAVE SPACE

P.NOS:	TLO F,(F.STRT!F.CLR!F.ACT) ;DEFAULT WHEN NO SWITCHES
	RET			;RETURN

   IFN FT.RH,<			;#8 IF DOING RH TYPE DISKS
CHNRST:	PUSH P,T1		;SAVE 1
	MOVX T1,.RHIVR!LR	;INTERRUPT VECTOR REGISTER
	HRR T1,INIVEC		;GET INITIAL CONTENTS
	CALL IOXCT		;GO WRIET DEVICE REGISTER
	DATAO .-.,1
	MOVE T1,PIA		;GET RH20 PI ASSIGNMENT
	CALL IOXCT		;GET DEVICE CODE
	CONO .-.,.RHDON!.RHAIE(T1) ;RESTORE ORIGINAL PI ASSIGNMENT
	POP P,T1		;RESTORE 1
	RET>			;AND DONE
IFE FT.MTA, <

IFN FT.RH, <			;#8 .

IOSET:	PUSH P,T1		;SAVE RP04 COMMAND
	MOVE T1,P5		;GET DISK ADDRESS
	TLZ T1,777770		;#1 KEEP JUST THE ADDRESS BITS (ISI CHANGE)
	MOVE T2,DSKTYP		;FIND TYP
	CAIN T2,.R7TYP
	JRST [	IDIVI T1,N.SCL7	;RP07?
		JRST IOSETC]
	CAIN T2,.R3TYP		;RM03?
	JRST [	IDIVI T1,N.SCL3
		JRST IOSETC]
	IDIVI T1,N.SCL4		;GET CYLINDER IN T1, SECTOR IN T2
IOSETC:	PUSH P,T2		;SAVE SECTOR WITHIN CYLINDER
IFN FT.RP,<
	IDIVI T1,N.CLUN		;GET UNIT # IN T1, CYL ON UNIT IN T2
>				;END IFN FT.RP
IFN FT.RH,<			;#8 .
	IDIV T1,NUMCYL		;GET UNIT NUMBER IN T1, CYL IN T2
>				;#8 END IFN FT.RH
	HRRZ P3,DSKTAB(T1)	;GET PHYSICAL UNIT NUMBER
	HLRZ T1,DSKTAB(T1)	;GET CHANNEL #, ENTRY-IN-USE FLAG
	TRZ T1,ENTFLG		;KEEP JUST THE CHANNEL NUMBER
	HRRI F,RH0_-2(T1)	;GET IO DEVICE CODE
	LSH T1,2		;GET CHANNEL * 4
	MOVE T3,[1B1+ICCW]	;GET JUMP CCW
	MOVEM T3,A%EPT+ICA(T1)	;STORE JUMP CCW IN EPT FOR RH20
	CALL IOXCT		;GO GET RH20 DEVICE CODE
	CONI .-.,T1		;GET RH20 PI ASSIGNMENT
	ANDI T1,.RHMBE+7	;KEEP JUST MB ENABLE AND PI
	MOVEM T1,PIA		;SAVE RH20 PI ASSIGNMENT
	MOVX T1,.RHIVR		;INTERRUPT VECTOR REGISTER
	CALL RHRD		;GET ORIGINAL CONTENTS OF IVR
	ANDI T1,177777		;KEEP JUST DATA BITS
	MOVEM T1,INIVEC		;NO, SAVE INITIAL IVR CONTENTS
	IOOP(CLEAR)		;RESET RH20
	MOVX T1,R4%DCA!LR	;DESIRED CYLINDER REGISTER IN RP04
	HRR T1,T2		;GET DESIRED CYLINDER #
	CALL RHWT		;TELL RP04 WHICH CYLINDER
	POP P,T1		;RESTORE SECTOR WITHIN CYLINDER
	MOVE T2,DSKTYP		;GET DISK TYPE AGAIN
	CAIN T2,.R7TYP		;RP07?
	SKIPA T2,[N.STK7]	;YES
	MOVEI	T2,N.STK4	;NO
	IDIVI T1,(T2)		;GET TRACK # IN T1, SECTOR IN T2
	LSH T1,^D8		;POSITION THE TRACK # FOR DATAO
	IOR T1,T2		;ADD A PINCH OF SECTOR
	PUSH P,T1		;SAVE DISK ADDRESS
	TXO T1,R4%DST!LR	;RP04 DESIRED SECTOR AND TRACK REGISTER
	CALL RHWT		;GO WRITE SECTOR, TRACK REGISTER
	POP P,T1		;RESTORE DISK ADDRESS
IFN FT.RH, <			;#8 .
	TXO T1,.RHSBR!LR	;RH20 BLOCK ADDRESS REGISTER
	CALL RHWT		;TELL RP04 WHERE THE DATA IS
>				; END OF IFN FT.RH


	POP P,T4		;RESTORE ORIGINAL INSTRUCTION
IOSET0:	TSO T4,P3		;INSERT UNIT # INTO COMMAND
	CALL GETPHY		;GET PHYSICAL ADDR IN T1
	 $ERROR (MEMMRF)	;BAD ADDRESS

IFN KLFLG, <

	JUMPN T1,IOSET1		;PAGE 0?
	MOVSI T1,(EXP 1B0+<LCORAD>B13) ;YES - SKIP FIRST FEW WDS
	MOVEM T1,ICCW		;STORE AS FIRST ELEMENT
	MOVE T1,[EXP 1B0+1B1+<1000-LCORAD>B13+LCORAD]
	MOVEM T1,ICCW+1		;SECOND AND LAST CCW
	JRST CPOPJ1		;GO DO IO
IOSET1:	TLO T1,(EXP 1B0+1B1+<1000>B13) ;BUILD CCW
	MOVEM T1,ICCW		;STORE
	JRST CPOPJ1		;RETURN

>				; END OF IFN KLFLG



IFE KLFLG, <

	MOVEI T3,-1000		;COUNT
	JUMPN T1,IOS.CM		;READ/WRITE PAGE 0?
	MOVE T3,[IOWD LCORAD,LCORAD] ;YES - MUST SKIP FIRST FEW WDS
	MOVEM T3,2(T2)		;STORE SKIP COMMAND
	MOVEI T1,LCORAD		;NEW ADDRESS
	MOVEI T3,-<1000-LCORAD>	;NEW COUNT
	ADDI T2,1		;BUMP CCW ADDR
IOS.CM:	SOS T1			;IOWD WANTS ADDR -1
	HRL T1,T3		;INSERT COUNT
	MOVEM T1,2(T2)		;STORE COMMAND LIST
	SETZM 3(T2)		;0 AT END OF LIST
	JRST CPOPJ1		;SKIP RETURN

>				; END OF IFE KLFLG


>				;#8  END OF IFN FT.RH
IFN FT.RP,<
IOSET:	HRRI F,DPC_-2		;DISK CONTROLLER CODE
	MOVE T1,P5		;GET DISK ADDR
	TLZ T1,777774		;CLEAR UNUSED BITS

	IDIVI T1,N.SCL4		;GET CYL, BLOCK IN CYL
	PUSH P,T2		;SAVE BLOCK WITHIN CYL
	IDIVI T1,N.CLUN		;GET UNIT, CYL
	LSH T2,^D10		;MOVE CYL FIELD
	TLZE T2,1		;MOVE CYL 256 BIT
	TRO T2,20		;IF NEEDED (AND RP03
	HLL T2,DSKTAB(T1)	;GET UNIT # & ENTRY-IN-USE FLAG
	TLZ T2,ENTFLG		;KEEP JUST UNIT #
	POP P,T1		;RECOVER BLOCK WITHIN CYL
	PUSH P,T2		;SAVE PARTIAL ADDR
	IDIVI T1,^D10		;GET TRACK, SECTOR
	LSH T1,5		;POSITION TRACK
	IOR T1,T2		;OR IN SECTOR
	POP P,T2		;RECOVER UNIT

	IOR T1,T2		;FINISH ADDRESS
	LSH T1,^D12		;MOVE TO WHERE HDWE WANTS IT

	IORI T1,ICCW		;CHANNEL ICCW ADDRESS
	TLO T1,400000		;OP=4 (SEEK)
	MOVE T4,T1		;COPY COMMAND
	CALL DOIO		;EXECUTE SEEK
	JUMPLE T1,CPOPJ		;FAIL IF ERRORS
	DPB P3,[POINT 3,T4,2]	;SET OP CODE
	MOVEI T2,ICCW		;GET INITIAL CHAN COMMAND ADDR
	SETZM 1(T2)		;CLEAR TERMINATION WORD
	MOVEI T1,2(T2)		;ADDR OF ACTUAL CHAN COMMAND LIST
	MOVEM T1,ICCW		;STORE ADDR OF CCW LIST
	CALL GETPHY		;GET PHYSICAL ADDR IN T1
	 $ERROR (MEMMRF)	;BAD ADDRESS
	MOVEI T3,-1000		;COUNT
	JUMPN T1,IOS.CM		;READ/WRITE PAGE 0?
	MOVE T3,[IOWD LCORAD,LCORAD] ;YES - MUST SKIP FIRST FEW WDS
	MOVEM T3,2(T2)		;STORE SKIP COMMAND
	MOVEI T1,LCORAD		;NEW ADDRESS
	MOVEI T3,-<1000-LCORAD>	;NEW COUNT
	ADDI T2,1		;BUMP CCW ADDR
IOS.CM:	SOS T1			;IOWD WANTS ADDR -1
	HRL T1,T3		;INSERT COUNT
	MOVEM T1,2(T2)		;STORE COMMAND LIST
	SETZM 3(T2)		;0 AT END OF LIST
	JRST CPOPJ1		;SKIP RETURN
>				;END IFN FT.RP

>				; END OF IFE FT.MTA
IFE FT.SA,<			;#8 .
IFN FT.MTA,<

;HERE TO SETUP THE CHANNEL FOR TAPE IO

TAPIO:	LDB T4,PCHAN		;GET CHANNEL NUMBER
	HRRI F,RH0_-2(T4)	;SET IO ADDRESS
	LDB P3,PKON		;GET TM02
	CALL IOXCT		;GET DEVICE CODE
	CONI .-.,T1		;GET RH20 PI ASSIGNMENT
	ANDI T1,.RHMBE+7	;KEEP JUST PI
	SKIPN PIA		;SAVED PI ASSIGNMENT YET ?
	MOVEM T1,PIA		;NO, SAVE IT NOW
	MOVX T1,.RHIVR		;INTERRUPT VECTOR REGISTER
	CALL RHRD		;GET ORIGINAL CONTENTS OF IVR
	ANDI T1,177777		;KEEP JUST DATA BITS
	SKIPN INIVEC		;SAVED ORIGINAL CONTENTS YET ?
	MOVEM T1,INIVEC		;NO, SAVE INITIAL IVR CONTENTS
	CALL IOXCT		;GET DEVICE CODE
	CONO .-.,.RHMBE!.RHRAE!.RHCTE!.RHDON ; RESET RH20
	CALL @TAPSIO(P6)	;SET CONTROLLER TO START THE IO
	MOVE T1,[EXP .TMATR!LR+377] ;CLEAR ATTN
	CALL RHWT		;
	MOVE T1,[EXP 1B1+ICCW]	;CHANNEL JUMP TO ICCW
	LSH T4,2		;COMPUTE OFFSET INTO EPT
	MOVEM T1,A%EPT+ICA(T4)	;STORE
	CALL GETPHY		;GET PHYS ADDR
	 $ERROR (MEMMRF)	;BAD ADDRESS
	JUMPN T1,TAPIO1		;PAGE 0?
	MOVSI T1,(EXP 1B0+<LCORAD>B13) ;YES - SKIP FIRST FEW WDS
	MOVEM T1,ICCW		;STORE AS FIRST ELEMENT
	MOVE T1,[EXP 1B0+1B1+<1000-LCORAD>B13+LCORAD]
	MOVEM T1,ICCW+1		;SECOND AND LAST CCW
	JRST TAPIO2		;GO DO IO
TAPIO1:	TLO T1,(EXP 1B0+1B1+<1000>B13) ;BUILD CCW
	MOVEM T1,ICCW		;STORE
TAPIO2:	MOVE T1,[EXP .RHSTR!LR!RCLP+.TMRDF+1777B29] ;SEND COMMAND
	CALL RHWT		; ...
	MOVSI T2,1		;SET WAIT COUNT
TAPWAT:	CALL IOXCT		;GET DEVICE CODE
	CONI .-.,T1		;GET DEVICE STATUS
	TRNN T1,.RHDON		;DONE ?
	SOJG T2,TAPWAT		;NO - LOOP
	TRNN T1,775000		;ERRORS+
	JUMPG T2,CPOPJ		; NO - EXIT
	JRST CPOPJ1		;YES - SKIP


BSPACE:	CALL IOXCT		;GET IO CODE
	CONO .-.,2000		;RESET THE RH20 BEFORE
	CALL IOXCT		; DOING BACKSPACE
	CONO .-.,4600		;...
	CALL @STRTMP(P6)	;START THE MICRO PROCESSOR (IF DX20)
	CALL @BACKRC(P6)	;BACKSPACE A RECORD
	MOVSI T2,5		;TIMED WAIT
	CALL @BKWAIT(P6)	;WAIT FOR BACKSPACE TO FINISH
	MOVE T1,[EXP .TMATR!LR+377] ;CLEAR ATTN
	CALL RHWT		;
	SKIPN T2		;TIMEOUT?
	 $ERROR (TAPHTE)	;YES - HARD TAPE ERROR
	RET			;NO

PCHAN:	POINT 6,DSKTAB,23	;POINTER TO CHAN NUMBER
PKON:	POINT 6,DSKTAB,29	;POINTER TO KON NUMBER
PUNIT:	POINT 6,DSKTAB,35	;POINT TO TAPE UNIT
>				;END IFN FT.MTA

IFN FT.RH!FT.MTA,<		;#8 .

RHRD:	TLZ T1,(LR)		;NO WRITE
RHWT:	TSO T1,P3		;INSERT TM02
	CALL IOXCT
	DATAO .-.,T1		;SEND COMMAND
	CALL IOXCT
	DATAI .-.,T1		;READ RESULT
	RET
IFN FT.MTA,<

;START IO
TAPSIO:	TM2SIO
	DX2SIO
	TM8SIO

;START MICROPROCESSOR
STRTMP:	R
	STDX20
	R

;BACKSPACE RECORD
BACKRC:	TM2BSR
	TM2BSR
	TM8BSR

;WAIT FOR BACKSPACE TO FINISH
BKWAIT:	BWAIT
	BXWAIT
	R			;(WAITED WHEN WE STARTED IT)

TM2SIO:	MOVEI T1,TMCD16		; SET DENSITY
	LDB T2,PUNIT		;GET DRIVE NUMBER
	IOR T1,T2		; ...
	HRLI T1,(.TMTCR!LR)	;TAPE CONTROL REG
	CALLRET RHWT		; ...

DX2SIO:	LDB T1,PUNIT		;PICK UP UNIT NUMBER
	TRO T1,.TDMOD		;SET THE MODES
	TXO T1,.TDDNR!LR	;GOES INTO DRIVE NUMBER REG
	CALL RHWT		;LOAD THE REG
	MOVX T1,<<-1000*5>&177777> ;SET CORRECT RECORD SIZE
	TXO T1,.TMFCR!LR	;GOES INTO BYTE COUNT REG
	CALL RHWT		;SET RECORD SIZE
	MOVX T1,.TMDSR		;GET THE DEVICE STATUS REG
	CALL RHRD		;
	TXNN T1,.TDMPR		;MAKE SURE IT IS STILL RUNNING
	CALL STDX20		;IF NOT, START IT
	RET

TM8SIO:	MOVEI T1,5000		;SET THE BYTE COUNT REGISTER
	HRLI T1,(LR!.T7BC)	;TELL THE HARDWARE HOW MUCH WE'LL READ
	CALL RHWT
	LDB T1,PUNIT		;SLAVE NUMBER
	TRO T1,T7.SER!T7.CDP!T7.1RC ;NO ERROR REPOS, CORE DUMPE, 1 RECORD
	HRLI T1,(.T7FMT!LR)	;WRITE THE FORMAT REG
	CALLRET RHWT

TM2BSR:	MOVE T1,[EXP .TMFCR!LR+177777] ;REPEAT COUNT
	CALL RHWT		;
	MOVE T1,[EXP .TMCSR!LR+.TMBSF] ;DO BACKSPACE
	CALLRET RHWT		;

TM8BSR:	MOVEI T1,T7.BSR_6	;BACK 1 RECORD
	PUSH P,P2
	MOVE P2,P3
	LDB P3,PUNIT		;GET ACS RIGHT
	CALL T78.ND		;DO IT AND WAIT TILL DONE
	POP P,P2
	LDB P3,PKON		;RESTORE ACS
	RET

BWAIT:	MOVSI T1,(.TMDSR)	;WAIT FOR NO POSN
	CALL RHRD		;
	TRNE T1,TMSPIP		;DONE YET?
	SOJG T2,BWAIT		;NO
	RET

BXWAIT:	MOVX T1,.TMDSR		;READ THE STATUS REG
	CALL RHRD		;
	TRNN T1,.TDATB		;ATTENTION UP?
	SOJG T2,BXWAIT		;NO, LOOP
	RET

IFE FT.DX2,<
DX2SIO:
STDX20:
BXWAIT:	RET
>
IFE FT.TM8,<
TM8SIO:
TM8BSR:	RET
>
>				; END OF IFE FT.MTA
>				; END OF IFN FT.RH!FT.MTA
>				;#8 end of IFE FT.SA

IFN FT.SA,<			;#8 .
IFN FT.MTA,<			;#8 .

TAPIO:				;#8 do I/O for Mag Tape
	PUSH P,P1		;#8 save P1
	LDB P1,PCHAN		;#8 get channel number
	LDB T2,PUNIT		;#8 get unit number
	MOVEI T2,.IDMTA(T2)	;#8 get device address
	STOR T2,SC%DEV,CMTCP	;#8 store device address in 1st DCW
	STOR T2,SC%DEV,CMTCP+1	;#8 store in 2nd DCW too
	STOR P3,SC%CMD,CMTCP+1	;#8 store command
	CALL GETPHY		;#8 get physical address
	 $ERROR(MEMMRF)		;#100 V5 ERROR MACRO FOR ERRORS
	MOVE T4,T1		;#8 copy address
	MOVEI T3,CMTIOW		;#8 address for IOW storage
	JUMPN T1,TAPIO1		;#8 page 0?
;page 0
	MOVEI T2,LCORAD	;#8 amount to skip
	MOVEI T1,0		;#8 indicate skip
	CALL MAKIOW		;#8 make an IOW
	MOVEI T2,^D<512-LCORAD> ;#8 amount to actually transfer
	MOVEI T1,LCORAD		;#8 where to read into
	CALL MAKIOW		;#8 make the IOW
	JRST TAPIO3		;#8 continue
TAPIO1:
 SSAPAG==SA0BAS&777000		;#8 page SA10 base registers are on
 SSALEN==<SSAN*SSANSC*4>	;#8 length of SA10 base registers
	CAIE T1,SSAPAG		;#8 is this the page containing SA10 base?
	 JRST TAPIO2		;#8 No
; SA10 base page
				;#8 don't clobber locations SA10 is using
	CAIE P3,.ICRDT		;#8 is this a read?
	 JRST TAPIO2		;#8 no, no need to worry
 IFN SSAPAG-SA0BAS,<		;#8 if data before the regs, read it in
	MOVEI T2,^D<SA0BAS-SSAPAG> ;#8 data before regs
	CALL MAKIOW		;#8 make IOW for it
 >				;#8 end of IFN SSAPAG-SA0BAS
	MOVEI T2,SSALEN		;#8 amount to skip
	MOVEI T1,0		;#8 skip
	CALL MAKIOW		;#8 .
 IFN <SA0BAS+SSALEN>&777,<	;#8 if data after regs
	MOVEI T2,^D<512-SSALEN-<SA0BAS&777>> ;#8 amount of data after regs
	MOVEI T1,SA0BAS+SSALEN	;#8 address of data after regs
	CALL MAKIOW		;#8 .
 >				;#8 end of IFN <SA0BAS+SSALEN>&777
	JRST TAPIO3		;#8 continue
;normal page
TAPIO2:	MOVEI T2,^D512		;#8 one page I/O
	CALL MAKIOW		;#8 make IOWs for it
	JRST TAPIO3		;#8 .
TAPIO3:	MOVX T1,SC%LST		;#8 mark last IOW
	IORM T1,-1(T3)		;#8 .
	SETZM 0(T3)		;#8 terminate IO list
	MOVEI T1,CMTCP		;#8 get address of CP
	CALL CMTGO		;#8 do the I/O
	 JRST TAPIER		;#8 error detected
	POP P,P1		;#8 restore P1
	RET			;#8 return +1 to indicate success

TAPIER:				;#8 some sort of error on tape I/O
	MOVEI T1,CMTSCP		;#8 get address of sense program
	LDB T2,PUNIT		;#8 get unit number
	MOVEI T2,.IDMTA(T2)	;#8 get device address
	STOR T2,SC%DEV,(T1)	;#8 store device address in DCW
	SETOM CMTSB		;#8 start with phony status in sense bytes
	CALL CMTGO		;#8 start I/O
	 JFCL			;#8 Phooey (FUy)
	POP P,P1		;#8 restore P1
	RETSKP			;#8 don't really care what the problem was,
				;#8 ... but needed to do the sense to clear
				;#8 ... the device

MAKIOW:				;#8 make IOWs 
				;#8  T1/ address or zero for skip
				;#8  T2/ count (words)
				;#8  T3/ address to store IOW at
				;#8  RETURNS +1 always
				;#8   T1,T2 destroyed
				;#8   T3 updated to next word
MAXIOW==<.RTJST(SC%CNT,SC%CNT)> ;#8 maximum count (words)
	CAIG T2,MAXIOW		;#8 small enough to fit in one IOW?
	 JRST MAKIO2		;#8 yes
	PUSH P,T2		;#8 save count
	MOVE T2,T1		;#8 copy address
	IORX T2,< IOW MAXIOW,0,CHN > ;#8 max count IOW
	MOVEM T2,0(T3)		;#8 store IOW
	AOJ T3,			;#8 next IOW slot
	SKIPE T1		;#8 do not bump address if skipping data
	ADDI T1,MAXIOW		;#8 bump address
	POP P,T2		;#8 get back count
	SUBI T2,MAXIOW		;#8 subtract amount accounted for
	JRST MAKIOW		;#8 make next IOW
MAKIO2:				;#8 count is less than max
	MOVNS T2		;#8 negative word count 
	STOR T2,SC%CNT,+T1	;#8 store negative count with address
	MOVEM T1,0(T3)		;#8 store IOW
	AOJA T3,R		;#8 bump pointer, return

CMTGO:				;#8 start I/O for tapes
	SETO T2,		;#8 no reset
	CALL SAINGO		;#8 start the I/O
	 RET			;#8 error: return +1
	MOVE T2,SAXBAS(P1)	;#8 get base address
	LOAD T1,S1%CHS,+1(T2)	;#8 get channel status
	JUMPN T1,R		;#8 should be 0 if no errors
	LOAD T1,S1%DVS,+1(T2)	;#8 get device status
	CAIN T1,.S1CHE+.S1DVE	;#8 normal (Channel End + Device End)?
	 RETSKP			;#8 yes, return +2 to signal success
	CAIE T1,.S1CHE		;#8 channel end alone?
	 RET			;#8 no, something funny
	CALL CMTGOW		;#8 wait for channel end
	 RET			;#8 bad errors
	LOAD T1,S1%DVS,+1(T2)	;#8 get device status
	CAIE T1,.S1DVE		;#8 device end now?
	 RET			;#8 funny
	RETSKP

CMTGOW:	MOVEI T4,100000		;#8 lots of waiting time
CMTGO1:	XCT SAXCNI(P1)		;#8 get contitions
	TXNE T1,SA%MPE!SA%NXM	;#8 bad news?
	 RET			;#8 yes
	TDNN T1,SAXSTF(P1)	;#8 status flag set?
	 SOJG T4,CMTGO1		;#8 not yet, try again
	JUMPE T4,R		;#8 quit if it timed out
	MOVE T1,1(T2)		;#8 get status word 1
	TXNE T1,FLD(.S1SER!.S1BIP!.S1CSE,S1%CHS) ;#8 check for bad status
	 RET			;#8 bad
	RETSKP			;#8 indicate nothing too bad wrong

BSPACE:				;#8 backspace tape 1 block
	MOVEI T1,CMTBCP		;#8 backspace CP
	LDB T2,PUNIT		;#8 get unit number
	MOVEI T2,.IDMTA(T2)	;#8 get device address
	STOR T2,SC%DEV,(T1)	;#8 store device address in cmd
	CALL CMTGO		;#8 do the command
	 $ERROR(TAPHTE)		;#102 V5 ERROR MARCO
	RET			;#8 success

PCHAN:	POINT 6,DSKTAB,23	;#8 Pointer to channel number
PUNIT:	POINT 6,DSKTAB,35	;#8 Point to tape unit

>				;#8 end of IFN FT.MTA
>				;#8 end of IFN FT.SA

>				; END OF IFE SMFLG
IFN SMFLG,<

P.NOS:	TLO F,(F.STRT!F.CLR!F.ACT)
	RET

REDPAG:	SKIPA T1,[R4%CRD!GO]	;RH11 READ
WRTPAG:	MOVEI T1,R4%CWR!GO	;RH11 WRITE
	AOS FILPAG		;INCREMENT FILE PAGE #
	PUSH P,TIMLOC		;SAVE A LOW CORE LOCATION
	PUSH P,RELWD		;SAVE RELOAD REASON ALSO
	PUSH P,P1		;SAVE A REGISTER
	PUSH P,P2		;SAVE COUNTER
   IFN FT.MTA,<
	MOVEI P2,^D100		;RETRY 100
	MOVE T4,T1		;GET COMMAND CODE
MRETRY:	CALL TAPIO		;DO TAPE I/O
	JRST RWSXIT		;WIN
	SKIPN P2		;DO RETRY?
	 $ERROR (TAPHTE)	;NO 
	CALL BSPACE		;YES -- BACKSPACE
	JRST MRETRY		;RETRY
   > ;END IFN FT.MTA
   IFE FT.MTA,<
	MOVEI P2,5		;RETRY COUNTER
DRETRY:	PUSH P,T1		;SAVE RP04 COMMAND
	MOVE T1,P5		;GET DISK ADDRESS
	TLZ T1,777774		;KEEP JUST THE ADDRESS BITS
	MOVE T2,DSKTYP		;FIND TYPE
	CAIN T2,.R3TYP		;RM03?
	JRST [	IDIVI T1,N.SCL3	;DO RM03 CONVERSION
		JRST DRETR3]
	IDIVI T1,N.SCL4		;GET CYL IN T1, SECTOR IN T2
DRETR3:	PUSH P,T2		;SAVE CYL
	IDIV T1,NUMCYL		;GET UNIT AND CYL
	HLRZ P1,DSKTAB(T1)	;FIND UNIT ADDRESS
	TRZ P1,ENTFLG
	HRRZ P3,DSKTAB(T1)	;GET PHYSICAL UNIT NUMBER
	MOVEI T1,RH1CLR		;CLEAR RH11
	WRIO T1,@RPCS2(P1)
	WRIO P3,@RPCS2(P1)	;SET UNIT NUMBR
	HRRZ T1,T2		;SET DESIREC CYL
	WRIO T1,@RPDC(P1)	;SET DESIRED CYL
	POP P,T1		;RESTORE SECTOR WITHIN CYL
	MOVE T2,DSKTYP		;GET TYPE
	CAIN T2,.R3TYP		;RM03?
	JRST [	IDIVI T1,N.STK3
		JRST	DRETR4]
	IDIVI T1,N.STK4		;GET TRACK # IN T1, SECTOR IN T2
DRETR4:	LSH T1,^D8		;POSITION IN THE TRACK #
	IOR T1,T2		;ADD THE ECTION
	WRIO T1,@RPDA(P1)	;SET DESIRED ADDRESS REG
	POP P,T4		;RESTORE ORIG INSTRUCTION
	CALL GETPHY		;GET PHYSICAL ADDR IN 1
	 $ERROR (MEMMRF)	;BAD ADDRESS

;
; ON THE SM10 LCORAD IS NOT USED SINCE IT IS LEGAL TO TRANSFER
; INTO LOW CORE (SHADOW AC'S) AND IT IS NECESSARY SINCE RH11
; WILL NOT PERMIT THE TRANSFER IN THE MIDDLE OF A BLOCK
;
IOSET1:	LSH T1,-^D9		;SET CORE ADDRESS
	IORI T1,UNVBIT!UN36B	;SET UNIBUS VALID BIT
	WRIO T1,@UNBMAP(P1)	;SET UNIBUS MAP
	SETZ T1,0		;SET THE UNIBUS ADDRESS TO 0
	WRIO T1,@RPBA(P1)
	MOVNI T1,RPPGSZ		;SET PAGE SIZE
	WRIO T1,@RPWC(P1)	;SET SIZE OF TRANSFER
TRYIT:	CALL DOIO		;DO I/O
	EXCH T1,T4		;GET BACK ORIG COMMAND
	JUMPG T4,RWSXIT		;IF NO ERROSR , EXIT SUCCESS
	SOJG P2,DRETRY		;GO RETRY TIL COUNT EXHAUSTED
	JRST RWFXIT		;OP FAILED

   > ; END IFE FT.MTA
RWSXIT:	AOS -4(P)		;SKIP RETURN
RWFXIT:	POP P,P2		;RESTORE P2
	MOVEI T1,RH1IE
	WRIO T1,@RPCS1(P1)
	POP P,P1		;RESTORE P1
	POP P,RELWD		;RESTORE RELOAD REASON
	POP P,TIMLOC		;RESTORE LOW CORE
	RET			;RETURN

DOIO:	MOVSI T1,2		;SAVE DELAY COUNT
	WRIO T4,@RPCS1(P1)	;DO COMMAND
	MOVEI T2,RH1RDY		;WAIT FOR READY
WAIT:	TION T2,@RPCS1(P1)
	SOJG T1,WAIT		;WAIT FOR DONE
	JUMPLE T1,CPOPJ		;RETURN
	MOVEI T2,RH1TRE		;CHECK FOR ERROR
	TIOE T2,@RPCS1(P1)	;CHECK STATUS
	SETOI T1,		;YES SET T1 MINUS AS FLAG
	RET			;RETURN
   IFN FT.MTA,<
TAPIO:	LDB P1,PCHAN		;GET THE CHANNEL
	LDB P3,PKON		;GET THE TM02 UNIT NUMBER
	WRIO P3,@RPCS2(P1)	;SET CHANNEL
	LDB T1,PUNIT		;GET SLAVE UNIT
	IORI T1,TMCD16		;SET 1600BPI
	WRIO T1,@RPDC(P1)	;SET IT
	CALL GETPHY		;GET PHYSICAL ADDRESS
	 $ERROR (MEMMRF)	;BAD ADDRESS
IOSET1:	LSH T1,-^D9		;SET CORE ADDRESS
	IORI T1,UNVBIT		;SET UNIBUS VALID BIT
	WRIO T1,@UNBMAP(P1)	;SET UNIBUS MAP
	SETZ T1,0		;SET THE UNIBUS ADDRESS TO 0
	WRIO T1,@RPBA(P1)	;SET BUS ADDRESS
	WRIO T1,@RPDA(P1)	;SET FRAME COUNTER TO 0
	MOVNI T1,RPPGSZ		;SET PAGE SIZE
	WRIO T1,@RPWC(P1)	;SET WORD COUNT REGISTER
	CALL DOIO		;DO I/O
	JUMPGE T1,CPOPJ		;OK RETURN
	RDIO T1,@RPER1(P1)	;READ ERROR REGISTER
	TRNN T1,75377
	JRST CPOPJ1
	JRST CPOPJ

BSPACE:	MOVEI T1,40000		;RESET RH11
	WRIO T1,@RPCS1(P1)
	MOVEI T1,-1		;BACKSPACE 1
	WRIO T1,@RPDA(P1)	;FRAME COUNT -1 (1 RECORD
	PUSH P,T4		;SAVE PREVIOUS COMMAND
	MOVEI T4,.TMBSF		;BACKSPACE
	CALL DOIO		;DO BACKSPACE
	SKIPA			;WAIT
	 $ERROR (TAPHTE)	;HARD TAPE ERROR
	POP P,T4		;RESTORE COMMAND
	MOVEI T1,TMSPIP		;CHECK FOR PIP
	TIOE T1,@RPDS(P1)
	JRST .-1
	RET

PCHAN:	POINT 6,DSKTAB,23	;POINTER TO CHANNEL NUMBER
PKON:	POINT 6,DSKTAB,29	;POINTER TO TM02 NUMBER
PUNIT:	POINT 6,DSKTAB,35	;POINT TO TAPE UNIT

    > ;END IFN FT.MTA
>				;END IFN SMFLG
;SUBROUTINE TO GET THE PHYSICAL ADDRESS CORRESPONDING
;TO THE ADDRESS IN P4 (EITHER PHYS OR VIRT DEPENDING ON F.PHYS)
;RETURN THE RESULT IN T1
;RETURNS NON-SKIP IF THE ADDR PAGE FAULTS OR NXMS


; PAGE TABLE SLOT USED FOR THIS TEST IS FOR THE LAST FREE PAGE BEFORE VBOOT

TSTSLT== <VFREE>+A%PTB	 	;PAGE TABLE SLOT FOR TESTING
				;I.E., THE SLOT IN A%PTB CORRESPONDING TO PAGE
				; VFREE
TSTADD==<VFREE>_9		;ADDRESS OF TEST PAGE

GETPHY:	MOVE T1,P4		;COPY ADDRESS
	LSH T1,-9		;CONVERT ADDRESS TO PAGE NUMBER
	TXNE F,F.PHYS		;PHYSICAL ADDRESS FOR ARGUMENT ?
	JRST GPY.P0		;YES, GO TEST FOR EXTANT PAGE

; ARGUMENT IS A VIRTUAL ADDRESS - CONVERT TO PHYSICAL AND TEST

	MAP T1,(P4)		;GET PHYSICAL PAGE NUMBER
	TLNN T1,(1B2)		;IS PAGE ACCESSIBLE ?
	RET			;NO, RETURN
	TLZ T1,777760		;YES, CLEAR ALL BITS BUT ADDRESS
	LSH T1,-^D9		;CONVERT ADDRESS TO A PAGE #

; HERE WITH A PHYSICAL ADDRESS TO TEST
;NOT ALL PHYSICAL PAGES MAY BE IN THE VIRTUAL MAP, SO FOR TESTING WE
;TEMPORARILY SNEAK THE PHYSICAL ADDRESS INTO A PAGE-TABLE SLOT AND TRY
;TO REFERENCE THE VIRTUAL PAGE ASSOCIATED WITH THAT SLOT.

GPY.P0:	TXO T1,IMMPTR		;FORM IMMEDIATE POINTER (+WRITEABLE+CACHEABLE)
	PUSH P,TSTSLT		;SAVE EXISTING PAGE TABLE ENTRY
	MOVEM T1,TSTSLT		;MAP PAGE TO BE TESTED
	CLRPT TSTADD		;INVALIDATE PAGE TABLE ENTRY FOR PAGE REFERENCED
				; BY "E", INVALIDATE CACHE
	CONO APR,AP.RNX		;TURN OFF NXM FLAG
	SKIP TSTADD		;REFERENCE VIRTUAL PAGE
	HRRZ T1,TSTSLT		;GET PHYSICAL PAGE #
	LSH T1,9		;CONVERT TO PHYSICAL ADDRESS
	POP P,TSTSLT		;RESTORE ORIGINAL MAP ENTRY
	CONSO APR,AP.NXM	;NXM ON REFERENCE ?
	JRST CPOPJ1		;NO, GIVE GOOD RETURN
	CONO APR,AP.RNX		;YES, RESET NXM FLAG
	RET			;RETURN BAD
;SUBROUTINE TO TEST IF A GIVEN VIRTUAL ADDRESS IS LEGAL
;VIZ DOES THE ADDR PAGE FAIL, NXM , OR POINT TO A VBOOT PAGE?
;IF SO, RETURN NON SKIP

	;FIRST, SEE IF THE ADDRESS SURVIVES PAGE-FAIL OR NXM TEST
TSTADR:	MOVE T1,P4		;GET ADDR TO TEST
	LSH T1,-9		;CONVERT TO PAGE
	CAMG T1,UPRLIM		;BELOW UPPER LIMIT?
	CAMGE T1,LWRLIM		;ABOVE LOWER LIMIT?
	RET			;NO - BAD
	CALL GETPHY		;CONVERT TO PHYSICAL ADDR
	RET			;BAD RETURN FROM GETPHY
	PUSH P,P4		;SAVE DEST
	PUSH P,F		;SAVE FLAGS
	TLZ F,(F.PHYS)		;TEST VIRT ADDR
	MOVE T2,T1		;PHYS ADDR
	MOVEI P4,A%VFST		;START OF VBOOT AREA

	;OK SO FAR, SEE IF THE PHYSICAL ADDRESS CORRESPONDS TO THE
	;PHYSICAL ADDRESS OF ANY VBOOT PAGES - IF SO, GIVE BAD RETURN
TA.NXT:	CALL GETPHY		;CONVERT TO PHYS ADDR
	 $ERROR (MEMMRF)	;IMPOSSIBLE CONDITION
	CAMN T1,T2		;SAME AS TARGET ADDR?
	JRST TA.BAD		;YES - FAIL RETURN
	ADDI P4,1000		;NO - TRY NEXT PAGE
	CAIG P4,VORG_9		;CHECKED ALL PAGES?
	JRST TA.NXT		;NO - LOOP FOR MORE
	AOS -2(P)		;SKIP RETURN (THIS IS PRETTY BAD...)

TA.BAD:	POP P,F			;RESTORE FLAGS
	POP P,P4		;RESTORE ADDRESS
	RET			;NON-SKIP RETURN
;ERROR MESSAGES

DEFINE ERSTR (SYM,TEXT),
<	SYM=%COUNT
	%COUNT=%COUNT+1
	[ASCIZ/TEXT/]
>
ERRPFX: [ASCIZ/  ?BOOT: /]

	%COUNT=0	;RESET COUNTER
ERRTAB:	ERSTR (IOER2,IO error - can't read super-index block)
	ERSTR (IOER3,IO error - can't read index block)
	ERSTR (IOER4,IO error - can't read directory page)
	ERSTR (IOER5,IO error - seek retry count exceeded)
	ERSTR (IOER6,IO error - can't read EXE-directory page)
	ERSTR (IOER7,IO error - can't read data page)
	ERSTR (IOER8,IO error - can't write data page)
	ERSTR (IOER9,IO error - can't write EXE-directory page)
	ERSTR (FILFNF,File not found)
	ERSTR (FILNEF,File not in EXE format)
	ERSTR (FILDRP,File's EXE-directory is longer than 1 page)
	ERSTR (IOER10,IO error - can't read root-directory index block)
	ERSTR (STRHOM,Bad home block)
	ERSTR (STRSNF,Structure not found)
	ERSTR (STRNID,No structure ID)
	ERSTR (STRNBS,Can't find bootable structure)
	ERSTR (STRMTO,More than 1 bootable structure found)	
	ERSTR (DMPFTS,Dump error - DUMP.EXE is too small: reconfigure with MAKDMP)
	ERSTR (COMERR,Command error)
	ERSTR (COMUNS,Unknown switch)
	ERSTR (COMINV,Invalid numeric value)
	ERSTR (MEMMRF,Memory reference failed)
	ERSTR (DSKHDE,Hard disk error)
	ERSTR (TAPHTE,Hard tape error)
	ERSTR (TAPNDR,No ready tape-drive available)
	ERRSTR=STRNID		;LAST ERROR MESSAGE FOR WHICH A STRUCTURE NAME
				; WILL BE OUTPUT
	ERRFIL=FILDRP		;LAST ERROR MESSAGE FOR WHICH A FILENAME WILL
				; BE OUTPUT
;SUBROUTINE TO CLEAR CORE

CLRCOR:	SETOI P4,		;INITIALIZE ADDRESS
   IFN SMFLG,<
	PUSH P,RELWD		;SAVE RELOAD WORD
   >
CLR.NP:	ADDI P4,1000		;NEXT PAGE
	TLNE P4,-1		;DONE 256K?
   IFE SMFLG,<
	RET
   >
   IFN SMFLG,<
	JRST [	POP P,RELWD
		RET]
   >
	CALL TSTADR		;NO - TEST IF ADDRESS LEGAL
	JRST CLR.NP		;NOT LEGAL - TRY NEXT PAGE
	MOVE T1,P4		;COPY ADDRESS
	TRZ T1,777		;CLEAR LOW ORDER BITS
 IFN FT.SA,<			;#8 .
	CAIN T1,SSAPAG		;#8 page SA10 registers are on?
	 MOVEI T1,SA0BAS+SSALEN	;#8 yes, start after registers
 >				;#8 end of IFN FT.SA
	SKIPN T1		;PAGE ZERO?
	MOVEI T1,LCORAD		;YES - START AT LOC LCORAD
CLR.NW:	SETZM (T1)		;CLEAR A WORD OF THE PAGE
	CAIGE T1,(P4)		;DONE?
	AOJA T1,CLR.NW		;NO - LOOP FOR MORE OF THIS PAGE
	JRST CLR.NP		;YES - LOOP FOR MORE

IFE FT.EXE, <

;ROUTINE TO GET A FILE FROM DISK TO MEMORY
;THE VIRTUAL ADDRESSES NEEDED BY THE FILE ARE ASSUMED
;TO HAVE BEEN MAPPED BY THE CALLER

GET:	MOVEI P4,A%FP0		;READ FILE PAGE ZERO
	MOVE P5,A%XB		; DISK ADDR FROM XB
	CALL REDPAG		;READ THE PAGE
	 $ERROR (IOER6)	;CAN'T READ DIRECTORY PAGE

	HLRZ T1,A%FP0		;CHECK FORMAT CODE
	CAIE T1,1000		;CODE OK?
	 $ERROR (FILNEF)	;NO
	TLNE F,(F.CLR)		;CLEAR CORE?
	CALL CLRCOR		;YES - CALL SUBR
	MOVN P1,A%FP0		;OK - GET COUNT OF PAGES
	HRLZS P1		;BUILD POINTER WORD
	HRRI P1,A%FP0+1		;FIRST DATA WORD

GET.NP:	MOVE T1,(P1)		;GET PAGE DESCRIPTOR
	MOVE P5,A%XB(T1)	;GET DISK ADDRESS OF PAGE
	LDB P4,[POINT 9,T1,17]	;GET MEMORY PAGE ADDR
	LSH P4,9		;CONVERT PAGE NO. TO ADDRESS
	CALL TSTADR		;CHECK IF ADDRESS IS LEGAL
	 JRST GT.NP1		;NO - SKIP READ
	CALL REDPAG		;READ THE PAGE
	 $ERROR (IOER7)		;CAN'T READ DATA PAGE
GT.NP1:	AOBJN P1,GET.NP		;BACK FOR MORE

	SKIPG P3,(P1)		;IF POSITIVE, IS IMMED. ADDR
	MOVE P3,(P3)		;IF NEG, IS POINTER
	CALLRET SETSA		;SET STARTING ADDR AND RETURN
;ROUTINE TO SAVE MEMORY
;ONLY THOSE PAGES WHICH ARE MAPPED ARE SAVED.

SAVE:	MOVEI Q2,[ASCIZ/[BOOT: DUMPING] /]
	CALL OUTSTR
	MOVE T1,[XWD A%FP0,A%FP0+1] ;CLEAR DESCR PAGE
	SETZB P2,A%FP0		; ...
	BLT T1,A%FP0+777	; ...
	TLNE F,(F.DUMP)		;DUMP?
	TLO F,(F.PHYS)		;YES - USE PHYSICAL ADDRESSES.
	SETOI P1,		;INITIALIZE ADDR
	SETZM PGCNT		;ZERO COUNT OF DISK PAGES WRITTEN
	TXZ F,F.DPER		;RESET DUMP ERROR FLAG

SAV.NP:	ADDI P1,1000		;NEXT PAGE
	TLNE P1,-1		;DONE ALL?
	JRST SAV.DN		;YES - WRITE DESCR PAGE
	MOVE P4,P1		;NO - SAVE ADDR FOR WRITE
	CALL TSTADR		;IS THIS ADDRESS LEGAL?
	 JRST SAV.NP		;NO - TRY NEXT PAGE
	LSH P4,9		;MASK LOW ORDER BITS
	HLLZS T1,P4		;SAVE PAGE FOR DESCR
	LSH P4,-9		;RECOVER ADDRESS
	TLO T1,520000		;READ,WRITE,EXECUTE ACCESS
	HRRI T1,2(P2)		;FILE PAGE NUMBER
	MOVEM T1,A%FP0+1(P2)	;STORE DESCRIPTOR
	SKIPN P5,A%XB+2(P2)	;PHYS DISK ADDR - SKIP IF NONE
	JRST SV.NP1
	CALL WRTPAG		;WRITE THE PAGE
	  $ERROR(IOER8)		;COULDN'T WRITE IT
SV.NP1:	AOJA P2,SAV.NP		;NEXT PAGE

SAV.DN:	SKIPE T1,START		;NONZERO START ADDR?
	HRLI T1,(<JRST>)	;YES - BUILD SHORT ENTRY
	MOVEM T1,A%FP0+1(P2)	;STORE IN DESCR PAGE
	TLO P2,1000		;FINISH DESCRIPTOR BLOCK
	MOVEM P2,A%FP0		;BY STORING TYPE AND COUNT
	TLZ F,(F.PHYS)		;CLEAR PHYSICAL ADDRESS REQUEST
	MOVEI P4,A%FP0		;PREPARE FOR FINAL WRITE
	MOVE P5,A%XB		; ...
	CALL WRTPAG		;WRITE THE DESCR PAGE AND RETURN
	 $ERROR(IOER9)		;COULDN'T WRITE DIRECTORY PAGE
	MOVEI Q2,[ASCIZ/[OK]
/]
	CALL OUTSTR
	RET

>				; END OF IFE FT.EXE
IFN FT.EXE, <

; EXE BLOCK TYPE DISPATCH TABLE

EXETAB:	.EXDIR ,, G.DIR
	.EXEND ,, R
	.EXENT ,, G.ENT

	EXESIZ==.-EXETAB

HCOREF:	0			;#7 FLAG SET WHEN HIGH CORE IS CLEARED

; ROUTINE TO GET A FILE FROM DISK TO MEMORY.  READS EXE FORMAT FILES.

GET:	IFN FT.MTA,<		;ONLY FOR MAGTAPE
	SKIPE DIRFLG		;EXE DIRECTORY READ YET ?
	JRST G.CLR		;YES, DO NOT READ IT AGAIN
	SETOM DIRFLG		;NO, INDICATE WE HAVE READ EXE DIR
   >				;END OF IFN FT.MTA CONDITIONAL

;#7 First clear high core if not cleared before

	SKIPE HCOREF		;#7 Have we cleared high core already?
	 JRST GET1		;#7 Yes - once is enough
	MOVEI P1,A%PTB		;#7 No - Load page table address
	MOVE P2,1(P1)		;#7 Get current mapping info
	MOVEM P2,HCOREF		;#7 Save in flag word
	CONO APR,AP.RNX		;#7 Keep a tiddy processor
	MOVEI P2,^D512		;#7 First page to clear
HICLP:	MOVSI P3,(IMMPTR)	;#7 Immediate pointer
	HRRI P3,(P2)		;#7 Load physical page number
	MOVEM P3,1(P1)		;#7 Goes to virtual page 1
	CLRPT 1000		;#7 Clear entry
	SETZM 1000		;#7 Clear first word in page
	CONSZ APR,AP.NXM	;#7 Does this page exist?
	 JRST HICNXM		;#7 No - try next page
	MOVE T1,[XWD 1000,1001]	;#7 Yes - generate BLT AC
	BLT T1,1777		;#7 Clear entire page
HICNXM:	CONO APR,AP.RNX		;#7 Clear NXM flag
	ADDI P2,1		;#7 Move to next physical page
	CAIGE P2,NCSTPG*1000	;#7 All done?
	 JRST HICLP		;#7 No - Clear next page
	MOVE P2,HCOREF		;#7 Yes - Get original mapping
	MOVEM P2,1(P1)		;#7 So we can restore it
	CLRPT 1000		;#7 Clear entry
	SETOM HCOREF		;#7 Set flag so we don't clear core again
GET1:				;#7 High core has been cleared
	SETZM FILPAG		;INITIALIZE FILE PAGE #
	MOVEI P4,A%FP0		;READ INTO FILE PAGE 0
	MOVE P5,A%XB+0		;EXE DIRECTORY IS PAGE 0 OF FILE
	CALL REDPAG		;READ THE EXE DIRECTORY PAGE
	 $ERROR (IOER6)		;CAN'T READ DIRECTORY PAGE


G.CLR:				; ** REMOVED NEXT 2 INSTRUCTIONS UNTIL MAP INSTR FIXED **

	TXNE F,F.CLR		;CLEAR CORE ?
	CALL CLRCOR		;YES, GO ZERO SOME MEMORY

	MOVEI P1,A%FP0		;INITIALIZE EXE DIRECTORY POINTER
G.DSP:	HLRZ T1,(P1)		;GET BLOCK TYPE FROM DIRECTORY
	MOVSI T2,-EXESIZ	;FORM AOBJN POINTER TO TYPE TABLE
G.DSP1:	HLRZ T3,EXETAB(T2)	;GET A KNOWN BLOCK TYPE CODE
	CAMN T3,T1		;FOUND A VALID BLOCK TYPE ?
	JRST G.GO		;YES, GO PROCESS THE BLOCK
	AOBJN T2,G.DSP1		;NO, GO CHECK REMAINING VALID CODES
	 $ERROR (FILNEF)	;BAD FORMAT

G.GO:	HRRZ T1,EXETAB(T2)	;GET ADDRESS OF PROCESSING ROUTINE
	JRST (T1)		;GO PROCESS BLOCK
; HERE TO PROCESS EXE FILE DIRECTORY BLOCK

G.DIR:	HRRZ P2,(P1)		;GET # OF WORDS IN EXE DIRECTORY
	SUBI P2,1		;GET # OF WORDS IN DIRECTORY - 1
	ADDI P1,1		;POINT TO FIRST 2-WORD DESCRIPTOR

G.DIR0:	LOAD Q2,DIRPT,(P1)	;GET REPEAT COUNT
	ADDI Q2,1		;GET # OF PAGES TO READ
	LOAD P4,DIPRO,(P1)	;GET PROCESS PAGE #
	LSH P4,9		;CONVERT PAGE # TO ADDRESS
	LOAD Q1,DIFIL,(P1)	;GET FILE PAGE #
G.DIR1:	JUMPE Q1,G.DIR4		;ALL ZERO PAGE, HANDLE SPECIALLY
	CALL TSTADR		;GO SEE IF MEMORY ADDRESS IS LEGAL
	 JRST G.DIR2		;NOT LEGAL, GO TRY NEXT PAGE
   IFN FT.MTA,<			;DOING MAGTAPE?
	CAMGE Q1,FILPAG		;READING PAGE ALREADY PASSED ?
	 $ERROR (FILNEF)	;YES, CANNOT GO BACKWARDS ON TAPE
	CAMLE Q1,FILPAG		;NEED NEXT SEQUENTIAL PAGE IN FILE ?
	JRST [	PUSH P,P4	;NO, SAVE CORE ADDRES
		MOVEI P4,A%DIR	;GET A USELESS PAGE FOR DUMMY READ
		CALL REDPAG	;READ NEXT SEQUENTIAL PAGE
		 $ERROR (IOER7)	;ERROR READING PAGE
		POP P,P4	;RESTORE ORIGINAL CORE ADDRESS
		JRST G.DIR1 ]	;GO TRY AGAIN
   >				;END OF IFN FT.MTA
	MOVE P5,A%XB(Q1)	;GET DISK ADDRESS FROM INDEX BLOCK
	CALL REDPAG		;READ A DATA PAGE FROM EXE FILE
	 $ERROR (IOER7)		;ERROR READING PAGE
	CALL CHGLIM		;CHANGE PAGE LIMITS IF NECESSARY
G.DIR2:	SOJLE Q2,G.DIR3		;DECREMENT REPEAT COUNT, LOOP IF MORE
	ADDI P4,1000		;NO MORE. POINT TO NEXT PROCESS PAGE
	AOJA Q1,G.DIR1		;GO READ NEXT PAGE OF EXE FILE.

G.DIR3:	ADDI P1,.DISIZ		;POINT TO NEXT DESCRIPTOR
	SUBI P2,.DISIZ		;DECREMENT DIRECTORY BLOCK WORD COUNT
	JUMPE P2,G.DSP		;GO PROCESS NEXT BLOCK IF DONE
	JRST G.DIR0		;GO READ NEXT SET OF PAGES FROM EXE FILE

G.DIR4:	CALL TSTADR		;TEST PAGE FOR LEGALITY
	 JRST G.DIR5		;BAD PAGE, DO NOT CLEAR IT
	SETZM (P4)		;CLEAR FIRST WORD OF PAGE
	MOVSI T1,(P4)		;GET START ADDRESS FOR BLT
	HRRI T1,1(P4)		;GET DESTINATION ADDRESS FOR BLT
	BLT T1,777(P4)		;CLEAR PAGE TO ZEROS
G.DIR5:	SOJA Q1,G.DIR2		;GO SEE IF MORE PAGES TO CLEAR
; HERE TO PROCESS ENTRY VECTOR BLOCK

G.ENT:	SKIPN 1(P1)		;ENTRY VECTOR SIZE NON-ZERO ?
	 $ERROR (FILNEF)	;NO, BAD FILE FORMAT
	MOVE P3,2(P1)		;#11 YES, GET START ADDRESS
	CALL SETSA		;GO SET STARTING ADDRESS
	HRRZ T1,(P1)		;GET SIZE OF ENTRY VECTOR BLOCK
	ADD P1,T1		;UPDATE POINTER INTO EXE DIRECTORY
	JRST G.DSP		;GO HANDLE NEXT EXE FILE BLOCK



;SUBROUTINE TO SEE IF THE UPPER LIMIT FOR READING OF A FILE SHOULD
;BE CHANGED AS SPECIFIED BY THE SYMBOL TABLE POINTER.  DISABLED IF ANY
;SPECIFIC CORE LIMITS WERE SPECIFIED, OR IF .JBSYM IS ZERO.


CHGLIM:	JUMPN P4,R		;ONLY CHECK PAGE 0 OF CORE IMAGE
	TXNN F,F.NCHL		;DON'T WANT TO CHANGE THE LIMITS?
	SKIPN T1,.JBSYM		;OR HAVE NO SYMBOL POINTER?
	RET			;YES, DO NOTHING
	HLRE T2,T1		;GET NEGATIVE LENGTH
	SUB T1,T2		;COMPUTE ADDRESS RIGHT AFTER SYMBOL TABLE
	MOVEI T1,-1(T1)		;BACK OFF TO LAST ADDRESS TO READ
	LSH T1,-^D9		;CONVERT TO PAGE NUMBER
	MOVEM T1,UPRLIM		;SET NEW UPPER LIMIT
	RET			;DONE
; ROUTINE TO DUMP CORE MEMORY TO A (PREALLOCATED) FILE
COMMENT \
	SUPPORTING CHARACTERS:

	Q1	STARTING PAGE OF A SET (PROCESS PAGE #)
	Q2	NUMBER OF PAGES IN A SET
	Q3	EXE DIRECTORY PAGE FIELD POINTER
	P1	VIRTUAL ADDRESS ON PAGE TO BE DUMPED
		(PG # *1000 +777)
	P2	STARTING PAGE OF A SET (FILE PAGE #)
	P4	ADDRESS ON PAGE TO BE DUMPED
		(PG # *1000 +777)
	\

SAVE:	MOVEI Q2,[ASCIZ/[BOOT: DUMPING] /]
	CALL OUTSTR		;...

	SETZM P2,A%FP0		;SET UP TO CLEAR EXE DIRECTORY
	MOVE T1,[A%FP0,,A%FP0+1] ;PREPARE TO CLEAR EXE DIRECTORY PAGE
	BLT T1,A%FP0+777	;ZERO EXE FILE DIRECTORY PAGE
	MOVEI P2,2		;GET INITIAL FILE PAGE #
	SETZB Q1,Q2		;CLEAR START PAGE #, # OF PAGES IN SET
	SETOI P1,		;INITIALIZE FIRST VIRTUAL ADDRESS
	TXNE F,F.DUMP		;DUMP REQUESTED ?
	TXO F,F.PHYS		;YES, USE PHYSICAL ADDRESSES
	MOVEI Q3,A%FP0+1	;INITIALIZE DIRECTORY ADDRESS
	SETZM PGCNT		;ZERO COUNT OF DISK PAGES WRITTEN
	TXZ F,F.DPER+F.IOER	;RESET FLAGS

	;HERE TO SELECT CANDIDATE FOR NEXT PAGE SAVE
SAV.NP:	ADDI P1,1000		;COMPUTE NEXT VIRTUAL ADDRESS
	TXNN F,F.PHYS		;DOING A DUMP OF PHYSICAL PAGES?
	TLNN P1,-1		;NO, END OF VIRTUAL PAGES?
	SKIPA P4,P1		;NO, GET PAGE NUMBER TO BE DUMPED
	JRST SAV.DN		;AT END OF VIRTUAL CORE, GO WRITE DIR
	CAMLE P1,[PHYADR+777]	;AT END OF PHYSICAL CORE?
	JRST SAV.DN		;YES, GO WRITE DIRECTORY
	CALL TSTADR		;IS THIS ADDRSS LEGAL ?

	 ;HERE IF PAGE-FAIL, NXM, VBOOT PAGE, OR PAGE OUTSIDE DUMP RANGE
	 ; SPECIFIED BY USER
	 JRST [	CAML P4,TOPBAS	;ARE WE WHERE BOOT NOW IS?
		CAMLE P4,TOPTOP	;ARE WE IN RANGE?
		JRST SAV.NS	;NO, GO ON TO NEXT PAGE SET
		JRST SAV.NQ]	;PAGE OK, SO WRITE THE SAVED DATA
				; TSTADR FAILED BECAUSE IT WAS A VBOOT PAGE -
				; GO PLAY MAPPING GAMES

	MOVE T1,P2		;LEGAL PAGE - GET START FILE PAGE # OF SET
	ADD T1,Q2		;COMPUTE CURRENT FILE PAGE #
	LDB P4,[POINT 18,T1,26]	;GET FILE PAGE NUMBER
	JUMPE P4,SAV.NQ		;ZERO IS ALWAYS SET UP CORRECTLY
	SKIPGE XBNUM		;IF SHORT FILE, THEN CANNOT GO FURTHER
	JRST SAV.NS
	CAMN P4,XBNUM		;IS THIS PAGE PART OF THE MAPPED XB?
	JRST SAV.NQ		;YES, XB IS SET UP ALREADY

	;HERE TO GET NEXT INDEX BLOCK FOR DUMP FILE
	LOAD P5,IDXADR,A%SXB(P4) ;GET ADR OF NEXT XB
	JUMPE P5,SAV.NS		;IF NONE, STEP TO NEXT SET
	MOVEM P4,XBNUM		;SAVE THE XB NUMBER OF MAPPED XB
	MOVEI P4,A%XB		;AND GO READ IN NEW XB
	PUSH P,F		;SAVE STATE OF FLAGS
	TXZ F,F.PHYS		;DO A VIRTUAL READ
	CALL REDPAG
	 $ERROR (IOER3)		;ERROR READING PAGE
	POP P,F			;RESTORE FLAGS
	;HERE TO CALCULATE INDEX-BLOCK INDEX FOR PAGE TO BE DUMPED
SAV.NQ:	MOVE T1,P2		;YES, GET START FILE PAGE # OF SET
	ADD T1,Q2		;COMPUTE CURRENT FILE PAGE #
	IDIVI T1,1000		;GET ADR WITHIN THIS XB
				; XB INDEX NOW IN T2
	MOVE P4,P1		;GET BACK THE PAGE TO BE WRITTEN

;THIS SECTION PLAYS MAPPING GAMES.  BOOT LANDED IN LOW CORE AND MOVED ITSELF.
;WHILE MOVING ITSELF TO HIGH CORE IT SAVED THE HIGH CORE DATA IN THE AREA IT
;LANDED IN.  NOW WE ARE WRITING A DUMP FILE.  THE AREA WHERE BOOT LANDED
;(WHICH NOW HOLDS SAVED HIGH CORE INFORMATION) WILL NOT BE WRITTEN INTO A DUMP
;FILE. INSTEAD THE LOW CORE AREA WILL BE WRITTEN OUT IN IT'S "VIRTUAL" HIGH
;CORE ADDRESS.

	;HERE TO SEE IF:
	  ;  (1) MICROCODE PAGE		- DON'T DUMP IT
	  ;  (2) TARGET PAGE		- WRITE PAGE SAVED IN SOURCE AREA
	CAML P4,LODBAS		;ARE WE IN SOURCE AREA? (SEE DIAGRAMS)
	CAMLE P4,LODTOP		;ARE WE IN RANGE?
	SKIPA			;NO - CONTINUE NORMALLY
	JRST SAV.NS		;YES - SKIP THIS PAGE
IFE SMFLG,<
	CAML P4,MCSPAG		;ARE WE IN MICROCODE PAGES
	CAMLE P4,MCEPAG		;ARE WE IN RANGE
	SKIPA			;NO - CONTINUE NORMALLY
	JRST SAV.NS		;YES - SKIP THIS PAGE
>
	CAML P4,TOPBAS		;ARE WE WHERE BOOT NOW IS? (TARGET AREA)
	CAMLE P4,TOPTOP		;ARE WE IN RANGE?
	SKIPA			;NO - CONTINUE NORMALLY

	;HERE TO SET POINTERS TO HIGH-CORE PAGES WE RELOCATED TO SOURCE AREA
	JRST [	SUB P4,TOPBAS	;YES - COMPUTE PAGE NUMBER WITHIN AREA
		ADD P4,LODBAS	;ADDRESS OF WHERE SAVED DATA LIVES
		JRST .+1]	;SAVE THE PAGE HERE

	;HERE TO WRITE THE MEMORY PAGE TO DISK
	AOS T1,PGCNT		;COUNT TOTAL PAGES WRITTEN TO DISK (INCLUDING
				; THIS ONE
	CAMGE T1,DEXEPC		;IS THERE ROOM FOR THIS PAGE (+ 1 DIR PAGE)?
	JRST DMPOK		;YES
	TXO F,F.DPER		;NO, SET DUMP ERROR FLAG
	JRST SAV.NS		;GO UPDATE DIRECTORY PAGE AND EXIT
DMPOK:	LOAD P5,IDXADR,A%XB(T2)	;GET DISK ADDRESS
	JUMPE P5,SAV.NS		;NO DISK ADDRESS, START NEW PAGE SET
	CALL WRTPAG		;WRITE THE DATA PAGE
	 TXO F,F.IOER		;MARK THAT AN ERROR OCCURED
	AOS Q2			;COUNT UP THE PAGES WRITTEN

	;LIMIT TESTING - SEE IF WE NEED TO START A NEW PAGE SET
LIMTST:	CAML P1,[PHYADR+777]	;HAVE WE JUST WRITTEN PHYPAG?
	JRST SAV.N1		;YES, GO FINISH CURRENT PAGE SET
	MOVE T1,P1		;GET ADDR OF PAGE WE JUST DUMPED
	ADDI T1,1000		;INCREMENT FOR PROPER VALUE
				; (CONSIDER NEXT PAGE)
	TRZ T1,777		;GET PAGE BOUNDARY
	JUMPLE T1,LIM1		;SKIP THIS TEST FIRST TIME THROUGH
	IDIV T1,[1000000]	;SEE IF PAGE FALLS ON A SECTION BOUNDARY
	JUMPE T2,SAV.N1		;IT DOES, SO FORCE A NEW PAGE SET
LIM1:	CAIGE Q2,1000		;REACHED THE END OF A SECTION?
	JRST SAV.NP		;NO


	;HERE TO START NEW PAGE SET
SAV.NS:	JUMPE Q2,SAV.ES		;GO UPDATE START PAGE # IF NULL PAGE SET
	CAIGE Q2,1000		;EARLY QUITTING? (LESS THAN FULL PAGE SET?)
	SUBI P1,1000		;YES MUST RETEST THIS PAGE
SAV.N1: CAILE Q3,A%FP0+777-.DISIZ-.EBSIZ-.VBSIZ+1 ;DIRECTORY TOO BIG ?
	 $ERROR (FILDRP)	;YES, IT'S GREATER THAN 1 PAGE
	MOVEI T1,100		;GET DI%WRT BIT, STORE IN FLAG WORD
	STOR T1,DIFLG,(Q3)	;STORE FLAGS
	STOR P2,DIFIL,(Q3)	;STORE STARTING FILE PAGE NUMBER
	SOS Q2			;GET CORRECT REPEAT COUNT
	STOR Q2,DIRPT,(Q3)	;STORE REPEAT COUNT
	STOR Q1,DIPRO,(Q3)	;STORE PROCESS PAGE #
	ADDI Q3,.DISIZ		;POINT TO NEXT DESCRIPTOR
	ADDI Q1,0(Q2)		;COUNT UP PROCESS PAGE #
	ADDI P2,1(Q2)		;GET CORRECT NEXT FILE PAGE #

SAV.ES:	SETZM Q2		;RESET SIZE OF PAGE SET
	TXNN F,F.DPER		;DUMP ERROR OCCURRED?
	AOJA Q1,SAV.NP		;NO, GO WRITE NEXT PAGE SET
				;YES, FALL THROUGH AND WRITE DIRECTORY PAGE
	;HERE TO WRITE DIRECTORY PAGE
SAV.DN:	MOVEI T1,.EXDIR		;GET DIRECTORY BLOCK TYPE
	STOR T1,DIDIR		;STORE IN EXE DIRECTORY
	MOVEI T1,-A%FP0(Q3)	;GET SIZE OF EXE DIRECTORY
	STOR T1,DISIZ		;STORE SIZE OF DIRECTORY BLOCK
	MOVEI T1,.EXENT		;GET ENTRY VECTOR BLOCK TYPE
	STOR T1,VBTYP,(Q3)	;PUT BLOCK TYPE IN ENTRY VECTOR BLOCK
	MOVEI T1,.VBSIZ		;GET SIZE OF ENTRY VECTOR BLOCK
	STOR T1,VBSIZ,(Q3)	;STORE SIZE OF ENTRY VECTOR BLOCK
	MOVEI T1,EVLEN		;GET LENGTH OF ENTRY VECTOR
	STOR T1,VBCNT,(Q3)	;STORE LENGTH OF ENTRY VECTOR
	MOVEI T1,EVADR		;GET ADDRESS OF ENTRY VECTOR
	STOR T1,VBADR,(Q3)	;STORE ADDRESS OF ENTRY VECTOR
	ADDI Q3,.VBSIZ		;POINT TO NEXT BLOCK IN EXE DIRECTORY
	MOVEI T1,.EXEND		;GET END BLOCK TYPE CODE
	STOR T1,EBTYP,(Q3)	;STORE BLOCK TYPE IN END BLOCK
	MOVEI T1,.EBSIZ		;GET SIZE OF END BLOCK
	STOR T1,EBSIZ,(Q3)	;STORE SIZE OF END BLOCK
	TXZ F,F.PHYS		;TURN OFF PHYSICAL ADDRESSES
	SKIPG XBNUM		;DO WE HAVE XB 0 MAPPED IN
	JRST SAV.D1		;YES
	LOAD P5,IDXADR,A%SXB+0	;NO, GO MAP IT IN
	MOVEI P4,A%XB		;READ INTO XB PAGE
	CALL REDPAG
	 $ERROR (IOER3)		;ERROR READING PAGE
SAV.D1:	LOAD P5,IDXADR,A%XB+0	;WRITE OUT PAGE 0 OF FILE
	SKIPN P5		;COMPLAIN IF NO PAGE ZERO
	 $ERROR (FILNEF)	;IF NO PAGE 0, COMPLAIN
	MOVEI P4,A%FP0		;GET CORE ADDRESS OF EXE DIRECTORY
	CALL WRTPAG		;WRITE DIRECTORY PAGE AND RETURN
	 $ERROR (IOER9)		;COULDN'T WRITE IT
	TXZE F,F.IOER		;DID A WRITE ERROR OCCUR?
	 $ERROR (IOER8)		;YES
	TXZE F,F.DPER		;DUMP ERROR?
	 $ERROR (DMPFTS)	;YES - DUMP.EXE TOO SHORT
	MOVEI Q2,[ASCIZ/[OK]
/]
	CALL OUTSTR

	RET			;ALL DONE


>				; END OF IFN FT.EXE
	LIT


	IFG <A%VORG-.>,<BLOCK <A%VORG-.>>
	BLOCK <777-<.&777>>
	JRST VBOOT		;MUST BE LAST INSTRUCTION IN LAST PAGE
IFG <.-A%VORG-1000>,<PRINTX ?MAXIMUM CODE SIZE EXCEEDED>
	DEPHASE

CODEND:
BOTMOV:	MOVE P5,(P3)		;GET NONBOOT WORD
	EXCH P5,(P2)		;EXCHANGE WITH BOOT
	MOVEM P5,(P3)		;BOOT INTO HIGH CORE
	AOS P2			;NEXT WORD
	AOS P3			;...
	SOJG P4,T1		;DO ALL WORDS
MOVEND:	JRST <CORMVD-ENT>+<A%CODE-1000-A%VORG>(P1) ;GO TO MOVED BOOT


;PAGE FAULT HANDLER UNTIL AFTER BOOT IS MOVED

PAGTRP:	AOS CODEND-ENT+UPTPFO(16) ;THE PC OF THE PAGE FAIL
	JRST @CODEND-ENT+UPTPFO(16) ;PROCEED

>				;END IFN FT.PRT&2
IFN FT.PRT&1,<END JRST ENT>	;GIVE START ADR IF ASSEMBLED PT 1
	BLOCK <777-<.&777>>
	END