Google
 

Trailing-Edge - PDP-10 Archives - bb-h138e-bm_tops20_v6_1_distr - 6-1-sources/boot.mac
There are 59 other files named boot.mac in the archive. Click here to see a list.
; UPD ID= 2243, SNARK:<6.1.MONITOR>BOOT.MAC.56,  19-Jun-85 15:14:08 by LEACHE
;Edit 311 fix minor bug in edit 310
;Also, make dump-file hole extend from LODBAS to MCEPAG
; UPD ID= 2050, SNARK:<6.1.MONITOR>BOOT.MAC.55,   3-Jun-85 14:16:39 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1754, SNARK:<6.1.MONITOR>BOOT.MAC.54,  14-Apr-85 16:28:43 by LEACHE
;Edit 310 - Fix smashing of CX in RETRY
;	    TCO 6.1.1321 Add BOOT homeblock parameters
;	    TCO 6.1.1320 Reload DX20A's on autoreload
;Edit 307 - Set up default prompt
;Load DX20's once per BOOT invocation
; UPD ID= 1639, SNARK:<6.1.MONITOR>BOOT.MAC.53,  14-Mar-85 16:02:26 by HAUDEL
;TCO 6.1.1254 - Add space at end of BOOT for temporary EPT.
; UPD ID= 1313, SNARK:<6.1.MONITOR>BOOT.MAC.50,  11-Jan-85 15:17:38 by LEACHE
;Edit 306 - TCO 6.1.1131 Fix long-file problem in MTBOOT
;<LEACHE>BOOT.MAC.32, 29-NOV-84 13:49:42, Edit by LEACHE
;Edit 305 - Increase dumpable core to 4 meg
;Make debugging work for 6.1
;<DONAHUE.BOOT>BOOT.MAC.3, 21-Nov-84 19:50:12, Edit by DONAHUE
;Edit 304 - Setup a valid pointer in TSTSLT after SETEPT - otherwise
;a monitor that wants to load a page into this location hangs when it 
;references the page
;<DONAHUE.BOOT>TEST.MAC.3, 20-Nov-84 20:20:41, Edit by DONAHUE
;Edit 303 - Fix SETEPT loop to check physical address at TSTMEM+3
;	and change loop at SETPTB to setup page table for all of BOOT
;<DONAHUE.BOOT>BOOT.MAC.8,  6-Nov-84 11:31:53, Edit by DONAHUE
;Edit 302 - Change GETPGS to use DEVDSP, add label SAV.EX
;Edit 301 - Change code at SETLCV to allow booting of a 5.1 monitor
;Back Version number up to 11
;Add missing edit history
;<DONAHUE.BOOT>BOOT.MAC.4, 21-Sep-84 11:45:11, EDIT BY DONAHUE
;Version 12, edit 300
; Make changes to speed up dumping, including:
;	Rewrite disk I/O code to write more than one page at a time
;	Rewrite SAVE routine to scan the dump file's index block
;	 checking for consecutive pages on the disk
;	Allow simultaneous I/O on different channels
; Also - Add a page for the CCW's (A%CCW)
;	Add device dispatch tables for the different disk types
;	Remove all references to KC/KS/RH11/RP10 etc...
; UPD ID= 4852, SNARK:<6.MONITOR>BOOT.MAC.48,  17-Sep-84 12:07:13 by PURRETTA
;Update copyright notice
; UPD ID= 4773, SNARK:<6.MONITOR>BOOT.MAC.47,  29-Aug-84 16:55:23 by LEACHE
;TCO 6.2207 - Stop output of null directory names on errors
; UPD ID= 4722, SNARK:<6.MONITOR>BOOT.MAC.46,  21-Aug-84 12:21:27 by LEACHE
;TCO 6.2179 - Teach BOOT to load long files
; UPD ID= 4682, SNARK:<6.MONITOR>BOOT.MAC.45,  13-Aug-84 16:55:03 by LEACHE
;TCO 6.2172  Clear channel before touching it in CHNRST
; UPD ID= 4628, SNARK:<6.MONITOR>BOOT.MAC.44,  29-Jul-84 18:41:59 by LEACHE
;Put PFERR code under debug conditional
; UPD ID= 4627, SNARK:<6.MONITOR>BOOT.MAC.43,  29-Jul-84 18:30:11 by LEACHE
;Fix CHNSAV,CHNRST routines
;Add more debugging stuff
; UPD ID= 4415, SNARK:<6.MONITOR>BOOT.MAC.42,   2-Jul-84 10:14:28 by LEACHE
;TCO 6.2105  Teach BOOT to ignore PDV in EXE directory
;Fix bugs in CHNSAV/CHNRST and CHKPG0
;Fix off by 1 bug in DDT preamble code
; UPD ID= 4368, SNARK:<6.MONITOR>BOOT.MAC.41,  20-Jun-84 17:01:36 by LEACHE
;TCO 6.2051 Restart DX20B's after MTBOOT has halted them with channel reset
;Define RP04 composite error bit correctly (was attention active)
;Add real trap handling for debugging
;Fix IOOP(CLEAR) to clear RAE
;TCO 6.2007  Fix pager-clear problem
;TCO 6.2011  Make BOOT unlock the port on dual-ported RP04567's
;Add subdirectory-lookup code
;Add debugging aids and support of new KDDT
;Fix bug in GET logic for MTBOOT relating to old-style (2-pass) loads
; UPD ID= 3835, SNARK:<6.MONITOR>BOOT.MAC.40,   1-Mar-84 13:15:19 by LEACHE
;More of previous - restore previous value of default UBSTR (340)
; UPD ID= 3812, SNARK:<6.MONITOR>BOOT.MAC.39,  29-Feb-84 16:43:53 by LEACHE
;TCO 6.1969
;Make BOOT load resident and swappable monitor in 1 pass
;Make BOOT able to write monitor pages to memory above first 256K
; UPD ID= 3651, SNARK:<6.MONITOR>BOOT.MAC.38,   2-Feb-84 16:55:47 by LEACHE
;Reduce code pages from 5 to 4
; UPD ID= 3639, SNARK:<6.MONITOR>BOOT.MAC.37,   2-Feb-84 11:52:53 by MURPHY
;Put definitions of lower core cells in PROLOG.
;Setup BUTSTA as start address instead of jump to lastpage+777 hack.
; UPD ID= 3605, SNARK:<6.MONITOR>BOOT.MAC.36,  31-Jan-84 14:39:31 by MURPHY
;TCO 6.1525 - Don't use .JBSYM to imply upper limit. POSTLD must know A%VFST.
; UPD ID= 2405, SNARK:<6.MONITOR>BOOT.MAC.35,   3-May-83 15:58:36 by COBB
;TCO 6.1639 - %s and ?s in PRINTX messages...
; UPD ID= 2206, SNARK:<6.MONITOR>BOOT.MAC.34,   8-Apr-83 06:04:10 by WACHS
;Remove TCO 6.1549 since HSC disks can't be PS:
; UPD ID= 2002, SNARK:<6.MONITOR>BOOT.MAC.33,  16-Mar-83 04:11:08 by WACHS
;TCO 6.1549 - Load KLIPA, KLNI microcode
; UPD ID= 1827, SNARK:<6.MONITOR>BOOT.MAC.32,  18-Feb-83 10:59:22 by LEACHE
;Replace error TAPHTE (removed in previous edit) 
; UPD ID= 1824, SNARK:<6.MONITOR>BOOT.MAC.31,  18-Feb-83 09:51:41 by LEACHE
;TCO 6.1498 - Increase IO retry count for disks, Add disk status
; UPD ID= 1759, SNARK:<6.MONITOR>BOOT.MAC.30,   4-Feb-83 05:04:29 by WACHS
;TCO 6.1495 - Don't attempt to use KLIPA/KLNI channels
; UPD ID= 1457, SNARK:<6.MONITOR>BOOT.MAC.29,  17-Nov-82 21:01:26 by PAETZOLD
;Add some comments
; UPD ID= 1175, SNARK:<6.MONITOR>BOOT.MAC.28,  13-Sep-82 22:54:12 by MILLER
;Fix up CST mask
; UPD ID= 1174, SNARK:<6.MONITOR>BOOT.MAC.27,  13-Sep-82 21:47:49 by MILLER
;And again
; UPD ID= 1173, SNARK:<6.MONITOR>BOOT.MAC.26,  13-Sep-82 21:17:43 by MILLER
;Once more on the previous edit
; UPD ID= 1155, SNARK:<6.MONITOR>BOOT.MAC.25,   8-Sep-82 12:01:44 by MILLER
;TCO 6.1094. Set CST write bit in all CST entries
; UPD ID= 1076, SNARK:<6.MONITOR>BOOT.MAC.24,  10-Aug-82 19:17:14 by HALL
;TCO 6.1000 - Support the 2080
;	Make TYI wait until data is available
; UPD ID= 1069, SNARK:<6.MONITOR>BOOT.MAC.23,  10-Aug-82 08:36:33 by HALL
;TCO 6.1000 - Support the 2080
;	Previous edit accidentally deleted a line
; UPD ID= 1067, SNARK:<6.MONITOR>BOOT.MAC.22,   9-Aug-82 17:47:50 by HALL
;TCO 6.1000 - Support the 2080
;	Set up P before the first subroutine call near GETCM1
; UPD ID= 1050, SNARK:<6.MONITOR>BOOT.MAC.21,   7-Aug-82 14:13:24 by HALL
;TCO 6.1000 - Support the 2080
;	At FNDDEV get the mask right for a physical address
; UPD ID= 1041, SNARK:<6.MONITOR>BOOT.MAC.20,   5-Aug-82 06:37:27 by HALL
;TCO 6.1000 - Support the 2080
;	Previous edit failed to update P1  for the KC
; UPD ID= 1039, SNARK:<6.MONITOR>BOOT.MAC.19,   4-Aug-82 14:47:01 by HALL
;TCO 6.1000 - Support the 2080
;	Add some console initialization functions
;	Remove OPDEFs that are also defined in PROLOG
; UPD ID= 1031, SNARK:<6.MONITOR>BOOT.MAC.18,   3-Aug-82 08:17:23 by HALL
;TCO 6.1000 - Support the 2080
;	On the KC, set CST base register to 0
; UPD ID= 1029, SNARK:<6.MONITOR>BOOT.MAC.17,   3-Aug-82 07:20:17 by HALL
;TCO 6.1000 - Support the 2080
;	On the KC, map all of memory
;	At TOP2, clear left half of P2 before setting bits
;	Add support for the console
;Also, fix definition of NCSTPG
; UPD ID= 1024, SNARK:<6.MONITOR>BOOT.MAC.16,   2-Aug-82 07:05:28 by HALL
;TCO 6.1000 - Support the 2080
;	Typo in previous edit
; UPD ID= 1023, SNARK:<6.MONITOR>BOOT.MAC.15,   1-Aug-82 10:46:29 by HALL
;TCO 6.1000 - Support the 2080
;	Search PROLOG
;	Add APR stuff for the KC
;	Change some bit numbers to symbol names
; UPD ID= 559, SNARK:<6.MONITOR>BOOT.MAC.14,  31-Mar-82 11:55:06 by LEACHE
;Update edit number for previous edit
; UPD ID= 531, SNARK:<6.MONITOR>BOOT.MAC.13,  18-Mar-82 15:48:22 by MILLER
;TCO 5.1762. Move code at start of FNDDEV to better place
; 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  BE  USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT  (C)  DIGITAL  EQUIPMENT  CORPORATION  1976, 1985.
;ALL RIGHTS RESERVED.

	TITLE BOOT - DISK AND TAPE BOOTSTRAP
	SALL
	SEARCH MONSYM,MACSYM,PROLOG
	bdebug==0		;BOOT'S INTERNAL DEBUG CONDITIONAL

V%WHO==0
V%MAJOR==11
V%MINOR==0
V%EDIT==311


	;These definitions reflect that version of the monitor for which
	;BOOT's loading behavior was radically changed
	M%MAJ==6
	M%MIN==0
	M%EDT==6070
	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 set BDEBUG non zero.
(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.)
It is sometimes a problem finding a hole in the monitor's image such that
when the monitor is loaded, BOOT's KDDT will not be overwritten.  FOr
V6, KDDT is loaded at 500000; for V6.1 KDDT is loaded at 300000.  These
values may have to be adjusted for certain monitors (see the symbols 
at DDTLEN to do this).

Now for how to link it:

@LINK
*/SET:.LOW.:40000		;BOOT CODE GOES HERE
*/SET:ERCOD:301000		;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 300000

-- 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 ERCOD is KDDT. The above LINK commands
load KDDT at 300000 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; loading it (for debugging) is optional.

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>/G300000
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  conditional  there to
build a 256K map and include
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 DBG1. 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 DBG2 (i.e. DBG2$b).
	This breakpoint is in an AC.
4.	Type $P

5.	You have hit the second breakpoint. Now set the third. Set this
	breakpoint at DBG3 (i.e DBG3$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, KDDT was not mapped
	properly - this shouldn't happen unless you've been playing with
	the code 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 $B.

9.	From here on it is just like monitor debugging. Good luck.

10.	Well, not quite. One of the more annoying things that can happen to
	you is the loss of symbols.  This may happen twice, depending on how
	far into the loading process you monitor BOOT with DDT.  The first
	occurrence happens when the CLRCOR routine clears page 0, destroying
	the symbol-table pointer in .JBSYM  (116).  The second occurence happens
	when BOOT loads in page 0 of the .EXE file, effectively replacing
	BOOT's symbol-table pointer with that of the .EXE file.  You will
	suddenly see a new set of totally inappropriate symbols.

	The BDEBUG conditional provides for the generation of code and data
	storage to save and restore the symbol table pointer semi-automatically.

	After the first occurrence of symbol lossage, do the following:

	1.  Make note of the current PC.  Restart KDDT with:

	        300000$G

	    You will again see the DDT herald displayed.

	3.  Do $: - this clears DDT's symbol table cache.  Now you
	    have BOOT symbols again.
	4.  Put a breakpoint at the old PC, and do pc$G to get there.
	    You are ready to debug again.

	After the second occurrence of symbol lossage, you must essentially
	repeat the above.  If you intend to monitor the loaded .EXE file
	(with it's own copy of DDT), then make the following changes to
	the procedure:

	Either:

	1.  Don't recover BOOT's symbols after the second-occurrence of
	    lossage.

	Or:

	1.  Before recovering BOOT's symbols after the second occurrence of
	    lossage, manually move the contents of location 116 to somewhere
	    in core (E.G. the patch area) or write down the contents.  This
	    is the pointer to the .EXE file BOOT is currently loading.

	2.  Before BOOT transfers control to the loaded .EXE file (at
	    DOSTRT), deposit the .EXE file's symbol table pointer in 116.
	    As soon as EDDT (or even MDDT) is initialized, the symbol table
	    pointer will be read and DDT will have the correct symbols.


11.	Patching.  It is sometime convenient to patch BOOT under timesharing,
	but the trick is to compensate for all symbols above and including
	FNDDEV pointing to the wrong place.  This accomplished by PMAPing
	the low-core BOOT pages into their usual high-core pages.  The BDEBUG
	conditional will automatically generate pre/post DDT code that plays
	this PMAP game and sets up the DDT location in JOBDAT to point
	to the preamble code.  Simply GET the .EXE file and enter DDT with the
	DDT command.  BE SURE TO EXIT DDT WITH ^Z (just like monitor patching).

	The BDEBUG conditional also creates the PATCH patching area.  This area
	can be used to patch either pre-FNDDEV or post FNDDEV code.  Patching
	is intended to make debugging easier, not to provide a mechanism for
	distributing bug fixes to the field.

	Always remember that future monitor changes could cause the resident
	monitor to overlay both the PATCH area and KDDT.
			BOOT's EXE-image map


	40		ENT + initialization code
	41(772)		FNDDEV - high-core code
	42(773)		high-core code
	43(774)		high-core code
	44(775)		high-core code
	45(776)		high-core code
	46(777)		high-core code
	47		moving code (BOTMOV), DX20A ucode
	50		DX20A ucode
	51		DX20A ucode
	52		DX20A ucode
	53		DX20A ucode


	300-332		KDDT+BOOT DDT preamble code (if present)


	773(41)		high-core code (in position)
	774(42)		high-core code (in position)
	775(43)		high-core code (in position)
	776(44)		high-core code (in position)
	777(45)		high-core code (in position)
		
	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 FTKLIPA,<FTKLIPA==0>	;SUPPORT FOR KLIPA/KLNI
FTKLIPA==0			;REMOVE KLIPA/KLNI SUPPORT
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

;PROCESSOR (ETC.) BITS

AP.RES==1B19			;IOB RESET (SAME ON KI AND KL)
AP.CLR==1B22
AP.SET==1B23
IFN KLFLG,<
AP.NXM==1B25
>
IFN KLFLG,<
AP.RNX==AP.CLR!AP.NXM
>

IFN KLFLG,<
IMMPTR==FLD(IMMCOD,PTRCOD)!PTWR!PTCACH	;IMMEDIATE PAGE POINTER.
				;1B2 = IMMEDIATE POINTER
				;1B4 = WRITEABLE
				;1B6 = CACHEABLE
>

;STATE TABLE DEFINATION
;
STTSIZ==^D29			;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

	;Definitions for DX20


.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
.TDERR==2B5			;Error register
.TDSTS==1B5			;Status 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)
DTES==1B19			;Disable Transfer Error Stop Bit
; RP04 DEVICE REGISTERS

R4%CSR==00B5			;Control and status register 1
	CR.DVA==4000		;Device available

R4%DSR==01B5			;DEVICE STATUS REGISTER
	DS.ATA==1B20		;Attention
	DS.ERR==1B21		;Composite error
	DS.PIP==1B22		;Position in progress
	DS.MOL==1B23		;Media on line
	DS.WRL==1B24		;Write-locked
	DS.LST==1B25		;Last sector transfered
	DS.PGM==1B26		;Programmable
	DS.DPR==1B27		;Drive present
	DS.DRY==1B28		;Drive ready
	DS.VV==1B29		;Volume valid

DS.GUD==DS.MOL!DS.DPR!DS.DRY!DS.VV
DS.MSK==DS.GUD!DS.ATA!DS.ERR!DS.PIP!DS.WRL ;MASK OF STATUS BITS TO CONSIDER

R4%ER1==02B5			;DEVICE ERROR-REGISTER ONE
R4%ATN==04B5			;RP04 PSEUDO-ATTENTION REGISTER
R4%DST==05B5			;DESIRED SECTOR/TRACK REGISTER
R4%DTR==06B5			;DRIVE TYPE REGISTER
R4%ER2==14B5			;DEVICE ERROR-REGISTER TWO
R4%DCA==12B5			;DESIRED CYLINDER REGISTER
R4%ER3==15B5			;DEVICE ERROR-REGISTER THREE
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

R4%CSK==02B34			;RP04 SEEK FUNCTION
R4%CRC==03B34			;RE-CALIBRATE FUNCTION IN CONTROL REGISTER
R4%CDC==04B34			;RP04 DRIVE CLEAR FUNCTION
R4%REL==5B34			;Release port 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
TIMOUT==^D50000			;COUNT FOR SOJG TIMEOUT

CCWSZ==PGSIZ/DSKSIZ		;Size of each channel's ccw region
MAXCHN==7			;Max channel number
NCHAN==^D8			;Number of channels
MAXDRV==7			;Max number of drives/channel
KLPCHN==7			;KLIPA/KLNI ON CHAN 7 IS A KLIPA
KLPMSK==400003,,0		;CONI BITS WHICH DEFINE A KLIPA/KLNI
DEFSTR(KLP.VR,T1,^D29,^D8)	;FIELD FOR VERSION NUMBER IN T1
; 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
.EXPDV==1774			;PDV block type

;Miscellaneous definitions
	PGSIZ==^D512		;Size Of A Page
	BLKSIZ==^D128		;Size of a block
	EXPGSZ==1		;Size of EXE file directory page
	.DRSIZ==2		;Size of EXE file directory entry
	MONACB==0		;Monitor AC block
	ELOC==141		;Start address of EDDT
	NDMPM==^D50		;Max # dump page-write failures to report
	MAPBTS==-1B13		;Useless bits returned by MAP instruction
	LCORAD==20		;Lowest core addr dumped/loaded

MSKSTR RPT,,777B8		;Repeat count in EXE file dir entry

; 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

;FDB STRUCTURE DEFINITIONS (MOST ARE IN PROLOG)
DEFSTR (FBCTL,.FBCTL,35,36)	;CONTROL BITS FROM FDB
DEFSTR (FBBYV,.FBBYV,35,36)	;POINTER TO PAGE COUNT WORD
;MACRO TO PERFORM IO OPERATIONS - USE IS INDEPENDENT OF WHICH DISK


; MACRO DEFINITION FOR RH20

DEFINE IOOP(OP,OPR)
<IFIDN <OP><CLEAR>,<
	CALL IOXCT
	CONO .-.,2000
	CALL IOXCT
	CONO .-.,5610
>				;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


;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.WRT==1B14			;ON=Write/OFF=Read
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
;PHYSICAL CORE PARAMETERS

;HOW MANY MEGS CAN WE DUMP?
;NMEG = INTEGRAL MEGS,,FRACTIONAL MEGS (# 1/4 MEGS)
	NMEG=4,,0

	NCSTPG==<<<NMEG>&<-1,,0>>*4>_-22+<<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


   IFN BDEBUG,<
	LOC 74
	DDTPRE			;Address of DDT preamble
	RELOC
   >

;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
	PHYORG==VORG+1		;FIRST PHYSICAL PAGE BEYOND VORG (ASSUMED TO
				;BE 1'ST PAGE IN PHYSICAL REGION ABOVE VBOOT'S
				;VIRTUAL REGION)
	A$CODE==6		;# Code pages allocated

PG	A%CODE,A$CODE		;Code pages
		A%CODE==A%CODE	;Get value in listing
PG	A%FP0			;FILE PAGE ZERO WINDOW
		A%FP0==A%FP0	;Get value in listing
PG	A%XB			;INDEX BLOCK BUFFER
		A%XB==A%XB	;Get value in listing
PG	A%SXB			;SUPER INDEX BLOCK BUFFER
		A%SXB==A%SXB	;Get value in listing
PG	A%PTB			;PAGE TABLE PAGE
		A%PTB==A%PTB	;Get value in listing
PG	A%EPT			;EXEC PROCESS TABLE
		A%EPT==A%EPT	;Get value in listing
PG	A%DPG			;DIRECTORY HEADER PAGE
		A%DPG==A%DPG	;Get value in listing
PG	A%DIR			;DIRECTORY DATA PAGE
		A%DIR==A%DIR	;Get value in listing
PG	A%CCW			;Page containing CCW's
		A%CCW==A%CCW	;...
PG	A%CST,NCSTPG		;CORE STATUS TABLE PAGES
		A%CST==A%CST	;Get value in listing
	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

	A%POST==740000		;ASSUMED VALUE OF A%VFST IN POSTLD
IF2,<IFL A%VFST-A%POST,<PRINTX %** A%VFST CHANGED, POSTLD MUST BE EDITED **>>

;If the above message occurs, the value of A%VFST in POSTLD must be
;changed to be .LE. the value in this assembly.  A%POST above must
;be changed to be the same as the value put in POSTLD so that
;the check here will continue to work.
	;Debugging definitions
DBG2==MOVAC+MVCLEN		;Breakpoint in AC for moving code
DBG3==A%CODE+TOP2-ENT-1000	;This is the location for the final breakpoint
				;before VM is turned on

	;Definitions for DDT
DDTLEN==35			;Assumed length of DDT in pages
DDTPG1==300			;First page of DDT (if present)
DDTPGL==DDTPG1+DDTLEN		;Last page of DDT (including preamble)
DDTADR==<DDTPG1+1>_9		;DDT load address
DDTPRE==DDTADR-1000		;DDT preamble code
;O is the relocation value for relocating symbols under timesharing
;(Only useful if older KDDT  or user DDT is used)
O==ENT-A%FP0
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
ALLOC(DIRTMP)			;POINTER TO SUBDIRECTORY 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$TMP,8)			;STRING STORAGE FOR SUBDIRECTORY 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

ALLOC(MAXUNI)			;LARGEST LOGICAL UNIT IN STR
ALLOC(FNDCMD)			;BYTE POINTER TO INITIAL TYPEIN
ALLOC(IOCNTR)			;Number of I/O request to dump
ALLOC(PGCNTR)			;Numnber of pages written
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
ENTFLG==400000			;Entry in use flag in DSKTAB
ALLOC(DSKTAB,DSKSIZ)		;LOGICAL/PHYSICAL MAPPING
				;Disk format is:  flag+chan,,unit
				;Tape format is:  flag,,cckkuu
				;			cc = 6bit channel
				;			kk = 6bit controller
				;			uu = 6bit unit
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(HIADDR)			;Highest Physical Page number
ALLOC(CCWADR)			;Store phys. addrs. of CCW page
ALLOC(CURCHN)			;Current channel
ALLOC(CURSEC)			;Sector I want to read/write
ALLOC(CURCYL)			;Cylinder...
ALLOC(CURUN)			;Unit...
;The following table is used for error recovery. The most recent xfer
;on each channel stores the pertinent information here
	XADR==0			;Word 0 - memory address
	XDSK==1			;Word 1 - disk address
	XCNT==2			;Word 2 - READ/WRITE bit and count of pages
	XCHAN==XCNT+1		;Number of entries per channel
ALLOC(CHNTAB,NCHAN*XCHAN)	;Channel table
ALLOC(ERACS,17)			;AC's(not P) stored here during error retries
ALLOC(IOIP)			;Keep track of channels with I/O in progress

;The following symbols are the defined offsets into the device type table
;which gets setup in GOTDV when the device type is discovered
	N.CLP==0		;# cylinders/unit
	N.SCL==1		;# sectors/cylinder
	N.STK==2		;# sectors/track
	N.BPP==3		;# blocks/page
	D.DOIO==4		;Routine to start the I/O
	D.SET==5		;Routine to setup I/O (sector,cylinder, etc..)
	TYPSZ==D.SET+1		;Size of table
ALLOC(DEVDSP,TYPSZ)		;Device dispatch table

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(DERCNT)			;COUNT OF REPORTED DUMP ERRORS
ALLOC(PFFLG)			;Indicates CHKNXM page failed
ALLOC(PASS)			;INDICATES WHICH PASS OF UNIT-SEARCH CODE
ALLOC(NOLDDX)			;Inhibits multiple loadings of DX20's
ALLOC(BTFLGS)			;BOOT parameter flags from home block
ALLOC(MSGHDR)			;Address of message header
	;Default flags
  DFFLGS==0
IFN BDEBUG,<
ALLOC (EDDBLK,100)		;Reserve breakpoint block for KDDT
ALLOC (MONPDV,1)		;Allocate dummy pointer to PDV
  INTERN EDDBLK,MONPDV		;Now, make them global
>
ALLOC(MONLOD)			;0 = LOADING RESIDENT MONITOR, N=WHICH PASS
ALLOC(PORTLK)			;0= can't lock this device
				;-1 = lock port on this device
ALLOC(PFLAGS)			;PROGRAM FLAGS SAVE-WORD
ALLOC(DEXEPC)			;DUMP.EXE DISK PAGE COUNT
ALLOC(DIRST)			;Working byte-pointer to directory string
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.
PDLEN==^D40			;PUSH DOWN STACK SIZE
ALLOC(PDL,PDLEN)		;PUSH DOWN STACK
ALLOC (DTCNOW)			;ALLOCATE CONO WORD
ALLOC(PIAINI,MAXCHN+1)		;RH20 Int vector reg,, PI assignment
ALLOC(APRSER)			;CPU SERIAL NUMBER

N.BKP4==4			;Number of blocks per page
N.SCL4==^D380			;SECTORS PER CYL (RP04/RP05/RP06)
N.SCL7==^D1376			;SECTORS PER CYL RP07
N.CLP4==^D400			;CYLS PER UNI (RP04/5)
N.CLP6==^D800			;CYLS PER UNI (RP06)
N.CLP7==^D629			;CYLS PER UNI (RP07)
N.STK7==^D43			;SECTORS PER TRACK (RP07)
N.STK4==^D20			;SECTORS PER TRACK (RP04)
N.SPG2==1			;SECTORS PER PAGE (RP20)

;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

;Lower core locations are in PROLOG
IFE FT.PRT,<END>		;END HERE IF SYMBOLS-ONLY ASSEMBLY
;LOCATIONS IN DIR AREA

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
HOMBTF==A%FP0+200+17		;BOOT PARAMETER FLAGS
HOMSER==A%FP0+200+164		;APR SERIAL NUMBER
HOMCOD==A%FP0+200+176		;FUNNY CODE
CODHOM==707070			;TYPE CODE FOR HOME BLOCK

; EXEC PROCESS TABLE LOCATIONS

EPTEST==540			;INDEX TO EXEC SECTION TABLE
EPTATR==421			;INDEX TO ARITHMETIC TRAP INSTRUCTION
EPTPDO==422			;INDEX FOR PDL OVERFLOW
EPTSPT==760			;INDEX TO SPT (ONE WORD TABLE FOR VBOOT)

;UPT DEFINITIONS

IFN KLFLG,<
UPTPFW==500			;PAGE FAIL ADDRESS
UPTPFN==503			;INDEX TO PAGE FAIL WORD
UPTPFO==502			;PAGE FAIL PC WORD
>

; OPDEF FOR STORING VALUES IN PAGER REGISTERS

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

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

; PAGER REGISTERS

IFN KLFLG,<
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
>				;END OF IFN KLFLG


	;ERROR MESSAGE MACRO
	DEFINE $ERROR (CODE,ADDR)
<	JRST [MOVEI Q2,CODE
	IFB <ADDR>,<JRST ERRTYP>
	IFNB <ADDR>,<JRST ADDR>
]
>
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:

IFN KLFLG,<
	;This constitutes BOOT's "entry-vector".
	;@SET ENTRY-VECTOR 40000 3 allows I VER to identify
	;the version # of BOOT.EXE under timesharing

	TDZ F,F		;DIALOGUE LOAD ALWAYS IF STARTED HERE
	SKIPA		;SPECIAL LOAD. PRESERVE BITS
	BYTE	(3)V%WHO(9)V%MAJOR(6)V%MINOR(18)V%EDIT
>				;END IFN KLFLG
;Do I/O reset.

	CONO APR,AP.RES		;IOB RESET - CLEAR I/O DEVICES
;Turn off paging and traps. Declare EPT address to be 0.

IFN KLFLG,<
	CONI PAG,15		;GET CURRENT STATE OF PAGER
	ANDI 15,PGCLKE!PGCLDE	;CLEAR ALL BUT CACHE STRATEGY BITS
>				;END IFN KLFLG
IFN KLFLG,<
	CONO PAG,0(15)		;TURN OFF PAGING
>				;END IFN KLFLG

;Figure out where we landed and determine offset for self-relocating code.

	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
;Set up the UPT and EPT to be the same page, starting at the end of the
;code. Point to a page fault handler. AC 15 contains control bits used in
;previous CONO PAG/WREBR.

	MOVEI T1,PAGTRP-ENT(16)	;THE PAGE FAULT HANDLER
IFN KLFLG,<
	MOVEM T1,CODEND-ENT+UPTPFN(16) ;SET UP TEMPORARY EPT/UPT
>
	MOVEI T1,CODEND-ENT(16) ;GET LOCAL ADDRESS OF EPT (END OF CODE)
	LSH T1,-11		;MAKE IT A PAGE NUMBER
	IOR 15,T1		;ADD PAGE NUMBER TO THE CONTROL BITS
IFN KLFLG,<
	CONO PAG,0(15)		;MAKE EBR POINT TO THAT PAGE
	TDO T1,[1B2+1B18]-ENT(16) ;AND SET UBR AND INHIBIT METER UPDATE
>				;END OF IFN KLFLG

	DATAO PAG,T1		;MAKE UBR POINT TO ITS PAGE
; DETERMINE HIGHEST PHYSICAL CORE ADDRESS .LE. 256K

IFN KLFLG,<
J1:	CONO APR,AP.RNX		;ENABLE PAGE-FAIL INTERRUPTS FOR APR AT LEVEL 0
	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
>				;END OF IFN KLFLG

; 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:
;Exchange BOOT code pages with monitor pages at high end of memory
	  MOVAC==1		;AC TO LOAD MOVING CODE INTO
	HRRI P5,MOVAC		;PUT CODE IN T1
	HRLI P5,BOTMOV-ENT(16)	;GET BOOT MOVING CODE
	BLT P5,T1+MOVEND-BOTMOV	;MOVE MOVING CODE TO AC'S
	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
	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)
DBG1:	JRST T1			;MOVE THE CODE
;Here when code is moved to high end of memory. Paging is still off
;AC contents:
;	P1/ address of first word in highest existing page .LE. 777
;	P/ Address of first word of first page moved from low end of core

CORMVD:	HRRZI 16,A%CODE-1000-A%VORG(P1)	;COMPUTE NEW BASE OF CODE
	MOVE P5,P1		;SAVE ADR OF HIGHEST PHYSICAL PAGE

; CLEAR AND SET UP EXEC PAGE TABLE (EPT)

	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

;Prepare to handle traps. Ignore arithmetic overflow. For the KC, trap PDL overflow.
;On the KL, a zero will be executed

IFN KLFLG,<
	MOVSI T1,(<JFCL>)	;NO-OP ARITH TRAP INST
>				;END OF IFN KLFLG
	MOVEM T1,EPTATR(P1)	;STORE IN EPT

;POINT TO THE NEXT PAGE FAULT HANDLER

	MOVEI T1,PFERR		;THE NEXT PAGE FAULT HANDLER
IFN KLFLG,<
	MOVEM T1,UPTPFN(P1)	;TO THE UPT
>

;Save page number for combined UPT/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
	MOVSI T1,(FLD(SHRCOD,PTRCOD)!PTWR) ;SHARE POINTER, 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

IFN KLFLG,<
	MOVEI T2,A%CST-A%PTB(P1) ;PHYSICAL ADDRESS IN RH OF T2
	LSH T2,-9		;CONVERT TO # OF CST PAGE 0
	HRLI T2,-< <VORG-A%CST_-9>+1 > ;NUMBER OF PAGES TO MAP

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

	IFN BDEBUG,<
;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
>
>				;END IFN KLFLG

;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. KC DOESN'T REQUIRE THIS
;BECAUSE CST BASE REGISTER IS SET TO 0

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

;Do DATAO PAG to point to the UPT. Make UPT and EPT be the same page.
;For the KL, also set previous AC block to 6 in order to initialize hardware
;tables.

	TLO P2,(PGLUBR)		;LOAD UBR
IFN KLFLG,<
	HRLI P2,(PGLACB!PGLUBR!FLD(HWRACB,PGPACB)!FLD(MONACB!PGCACB))
>				;END OF IFN KLFLG
J3:	DATAO PAG,P2		; AND LOAD THE UBR

;Tell the hardware where things are, like the CST, SPT, etc.
IFN KLFLG,<
	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
	MOVE T1,[77B5+1B18]-ENT(16)  ;Get CST mask reg
	XCTU [MOVEM T1,CSTMSK]-ENT(16) ;STORE CST MASK VALUE IN PAGER AC 0
>				;END IFN KLFLG
;Do CONO PAG to turn on traps and paging. Use the same address for the EPT
;as for the UPT

IFN KLFLG,<
	TRO P2,PGKLMD!PGTPEN	;TRAP EN AND KL PAGING
>				;END IFN KLFLG
IFN KLFLG,<
	CONI PAG,T1		;GET PAGER BITS AGAIN
	ANDI T1,PGCLKE!PGCLDE	;PRESERVE CACHE BITS
	IOR P2,T1		;ADD IN CACHE BITS
>				;END IFN KLFLG
IFN KLFLG,<
	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

;Here when paging is turned on.

CODE:
	PHASE A.DATA

IFN KLFLG,<
FNDDEV:	MOVEM F,LODTYP		;SAVE STARTING FLAGS FROM KLINIT
>
;Save some info about the memory ranges that have been affected.

	MOVEM P,P1		;Move so we can shift it
	LSH P1,^D-9		;Shift to page number
	MOVEM P1,LODBAS		;SAVE START ADDRESS OF SOURCE AREA (SEE DIAGRAMS)
	MOVEI P,<1000+A%VORG-A%VFST>-1(P)	;SAVE END OF SOURCE AREA
	LSH P,^D-9		;Shift to page number
	MOVEM P,LODTOP		;LAST ADDRESS MOVED
	HRRZI P,A%VFST-A%VORG(P5)	;TOP ADDRESS ROUNDED TO PAGES
	LSH P,^D-9		;Shift to page number
	MOVEM P,TOPBAS		;SAVE START ADDRESS OF TARGET AREA (SEE DIAGRAM)
	MOVEI P5,777(P5)	;SET UP TOP OF SAVED FOR THE SAVE
	LSH P5,^D-9		;Shift to page number
	MOVEM P5,TOPTOP		;SAVE END OF TARGET AREA
	LSH P5,^D9		;And shift back to address

; CODE TO MAP LOW CORE USING KL STYLE PAGING

	SETZB P1,P3		;P1=VIRTUAL, P3=PHYSICAL PAGE #
	SETZM HIADDR		;Set highest address yet




SETEPT:	CONO APR,AP.RNX		;RESET NXM FLAG
	MOVE T1,P3		;GET PHYSICAL PAGE NUMBER
	TXO T1,1B2!1B4		;CODE = 1, WRITE
	MOVEM T1,A%PTB(P1)	;PUT ENTRY INTO PAGE TABLE
	MOVE T1,P1		;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
	SKIP 21(T1)		;Try next 3 words
	SKIP 22(T1)		;... in case interleaving
	SKIP 23(T1)		;...   was bad
TSTMEM:	CONSZ APR,AP.NXM	;NXM OCCUR ?
	SKIPA			;Yes don't save this page
	MOVEM P3,HIADDR		;Save highest page seen yet
IFN BDEBUG,<
	CAIL P3,DDTPG1		;Have we done up to DDT yet?
	JRST TSTM1		;Yes 
>				;End IFN BDEBUG
	CAIGE P3,VFREE		;Have we done up to BOOT yet???
	AOJA P1,SETEP1		;NO, NEXT PAGE TABLE SLOT
TSTM1:	MOVEI P1,TSTADD_-^D9	;And use this virtual address
SETEP1:	AOS P3			;NEXT PHYSICAL PAGE #
	CAMG P3,[PHYPAG]	;DONE ALL OF CORE?
	JRST SETEPT		;NO, GO DO NEXT PAGE
	MOVEI P,TSTADD_-^D9	;Get physical address of 'test page'
	TXO P,1B2!1B4		;Setup a valid pointer
	MOVEM P,TSTSLT		;Restore it
IFN KLFLG,<
	;Defend against memory parity errors in A%CCW (this is the page
	;used to store the channel command lists) caused by the channel
	;referencing these locations on a freshly-powered up machine in which
	;these locations may "appear" to have parity errors

	SETZM A%CCW		;WIPE OUT PARITY ERRORS
	MOVE T1,[A%CCW,,A%CCW+1];ZERO WHOLE AREA
	BLT T1,A%CCW+777	;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 IFN KLFLG
	MOVEM P5,MAXCOR		;SAVE MAX CORE AVAILABLE
	SETOM CURPAG		;INITIALIZE CURRENTLY IN-CORE DIR PAGE
IFN KLFLG,<
;HERE TO CALCULATE LENGTH OF THE DX20 MICROCODE

	MOVEI T1,DXASA		;Get start of TU7x Microcode
	MOVEI T2,DXBSA		;Get start of RP20 Microcode (if any)
	JUMPE T2,NORP20		;Don't have any?
	CAMLE T1,T2		;Is TU7x first?
	MOVE T1,T2		;No, RP20 is

NORP20:	MOVE T2,T1		;Keep a copy here
	LSH T2,-^D9		;SHIFT ADDRESS TO PAGE NUMBER
	MOVEM	T2,MCSPAG	;SAVE STARTING MICROCODE PAGE
				; NOTE THAT THIS PAGE BEGINS WITH THE BOOT
				; MOVING CODE
	ADDI	T1,DXASZ+DXBSZ-1 ;ADD LENGTH OF EACH MICROCODE MODULE


IFN FTKLIPA,<	ADDI T1,KLPLEN+NILEN> ;KLIPA, KLNI MICROCODES TOO
	LSH T1,-^D9		;SHIFT ADDRESS TO PAGE NUMBER
	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
>
	SETZM NOLDDX		;Reset DX20-loading flag
	MOVEI T1,[ASCIZ/[BOOT: /] ;Get usual prompt
	MOVEM T1,MSGHDR		;Set it up
	;When debugging, handle traps for real
   IFN BDEBUG,<

	MOVE T1,[JSP T1,TRAP]	;Setup EPT trap locations
	MOVEM T1,A%EPT+420
	MOVEM T1,A%EPT+421
	MOVEM T1,A%EPT+422
	MOVEM T1,A%EPT+423
	JRST RSTART		;Enter program proper
TRAPPC:
	;Here on a trap
TRAP:	MOVEM T1,TRAPPC		;Save it here
	MOVE P,PDP		;Get us a stack
	MOVEI Q2,[ASCIZ/?****TRAP AT /]
	CALL OUTSTR		;Output it
	MOVE Q2,TRAPPC		;Get flags+PC
	CALL OUTOCT		;Output it
	MOVEI Q2,[ASCIZ/
/]
	CALL OUTSTR	
	JRST RSTART		;Reenter program
   >				;End IFN BDEBUG conditional
;DISPLAY PROGRAM VERSION

RSTART:	MOVEI T1,PFH		;Address of page fault handler
	MOVEM T1,A%EPT+UPTPFN	;Store it
	MOVE P,PDP		;SETUP PDL
	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
	SETZM IOIP		;Say no I/O in progress
	IFE FT.MTA,<MOVSI T1,'PS '> ;DISK DEFAULT DEVICE
	MOVEM T1,STRNAM		;STORE THE DEFAULT NAME
	BLKI APR,T1		;GET CPU SERIAL NUMBER
   IFN KLFLG,< ANDI T1,7777>	;IF KL
	MOVEM T1,APRSER		;STORE SERIAL NUMBER
	MAP T1,A%CCW		;Want physical address of CCW page
	TXZ T1,MAPBTS		;Get rid of unwanted bits
	MOVEM T1,CCWADR		;And store it

;Here to prompt for input

GETCOM:	SETZB CX,DEV		;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
IFE FT.MTA, <
	MOVEI Q2,[BYTE (7)"B","O","O","T",76,0]
>
IFN FT.MTA, <
	MOVX T2,DFFLGS		;Get defaults
	MOVEM T2,BTFLGS		;Save them
	MOVEI Q2,[BYTE (7)"M","T","B","O","O","T",76,0]
>
	CALL OUTSTR		;OUTPUT PROMPT
GETCO1:	CALL GETSTR		;GET COMMAND FROM OPERATOR
	MOVEM T1,FNDCMD		;SAVE COMMAND POINTER
	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
;Setup EPT pointers to the CCW regions
	MOVE T1,CCWADR		;Get phys. addr of CCW page
	TXO T1,1B1		;Get jump CCW
	SETZM T2		;Start at channel 0
	MOVSI T3,-MAXCHN	;Setup AOBJN word
DVXLP:	MOVEM T1,A%EPT+ICA(T2)	;Yes - store jump word in EPT
	ADDI T2,4		;Point to next 4 RH words
	ADDI T1,CCWSZ		;Point to next CCW list
	AOBJN T3,DVXLP		;Have we done them all?
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, <


FDSK:	SETZM CURCHN		;Init the channel #
	SETZM CURUN		;Init the unit #
	SETZM DIORG		;INITIALIZE DIRECTORY ORIGIN
	MAP T3,A%FP0		;GET PHYS ADDR OF FP0

	TXZ T3,MAPBTS		;KEEP JUST THE ADDRESS BITS
	TLO T3,(<1B0+1B1+<1000B13>>) ;DATA XFR, LAST CCW, # OF WORDS
	MOVSI T2,-MAXCHN	;Setup AOBJN word
FDLP:	HRRZ T1,T2		;Get channel number
	IMULI T1,CCWSZ		;Determine offset into CCW region
	MOVEM T3,A%CCW(T1)	;Store it
	SETZM A%CCW+1(T1)	;Add the halt word to be sure
	AOBJN T2,FDLP		;Go do next

FDSK1:	SETZM CURUN		;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 T1,CURUN		;Get next unit number
	CAIG T1,MAXDRV		;CHECKED ALL DRIVES YET ?
	JRST FDSK2		;NO GO CHECK NEXT DRIVE
FDSK4:	AOS T1,CURCHN		;Get next channel
	CAIG T1,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 NOLDDX		;Skip if load cycle already done
	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
	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 KLFLG,<

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
	HRLI T1,RP4TYP		;Setup for BLT
	CAIE T2,.R4TYP		;RP04?
	HRLI T1,RP6TYP		;NO - ASSUME RP06
	CAIN T2,.R7TYP		;RP07?
	HRLI T1,RP7TYP		;YES
	HRRI T1,DEVDSP		;Setup rest of BLT
	BLT T1,DEVDSP+TYPSZ-1	;Setup the type table
	JRST FDSK3		;OK, GO CHECK NEXT UNIT
GOTDV2:	CALL RD10		;GO READ BACKUP HOME BLOCK
	MOVE T1,[A%FP0,,HOMNAM]	;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:	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:	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
	SETOM NOLDDX		;All DX20's have been loaded - don't  try again
	JRST FDSK
CHKSTR:	SKIPN DSKTAB(T1)	;ANY ID?
	 $ERROR (STRNID)	;NO STRUCTURE ID
	SOJGE T1,CHKSTR		;YES - LOOP FOR OTHER UNITS

	SETZM PORTLK		;ASSUME WE CAN'T DO PORT LOCKING/UNLOCKING
	MOVE T1,DSKTYP		;GET DISK TYPE
	CAIE T1,.R4TYP		;RP04?
	CAIN T1,.R5TYP		;RP05?
	SETOM PORTLK		;YES
	CAIE T1,.R6TYP		;RP06?
	CAIN T1,.R7TYP		;RP07?
	SETOM PORTLK		;YES
	MOVE T2,HOMBTF		;Get the BOOT flags
	TXNN T2,BT%RPM		;Are they valid?
	MOVX T2,DFFLGS		;No, so use defaults
	MOVEM T2,BTFLGS		;Save them
	JRST FOUND		;PASS COMMAND TO VBOOT

>				; END OF IFE FT.MTA
;SUBR TO CHECK IF A CHAN IS PRESENT
;RETURNS:	+1	CHANNEL EXISTS
;		+2	CHANNEL DOESN'T EXIST

IFN KLFLG, <

CHKCHN:	HRRZ T1,CURCHN		;Get channel number
	HLLM T1,PIAINI(T1)	;Zero out interrupt vector for this channel
	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			;NO
	AND T1,[KLPMSK]		;GET BITS WHICH DEFINE A KLIPA/KLNI
	CAME T1,[KLPMSK]	;IS IT A KLIPA OR KLNI?
	RET			;NO, RETURN SAYING CHAN EXISTS
IFE FTKLIPA,<
	RETSKP			;YES. SAY CHAN DOESN'T EXIST SO UCODE WON'T GET BLOWN
>
IFN FTKLIPA,<
	MOVE T2,CURCHN		;Get current channel
	CAIE T2,KLPCHN		;YES. WHICH?
	SKIPA T2,NIPTR		;KLNI
	MOVE T2,KLPPTR		;KLIPA
	CALL KLPLOD		;LOAD THE CORRECT MICROCODE
	RETSKP			;AND RETURN SAYING CHAN DOESN'T EXIST
>				; END IFN FTKLIPA
>				; END IFE SMFLG
;SUBROUTINE TO SEE IF A UNIT EXISTS
;RETURNS:	+1	UNIT EXISTS
;			DEVICE BITS IN T2
;		+2	UNIT DOESN'T EXIST

IFN KLFLG,<
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		; ...
	RET			;ALL IS WELL
	MOVEI T1,.RHRAE!.RHMBE	;CLEAR RAE, ENABLE
	CALL RHCO1		;DO CONO
	JRST RSKP		;LOSE


RHRD1:	TLZ T1,(LR)		;CLEAR LR BIT
RHWT1:	TSO T1,CURUN		;INSERT UNIT NUMBER
RHDIO1:	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:	HRR F,CURCHN		;Get RH #
	ADDI F,RH0_-2		;Produce device code for that RH
IOXCT:	DPB F,[POINT 7,@(P),9]	;PLUG IOADDR
	RET			;EXECUTE INSTR
>				;END IFN KLFLG
IFN FT.MTA,<
FTAP:
IFN FT.DX2,<
	CALL LALLDX		;LOAD MICROCODE INTO ALL DX20S
>;END IFN FT.DX2
	SETZM CURCHN		;Start at channel zero
	SETZM CURUN		; and controller zero
GETTCH:	CALL CHKCHN		;DOES THIS CHANNEL EXIST?
	JRST GOTTCH		;YES - TRY UNITS
NXTTCH:	AOS T1,CURCHN		;No, try next channel
	CAIG T1,MAXCHN		;No more 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 T1,CURUN		;Try next controller
	CAIG T1,7		;ANY MORE
	JRST GOTTCH		;YES - SEE IF THIS WINS
	SETZM CURUN		;No, try next channel, starting at controller 0
	JRST NXTTCH		; ...

GOTTUN:	ANDI T2,777		;ISOLATE CONTROLLER TYPE
	SETZ P3,		;START AT UNIT 0
IFN FT.DX2,<
	MOVEI P6,DA.IDX		;Get device index for DX20A's
	CAIN T2,.DXATP		;IS THIS ONE?
	JRST GOTDX2		;YES, PROCESS IT
	CAIE T2,.DXBTP		;DX20B?
	JRST GOTUN1		;No
	MOVEI P6,DB.IDX		;Get device code for DX20B's
	CALL STDX20		;Restart it
	JRST NXTTUN		;Check next unit
>

GOTUN1:

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
IFN KLFLG,<
	CALL RHWT1		;INSERT KON, SEND TO CHN
	MOVSI T1,(.TMDSR)	;READ DEVICE STATUS
	CALL RHRD1		; ...
>				;END KLFLG
	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:	SKIPE NOLDDX		;Have we done this yet?
	RET			;Yes, just return
	SETZM CURCHN		;Start with channel zero
	SETZM CURUN		; and controller zero
LALLD1:	CALL CHKCHN		;DOES THIS CHANNEL EXIST?
	 JRST LALLD3		;YES, SEE IF ANY DX20S OUT THERE
LALLD2:	AOS T1,CURCHN		;Look at next channel
	CAIG T1,MAXCHN		;LOOKED AT ALL THE CHANNELS?
	JRST LALLD1		;NO, LOOK AT NEXT CHANNEL
	SETOM NOLDDX		;Don't need to do it again
	RET			;ALL DONE
LALLD3:	CALL CHKUNI		;SEE WHAT EXISTS ON THIS CHANNEL
	 JRST LALLD5		;SOMETHING THERE, GO SEE IF DX20
LALLD4:	AOS T1,CURUN		;Get next controller
	CAIG T1,7		;LOOKED AT ALL CONTROLLERS?
	JRST LALLD3		;NO, LOOK AT NEXT ONE
	SETZM CURUN		;Start with controller zero
	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]
IFN KLFLG,<
	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,CURCHN		;GET CHAN
	LSH T2,6		;SHIFT
	IOR T2,CURUN		;WITH KONTROLLER
	LSH T2,6		;AGAIN
	IOR T2,P3		;AND SUBUNIT
	TLO T2,ENTFLG		;SET NEGATIVE
	MOVEM T2,DSKTAB		;STORE
	JRST FOUND		;WIN.


WTRDY:	MOVSI T2,5		;TIMEOUT COUNTER
WTRDY1:	MOVSI T1,(.TMDSR)	;WAIT FOR DRIVE READY
IFN KLFLG,<
	CALL RHRD1		; ...
>				;END IFE 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
IFN KLFLG,<
	CALL RHWT1		; ...
>				;END IFN KLFLG
	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
>				;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:	SETZ P6,		;ASSUME NOT A DX20
	CAIE T2,.DXATP		;TAPE STYLE DX20?
	JRST DCHK		;No

	;HERE IF WE HAVE A TAPE DX20
TDX20:	MOVEI P6,DA.IDX		;YES, SET UP CODE
	JRST GOTDX		;JOIN COMMON CODE

DCHK:	CAIE T2,.DXBTP		;DISK STYLE DX20?
	RET			;NO, NEITHER TYPE OF DX20
IFE FT.RP2,
<	RET			;It's a disk DX20, but we have no U-code
>
	;HERE IF WE HAVE A DISK DX20
DDX20:	MOVEI P6,DB.IDX		;YES, SET UP CODE

GOTDX:	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:	MOVE Q2,MSGHDR		;Get message header
	CALL OUTSTR		;Display it
	MOVEI Q2,[ASCIZ\STARTING\]
	CALL OUTSTR
	CALL TYPDX2		;TYPE OUT DX20 AND CHANNEL NUMBERS
	MOVEI Q2,[ASCIZ \MICROCODE V\]
	CALL OUTSTR
	MOVE T1,DXAMCV		;ASSUME DX20A
	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:
	;	CURCHN, CURUN set up
	;	P6:		DX20 TYPE

TYPDX2:	PUSH P,Q2		;PRESERVE Q2
	MOVEI Q2,[ASCIZ \ CHN:\]
	CALL OUTSTR		;OUTPUT CHN:
	MOVE Q2,CURCHN		;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,CURUN		;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
IFN FTKLIPA,<
EXTERN KLPPTR,NIPTR,KLPVER,NIVER,KLPLEN,NILEN

;LOAD THE KLIPA MICROCODE
;CALL	T2/AOBJN WORD TO PICK UP ADDRESS/WORD 1/WORD 2

KLPLOD:	CALL XIO1
	CONO .-.,400000
	MOVE T1,CURUN		;Get unit #
	MOVEI F,RH0_-2(T1)	;PRODUCE DEVICE CODE
	DPB F,[POINT 7,KLPLD2,9] ;INSERT INTO DATAO'S
	DPB F,[POINT 7,KLPLD3,9] ; RATHER THAN CALL XIO1 A FEW THOUSAND TIMES
	DPB F,[POINT 7,KLPLD4,9] ; FOR THE SAME DEVICE CODE
	DPB F,[POINT 7,KLPLD5,9]
KLPLD1:	MOVE T1,(T2)		;PICK UP ADDRESS
KLPLD2:	DATAO .-.,T1
KLPLD3:	DATAO .-.,1(T2)		;(LH) MICROWORD
	TXZ T1,1B13
KLPLD4:	DATAO .-.,T1
KLPLD5:	DATAO .-.,2(T2)		;(RH) MICROWORD
	ADDI T2,2
	AOBJN T2,KLPLD1
	MOVE Q2,MSGHDR		;Get message header
	CALL OUTSTR		;Display it
	MOVEI Q2,[ASCIZ\LOADING \]
	CALL OUTSTR
	MOVEI Q2,[ASCIZ \KLIPA\] ;ASSUME IT'S A KLIPA
	CAIE P1,KLPCHN
	MOVEI Q2,[ASCIZ \KLNI\]	;BAD GUESS
	CALL OUTSTR		;TELL WHAT DEVICE WE'RE LOADING
	MOVEI Q2,[ASCIZ \ MICROCODE V\]
	CALL OUTSTR
	MOVE T1,KLPVER		;ASSUME KLIPA
	CAIE P1,KLPCHN
	MOVE T1,NIVER		;BAD GUESS
	LOAD Q2,KLP.VR		;GET VERSION NUMBER
	CALL OUTOCT		;TYPE IT
	MOVEI Q2,[ASCIZ\]
\]	;CLOSE THE EXPRESSION
	CALL OUTSTR
	RET
>
;PAGE FAULT HANDLER DURING STARTUP
IFN KLFLG,<
PFERR:	AOS A%EPT+UPTPFO	;THE PC OF THE FAULT
	JRST @<A%EPT+UPTPFO>	;PROCEED

;Page Fault Handler while BOOT is running normally

PFH:	PUSH P,Q1		;Save an AC
	PUSH P,Q2
	PUSH P,Q3		;All get clobberred by the output routines
	HRRZ Q1,A%EPT+UPTPFO	;Get PC of fault
	CAIE Q1,CHKAD		;Was it in CHKNXM routine?
	JRST PFH1		;No, continue
	SETOM PFFLG		;Yes, set flag to notify CHKNXM
	POP P,Q3		;Restore saved ACs
	POP P,Q2
	POP P,Q1
	JRST CHKDON		;And continue CHKNXM

PFH1:	CALL CRLF		;New line here
	MOVE Q2,ERRPFX		;Get the prefix
	CALL OUTSTR		;Output it
	MOVEI Q2,[ASCIZ/ Page Fail at PC: /]
	CALL OUTSTR
	MOVE Q2,A%EPT+UPTPFO	;Get the PC
	CALL OUTOCT		;Print it out
	MOVEI Q2,[ASCIZ/, Page Fail Word: /]
	CALL OUTSTR
	MOVE Q2,A%EPT+UPTPFW	;Get PFW
	CALL OUTOCT
	JRST ERRET		;Start over again

>				;END IFN KLFLG

RSKP:
CPOPJ1:	AOS (P)			;SKIP RETURN

R:
CPOPJ:	RET
;	SUBROUTINE TO CHECK STRUCTURE NAME OF PACK ON CURRENT CHANNEL AND UNIT
;	RETURNS +1	NO MATCH
;		+2	MATCH
;	OR ERROR RETURN TO COMMAND PARSER
   IFE FT.MTA,<
CHKHOM:	MOVE T1,HOMNAM		;CHECK BLOCK NAME
	CAME T1,[SIXBIT 'HOM']
	RET			;BAD
	MOVE T1,HOMCOD		;CHECK BLOCK CODE
	CAIE T1,CODHOM		;...
	RET			;BAD
	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:	HRRZ T1,HOMLUN		;GET LOGICAL UNIT
	SKIPE DSKTAB(T1)	;IS THERE ALREADY AN ENTRY?
	$ERROR(STRMTO)		;YES - MORE THAN 1 BOOTABLE STRUCTURE
	MOVE T2,CURUN		;Get unit #
	HRRZM T2,DSKTAB(T1)	;Store it
	MOVE T2,CURCHN		;Get channel #
	MOVEI T2,ENTFLG(T2)	;GET CHANNEL & ENTRY-IN-USE FLAG
	HRLM T2,DSKTAB(T1)	;STORE CHANNEL NUMBER
	HLRZ T1,HOMLUN		;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
	RETSKP			;SUCCESS
   >	;End IFE FT.MTA
;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,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
	SETZI T2,		;TERMINATING NULL
	IDPB T2,Q3		; STORE
	RET			;RETURN

CRLF:	MOVEI Q1,15		;CR WITH PARITY
	CALL TYO		;TYPE OUT
	MOVEI Q1,12		;LF
	CALLRET TYO
;KLINIT HAS REQUESTED SPECIAL LOAD. PROCESS THE BITS

GETST1:	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,<
;KL10 CONSOLE ROUTINES
;TYI - Read terminal input
;	CALL TYI
;Returns +1: always,
;	Q1/ one character, right-justified

;Reads the character and echoes it

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 IFN KLFLG
>				;END IFE FT.UDB
IFE FT.MTA, <
IFN KLFLG ,<

; ROUTINES TO READ PAGES CONTAINING PRIMARY AND SECONDARY HOME BLOCKS
; CURCHN and CURUN must be setup
;		CALL RD10
; RETURNS +1 IF NO ERRORS, ELSE CAUSES DSKHDE ERROR RETURN


	NRETRY==500		;Number of times to retry.
				;Note:  the retry count must take into account
				;dual ported devices in which the other side
				;is keeping the port very active


	;Read secondary home block
RD10:	SKIPA P4,[.RHSBR!LR!0B27!^D10B35] ;DESIRED SECTOR AND TRACK
	;Read primary home block
RD0:	MOVE P4,[.RHSBR!LR!0B27!0B35] ;RH20 XFR CONTROL REGISTER


	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,DS.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


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

; ACCEPTS IN T4/	DATAO DATA
;	     P4/	POSITION SELECT WORD
;	CURCHN and CURUN must be setup
; 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,DS.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

>				;END IFN KLFLG
>				;END IFE FT.MTA
; PUSH-DOWN POINTER
PDP:	IOWD PDLEN,PDL

;Here when command has been read. Call VBOOT to do the work.

FOUND:	MOVEI T1,[ASCIZ/[BOOT: /] ;Get usual prompt
	MOVE T2,BTFLGS		;Get parameter flags
	TXNE T2,BT%RPM		;Parameters from disk?
	MOVEI T1,[ASCIZ/[*BOOT: /] ;Yes, notify user we are using them
	MOVEM T1,MSGHDR		;Save address of message header
	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 ERRORS, ARRIVE HERE WITH ERROR TYPE IN Q2
ERRTYP:
	MOVE T1,BTFLGS		;Get home-block flags
	TXNE T1,BT%HOD		;Halt on dump errors?
				;(Nothing to halt on any other errors)
	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 STATUS IF MTBOOT

	MOVEI T1,^D35		;TURN ERROR SYMBOL INTO A BIT
	SUB T1,(P)
	MOVEI T2,1
	LSH T2,(T1)
	MOVEM T2,(P)		;SAVE THE BIT

	   IFE FT.MTA,<
	MOVE Q2,[%SNAM]		;DO WE REQUIRE A STRUCTURE NAME?
	TDNN Q2,(P)		;...
	JRST TFIL		;NO
	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
TFIL:	MOVE Q2,[%FNAM]		;DO WE REQUIRE A FILE NAME?
	TDNE Q2,(P)		;...
	CALL TYPFIL		;YES
>				;END FT.MTA CONDITIONAL
	CALL CRLF		;OUTPUT CRLF
	MOVE Q2,[%DVSTS]	;WANT DEVICE STATUS?
	TDNE Q2,(P)		;...
	CALL OUTSTS		;YES

ERRET:	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
	SETZB F,PIAINI		;CLEAR FLAGS AND RH20 PI ASSIGNMENT
	MOVEM T1,ISTRNG		;T1 HAS STRING POINTER
	MOVE T2,[PIAINI,,PIAINI+1] ;Setup to clear the whole table
	BLT T2,PIAINI+MAXCHN	;Do it
	MOVE P6,TAPTYP		;PICK UP THE TAPE TYPE
	CALL CHNSAV		;SAVE CHANNEL STATE
	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
	JUMPGE F,LODRUN		;DUMP DESIRED? (B0 OF F)
	CALL SAVE		;YES - DO DUMP
	RET
>				;END IFE FT.MTA

;IFN FT.MTA, JUST FALL INTO THIS ROUTINE
LODRUN:	MOVE Q2,MSGHDR		;Get prompt header
	CALL OUTSTR		;Display it
	MOVE T1,MONLOD		;GET VBOOT INVOCATION COUNT
	JUMPE T1,PASS0		;JUMP IF FIRST INVOCATION
	MOVEI Q2,[ASCIZ/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/LOADING] /]
	CALL OUTSTR

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

IFN KLFLG,<
	SETZM DTEMTI		;ZERO INPUT READY FLAG
	CALL SETLCV		;SETUP LOW CORE VARS
EXIT:	CALL CHNRST		;RESTORE CHANNNEL
>				; END OF IFN KLFLG
	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
	XMOVEI T1,VBOOT		;SET START ADDRESS
	MOVEM T1,BUTSTA
	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%CCW-A%VORG(T1) ;GET PHYSICAL ADDRESS OF FIRST PAGE
	HRLI T1,-<<A%VORG-A%CCW>_-9+1> ;GET # OF PAGES MONITOR MUST MAP
	MOVEM T1,BUTPHY		;SAVE MAPPING INFO FOR MONITOR
	MOVEI T1,A%CCW		;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
	Z			;DEFAULT LBSTR
	POINT 7,D$TMP		;DEFAULT DIRTMP

;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.1B,".",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 1B - ACCUMULATE DIRECTORY STRING.

ST.1B:	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
IFN KLFLG,
<
	;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
 >
IFN FTKLIPA,<
	MOVEI Q2,[ASCIZ/KLIPA: /] ;OUTPUT STRING
	CALL OUTSTR
	MOVE T1,KLPVER		;GET KLIPA MCODE VERSION
	MOVEI Q2,[ASCIZ/KLNI: /] ;OUTPUT STRING
	CALL OUTSTR
	MOVE T1,KLPVER		;GET KLNI MCODE VERSION
>
>				;END IFN KLFLG
	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


OUTSTS:	PUSH P,F		;SAV AC'S
	MOVEI Q2,[ASCIZ/	Channel-status (CONI RH,):  /]
	CALL OUTSTR		;OUTPUT THE STRING
	CALL XIO1		;SET UP FOR CHANNEL STATUS
	CONI .-.,Q2		;GET THE STATUS
	CALL OUTOCN		;OUTPUT THE CHANNEL STATUS
	MOVEI Q2,[ASCIZ/   Device-status:  /]
	CALL OUTSTR		;OUTPUT THE STRING
	MOVX T1,R4%DSR		;SET UP FOR DEVICE STATUS
	CALL RHRD1		;READ THE DEVICE REGISTER
	MOVE Q2,T1		;GET THE STATUS
	TDZ Q2,[-1,,600000]	;MASK OUT THE JUNK
	CALL OUTOCN		;OUTPUT THE STATUS
	CALL CRLF		;OUTPUT A CRLF
	MOVEI Q2,[ASCIZ/	Device error-registers  (1)  /]
	CALL OUTSTR
	MOVX T1,R4%ER1		;SET UP FOR ERROR REG 1
	CALL RHRD1		;READ IT
	MOVE Q2,T1		;GET THE STATUS
	TDZ Q2,[-1,,600000]	;MASK OUT THE JUNK
	CALL OUTOCN		;OUTPUT IT
   IFE FT.MTA,<
	MOVEI Q2,[ASCIZ/  (3)  /]
	CALL OUTSTR		;OUTPUT THE STRING
	MOVX T1,R4%ER3		;SET UP FOR ERROR REG 3
	CALL RHRD1		;READ IT
	MOVE Q2,T1		;GET THE STATUS
	TDZ Q2,[-1,,600000]	;MASK OUT THE JUNK
	CALL OUTOCN		;OUTPUT IT
>				;END FT.MTA CONDITIONAL
	CALL CRLF		;OUTPUT A CRLF
	POP P,F			;RESTORE AC'S
	RET			;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
	MOVEI Q1,":"		;ADD A COLON
	CALL TYO
	RET

	;SUBROUTINE TO TYPE OUT FILENAME
TYPFIL:	MOVEI Q1,"<"		;OUTPUT LEFT ANGLE
	CALL TYO
	MOVE Q2,DIRSTR		; POINTER TO DIRECTORY STRING
	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 byte pointer to directory string
	MOVEM T1,DIRST		;Keep a working copy here
FND1:	MOVE Q1,DIRTMP		;Use this BP for depositing
	SETZM @DIRTMP		;Insure trailing nulls for fullword compare
				;on first 5 bytes of name
FND2:	ILDB T1,DIRST		;Get next character from dir string
	CAIN T1,"."		;End of (sub)directory name?
	SETZM T1		;Yes
	IDPB T1,Q1		;Store character
	JUMPN T1,FND2		;End of processing this directory level?
	MOVE T1,DIRTMP		;Yes, get pointer to (sub)directory 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
	LDB T1,DIRST		;Look at last char read
	JUMPN T1,FND1		;Get next level 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

;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
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 ROUTINES
IFN KLFLG, <
IFE FT.MTA, <
;WRTPAG - Routine to write a set of contiguous pages
;Called with T2/ Count of pages to write
;	     P4/ Address of first page in memory to write
;	     P5/ Disk address to write to
;Returns +1 Always

WRTPAG:	MOVE T1,P5		;Get disk address in T1
	PUSH P,T2		;Save it over call
	CALL CHNSET		;Go get channel info
	CALL IOWAIT		;T1 has channel # - go wait for it
	 CALL DMPERR		;Report error on previous write
	MOVE T2,(P)		;Get back count of pages
	TXO F,F.WRT		;Say we want to write
	CALL RWCMN		;Call the common I/O code
	POP P,T2		;Get page count
	CALL SETRTY		;Go setup CHNTAB for retry
	RET

;Routine to write a page and wait for it to complete
;Accepts same arguments as above
WRTWAT:	CALL WRTPAG		;Call routine to do work
	MOVE T1,CURCHN		;Get channel number of xfer
	CALL IOWAIT		;Wait for it to finish
	 RET			;Error...
	RETSKP			;No problem

;REDPAG - Routine to read a page from the disk
;Accepts P4/ Address in memory to write to
;	 P5/ Disk address to read
;Returns +1 - Failure
;	 +2 - Success
REDPAG:	MOVE T1,P5		;Setup disk address
	CALL CHNSET		;Setup channel info
	CALL IOWAIT		;Make sure channel is idle
	 CALL DMPERR		;Calling DMPERR assumes that we are about
				; to read a new XB while dumping, and the
				; previous xfer (a write) was unsuccessful
				;Note that if the previous xfer was a read
				; it would have been noted before the REDPAG
				; routine returned control
	MOVEI T2,1		;Number of pages to do
	TXZ F,F.WRT		;Say we want to read
	CALL RWCMN		;Do the work
	MOVEI T2,1		;Page count
	CALL SETRTY		;Go setup CHNTAB for retry
	MOVE T1,CURCHN		;Which channel??
	CALL IOWAIT		;Make sure it finishes
	 RET			;Error!!!
	RETSKP			;No problems

RWCMN:	CALL @DEVDSP+D.SET	;Setup variables
	CALL @DEVDSP+D.DOIO	;Start IO 
	RET			;RETURN
;Routine to save information needed if a retry is necessary
;Accepts T2/ Page count
;	 P4/ Starting memory address of xfer
;	 P5/ Starting disk address
;Returns +1 Always
SETRTY:	MOVE T1,CURCHN		;Get channel number
	IMULI T1,XCHAN		;Get offset into retry table
	MOVEM P4,CHNTAB+XADR(T1);Store memory address of latest xfer on channel
	MOVEM P5,CHNTAB+XDSK(T1);Store disk address
	SETZM T3		;Guess read
	TXNE F,F.WRT		;Was this a write?
	MOVX T3,1B0		;Yes, set the write bit
	MOVEM T3,CHNTAB+XCNT(T1);And store it
	HRRM T2,CHNTAB+XCNT(T1)	;With the page count
	RET			;Done

;Routine to start I/O on an RH20 after registers have been setup
;Called with T4/ STCR register
DOIO:	IOOP(CLEAR)		;CLEAR CONTROLLER/UNIT
	CALL CKPORT		;Do we still have port?
	RET			;No - return and let error recovery do it
	IOOP(XCTOP,T4)		;EXECUTE OPERATION
	RET			;

;CHKIO - Routine to insure that all I/O has completed
;If it discovers that some channel had errors, it calls DMPERR to report them
;Returns: +1 - Always, I/O has completed
CHKIO:	SETZM T1		;Start with channel 0
CHKLP:	PUSH P,T1		;Save current channel number
	HRRM T1,CURCHN		;Setup the channel number
	HRR F,CURCHN		;Also in F for I/O instructions
	ADDI F,RH0_-2		;And the device code
	CALL IOWAIT		;See if this channel is done
	 CALL DMPERR		;Report error on this channel
	POP P,T1		;Restore channel number
	CAIGE T1,MAXCHN		;Have we done them all?
	AOJA T1,CHKLP		;No - go do next channel
	HRRZ T1,IOIP		;Check if all channels are done
	JUMPN T1,CHKIO		;No - try again
	CALL CHNRST		;And reset the RH's
	RET			;Yes - return
;Routine IOWAIT - to wait for Xfer on current channel to complete
;If there was an error on the previous transfer, this routine will
;requeue the failing transfer and wait for it
;Call T1/ Channel #
;Returns +1/ Error on previous xfer - channel is idle
;	 +2/ Success - channel is idle

IOWAIT:	MOVX T2,1		;Setup bit to shift
	LSH T2,@T1		;Shift bit to channel #
	TDNN T2,IOIP		;Is this channel idle?
	RETSKP			;No xfer - no errors...(makes sense)
	PUSH P,T2		;Save bit for this channel
	MOVE T4,T1		;Get channel number, in case of error
	IMULI T4,XCHAN		;Number of entries per channel
	MOVX T2,15		;Setup retry count
TIMSET:	MOVSI T3,1		;Setup timeout
IOLOOP:	IOOP (SKIPDONE)		;Is the xfer done?
	SOJGE T3,IOLOOP		;No - check again	
	JUMPLE T3,IORTRY	;Timeout - retry
	IOOP(SKIPNOERR)		;Error?
	 JRST IORTRY		;Yes - retry
	CALL UKPORT		;Unlock the port (if needed)
	POP P,T2		;Get back channel's bit
	ANDCAM T2,IOIP		;Note channel idle
	RETSKP			;And return good
IORTRY:	SOSGE T2		;Retry count expired??
	 JRST [	POP P,T2	;Get back channel's bit
		ANDCAM T2,IOIP	;Note channel idle
		RET ]		;Error on previous command
	CALL RETRY		;Retry it
	JRST TIMSET		;Go wait for it

;Routine to retry failed I/O
;Called with offset into CHNTAB in T4
RETRY:	MOVEM CX,ERACS+CX	;Save it
	MOVEI CX,ERACS		;Setup BLT
	BLT CX,ERACS+15		;Save ACs
	MOVE CX,ERACS+CX	;Restore CX
	PUSH P,CURSEC		;Save
	PUSH P,CURCYL		;  these
	PUSH P,CURUN		;    too
	MOVE P4,CHNTAB+XADR(T4)	;Get address from previous xfer
	MOVE P5,CHNTAB+XDSK(T4)	;Get previous disk address
	HRRZ T2,CHNTAB+XCNT(T4)	;Get count
	SKIPGE CHNTAB+XCNT(T4)	;Was last function read?
	TXOA F,F.WRT		;No - set write bit
	TXZ F,F.WRT		;Yes
	PUSH P,T2		;Save page count
	MOVE T1,P5		;Get disk address for CHNSET
	CALL CHNSET		;Go set it up for this xfer
	POP P,T2		;Restore page count
	CALL RWCMN		;Start the xfer
	POP P,CURUN		;Restore saved values
	POP P,CURCYL
	POP P,CURSEC
	MOVSI CX,ERACS		;Setup for BLT
	BLT CX,16		;And restore ACs (NOT P!)
	MOVE CX,ERACS+CX	;Restore CX
	RET			;Done...
;CHNSET - Routine to setup channel info for I/O
;Accepts T1/ Disk address
;Returns +1 Always
;	 F/ Setup with RH device code
;	 T1/ Channel number

CHNSET:	TLZ T1,777774		;Keep just the address bits
	IDIV T1,DEVDSP+N.SCL	;Get cylinder in T1, sector in T2
	IDIV T2,DEVDSP+N.STK	;Get track in T2, sector in T3
	LSH T2,^D8		;Position the track # for DATAO
	IOR T2,T3		;Add a pinch of sector
	MOVEM T2,CURSEC		;Save sector within cylinder
	IDIV T1,DEVDSP+N.CLP	;Get unit number in T1, cyl in T2
	MOVEM T2,CURCYL		;Save it
	HRRZ P3,DSKTAB(T1)	;Get physical unit number
	MOVEM P3,CURUN		;Store it (P3 preserved for RHRD/RHWT)
	HLRZ T1,DSKTAB(T1)	;Get channel #, Entry-In-Use flag
	TRZ T1,ENTFLG		;Don't forget ENTFLG
	MOVEM T1,CURCHN		;Save for later
	HRRI F,RH0_-2(T1)	;Get IO device code
	RET

;Routine to setup the channel command list for this xfer
IOSET:	PUSH P,T2		;Save count of pages
	MOVE T3,CURCHN		;Channel number (again)
	IMULI T3,CCWSZ		;Get offset into CCW page
	ADD T3,CCWADR		;And add it in
	TXO T3,1B1		;Get jump CCW	
	MOVE T1,CURCHN		;Channel number (again)
	LSH T1,2		;Shift it
	MOVEM T3,A%EPT+ICA(T1)	;Store Jump CCW in EPT for RH20
	IOOP(CLEAR)		;Reset RH20
	CALL LKPORT		;Lock the port (if necessary)
	$ERROR(IOER11)		;Couldn't get it
	MOVX T1,R4%DCA!LR	;Desired cylinder register in RP04
	HRR T1,CURCYL		;Get cylinder
	CALL RHWT1		;Tell RP04 which cylinder
	MOVE T1,CURSEC		;Restore sector within cylinder
	PUSH P,T1		;Save disk address
	TXO T1,R4%DST!LR	;RP04 desired sector and track register
	CALL RHWT1		;Go write sector, track register
	POP P,T1		;Restore disk address
	TXO T1,.RHSBR!LR	;RH20 Block address register
	MOVE T4,CURCHN		;Get channel #
	MOVX T2,1		;Setup bit to shift
	LSH T2,@T4		;Do it
	IORM T2,IOIP		;Say xfer in progress
	CALL RHWT1		;Tell RP04 where the data is
	CALL GETPHY		;Get physical addr in T1
	 $ERROR (MEMMRF)	;Bad address
	JUMPE T1,DOPG0		;Handle separately if for page 0
	MOVE T2,(P)		;Get back count of pages
	IMUL T2,DEVDSP+N.BPP	;Make it number of blocks
	MOVEM T2,T3		;Make a copy
	IDIVI T3,^D15		;Max number of blocks in one IOWD
	SKIPE T4		;Remainder?
	AOS T3			;Yes - increment count of IOWDs needed
	MOVNS T3		;Negate it
	HRLZS T3		;Make AOBJN pointer
	MOVE T4,CURCHN		;Get channel number
	IMULI T4,CCWSZ		;Get offset into CCW page
	HRR T3,T4		;And store in AOBJN pointer
	TXO T1,1B0		;Setup Channel jump (xfer - don't halt)
IOSLP:	MOVEM T1,A%CCW(T3)	;Store address and opcode
	CAIGE T2,^D15		;Do we have more than 1 xfer's worth?
	SKIPA T4,T2		;No - use only what we have left
	MOVEI T4,^D15		;Yes - use max of 15
	SUB T2,T4		;Number of blocks remaining	
	IMULI T4,BLKSIZ		;Convert to number of words
	DPB T4,[POINT 11,A%CCW(T3),13] ;Put it into the IOWD
	ADD T1,T4		;Increment memory address
	AOBJN T3,IOSLP		;More to do?
	SETZM A%CCW(T3)		;Add halt word at end
IOSEXI:	POP P,T1		;Get count of pages
	TXNN F,F.WRT		;Is this a write?
	SKIPA T4,[.RHSTR!LR!RCLP!STLW!DTES!<-4&1777>B29!R4%CRD!GO];READ DATAO
	JRST [ 	MOVE T4,[.RHSTR!LR!RCLP!STLW!DTES!R4%CWR!GO];RH20 WRITE DATAO
		IMULI T1,-4	;Make it number of blocks
		DPB T1,[POINT 10,T4,29] ;Store count in command
		JRST .+1]	;And continue
	TSO T4,CURUN		;Set correct unit
	RET			;Return success

DOPG0:	MOVE T3,CURCHN		;Get channel number
	IMULI T3,CCWSZ		;Get it's offset into CCW page
	MOVX T1,1B0+<<LCORAD>B13> ;Setup skip word
	MOVEM T1,A%CCW(T3)	;Store it
	MOVE T1,[1B0+1B1+<1000-LCORAD>B13+LCORAD] ;Setup IOWD for rest of page
	MOVEM T1,A%CCW+1(T3)	;Store it too
	JRST IOSEXI		;And done
>				; END IFE FT.MTA
	;ROUTINES TO SAVE AND RESTORE CHANNEL
	;NOTE:  On a 2-pass load, incorrectly restoring the channel
	;	can cause PH2PIM BUGHLT's.  Incorrectly restoring the IVR
	;	can cause IOPGF's.
	;For simplicity's sake, we keep IO unit number out of IVIR register

CHNSAV:	PUSH P,T1		;SAVE T1
	PUSH P,P4		;Save P4
	HRLZI P4,-NCHAN		;Get AOBJN pointer
SAVLP:	MOVE T1,DSKTAB(P4)	;Get status of logical unit
	TLZN T1,ENTFLG		;In use?
	JRST SAVLP1		;No
   IFN FT.MTA,<	
	LSH T1,6		;Shift channel # into left half
   >
	HLRZM T1,CURCHN		;Store channel #
	CALL XIO1		;GET DEVICE CODE
	CONI .-.,T1		;GET RH20 PI ASSIGNMENT
	ANDI T1,.RHMBE+7	;KEEP JUST MASBUS ENA + PI
	HRRM T1,PIAINI(P4)	;SAVE IT
	MOVX T1,.RHIVR		;INTERRUPT VECTOR REGISTER
	CALL RHDIO		;GET ORIGINAL CONTENTS OF IVR
	ANDI T1,177777		;KEEP JUST DATA BITS
	HRLM T1,PIAINI(P4)	;SAVE IT
SAVLP1:	AOBJN P4,SAVLP		;DO ALL PHYSICAL UNITS
	POP P,P4		;Restore P4
	POP P,T1		;RESTORE T1
	RET

CHNRST:	PUSH P,T1		;SAVE 1
	PUSH P,P4		;Save P4
	HRLZI P4,-NCHAN		;Get AOBJN pointer
RSTLP:	MOVE T1,DSKTAB(P4)	;Get status of logical unit
	TLZN T1,ENTFLG		;In use?
	JRST RSTLP1		;No
   IFN FT.MTA,<	
	LSH T1,6		;Shift channel # into left half
   >
	HLRZM T1,CURCHN		;Store channel #
	HLR F,T1		;Get RH # in F
	ADDI F,RH0_-2		;Produce device code for that RH
	IOOP(CLEAR)		;RESET RH20
	MOVX T1,.RHIVR!LR	;INTERRUPT VECTOR REGISTER
	HLR T1,PIAINI(P4)	;GET INITIAL CONTENTS
	CALL RHDIO		;RESTORE THEM
	HRRZ T1,PIAINI(P4)	;GET RH20 PI ASSIGNMENT
	CALL IOXCT		;GET DEVICE CODE
	CONO .-.,.RHDON!.RHAIE(T1) ;RESTORE ORIGINAL PI ASSIGNMENT
RSTLP1:	AOBJN P4,RSTLP		;DO ALL PHYSICAL UNITS
	POP P,P4		;Restore P4
	POP P,T1		;RESTORE 1
	RET			;AND DONE
	;SUBROUTINES TO GRAB/RELEASE PORT ON DUAL-PORTED RP04567


   IFE FT.MTA,<

	;LOCK PORT - return +1 failure, +2 success
LKPORT:	SKIPN PORTLK		;Can we do it?
	RETSKP			;No, wrong device type
	ADJSP P,2		;Make room for 2 AC's
	DMOVEM T1,-1(P)		;Save T1-T2
	MOVEI T2,TIMOUT		;Timer count
	JRST LKPT2		;Skip channel clear and enter loop


	;This loop is coded this way to preserve the channel status
	;if our little nest of timeouts actually times out and we branch
	;to the ERRTYP code
LKPT1:	IOOP(CLEAR)		;No, try clearing channel and unit
	;Cover the case where an IO error or popped LAP plug has
	;caused Volume-Valid to be cleared
LKPT2:	MOVE T1,[R4%CPA!LR!GO]  ;Do pack acknowledge and attempt to seize port
	CALL RHWT1		;Send to drive
	MOVSI T1,(R4%CSR)	;Get port-status
	CALL RHRD1		
	TXNN T1,CR.DVA		;Drive available?
	JRST LKPT3		;No, try again
	MOVSI T1,(R4%DSR)	;Get device status
	CALL RHRD1
	TXNE T1,DS.PGM		;Programmable?
	TXZ T1,DS.ATA		;yes. Ignore attention status then as
				; dual-ported drives roll attentions!
	ANDI T1,DS.MSK		;Keep only appropriate bits
	CAIN T1,DS.GUD		;Drive OK?
	JRST LKPTRS		;Yes, return success
LKPT3:	SOJG T2,LKPT1		;Keep trying
	JRST LKPTR		;Timeout error, return failure


	;UNLOCK PORT - returns +1 always
UKPORT:	SKIPN PORTLK		;Can we do it?
	RET			;No, wrong device type
	ADJSP P,2		;Make room for 2 AC's
	DMOVEM T1,-1(P)		;Save T1-T2
	IOOP(CLEAR)		;Clear channel and unit
	MOVSI T1,(.TMDSR)	;Get status
	CALL RHRD1
	TXNN T1,DS.PGM		;Still in AB mode?
	JRST LKPTR		;No, so no problem with it being locked
	MOVE T1,[R4%CSR!LR!R4%REL!GO] ;Get unlock command
	CALL RHWT1		;Send to drive
	JRST LKPTR		;Return

	;Restore AC's
LKPTRS:	AOS -2(P)
LKPTR:	DMOVE T1,-1(P)		;Restore T1-T2
	ADJSP P,-2		;Back up stack pointer
	RET


	;Routine to check if the dual port is still ours
CKPORT:	SKIPN PORTLK		;Dual-ported device?
	JRST RSKP		;No, so we always have the port
	MOVSI T1,(R4%CSR)	;Get port-status
	CALL RHRD1		
	TXNN T1,CR.DVA		;Drive available?
	RET			;No, return failure
	MOVSI T1,(.TMDSR)	;Get device status
	CALL RHRD1
	;If VV is reset, we may have lost+regained port
	;if DPR is reset, we have lost port
	TXNE T1,DS.VV		;Have we lost Volume Valid?
	TXNN T1,DS.DPR		;Is drive present?
	RET			;Return failure, port ownership in question
	JRST RSKP		;Return success

;DISK DEVICE DISPATCH TABLES

DEFINE TYPTAB (NAME,INFO)  <	;CLP,SCL,STK,DOI,CSET,CRST,RTY
NAME':		..XXX=0
	IRP INFO, < EXP INFO
		    ..XXX=..XXX+1>
IFN ..XXX-TYPSZ,<PRINTX ?DSKTYP table wrong size>
>				;End TYPTAB Macro
TYPTAB (RP4TYP,<N.CLP4,N.SCL4,N.STK4,N.BKP4,DOIO,IOSET>) ;RP04
TYPTAB (RP6TYP,<N.CLP6,N.SCL4,N.STK4,N.BKP4,DOIO,IOSET>) ;RP06
TYPTAB (RP7TYP,<N.CLP7,N.SCL7,N.STK7,N.BKP4,DOIO,IOSET>) ;RP07

   >	;End IFE FT.MTA
IFN FT.MTA,<

REDPAG:	MOVE T1,[.RHSTR!LR!RCLP!STLW!<-4&1777>B29!R4%CRD!GO] ;RH20 READ DATAO
	AOS FILPAG		;INCREMENT FILE PAGE #
	PUSH P,P2		;SAVE COUNTER
	MOVEI P2,^D100		;RETRY COUNT FOR MAGTAPE
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
RWSXIT:	AOS -1(P)		;SKIP RETURN
RWFXIT:	POP P,P2		;RESTORE P2
	RET			;RETURN

;HERE TO SETUP THE CHANNEL FOR TAPE IO

TAPIO:	HRR F,CURCHN		;Get RH #
	ADDI F,RH0_-2		;Produce device code for that RH
	LDB P3,PKON		;GET TM02
	LDB T4,PCHAN		;GET CHANNEL NUMBER
	CALL XIO1		;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,CCWADR		;Get address of CCW page
	TXO T1,1B1		;Make it a channel jump
	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,A%CCW		;STORE AS FIRST ELEMENT
	MOVE T1,[EXP 1B0+1B1+<1000-LCORAD>B13+LCORAD]
	MOVEM T1,A%CCW+1	;SECOND AND LAST CCW
	JRST TAPIO2		;GO DO IO
TAPIO1:	TLO T1,(EXP 1B0+1B1+<1000>B13) ;BUILD CCW
	MOVEM T1,A%CCW		;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
;TAPE I/O SUBROUTINES
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


RHRD:	TLZ T1,(LR)		;NO WRITE
RHWT:	TSO T1,P3		;INSERT TM02
RHDIO:	CALL IOXCT		;Here to avoid insertion of unit #
	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 KLFLG
;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 GETPH1		;YES, GO TEST FOR EXTANT PAGE

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

	MAP T1,(P4)		;GET PHYSICAL PAGE NUMBER
IFN KLFLG,<
	TLNN T1,(1B2)		;IS PAGE ACCESSIBLE ?
	RET			;NO, RETURN
>				;END IFN KLFLG
	TXZ T1,MAPBTS		;YES, CLEAR ALL BITS BUT ADDRESS
	LSH T1,-^D9		;CONVERT ADDRESS TO A PAGE #
GETPH1:	CALL CHKNXM		;Go check out phys address
	RET			;N.G.
	LSH T1,9		;Shift it back to address
	RETSKP			;
; 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.

CHKNXM:	TXO T1,IMMPTR		;FORM IMMEDIATE POINTER (+WRITE+CACHE)
	PUSH P,TSTSLT		;SAVE EXISTING PAGE TABLE ENTRY
	MOVEM T1,TSTSLT		;MAP PAGE TO BE TESTED
	CLRPT TSTADD		;CLEAR PAGER ENTRY FOR TSTADD PAGE
IFN KLFLG,<
	CONO APR,AP.RNX		;TURN OFF NXM FLAG
>				;END IFN KLFLG
	SETZM PFFLG		;Zero PF flag
CHKAD:	SKIP TSTADD+20		;Reference Virtual Page
CHKDON:	HRRZ T1,TSTSLT		;Get Physical Page #
	POP P,TSTSLT		;Restore Original Map Entry
	CLRPT TSTADD		;The Gene Leache memorial instruction
				;Clear pager entry for TSTADD page
IFN KLFLG,<
	CONSO APR,AP.NXM	;NXM ON REFERENCE ?
	SKIPE PFFLG		;Did it page fail??
	SKIPA			;Yes or Yes
	JRST CPOPJ1		;NO, GIVE GOOD RETURN
	CONO APR,AP.RNX		;YES, RESET NXM FLAG
	RET			;RETURN BAD
>				;END IFN KLFLG

;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,SNAM,FNAM,DVSTS,TEXT),
<	SYM==%COUNT
	IFG SNAM,<%SNAM=%SNAM!<1B<%COUNT>>> ;;TYPE STRUCTURE NAME
	IFG FNAM,<%FNAM=%FNAM!<1B<%COUNT>>> ;;TYPE FILE NAME
	IFG DVSTS,<%DVSTS=%DVSTS!<1B<%COUNT>>> ;;TYPE DEVICE STATUS

	%COUNT=%COUNT+1
	[ASCIZ/TEXT/]
>
ERRPFX: [ASCIZ/  ?BOOT: /]

	%COUNT==0	;RESET COUNTER
	%SNAM==0		;STRUCTURE NAMES
	%FNAM==0		;FILE NAMES
	%DVSTS==0	;DEVICE STATUS

ERRTAB:	ERSTR (IOER2,1,1,1,IO error - can't read super-index block)
	ERSTR (IOER3,1,1,1,IO error - can't read index block)
	ERSTR (IOER4,1,1,1,IO error - can't read directory page)
	ERSTR (IOER6,1,1,1,IO error - can't read EXE-directory page)
	ERSTR (IOER7,1,1,1,IO error - can't read data page)
	ERSTR (IOER9,1,1,1,IO error - can't write EXE-directory page)
	ERSTR (IOER10,1,0,1,IO error - can't read root-directory index block)
	ERSTR (IOER11,0,0,1,IO error - Port-seize logic timed out)

	ERSTR (TAPHTE,0,0,1,Hard tape error)
	ERSTR (FILFNF,1,1,0,File not found)
	ERSTR (FILNEF,1,1,0,File not in EXE format)
	ERSTR (FILDRP,1,1,0,File's EXE-directory is longer than 1 page)
	ERSTR (STRHOM,1,0,0,Bad home block)
	ERSTR (STRSNF,1,0,0,Structure not found)
	ERSTR (STRNID,1,0,0,No structure ID)
	ERSTR (STRNBS,0,0,0,Can't find bootable structure)
	ERSTR (STRMTO,0,0,0,More than 1 bootable structure found)
	ERSTR (DMPFTS,0,0,0,Dump error - DUMP.EXE is too small: reconfigure with MAKDMP)
	ERSTR (COMERR,0,0,0,Command error)
	ERSTR (COMUNS,0,0,0,Unknown switch)
	ERSTR (COMINV,0,0,0,Invalid numeric value)
	ERSTR (MEMMRF,0,0,0,Memory reference failed)
	ERSTR (TAPNDR,0,0,0,No ready tape-drive available)
	%SNAM==%SNAM		;FORCE INTO LISTING
	%FNAM==%FNAM
	%DVSTS==%DVSTS
;SUBROUTINE TO CLEAR CORE

CLRCOR:	SETOI P4,		;INITIALIZE ADDRESS
CLR.NP:	ADDI P4,1000		;NEXT PAGE
	TLNE P4,-1		;DONE 256K?
	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

	;This test is to protect against zeroing DDT (when loaded)
IFN BDEBUG,<
	CAIL T1,<DDTPG1_9>	;Is this page within the DDT interval?
	CAILE T1,<DDTPGL_9>	;...
	SKIPA			;No
	JRST CLR.NP		;Yes, lets not wipe DDT
	>			;End IFN BDEBUG

	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:	SETZM MONFLG		;INDICATE NO SPECIAL ASSUMPTIONS ABOUT FILE
	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

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

; EXE BLOCK TYPE DISPATCH TABLE

EXETAB:	.EXDIR ,, G.DIR
	.EXEND ,, R
	.EXENT ,, G.ENT
	.EXPDV ,, G.PDV
	EXESIZ==.-EXETAB

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

GET:	IFN FT.MTA,<		;ONLY FOR MAGTAPE
	SETOM XBNUM		;Only "short" files on mag tape
	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
	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:	TXZ F,F.PHYS		;ASSUME VIRTUAL ADDRESS
	SKIPG MONLOD		;DON'T DO THIS IF NOT FIRST PASS OF LOAD
	CAIG P4,777777		;IS THIS PAGE BEYOND OUR 1-SECTION
				; VIRTUAL SPACE?
	JRST G.DIR8		;NO
	TXO F,F.PHYS		;YES, CONSIDER IT PHYSICAL
	
G.DIR8:	JUMPE Q1,G.DIR4		;ALL ZERO PAGE, HANDLE SPECIALLY
	MOVEI T1,TSTADR		;ASSUME THIS IS OUR CHECK ROUTINE
	TXNE F,F.PHYS		;ARE WE WRITING TO A PHYSICAL PAGE?
	MOVEI T1,GETPHY		;YES, USE THIS ROUTINE
	CALL (T1)		;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

	SKIPGE XBNUM		;Long or short file?
	JRST LODPAG		;Short, we always have correct XB
	LDB T1,[POINT 18,Q1,26]	;Get index-block # for this file page
	CAMN T1,XBNUM		;Correct XB currently loaded?
	JRST LODPAG		;Yes
	LOAD P5,IDXADR,A%SXB(T1) ;No, get the disk address of the correct one
	SKIPG P5		;Do we have an address?
	 $ERROR(FILNEF)		;EXE directory data and super-index block
				; do not agree
	MOVEM T1,XBNUM		;Set up XB # for soon-to-be loaded XB
	PUSH P,P4		;Save P4
	PUSH P,F		;Save flags
	TXZ F,F.PHYS		;Do virtual read for XB
	MOVEI P4,A%XB		;Load XB here
	CALL REDPAG		;Load it
 	 $ERROR(IOER3)		;Failed
	POP P,F			;Recover F
	POP P,P4		;Recover P4	
LODPAG:	MOVE T1,Q1		;Get file page number
	ANDI T1,777		;Keep only section-relative page #
	MOVE P5,A%XB(T1)	;GET DISK ADDRESS FROM INDEX BLOCK
	CALL REDPAG		;READ A DATA PAGE FROM EXE FILE
	 $ERROR (IOER7)		;ERROR READING PAGE
	JUMPN P4,G.DIR2		;PAGE ZERO?
	SKIPN MONLOD		;PASS ZERO?
	CALL CHKPG0		;YES
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:	MOVEI T1,TSTADR		;ASSUME THIS IS OUR CHECK ROUTINE
	TXNE F,F.PHYS		;ARE WE WRITING TO A PHYSICAL PAGE?
	MOVEI T1,GETPHY		;YES, USE THIS ROUTINE
	CALL (T1)		;GO SEE IF MEMORY ADDRESS IS LEGAL
 	  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

COMMENT %
	Used to analyze errors in page selection/rejection logic.
	Can get a bit tedious on 2-pass loads

	;Routine to report when we couldn't or wouldn't load a page
LODERR:	PUSH P,Q1		;Save the Q's
	PUSH P,Q2
	PUSH P,Q3
	CALL CRLF
	MOVE Q2,ERRPFX
	CALL OUTSTR
	MOVEI Q2,[ASCIZ/Failed to load file page /]
	CALL OUTSTR
	MOVE Q2,-2(P)		;Get file page from saved copy of Q1
	CALL OUTOCT		;Output it
	MOVEI Q2,[ASCIZ/ to memory page /]
	CALL OUTSTR
	MOVE Q2,P4		;Get process page
	LSH Q2,-9		;Convert to page
	CALL OUTOCT		;Output it
	CALL CRLF		;Terminate line
	POP P,Q3		;Restore Q's
	POP P,Q2
	POP P,Q1
	RET		%	;End comment
	;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)		;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

	;Here to process PDV block
G.PDV:	HRRZ T1,(P1)		;GET SIZE OF PDV BLOCK
	ADD P1,T1		;UPDATE POINTER INTO EXE DIRECTORY
	JRST G.DSP		;GO HANDLE NEXT EXE FILE BLOCK



	COMMENT %
Routine to read memory page zero of .EXE file and set BOOT parameters
accordingly.

This routine has 2 different behaviors, depending on the version number of
the monitor.  In V6 and later monitors, this routine reads data from
the BOOT communications region in the .EXE file and sets various BOOT
parameters.

For older monitors, or non-monitor .EXE files, BOOT behaves as follows:

If .JBSYM is non-zero, BOOT will not load in any pages above the
end of the symbol table, unless specific page-limits are specified in
the command.  BOOT uses this feature to load only that portion of the
monitor up to the end of the symbols.  MEXEC will then specify a page-range
in order to get the swappable monitor loaded.

	%	;End comment

CHKPG0:	MOVE T1,BUTCOD		;Get the code
	CAME T1,[BTCOD]		;Correct?
	JRST CHGLIM		;No, older-style load
	LDB T1,[POINT 6,137,11]	;Get the major version
	CAILE T1,M%MAJ		;Above the threshold version?
	JRST SETLIM		;Yes, do new-style load
	CAIE T1,M%MAJ		;At the threshold version?
	JRST CHGLIM		;No, older-style load
	LDB T1,[POINT 6,137,17] ;Get the minor version
	CAILE T1,M%MIN		;The threshold minor version?
	JRST SETLIM		;Above it, do new-style load
	HRRZ T1,137		;Get the edit number
	CAIGE T1,M%EDT		;The threshold edit?
	JRST CHGLIM		;No, older-style load

SETLIM:	MOVE T1,BUTLLM		;Get the lower load limit
	MOVEM T1,LWRLIM		;Set it
	MOVE T1,BUTULM		;Get the upper load limit
	MOVEM T1,UPRLIM		;Set it
	RET

CHGLIM:	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
IFE FT.MTA, <
;Routine called to write the DUMP.EXE file on the structure pointed to
;by STRNAM
SAVE:	MOVE Q2,MSGHDR		;Get message header
	CALL OUTSTR		;Display it
	MOVEI Q2,[ASCIZ/DUMPING] /]
	CALL OUTSTR		;Write out something to make me feel good
	MOVEI T1,NDMPM		;Get report limit for dump errors
	MOVEM T1,DERCNT		;Keep it here
	SETZM XBNUM		;XB #0 already mapped
	SETZM IOCNTR		;Count of number of calls to WRTPAG
	SETZM PGCNTR		;Count of number of pages written
	SETZM A%FP0		;Zero out directory page 
	MOVE T1,[A%FP0,,A%FP0+1]; ...
	BLT T1,A%FP0+777	; ...
	SETOM A%FP0		;Flag to say directory page not created yet
	TXO F,F.PHYS		;Say we are using physical addresses
	SETZM T1		;Start at page 0
SAV.LP:	PUSH P,T1		;Save starting physical page number
	CALL GETPGS		;Go get set of contiguous pages
	SKIPN T2		;Anything to write?
	JRST [	POP P,T1	;Get back page we started with
		AOS T1		;Do next page
		JRST SAV.EX ]	;
	LSH P4,^D9		;Shift page number to an address
	PUSH P,T2		;Save number of pages to write
;Have to check here if T2.G.1020. pages. If so - have to make several
;write requests - currently impossible, as no disks have cylinders that large
	CALL WRTPAG		;Go write the pages
	POP P,T2		;Get back count of pages
	POP P,T1		;Starting page number
	CALL MAKDIR		;Set up dir page info
	AOS IOCNTR		;Increment counter of IO requests
	ADDM T2,PGCNTR		;Count up how many pages we have written
	ADD T1,T2		;Get address of first page in next group
SAV.EX:	CAMLE T1,HIADDR		;Higher than we have?
	JRST WRTDIR		;Yes - done, go write out directory page
	CAMGE T1,DEXEPC		;Is there room in the file for another page?
	JRST SAV.LP		;Yes - go get next set
	TXO F,F.DPER		;No - say so
	JRST WRTDIR		;Write directory page and finish up
;GETPGS - Get a set of contiguous pages to write out
;Accepts T1/ Physical page to start checking at
;
;Returns +1   P4/ Physical memory page to start writing
;	      T2/ Number of pages to write
;	      P5/ Disk address to write to
;
;Use of ACs herein:
;		T1 - Physical page we are checking out
;		T2 - Current cylinder
;		T3 - Current sector - to check if it is contiguous
;		T4 - Offset into index block
;		P1 - Copy of T1 at call, incremented each time thru loop
;			this value is passed to CHKADR
;		P2 - Number of pages to write
;		Q3 - Last page address returned by CHKADR
;			this value is used to compare against the next
;			value returned by CHKADR, to see if we have
;			consecutive pages

GETPGS:	PUSH P,T1		;Save physical page we are looking at
	AOS T4,T1		;Increment it and move to T4
	LSH T1,-^D9		;Determine which XB is needed
	CALL MAPXB		;And go get it
	POP P,T1		;Get back physical page we are looking at
	SETZM P2		;Zero out page counter
	ANDI T4,777		;Keep just low order bits
	LOAD T2,IDXADR,A%XB(T4) ;Get disk address for this page
	SKIPN T2		;Real disk address?
	 RET			;No - can't write this page
	PUSH P,T2		;Save disk address to write
	MOVEM T1,P1		;Store physical page number to check out
	CALL CHKADR		;See if we should write page in T1 or
				; if CHKADR tells us to write some other page
	 JRST DONE		;Can't write this page
	AOS P2			;Increment page counter
	JUMPE T1,[ MOVEM T1,Q3	;If this is page 0 write it out separately
		   JRST DONE]	;
	IDIV T2,DEVDSP+N.SCL	;Isolate cyl/sect in T2/T3
CHKNXT:	MOVEM T1,Q3		;Save page number returned by CHKADR
	AOS T1,P1		;Determine next page to check out
	CAMLE T1,HIADDR		;Higher than we have?
	JRST DONE		;Yes - done with this group
	AOS T4			;Increment XB index
	CAILE T4,777		;Are we into next XB yet?
	CALL NEXTXB		;Go get next XB
	LOAD Q1,IDXADR,A%XB(T4) ;Get disk address for next page
	SKIPN Q1		;Real disk address?
	JRST DONE		;No - can't write this page
	IDIV Q1,DEVDSP+N.SCL	;Get Sec/Cyl in Q1/Q2
	CAME Q1,T2		;Same cylinder?
	JRST DONE		;No - can't add this page to group
	ADD T3,DEVDSP+N.BPP	;Add number of blocks per page
	CAMN Q2,T3		;Same sector?
	CALL CHKADR		;See if page is OK to write
	JRST DONE		;Don't write out this page
	CAIE T1,1(Q3)		;Is this the next contiguous page?
	JRST DONE		;No - don't write it out then
	AOJA P2,CHKNXT		;Add this page to group and check next page

;Done with this group - return proper arguments
DONE:	MOVE P4,Q3		;Get starting page number to write out
	SUBI P4,-1(P2)		; by subtracting amount-1 from last page
	MOVE T2,P2		;Get number of pages to write
	POP P,P5		;Get starting disk address
	RET

;CHKADR - Routine to determine if page should be written out
;It may return the address of another page to write out, as in the
;case where BOOT has moved itself and saved what it clobberred. In this
;case, CHKADR returns the page number of the page that SHOULD be in
;the page we have called CHKADR to check out (i.e. the page that should
;be written out in the place of this page)
;Called with T1/ Phys. Memory address
;Returns +1/ Don't write this page
;	 +2/ Write a page (may not be the page in the call)
;		T1/ Phys. Memory address to write
CHKADR:	CAML T1,LODBAS		;Where BOOT landed?
	CAMLE T1,MCEPAG		;In microcode pages?
	SKIPA			;No - continue
	RET			;Yes - don't write it yet
	CAML T1,TOPBAS		;Where BOOT now resides?
	CAMLE T1,TOPTOP		;...
	JRST CHKRET		;No - continue
	SUB T1,TOPBAS		;Get offset into source area
	ADD T1,LODBAS		;  and return the address of page that should
				;  be written out in it's place
CHKRET:	CALL CHKNXM		;See if page OK - NXM etc...
	RET			;No - return bad
	RETSKP			;Address is good
NEXTXB:	PUSH P,T1		;Save T1 over call
	MOVE T1,XBNUM		;Get current XB
	AOS T1			;Increment it for next one
	CALL MAPXB		;Map in next
	POP P,T1		;Get Back T1
	SETZM T4		;Reset XB index
	RET			;Return

;MAPXB T1/ Number of XB we want - clobbers T1
MAPXB:	CAMN T1,XBNUM		;Is the one we want here?
	RET			;Yes - return
	PUSH P,T1
	PUSH P,T2
	PUSH P,T3
	PUSH P,T4
	MOVEM T1,XBNUM		;Store number of new XB
	LOAD P5,IDXADR,A%SXB(T1);Get disk address
	MOVEI P4,A%XB		;READ INTO XB PAGE
	TXZ F,F.PHYS		;Read a virtual page
	CALL REDPAG		;Go do it
	 $ERROR (IOER3)		;ERROR READING PAGE
	TXO F,F.PHYS		;Back to physical addressing
	POP P,T4
	POP P,T3
	POP P,T2
	POP P,T1
	Ret 			;And done
;MAKDIR - Routine to add an entry to the Dir page of the EXE file
;Called with T1/ Physical page number we just wrote
;	     T2/ number of pages we just wrote
;Returns +1 OK

MAKDIR:	SKIPG T3,A%FP0		;Have we started dir page yet?
	JRST NEWENT		;No - make first entry
	HRRZ Q1,A%FP0+1(T3)	;Get last process page written
	LOAD Q2,RPT,A%FP0+1(T3)	;Get repeat count of this entry
	ADD Q1,Q2		;Increment it to see
	CAIE Q1,-1(T1)		; if we have a contiguous set
	JRST NEWENT		;No - go write new entry
	ADD Q2,T2		;Does this group make
	CAIL Q2,1000		; it too big?
	JRST NEWENT		;Yes - new entry
MAKDON:	STOR Q2,RPT,A%FP0+1(T3)	;No - increment count
	RET			; And done...

NEWENT:	ADDI T3,.DRSIZ		;Increment index
	CAIL T3,PGSIZ		;Have we exceeded max size of directory page?
	 $ERROR(FILDRP)		;Yes - report it
	MOVEM T3,A%FP0		;And save for next time
	HRRM T1,A%FP0(T3)	;Save file page number to write
	AOS A%FP0(T3)		;Increment it...
	MOVEM T1,A%FP0+1(T3)	;Store process page number 
				; (physical page address)
	MOVEM T2,Q2		;Get number of pages
	SOS Q2			;Decrement for repeat count
	JRST MAKDON		;And finish

;WRTDIR - Finish directory page and write it out

WRTDIR:	MOVEI T1,2		;Increment size of directory block
	ADDM T1,A%FP0		; ...
	MOVEI T1,.EXDIR		;Get directory block type
	STOR T1,DIDIR		;Store In EXE Directory
	HRRZ Q3,A%FP0		;Get size
	ADDI Q3,A%FP0		;Get offset into page
	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
	SETZM T1		;Say we want XB 0
	CALL MAPXB		;And go get it mapped
	LOAD P5,IDXADR,A%XB+0	;Write out Page 0 of file
	SKIPN P5		;Complain if no Page zero
	 $ERROR (FILNEF)	;No page 0
	MOVEI P4,A%FP0		;Get core address of EXE directory
	MOVEI T2,1		;Say just write one page, please
	CALL WRTWAT		;Write directory page and wait for completion
	 $ERROR(IOER9)		;Error writing directory page
	CALL CHKIO		;Wait until all I/O has completed
	TXZE F,F.DPER		;Dump error?
	 $ERROR (DMPFTS)	;Yes - DUMP.EXE too short
	MOVEI Q2,[ASCIZ/[OK]
/]
	TXZN F,F.IOER		;Don't say OK if there were errors
	CALL OUTSTR
	MOVEI Q2,[ASCIZ/
  Number of pages written: /]
	CALL OUTSTR		;Output it
	MOVE Q2,PGCNTR		;Get number of pages
	CALL OUTOCT		;Output it
	MOVEI Q2,[ASCIZ\
  Number of I/O requests: \]
	CALL OUTSTR		;...
	MOVE Q2,IOCNTR		;Get it
	CALL OUTOCT		;Output it
	CALL CRLF
	RET			;ALL DONE
DMPERR:	SOSG DERCNT		;HAVE WE REACHED THE REPORT LIMIT?
	POPJ P,			;YES, RETURN
	PUSH P,Q1		;SAVE OUR AC'S
	PUSH P,Q2
	PUSH P,Q3
	TXO F,F.IOER		;INDICATE A WRITE ERROR OCCURRED
	MOVE T1,DERCNT		;GET THE LIMIT
	CAIN T1,NDMPM-1		;FIRST TIME THROUGH?
	CALL CRLF		;YES
	MOVE Q2,ERRPFX		;GET THE ERROR PREFIX
	CALL OUTSTR		;OUTPUT IT
	MOVEI Q2,[ASCIZ/IO error while dumping page:  /]
	CALL OUTSTR		;OUTPUT IT
	MOVE T1,CURCHN		;Get current xferring channel 
	IMULI T1,4		;4 words per channel logout area
	LDB Q2,[POINT 13,A%EPT+2(T1),26];Get address of page 
	CALL OUTOCT		;OUTPUT IT
	CALL CRLF		;OUTPUT A CRLF
	CALL OUTSTS		;OUTPUT CHANNEL/DEVICE STATUS
	POP P,Q3		;RESTORE AC'S
	POP P,Q2
	POP P,Q1
	POPJ P,			;RETURN
>				; END IFE FT.MTA
>				; 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:

;This code is executed in the AC's near GOTCOR.
;	P2/ address of first word to be moved from low end to high
;	P3/ address of first word to be moved from high end to low
;	P4/ number of words to move

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
  MVCLEN==MOVEND-BOTMOV		;Length of moving code (-1)

;PAGE FAULT HANDLER UNTIL AFTER BOOT IS MOVED

PAGTRP:
IFN KLFLG,<
	AOS CODEND-ENT+UPTPFO(16) ;THE PC OF THE PAGE FAIL
	JRST @CODEND-ENT+UPTPFO(16) ;PROCEED
>				;END OF IFN KLFLG

>				;END IFN FT.PRT&2
	BLOCK <1000-<.&777>>	;LEAVE SPACE FOR TEMPORARY EPT
;This code interfaces with the V6 KDDT and also allows BOOT's timeshareing
;core image to be mapped to high-core (so that the symbols can be used) and
;unmaps the pages when ^Z is typed to KDDT (again, in user mode).
;BOOT knows nothing about this code, and it is not moved when BOOT moves
;to high core.  It should be remembered that future monitor changes might
;cause the resident monitor to overlay this code (and, indeed, KDDT itself).

IFN BDEBUG,<
	.PSECT MAPCOD,DDTPRE	;Linked on first page preceding DDT

	EXTERN DDTX
	MSEC1==:1		;KDDT wants this

DDTENT:	XSFM PCSTOR		;Get PC flags
	EXCH T1,PCSTOR		;Get the flags
	TXNN T1,1B5		;User mode?
	JRST EXEC		;No

	;Here in user mode
	MOVE T1,[.FHSLF,,<ENT_-9>+1]
	MOVE T2,[.FHSLF,,<A%CODE>_-9]
	MOVE T3,[PM%RD!PM%WR!PM%EX!PM%CNT!A$CODE]
	PMAP
	JRST DDTX		;Enter KDDT in user mode

	;Here if in EXEC mode
EXEC:	SKIPE EFLAG		;First time through?
	JRST EXEC1		;No
	;1'st time through preamble
	MOVE T1,116		;Get pointer to symbol table
	MOVEM T1,SYMTAB		;Save symbol table pointer
	JRST DDTGO		;Prepare to enter KDDT
	;N'th time through preamble
EXEC1:	MOVE T1,SYMTAB		;Get symbol table pointer
	MOVEM T1,116		;Restore it		

DDTGO:	MOVE T1,PCSTOR		;Recover contents of T1
				;Very important if he has restarted DDT
	SETOM EFLAG		;Indicate we have been through preamble
	JRST DDTX		;Enter KDDT in exec mode

				

	;Here after exiting EDDT in user mode with ^Z
	;We are guaranteed to get here only in user mode
DDTCZ::	SETOM T1		;Unmap the pages
	MOVE T2,[.FHSLF,,<A%CODE>_-9]
	MOVE T3,[PM%RD!PM%WR!PM%EX!PM%CNT!A$CODE]
	PMAP
DDTEX:	HALTF
	JRST DDTENT

	;Storage for DDT preamble code
PCSTOR:	Z			;Storage for PC flags
EFLAG:	Z			;Nonzero means we have been here before
SYMTAB:	Z			;Place to save symbol table pointer

	Z
	Z
	LIT
PATCH:	BLOCK <777-<.&777>>	;Our patch area

	>			;End IFN BDEBUG


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