Google
 

Trailing-Edge - PDP-10 Archives - bb-bt99m-bb - boot.mac
There are 59 other files named boot.mac in the archive. Click here to see a list.
UNIVER	BTSPRM - PARAMETER FILE FOR DECSYSTEM-10 BOOTSTRAP
SUBTTL	D. MASTROVITO /DPM/JAD	31-DEC-87


;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1980,1981,1982,1983,1984,1985,1986,1987.
;ALL RIGHTS RESERVED.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.


	BOOWHO==0		;WHO EDITED
	BOOVER==4		;MAJOR VERSION NUMBER
	BOOMIN==0		;MINOR VERSION NUMBER
	BOOEDT==72		;EDIT NUMBER
	%%BTS==<BYTE(3)BOOWHO(9)BOOVER(6)BOOMIN(18)BOOEDT>
IFDEF .MCRV.,<.VERSION <%%BTS>>
	SUBTTL	REVISION HISTORY


COMMENT `

Version 1

1   05-Feb-80	Add the /REBOOT switch and support for system sleep.
2   15-Jun-80	Change the default filename for /REBOOT from SYSTEM to
		CRASH.
3   05-Jul-80	Change the definitions of APRRST and CLRAPR for the
		KS10 to reflect empirical evidence (i.e. make it work)
4   05-Jul-80	After powerup, the KS10 wants a WREBR 0 before the
		WREBR to set the EBR.  I'm not sure why it's true or
		why it works but it fixes the ?PAR ERR's.
5   07-Feb-81	Add the /EDDT switch to be equivalent to /START:401.

Version 2

6   06-Jun-81	Add conditinal assembly for KL paging.
7   01-Oct-81	Fix typo that caused BOOT to give up on a structure
		if the first HOME block was bad even if the second one
		was OK.
10  01-Oct-81	Make it possible to load the DX20/RP20 microcode with
		BOOT and pass the physical address of the loaded
		microcode to the monitor when it is started.
11  16-Feb-81	Fix a problem with finding 18 bit DF10s.  This fix was
		only installed in maintenance versions since DF10s
		aren't supported with the next field release of BOOT.
		The result is no code change is this source.
12  25-Apr-82	Remove the FTKI10 conditionals and the code that they
		surround.
13  19-Aug-82	More of edit 7.
14  08-Mar-83	Can't boot a KS if one of the drives is dual ported.
		See MCO 10633.
15  08-Jul-83	Fix a typo introduced by edit 6 which causes MUUO EA to
		get printed incorrectly on a trap other than page fail.
16  11-Jul-83	Cause version number to be in .JBVER and the EXE file.
17  22-Nov-83	Be sure to put copyright in a format that is readable
		once the '11 gets the .EXB file
Version 3

20  12-Aug-84	Teach BOOT how to do KL-paging on the KS.  Also, include
		CJA's support for silent switch boot.  (Expanded for KL)
		Process ^R in GETLIN since it fits in all assemblies.

21  26-Sep-84	Remove FTKLP conditionals.  Defend against KLIPAs and KLINIs.

22  31-Oct-84	Merge 702+ and 703 versions together.  Add SAVE. UUO to loader.

23   9-Dec-84	Completely rewrite microcode loader.  Include in it code to
		write .EXB files for KL10s.

24  10-Dec-84	Propagate monitor filespec across monitor/bootstrap reloads
		so typing just optional switches and/or CRLF will reload the
		old monitor instead of DSK:SYSTEM.EXE[1,4].

25  11-Dec-84	Add code to scan the SDL for structures on which to dump.
		Add /FORCE to load from DSKA-DSKZ instead of the SSL or
		dump to DSKA-DSKZ instead of the SDL.  /FORCE is implied if
		either the SSL or SDL is empty on the appropriate operations.

26  13-Dec-84	Preserved ASL entries are now one word per unit.

27  18-Dec-84	Make SSL, ASL, and SDL words contain -LENGTH,,OFFSET to the
		desired preserved data.

30   4-Jan-85	Fix filespec defaulting problems for dump operations.

31  21-Jan-85	Prevent DTE reloads by not clobbering the APR.

32   2-Apr-85	Make BOOT work on a KS10.  Add BTSPRM universal.  Rework
		microcode loader to convert files directly into binary.

33  16-Apr-85	Check validity of data page at the start of COPDAT.

34  22-Apr-85	BOOT hangs on KS10 because KLINIK command word left non-zero
		by the loader's SAVE. UUO, and the KS10 8080 code is irrational

35  24-Apr-85	KS10s don't like XJRST.

36  25-Apr-85	Add system sleep and page replacement support.

37  01-May-85	Fix up some problems with /REBOOT after system sleep.
		BOOT will now reload in place, after checking that enough
		core was reserved for it.
40  19-Jul-85	Don't attempt to save/restore the PI system state.  The
		monitor already does this, and we can lose pending inter-
		rupts if we clear the PI system (causing KAF after taking
		a dump).

41  15-Aug-85	Do Copyrights./LEO

42  15-Nov-85	Forcibly halt internal channel devices when BOOT is started
		(KLNI and KLIPA).  Re-arrange the vector so it is easily
		expanded without causing monitor/BOOT skews.  Preserve
		cache strategy from KLI on the KL, and add a word for
		saving the cache strategy across reloads/CPU restarts.
		Add code from 7.02 MONBTS to save/restore KS UBA mapping
		registers around calls to BOOT.

43  25-Nov-85	Fix bug in EXBDAT which would drop a few words at the end
		of the .EXB file.  Don't create .EXB file for KS BOOT.
		Conditionalize the UCODES entries so we don't ask about KL
		microcodes on a KS, and vice versa.

44   1-Dec-85	More work to get BOOT to work on the KS.  Retrieve code
		from 7.02 MONBTS to save UBA status during R11INI and
		ditto for RH20 status during R12INI.

45  17-Dec-85	Don't default on system sleep dump function.  If can't
		dump for some reason just ask where to dump rather than
		asking if they want to keep the dump.

46  18-Dec-85	Remove the need for BOOTM by teaching BOOT about magtapes.
		(Unsupported) code is under the FTTAPE conditional, which
		is OFF in the distributed version.

47   7-Jan-86	Get version number from the "correct" place in .ULD files.

Start of version 3A

50  19-Jun-86	Remove crocks about loading high segments following low
		segments and just load into the physical pages specified
		by the .EXE directory.

51  18-Nov-86	Save the IA/IVIR registers at R12INI and restore on exit.
		Not restoring the registers can lead to UIL stopcodes if
		the device interrupts and picks up a zeroed EPT index.

Start of version 4

60  18-Nov-86	Turn on FTTAPE conditional so we can get rid of BOOTM for
		the 7.04 release.

61   4-Mar-87	Modify REFMEM to detect memory interleaving errors.  This
		is in preparation for removing similar code in SYSINI so
		the monitor starts up faster.

62   5-Mar-87	Inform the user when the monitor extends into BOOT rather
		than just reporting "memory too complex".

63   6-Mar-87	To aid monitor debugging, report the function code on
		"Illegal function code" errors.

64  16-Mar-87	Rebuild NXMTAB on RESTART or REBOOT functions.  NXMTAB from
		the monitor is incorrect, as it is not a table of non-existant
		pages, but a table of pages the monitor wants to hide from
		itself.

65   6-May-87	Make microcode text more descriptive.  Change KLIPA/CI
		to CI20 and KLNI/NI to NIA20.

66   8-Jun-87	Fix bug in compare logic that prevented us from ever restarting
		a suspended monitor.  Must also throw away tape drivers at
		this time so we use the adjusted size of bootstrap.

67  28-Jul-87	Fix asking/defaulting of questions to avoid hanging in
		automatic dump/reload of monitor.  If we can't do the dump,
		punt it.

70   4-Aug-87	Fix system sleep to mark the suspended system as a dump.
		This way, we won't overwrite it by accident with a useless
		STOPCD dump.  Requires edit 53 to CRSCPY.

71  28-Dec-87	Use a word in the bootstrap vector to store the software
		incarnation level of the host's SCA interface.

72  31-Dec-87	Fix RSTHDW to properly restore the DTE20 status.

`
	SUBTTL	MICROCODE STORAGE DEFINITIONS

; THIS MACRO DEFINES THE MICROCODE STORAGE DATA BASE FOR BOOT.  DUMMY
; ENTRIES IN THE MACRO ALLOW UPWARD AND DOWNWARD COMPATIBILTY BETWEEN
; VERSIONS OF THE MONITOR AND BOOT.  AS NEW MICROCODES ARE ADDED, THE
; DUMMY ENTRIES ; SHOULD BE REMOVED.  DUMMY ENTRIES RESERVED FOR DEC
; ARE LABELED 'DEC'.  THOSE FOR CUSTOMERS ARE LABELED 'CST'.  ALSO, WHEN
; ADDING NEW MICROCODES, MAKE SURE THE DESCRIPTIVE TEXT IS PADDED OUT TO
; THE FULL 19 CHARACTERS.  THIS IS USED BY THE MICROCODE LOADER IN BOOT
; AND MAKES FOR A PRETTY DISPLAY.

DEFINE	UCODES,<

;; L,PFX, NAME ,EXT,DESCRIPTIVE TEXT	 , MODE ,MAXIMUM-SIZE
X (FTKL10,TX1,DXMPA ,A8 ,<DX10/TX01 microcode>,.IOASC,<10000/3>)
X (FTKL10,TX2,DXMCA ,ADX,<DX20/TX02 microcode>,.IOASC,<2000+400+^D32+1>)
X (FTKL10,RP2,DXMCD ,ADX,<DX20/RP20 microcode>,.IOASC,<2000+400+^D32+1>)
X (FTKL10,KLP,KLPCOD,ULD,<CI20 microcode     >,.IOASC,<<10000*^D60+^D35>/^D36>)
X (FTKL10,KNI,KNICOD,ULD,<NIA20 microcode    >,.IOASC,<<10000*^D60+^D35>/^D36>)
X (0,UNA,DEUCOD,ULD,<DEUNA/NI microcode >,.IOASC,<<10000*^D60+^D35>/^D36>)
X (0,   ,DUMMY ,DEC,<0>)
X (0,   ,DUMMY ,DEC,<0>)
X (0,   ,DUMMY ,DEC,<0>)
X (0,   ,DUMMY ,DEC,<0>)
X (0,   ,DUMMY ,DEC,<0>)
X (0,   ,DUMMY ,CST,<0>)
X (0,   ,DUMMY ,CST,<0>)

>
DEFINE	X	(L,PFX,NAM,EXT,TXT,MOD,SIZ),<
	IFNB <PFX>,<.BT'PFX==ZZ>
	ZZ==ZZ+2
	IFL ZZZ-<SIZ>,<ZZZ==SIZ>
>

	ZZZ==<ZZ==0>
	UCODES
	UCDNUM==ZZ_-1
	UCDSIZ==ZZZ

	PURGE	ZZ,ZZZ
	SUBTTL	ENTRY VECTOR

; THIS IS THE ACTUAL BOOTSTRAP ENTRY VECTOR.  NOTE THAT THE
; MICROCODE OFFSET DEFINITIONS (FROM THE UCODES MACRO) INDEX
; INTO A STATIC BLOCK INSIDE THE VECTOR RATHER THAN BEING ABSOLUTE
; OFFSETS INTO THE VECTOR ITSELF.  THIS ALLOWS FOR SKEWS BETWEEN
; THE MONITOR AND BOOT WHEN NEW MICROCODES ARE ADDED.

	 .ORG	0

.BTVEC:!			;START OF VECTOR
.BTNAM:! BLOCK	1		;SIXBIT /BOOT/
.BTSIZ:! BLOCK	1		;XWD -SIZE IN PAGES, SIZE IN WORDS
.BTVER:! BLOCK	1		;BOOT VERSION
.BTSTA:! BLOCK	1		;BOOT START ADDRESS
.BTDDT:! BLOCK	1		;DDT START ADDRESS
.BTBPT:! BLOCK	1		;UNSOLICITED BREAKPOINT ADDRESS
.BTSYM:! BLOCK	2		;POINTER TO SYMBOL TABLES
.BTFLG:! BLOCK	1		;FLAGS
.BTFNC:! BLOCK	1		;SUBROUTINE FUNCTION CODE
.BTDAT:! BLOCK	1		;SUBROUTINE OFFSET TO DATA STORAGE
.BTDSP:! BLOCK	1		;SUBROUTINE DISPATCH OFFSET
.BTXPC:! BLOCK	4		;SUBROUTINE XPCW ENTRY POINT
.BTACS:! BLOCK	2		;SUBROUTINE STORAGE FOR CALLER'S ACS 16 AND 17
.BTUCD:! BLOCK	UCDNUM*2	;MICROCODE STORAGE POINTERS (TWO WORD PAIRS)
.BTMSZ:! BLOCK	1		;OFFSET TO SIZE OF MEMORY IN P
.BTNXM:! BLOCK	1		;-LENGTH,,OFFSET TO NXMTAB
.BTCPN:! BLOCK	1		;CPU NUMBER OF CPU INVOKING BOOT
.BTCUS:! BLOCK	4		;4 WORDS FOR CUSTOMER USE
.BTSIN:! BLOCK	1		;SCA SOFTWARE INCARNATION NUMBER
				;*** ADD NEW NON-PRESERVED VARIABLES HERE ***
	.ORG	100		;LEAVE SOME ROOM FOR FUTURE EXPANSION
.BTSVB:!			;BEGINING OF PRESERVED DATA
.BTSAV:! BLOCK	1		;NUMBER OF PRESERVED WORDS
.BTDEV:! BLOCK	1		;DEVICE
.BTFIL:! BLOCK	1		;FILE NAME
.BTEXT:! BLOCK	1		;EXTENSION
.BTPTH:! BLOCK	7		;PATH (PLUS ZERO TERMINATING WORD)
.BTSSL:! BLOCK	1		;-LENGTH,,OFFSET TO SSL
	 BLOCK	^D36		;SYSTEM SEARCH LIST
.BTASL:! BLOCK	1		;-LENGTH,,OFFSET TO ASL
	 BLOCK	^D8		;ACTIVE SWAPPING LIST
.BTSDL:! BLOCK	1		;-LENGTH,,OFFSET TO SDL
	 BLOCK	^D36		;SYSTEM DUMP LIST
.BTSCS:! BLOCK	1		;SAVED CACHE STRATEGY (KL)
				;*** ADD NEW PRESERVED VARIABLES HERE ***
.BTSVE:!			;END OF PRESERVED DATA
.BTVCE:!			;END OF VECTOR

.BTVLN==<.BTVCE+777>_-11	;LENGTH OF VECTOR IN PAGES

	 .ORG


	PRGEND
TITLE	BOOT - DECSYSTEM-10 BOOTSTRAP
SUBTTL	G.M. UHLER/GMU/DPM	04-AUG-87


	SEARCH	BTSPRM
	SEARCH	JOBDAT
	SEARCH	UUOSYM

	SALL
	.DIRECTIVE FLBLST

IFNDEF	FTKL10,<FTKL10==-1>
IFNDEF	FTKS10,<FTKS10==0>
IFNDEF	FTTAPE,<FTTAPE==-1>	;INCLUDE BOOTM EMULATION IF NON-ZERO

IF1,<
  IFN FTKL10,<PRINTX [Assembling BOOT for a KL10]>
  IFN FTKS10,<PRINTX [Assembling BOOT for a KS10]>
>

	LOC	.JBVER
	EXP	%%BTS
	RELOC

COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1980,1987. ALL RIGHTS RESERVED.
\;END OF COPYRIGHT MACRO

;THE "\|"s BELOW ARE BECAUSE THE IRPC IN ASCI11 CAN'T DEAL WITH<CR>(!)
DEFINE CPYTXT,<ASCI11	<\|COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1980,1987.\|ALL RIGHTS RESERVED.\|>>
	SUBTTL	MEMORY USAGE


;	SYMBOL	              CONTENTS			ADDRESS
;
;	LOADER	+====================================+	   140
;		|          MICROCODE LOADER          |
;	LOADEN	+------------------------------------+
;		|            UNUSED CORE             |
;	BTSVEC	+------------------------------------+	700000
;		|       ENTRY VECTOR PAGE(S)         |
;		|           (PAGE ALIGNED)           |
;	EPT	+------------------------------------+
;		|       EPT/UPT/SECTION 0 MAP        |
;	DATA	+------------------------------------+
;		|         IMPURE DATA STORAGE        |
;	BOOT	+------------------------------------+
;		|             BOOTSTRAP              |
;	EDDT	+------------------------------------+
;		|              EXEC DDT              |
;	DDTEND	+------------------------------------+
;		|            PATCH SPACE             |
;		+------------------------------------+
;		|            SYMBOL TABLE            |
;		+------------------------------------+
;		|          MICROCODE STORAGE         |
;		+------------------------------------+
;		|            UNUSED CORE             |
;		+====================================+	777777
	SUBTTL	FEATURE TEST NORMALIZATION


;MAKE SURE FEATURE TESTS AREN'T SCREWED

IFE FTTAPE,<			;IF NO TAPE DRIVER CODE
	FTDX10==0		;NO DX10/TU70
	FTTM02==0		;NO TM02/RH10/RH11/RH20
	FTDX20==0		;NO DX20/TU72
	FTTM78==0		;NO TM78
>; END IFE FTTAPE

IFN FTTAPE,<			;IF TAPE DRIVER CODE
  IFN FTKL10,<			;FOR A KL10
    IFNDEF FTDX10,<FTDX10==-1>	;DX10/TU70 BY DEFAULT
    IFNDEF FTTM02,<FTTM02==-1>	;TM02/RH10/RH20 BY DEFAULT
    IFNDEF FTDX20,<FTDX20==-1>	;DX20/TU72 BY DEFAULT
    IFNDEF FTTM78,<FTTM78==-1>	;TM78 BY DEFAULT
  >; END IFN FTKL10
  IFN FTKS10,<		;FOR A KS10
    IFNDEF FTTM02,<FTTM02==-1>	;TM02/RH11 BY DEFAULT
	FTDX10==0		;THE REST STAY OFF
	FTDX20==0		;...
	FTTM78==0
  >; END IFN FTKS10

  IF1,<
    IFN FTDX10,<PRINTX [Including DX10/TX01 driver]>
    IFN FTTM02,<PRINTX [Including TM02 driver]>
    IFN FTDX20,<PRINTX [Including DX20/TX02 driver]>
    IFN FTTM78,<PRINTX [Including TM78 driver]>
  >; END IF1
>; END IFN FTTAPE
	SUBTTL	AC DEFINITIONS


	S=0		;FLAGS
	P=1		;PUSH DOWN POINTER
	T1=2		;FOUR
	T2=T1+1		; TEMPORARY
	T3=T2+1		;  ACS
	T4=T3+1		;   ...
	W=6		;OFFSET INTO THE TYPE TABLE (RH10, RH20, RH11, ETC.)
	M=7		;NUMBER OF BLOCKS TO TRANSFER
	U=10		;PHYSICAL UNIT NUMBER
	P1=11		;FOUR
	P2=P1+1		; PRESERVED
	P3=P2+1		;  ACS
	P4=P3+1		;   ...
	J=15		;INDEX INTO DEVICE CODE TABLE
	F=16		;LOGICAL BLOCK ON UNIT OF FIRST BLOCK TO TRANSFER
	R=17		;RELOCATION REGISTER OR ADDRESS OF START OF TRANSFER
	SUBTTL	FLAG DEFINITIONS


;FLAGS IN S.  NOTE THAT THE FR.XXX FLAGS MUST BE IN THE SAME ORDER
;AS SWTTAB SINCE THE OFFSET INTO SWTTAB IS USED TO SET THE BIT IN S.

FL.RUB==1B0	;CURRENTLY PROCESSING RUBOUT
FL.OVW==1B1	;IGNORE UNPROCESSED DUMPS
FL.WLD==1B2	;DEVICE IS WILD
FL.RIB==1B3	;SKIP 1 BLOCK IN SELBLK SO THAT WE SKIP THE RIB
FL.NOP==1B4	;SCHED 400 IN EFFECT
FL.EXR==1B5	;READING IN AN EXTENDED RIB
FL.IO==1B6	;1 IF DOING OUTPUT, 0 IF DOING INPUT
FL.DEF==1B7	;DON'T DEFAULT ANY ANSWERS IN REDLIN
FL.CMD==1B8	;PARSE COMMANDS FROM COMMAND BUFFER
FL.1CM==1B9	;PARSE JUST NEXT COMMAND FROM COMMAND BUFFER
FL.LDE==1B10	;ERROR BEING PROCESSED WAS FROM LOAD, NOT DUMP
FL.SDT==1B11	;SUCCESSFUL DUMP TAKEN
FL.SSD==1B12	;THIS DUMP IS FOR A SYSTEM SLEEP
FL.DDD==1B13	;DON'T DO DUMP (DEBUGF HAS DF.RAD LIT)
FL.FFL==1B14	;FOUND FILE IN FNDFIL
		;*** BIT 15 FREE
IFN FTTAPE,<
FL.EXS==1B16	;EXTENSION SEEN
FL.REW==1B17	;REWIND IN PROGRESS
>; END IFN FTTAPE

FR.DEV==1B18	;DEVICE SEEN
FR.FIL==1B19	;FILENAME SEEN
FR.EXT==1B20	;EXTENSION SEEN
FR.PTH==1B21	;PATH SEEN

FR.1ST==1B35	;RIGHT-MOST BIT OF SWITCH BITS. SHIFT THIS BIT BY THE
		; OFFSET INTO SWTTAB TO SET THE APPROPRIATE SWITCH BIT
;DEFINE SWITCH BITS

DEFINE	SWBIT(NAM),<
	FR.'NAM==ZZ
	FR.SWT==FR.SWT!FR.'NAM
	ZZ==ZZ_1
>; END SWBIT

ZZ==FR.1ST	;START AT FIRST BIT
FR.SWT==0	;NO BITS SET YET

SWBIT	(STA)	;/START:N SEEN
SWBIT	(DDT)	;/EDDT SEEN
SWBIT	(LOD)	;/LOAD SEEN
SWBIT	(DMP)	;/DUMP SEEN
SWBIT	(RBT)	;/REBOOT SEEN
SWBIT	(FRC)	;/FORCE SEEN
IFN FTTAPE,<
SWBIT	(REW)	;/REWIND SEEN
SWBIT	(SKP)	;/SKIP SEEN
SWBIT	(NOR)	;/NOREWIND SEEN
>; END IFN FTTAPE

IFN FTTAPE,<
FR.TAB==FR.REW!FR.SKP
		;TAPE ACTION BITS
FR.TSB==FR.REW!FR.SKP!FR.NOR
		;TAPE-SPECIFIC BITS
>; END IFN FTTAPE

FR.ALL==FR.DEV!FR.FIL!FR.EXT!FR.SWT
		;ALL PARSE BITS

FX.CLR==FL.RUB!FL.OVW!FL.WLD!FL.SDT!FR.ALL
		;BITS TO CLEAR ON ENTRY TO PARSE
	SUBTTL	PARAMETER DEFINITIONS


;MONITOR PARAMETERS WHICH MUST AGREE WITH COMMON/COMMOD.
;
;HOME BLOCK DEFINITIONS

HOMNAM==0		;SIXBIT/HOM/
HOMSNM==4		;SIXBIT STRUCTURE NAME
HOMLUN==10		;LOGICAL UNIT NUMBER WITHIN FILE STRUCTURE
HOMBSC==14		;BLOCKS PER SUPERCLUSTER
HOMSCU==15		;SUPER CLUSTERS PER UNIT
HOMCNP==16		;BYTE POINTER TO CLUSTER COUNT IN RETRIEVAL PTR
HOMCLP==20		;BYTE POINTER TO CLUSTER ADDRESS IN RET. PTR
HOMBPC==21		;BLOCKS PER CLUSTER
HOMREF==23		;NON-ZERO IF STRUCTURE NEEDS REFRESHING
HOMMFD==46		;LOGICAL BLOCK NUMBER IN STR OF RIB FOR MFD
HOMCOD==176		;CONTAINS UNLIKELY CODE
CODHOM==707070		;THE CODE
HOMSLF==177		;SELF BLOCK POINTER


;RIB DEFINITIONS

RIBFIR==0		;AOBJN POINTER TO FIRST RETRIVAL POINTER IN RIB
RIBPPN==1		;PPN OF FILE
RIBNAM==2		;SIXBIT FILENAME
RIBEXT==3		;SIXBIT EXTENSION
RIBSIZ==5		;SIZE OF FILE IN WORDS
RIBSTS==17		;STATUS BITS
RIPDMP==100000		;THIS FILE CONTAINS AN UNPROCESSED DUMP
RIBXRA==34		;POINTER TO NEXT EXTENDED RIB
RIPNUB==400000		;NEW UNIT POINTER IN RETRIEVAL POINTER
RIBCOD==176		;CONTAINS UNLIKELY CODE
CODRIB==777777		;THE CODE
RIBSLF==177		;SELF BLOCK POINTER


;MICROCODE LOADER DEFINITIONS

EXBBYT==20000		;MAXIMUM NUMBER OF BYTES IN AN EXB FILE RECORD
			;(ABSOLUTE MAXIMUM IS 777777)
EXBMAX==<EXBBYT/4>-<EXBBYT/8> ;CORRESPONDING NUMBER OF PDP-10 WORDS
EXBWDS==EXBBYT/4	;SIZE OF EXB RECORD BUFFER
QWDS==6			;NUMBER OF WORDS IN THE QUESTION BUFFER
IOC==1			;I/O CHANNEL
;SYMBOLIC CHARACTER DEFINITIONS

.CHNUL==000	;NUL
.CHCNC==003	;CONTROL C
.CHCND==004	;CONTROL D
.CHBEL==007	;BELL
.CHCNH==010	;BACKSPACE
.CHTAB==011	;TAB
.CHLFD==012	;LINE-FEED
.CHVTB==013	;VERTICAL TAB
.CHFFD==014	;FORM FEED
.CHCRT==015	;CARRIAGE RETURN
.CHCNR==022	;CONTROL R
.CHCNU==025	;CONTROL U
.CHCNZ==032	;CONTROL Z
.CHESC==033	;ESCAPE
.CHDEL==177	;DELETE


;MISCELANEOUS DEFINITIONS

BOOTSA==20		;PHYSICAL ADDRESS OF BOOT ORIGIN STORED HERE
BOOTWD==22		;RH10/DF10 CHANNEL COMMAND PAIR
SYSDDT==401		;EDDT MONITOR START ADDRESS
LBNHOM==1		;BLOCK ADDRESS OF FIRST HOME BLOCK
LB2HOM==12		;BLOCK ADDRESS OF SECOND HOME BLOCK
LBOBAT==1		;OFFSET OF BAT BLOCK FROM HOME BLOCK
LIMLVL==5		;NUMBER OF SFD'S
MBTCOM==411		;COMMUNICATIONS WORD IN LOW CORE FOR REBOOT
			;REQUESTS.  CONTAINS THE PHYSICAL PAGE NUMBER
			;OF WHERE TO PUT BOOT DURING REBOOT PROCESSING
MAXPGS==<FTKL10&^D8192>!<FTKS10&^D1024>
			;MAXIMUM NUMBER OF PAGES POSSIBLE IN MEMORY
MEMITL==^D4		;NUMBER OF WAYS MEMORY CAN BE INTERLEAVED
NXMLEN==<MAXPGS/^D36>+1	;LENGTH OF NXMTAB
; DEVICE CODES
	APR==0			;PROCESSOR
	PI==4			;PI SYSTEM
	PAG==10			;PAGER
	CCA==14			;CACHE
	DTE0==200		;DTE20

; CONI APR BITS
	LP.SBE==1B24		;S-BUSS ERROR
	LP.NXM==1B25		;NXM
	LP.PAR==1B27		;PARITY ERROR
	LP.CSD==1B31		;CACHE SWEEP DONE

; CONO APR (KS10)
	SP.SSF==1B23		;SET SELECTED FLAGS (BITS 24-31)
	SP.IFE==1B25		;INTERRUPT FRONT END
	SP.NXM==1B27		;NXM
	SP.HMP==1B28		;HARD MEMORY PARITY ERROR

; CONO PI BITS
	PI.CPI==1B23		;CLEAR PI SYSTEM
	PI.OFF==1B27		;TURN PI SYSTEM OFF

; CONO PAG BITS (KL10)
	LG.CSL==1B18		;CACHE STRATEGY LOOK
	LG.CSW==1B19		;CACHE STRATEGY WRITE (LOAD)
	XG.KLP==1B21		;KL PAGING
	XG.TEN==1B22		;TRAP ENABLE
	LG.EPT==17777		;ADDRESS OF EPT (KL10)
	SG.EPT==3777B35		;ADDRESS OF EPT (KS10)

; DATAO PAG BITS (KL10)
	XG.LAB==1B0		;LOAD AC BLOCKS
	LG.LPC==1B1		;LOAD PREV CONTEXT (KL10)
	XG.LUB==1B2		;LOAD USER BASE REGISTER
	LG.IAM==1B18		;INHIBIT STORING ACCOUNTING METER (KL10)

; KS10 I/O INSTRUCTIONS FOR WHICH THERE ARE NO REASONABLE
; KL10 EQUIVALENTS
	OPDEF RDHSB [702300,,0]	;READ HALT STATUS BLOCK ADDRESS
	OPDEF WRHSB [702700,,0]	;WRITE HALT STATUS BLOCK ADDRESS
	OPDEF TIOE  [710000,,0]	;TEST UNIBUS, SKIP EQUAL
	OPDEF TION  [711000,,0]	;TEST UNIBUS, SKIP NOT EQUAL
	OPDEF RDIO  [712000,,0]	;READ I/O
	OPDEF WRIO  [713000,,0]	;WRITE I/O
	OPDEF WRIOB [723000,,0]	;WRITE I/O BYTE
	OPDEF WRCSB [702440,,0]	;WRITE CST BASE REGISTER
; KL10/DTE FUNCTION FLAGS
	DT.MTO==10B27		;CTY OUTPUT
	DT.ESP==11B27		;ENTER SECONDARY PROTOCOL

; KL10/DTE COMMUNICATION WORDS IN THE EPT
	DTEEPW==144		;EXAMINE/PROTECTION WORD
	DTEFLG==444		;COMMAND COMPLETE FLAG
	DTEF11==450		;FROM -11 DATA
	DTECMD==451		;COMMAND WORD
	DTEMTD==455		;OUTPUT DONE FLAG
	DTEMTI==456		;INPUT READY FLAG

; KL10/DTE CONO BITS
	TO11DB==1B22		;TO -11 DOOR BELL
	PILDEN==1B31		;ENABLE LOADING PIA
	PI0ENB==1B32		;PI0 ENABLE
	PIA==7B35		;PIA

; FLAGS FROM KLI PASSED IN AC 0 (S)

	KL.SIL==1B0		;SILENT LOAD
	KL.DMP==1B1		;DUMP


; KS10 RELOAD WORD
	RLWORD==31		;RELOAD WORD
	   AUTOBT==1B32		   ;BOOT SWITCH OR POWER UP CONDITION
	   FORREL==1B34		   ;FORCED RELOAD

; KS10 CTY PARAMETERS
	CTYIWD==32		;INPUT WORD
	CTYOWD==33		;OUTPUT WORD
	   CTYOVL==1B27		   ;OUTPUT VALID FLAG

; KS10 KLINIK LINE PARAMETERS
	KLIIWD==34			;KLINIK INPUT WORD

	KLIOWD==35			;KLINIK OUTPUT WORD
	   KLIOVL==1B27			   ;KLINIK OUTPUT VALID

; INSTRUCTION OPDEFS
	OPDEF	XMOVEI	[SETMI	0,]	;EXTENDED MOVE IMMEDIATE
	OPDEF	XJRST	[JRST	15,]	;JRST AND SWITCH SECTIONS
	OPDEF	APRID	[BLKI	APR,]	;READ PROCESSOR SERIAL NUMBER
	OPDEF	RDERA	[BLKI	PI,]	;READ ERROR ADDRESS REGISTER
	OPDEF	CLRPT	[BLKO	PAG,]	;CLEAR ONE ENTRY IN HARDWARE
	OPDEF	SWPUA	[DATAO	CCA,]	;UNLOAD ALL PAGES, UPDATING
					; CORE AND INVALIDATING CACHE
	OPDEF	PJRST	[JUMPA	17,]	;PUSHJ/POPJ
; PAGE FAIL OFFSETS
	.LMPFW==500			;PAGE FAIL WORD
	.LMPFP==501			;OLD PC WORD
	.LMPFN==502			;NEW PC WORD


; MUUO TRAP OFFSETS
	.UPMUO==424			;LOCATION OF MUUO
	.UPMUP==425			;LOCATION OF MUUO PC
	.UPMUE==426			;MUUO EFFECTIVE ADDRESS
;MISCELANEOUS HARDWARE PARAMETERS

APRRST==<FTKL10&327760>!<FTKS10&221700>
			;CONO BITS TO CLEAR THE WORLD
CLRAPR==<FTKL10&127700>!<FTKS10&021700>
			;CONO BITS TO CLEAR APR ERROR FLAGS
ASNMSK==<IFN FTKL10,<7777>>!<IFN FTKS10,<77777>>
			;MASK OF APR SERIAL NUMBER RETURNED BY APRID
IFN FTKS10,<.EPHSB==424>;KS10 HALT STATUS BLOCK ADDRESS
SV.DIR==1776		;.EXE DIRECTORY START CODE
SV.END==1777		;.EXE DIRECTORY END CODE

; KL PAGING PAGE MAP BITS
PM.DCD==1		;DIRECT POINTER
PM.WRT==1B4		;WRITABLE PAGE

;MISCELANEOUS PARAMETERS

PDLLEN==^D36		;SIZE OF PDL
LINBFL==^D16		;SIZE OF COMMAND LINE BUFFER IN WORDS
BLKSIZ==200		;SIZE OF A DISK BLOCK
PAGSIZ==1000		;SIZE OF A PAGE
MAXUNI==^D8		;MAX NUMBER OF UNITS ON A CONTROLLER
P2BLSH==2		;AMOUNT TO LSH A PAGE COUNT TO GET BLOCKS
B2WLSH==^D7		;AMOUNT TO LSH A BLOCK COUNT TO GET WORDS
W2BLSH==-B2WLSH		;AMOUNT TO LSH A WORD COUNT TO GET BLOCKS
P2WLSH==^D9		;AMOUNT TO LSH A PAGE NUMBER TO GET WORDS
W2PLSH==-P2WLSH		;AMOUNT TO LSH A WORD COUNT TO GET PAGES
WATTIM==<FTKL10&50>+<FTKS10&10>
			;TIME TO WAIT FOR OPERATOR RESPONSE IN REDLIN
DATLEN==20		;WORDS OF SUBROUTINE DATA STORAGE
IFN FTTAPE,<
ERRTRY==^D40		;NUMBER OF TIMES TO RETRY ON A TAPE ERROR
>; END IFN FTTAPE

;DEVICE(DRIVE) TYPES

TY.T2L==10		;LOWEST TM02 TYPE
TY.T2H==17		;HIGHEST TM02 TYPE
TY.T3L==50		;LOWEST TM03 TYPE
TY.T3H==57		;HIGHEST TM03 TYPE
TY.DXA==60		;DX20A (TX02 TAPE CONTROLLER)
TY.T78==101		;TM78
;DEFINITIONS FOR BACKUP FORMAT MAGTAPES (STOLEN FROM BACKRS)

IFN FTTAPE,<

;WORDS IN HEADER (FIRST 32. WORDS OF EACH RECORD)

G$TYPE==0	;RECORD TYPE
	T$LBL==1	;LABEL IDENTIFICATION RECORD
	T$BEG==2	;SAVE START
	T$END==3	;SAVE END
	T$FIL==4	;DISK FILE DATA
	T$UFD==5	;UFD RIB
	T$EOV==6	;END OF VOLUME
	T$COM==7	;COMMENT
	T$CON==10	;CONTINUE (SAME DATA AS T$BEG-T$END)
	T$MAX==T$CON	;MAXIMUM RECORD TYPE
G$SEQ==1	;SEQUENCE NUMBER
G$RTNM==2	;RELATIVE TAPE NUMBER
G$FLAG==3	;RECORD DEPENDENT BITS
	GF$EOF==1B0	;LAST RECORD OF FILE
	GF$RPT==1B1	;REPEAT OF LAST RECORD WRITE ERROR
	GF$NCH==1B2	;IGNORE CHECKSUM
	GF$SOF==1B3	;START OF FILE
G$CHK==4	;CHECKSUM
G$SIZ==5	;NUMBER OF DATA WORDS
G$LND==6	;TOTAL LENGTH OF NON-DATA SECTION

;SUB-BLOCK CODES FOR FILE NAME BLOCK IN A T$FIL RECORD

.FCDEV==1	;DEVICE
.FCNAM==2	;FILE NAME
.FCEXT==3	;EXTENSION
.FCDIR==40	;DIRECTORY (PPN), SFD'S ARE 41-45

;RECORD SIZE

MTHLEN==^D32	;LENGTH OF MAGTAPE HEADER RECORD
LNMTBF==PAGSIZ+MTHLEN	;LENGTH OF TAPE BUFFER (HEADER PLUS DATA AREA)

>; END IFN FTTAPE
;DEFINITIONS FOR THE .VBOOT VIRTUAL ADDRESS SPACE.  WITH KL PAGING,
;THE MAP SLOT ASSIGNMENTS ARE ALL DIFFERENT AND WE PUT THE ADDRESS
;SPACE INTO THE LOW SEGMENT TO AVOID CONFLICTS WITH THE RH20 IOWDS.

.VBOOT==700000		;VIRTUAL ADDRESS AT WHICH BOOT RUNS
.VPAG0==302000		;PAGE 0 MAPPED THROUGH THIS VIRUAL ADDRESS
			;PAGE 1 MAPPED THROUGH .VPAG0+PAGSIZ
.VMOVE==304000		;FIRST VIRTUAL ADDRESS USED TO MOVE BOOT TO
			;  HIGH CORE
.VVECT==306000		;VIRTUAL ADDRESS OF OLD BOOT VECTOR
.VZERO==300000		;VIRTUAL ADDRESS USED TO ZERO CORE


;MACRO TO COMPUTE THE MAP SLOT OFFSET FOR A GIVEN VIRTUAL ADDRESS

DEFINE VMAP(SYMBOL,ADDR),<
  SYMBOL==<ADDR/PAGSIZ>
>
    

VMAP(.MBOOT,.VBOOT)	;MAPPED BOOT ORIGIN
VMAP(.MPAG0,.VPAG0)	;MAPPED PHYSICAL PAGE 0
			;MAPPED PHYSICAL PAGE 1 IS AT .VPAG0+PAGSIZ
VMAP(.MMOVE,.VMOVE)	;MAPPED PAGE FOR MOVING BOOT
VMAP(.MZERO,.VZERO)	;MAPPED PAGE FOR ZEROING CORE
VMAP(.MVECT,.VVECT)	;MAPPED BOOT VECTOR OF PREVIOUS BOOT
IFN FTKL10,<

;INTERNAL CHANNEL DEVICE DEPENDENT PARAMETERS

FSTICD==540		;FIRST INTERNAL CHANNEL DEVICE CODE
LSTICD==574		;LAST INTERNAL CHANNEL DEVICE CODE

;CI20/NIA20 DEVICE DEPENDENT PARAMETERS

;CONO BITS
CO.CPT==400000		;CLEAR PORT

;RH10/RH20 DEVICE DEPENDENT PARAMETERS

;CONI BITS
CI.XDN==10		;TRANSFER DONE (RH10/RH20)
CI.122==4000,,0		;22 BIT CHANNEL (RH10/DF10C)
CI.1ER==736320		;DBPE, FXCEP, CHNER, OVR, DRE, ILC, PSFAIL,
			;CBOV, RAE, BUSY (RH10)
CI.1RA==100		;RAE (RH10)
CI.2ER==515000		;DPE, LWCE, DR, RAE, DOE (RH20)
CI.2RA==4000		;RAE (RH20)

;CONO BITS
CO.XDN==10		;CLEAR DONE (RH10/RH20)
CO.XSX==20		;STOP TRANSFER (RH10/RH20)
CO.XMI==2000		;MASSBUS INIT (RH10/RH20)
CO.1RB==47		;CONI BITS TO RESTORE - AIE, PIA (RH10)
CO.1AE==40		;AIE (RH10)
CO.2RB==447		;CONI BITS TO RESTORE - MBE, AIE, PIA (RH20)
CO.2ME==400		;MASSBUS ENABLE (RH20)

;DATAI/DATAO BITS

DO.LDR==004000,,0	;LOAD REGISTER (REGISTER NUMBER IN BITS 0-5)
DO.XCR==004400,,0	;DRIVE CONTROL REGISTER (RH10/RH20)
DO.XSR==010400,,0	;STATUS REGISTER (RH10/RH20)
  DI.XCE==40000		;COMPOSITE ERROR (RH10/RH20)
  DI.XSM==172777	;BIT MASK OF BITS TO CHECK FOR IN INITIALIZATION
  DI.XSB==10700		;LEGAL VALUE IN SR (MOL, DP, DR, VV)
DO.XDS==054000,,0	;BLOCK ADDRESS REGISTER, LR (RH10/RH20)
DO.XDT==060000,,0	;DRIVE TYPE REGISTER (RH10/RH20)
DO.XDC==124000,,0	;DESIRED CYLINDER REGISTER, LR (RH10/RH20)
DO.1CR==404000,,0	;CONTROL REGISTER (RH10)
DO.1IA==440000,,0	;INTERRUPT ADDRESS REGISTER (RH10)
DO.2ST==716200,,0	;STCR, LR, RCLP, STORE (RH20)
  DO.XCL==11		;FUNCTION CODE FOR DRIVE CLEAR (RH10/RH20)
  DO.XRP==21		;FUNCTION CODE FOR READIN PRESET (RH10/RH20)
  DO.XRD==71		;FUNCTION CODE FOR READ (RH10/RH20)
  DO.XWT==61		;FUNCTION CODE FOR WRITE (RH10/RH20)
DO.2IV==740000,,0	;INTERRUPT VECTOR INDEX REGISTER (RH20)
;MISCELANEOUS

RH2TRA==1B0		;CHANNEL COMMAND OPCODE FOR TRANSFER (RH20)
RH2JMP==1B1		;CHANNEL COMMAND OPCODE FOR JUMP (RH20)
R2IOWL==^D66		;NUMBER OF IOWDS TO ALLOCATE FOR THE LARGEST
			;POSSIBLE TRANSFER
R2BCNT==^D15		;MAX NUMBER OF BLOCKS WHICH MAY BE SPECIFIED
			;IN ONE IOWD FOR AN RH20
R2WCNT==R2BCNT*BLKSIZ	;CORRESPONDING WORDCOUNT
R1BCNT==^D127		;MAX NUMBER OF BLOCKS WHICH MAY BE SPECIFIED
			;IN ONE IOWD FOR AN RH10
R1WCNT==R1BCNT*BLKSIZ	;CORRESPONDING WORDCOUNT

>; END IFN FTKL10
IFN FTKS10,<

;RH11 DEVICE DEPENDENT PARAMETERS

;UBA ADDRESSES/BITS

SO.UPR==763000		;UBA PAGING RAM ADDRESS
  SO.VFT==140000	;VALID+FAST XFER
  SO.RBT==100,,277	;BITS TO RESTORE IN CS1 AND UBA SR
SO.USR==763100		;UBA STATUS REGISTER
  SO.UBI==100		;UNIBUS INIT
  SI.UER==740000	;TIME OUT, BMD, BUS PAR, NXD

;DRIVE ADDRESSES/BITS

SO.CS1==776700		;CONTROL STATUS REGISTER 1
  SI.RDY==200		;READY AT END OF XFER
  SI.S1E==140000	;SC, TRE
SO.WC==776702		;WORD COUNT REGISTER
SO.BA==776704		;BUS ADDRESS REGISTER
SO.DA==776706		;DESIRED ADDRESS REGISTER
SO.CS2==776710		;CONTROL STATUS REGISTER 2
SO.DS==776712		;DRIVE STATUS REGISTER
  SO.DSM==172700	;MASK FOR BITS RETURNED
  SO.DSB==10700		;LEGAL VALUE (MOL, DP, DR, VV)
SO.ASR==776716		;ATTENTION SUMMARY REGISTER
SI.DT==776726		;DRIVE TYPE REGISTER
  SI.DSK==20000		;DEVICE IS A DISK
SO.DC==776734		;DESIRED CYLINDER REGISTER

;MISCELLANEOUS

SO.DCL==11		;FUNCTION CODE FOR DRIVE CLEAR
SO.RIP==21		;FUNCTION CODE FOR READIN PRESET
SO.WRT==61		;FUNCTION CODE FOR WRITE
SO.RED==71		;FUNCTION CODE FOR READ

RSBCNT==^D252		;MAX NUMBER OF BLOCKS WHICH MAY BE TRANSFERED
			;AT ONE TIME BY THE RH11

>;END IFN FTKS10
;TM02 DEVICE-DEPENDENT PARAMETERS

IFN FTTM02,<

;PARAMETERS COMMON TO BOTH KL AND KS

;TAPE CNTRL REGISTER BITS
T2.M7T==20		;7-TRACK CORE DUMP

;FUNCTIONS
T2.RWF==7		;REWIND
T2.DCF==11		;DRIVE CLEAR
T2.SFF==31		;SKIP-FORWARD
T2.SBF==33		;SKIP BACKWARD
T2.RDF==71		;READ

IFN FTKL10,<

;REGISTERS
T2.DSR==010000,,0	;STATUS REGISTER
T2.DER==020000,,0	;ERROR
T2.DFC==050000,,0	;FRAME COUNTER
T2.DTC==110000,,0	;TAPE CNTRL
T2.DRH==400000,,0	;RH10 CNTRL REG

T2.DLR==004000,,0	;LOAD REGISTER

;CONI BITS
T2.DON==10		;DONE

;STATUS BITS
T2.SER==40000		;ERROR
T2.SPP==20000		;POSITION IN PROGRESS
T2.SRY==200		;READY
T2.SPE==40		;PHASE ENCODED
T2.SEF==4		;EOF
T2.SBT==2		;BOT

;ERROR REG
T2.NER==102200		;NOT ERRORS IF PE MODE
T2.ERR==176377		;ERROR IF ON
>; END IFN FTKL10
IFN FTKS10,<
TRHBAS==3,,772440	;BASE UBA ADDRESS FOR TAPE RH11

;RH11/TM02 REGISTER OFFSETS

MTCS1==0		;CONTROL REGISTER
MTWC==2			;WORD COUNT REGISTER
MTBA==4			;BUS ADDRESS REGISTER
MTFC==6			;FRAME COUNT REGISTER
MTCS2==10		;STATUS REGISTER
MTDS==12		;DRIVE STATUS REGISTER
MTER==14		;ERROR REG
MTAS==16		;ATTENTION SUMMARY
MTCC==20		;CHARACTER CHECK REGISTER
MTDB==22		;DATA BUFFER
MTMR==24		;MAINT REGISTER
MTDT==26		;DRIVE TYPE
MTSN==30		;SERIAL NUMBER
MTTC==32		;TAPE CONTROL REGISTER

;CONTROL REGISTER BIT ASSIGNMENTS

C1.SC==100000		;(R) SPECIAL CONDITION (ALL ERRORS)
C1.TRE==40000		;(R/W) TRANSFER ERROR
C1.CPE==20000		;(R) CONTROL BUS PARITY ERROR
C1.DVA==4000		;(R) DRIVE AVAILABLE
C1.PSL==2000		;(R/W) PORT SELECT
C1.RDY==200		;(R) READY
C1.IE==100		;(R/W) INTERRUPT ENABLED

;STATUS REGISTER BIT ASSIGNMENTS

C2.DLT==100000		;(R) DATA LATE (OVERRUN)
C2.WCE==40000		;(R) WRITE CHECK ERROR
C2.UPE==20000		;(R/W) UNIBUS PARITY ERROR
C2.NXD==10000		;(R) NON-EXISTANT DRIVE
C2.NXM==4000		;(R) NON-EXISTANT MEMORY
C2.PGE==2000		;(R) PROGRAM ERROR
C2.MXF==1000		;(R/W) MISSED TRANSFER
C2.DPE==400		;(R) DATA BUS PARITY ERROR
C2.OR==200		;(R) OUTPUT READY
C2.IR==100		;(R) INPUT READY
C2.CLR==40		;(W) CONTROLLER CLEAR
C2.PAT==20		;(R/W) PARITY TEST
C2.BAI==10		;(R/W) UNIBUS ADDRESS INCREMENT INHIBIT
;DRIVE STATUS REGISTER

DS.ATA==1B20		;ATTENTION
DS.ERR==1B21		;COMPOSITE ERROR
DS.PIP==1B22		;POSITIONING IN PROGRESS
DS.MOL==1B23		;MEDIUM ON LINE
DS.WRL==1B24		;WRITE LOCKED
DS.EOT==1B25		;END OF TAPE
DS.DPR==1B27		;DRIVE PRESENT
DS.DRY==1B28		;DRIVE READY (NOT GO)
DS.SSC==1B29		;SLAVE STATUS CHANGE
DS.PES==1B30		;PHASE ENCODED STATUS
DS.SDN==1B31		;SHUTDOWN BIT
DS.IDB==1B32		;IDENT BURST (FOR PE)
DS.TM==1B33		;TAPE MARK
DS.BOT==1B34		;BEGINNING OF TAPE
DS.SLA==1B35		;SLAVE ATTENTION
DS.OK==DS.EOT!DS.PES!DS.TM!DS.BOT!DS.SSC!DS.SDN!DS.IDB	;BITS WHICH DON'T MATTER
DS.GUD==DS.MOL!DS.DPR!DS.DRY	;THESE BITS MUST BE ON

;DRIVE ERROR REGISTER

ER.COR==1B20		;CORRECTABLE DATA/ CRC ERROR
ER.UNS==1B21		;UNSAFE
ER.OPI==1B22		;OPERATION INCOMPLETE
ER.DTE==1B23		;DRIVE TIMING ERROR
ER.NEF==1B24		;NON-EXISTANT FUNCTION
ER.CS==1B25		;CORRECTABLE SKEW/ ILLEGAL TAPE MARK
ER.FCE==1B26		;FRAME COUNT ERROR
ER.NSG==1B27		;NON-STANDARD GAP (CRAP IN THE GAP)
ER.LRC==1B28		;LRC ERROR/ FORMAT (PREAMBLE POSTAMBLE) ERROR
ER.INC==1B29		;INCORRECTABLE DATA/ VERTICAL PARITY ERROR
ER.DPA==1B30		;DATA BUS PARITY ERROR
ER.FMT==1B31		;FORMAT ERROR
ER.CPA==1B32		;CBUS PARITY ERROR
ER.RMR==1B33		;REG MODIFICATION REFUSED
ER.ILR==1B34		;ILLEGAL REGISTER ADR
>; END IFN FTKS10
>; END IFN FTTM02
;TX01/DX10 DEVICE-DEPENDENT PARAMETERS

IFN FTDX10,<
;DEVICE DATAO BITS

DO.RES==1B16		;DO LOCAL RESET
DO.LRS==1B17		;LOAD REG SELECT
DO.UC0==4		;MP CTL 0
DO.UC1==5		;MP CTL 1
DU0HLT==1B19		;HALT
DU0CON==1B20		;CONTINUE
DU0EXM==1B22		;EXAMINE
DU0DEP==1B23		;DEPOSIT

UP.SA==200		;MP START ADDRESS
PDC==220		;DEVICE CODE
ICPC==20		;PLACE FOR INITIAL CHL PC

;CHL BITS

CH.COP==1B1+1B3		;DEVICE COMMAND, AUTO ERROR RETRY
CH.GO==1B2		;GO BIT
CH.JMP==1B3		;CHL JMP
CH.STS==1B4		;STORE STATUS
CH.FRC==1B5		;FORCE SENSE BYTES

;DEVICE COMMANDS

TX.NOP==3		;NOOP
TX.FRD==2		;READ FORWARD
TX.FSR==67		;FORWARD SPACE RECORD
TX.BSR==47		;BACK SPACE RECORD
TX.REW==7		;REWIND

;CONI BITS
 
TX.RUN==1B17	;RUN BIT  
TX.ILI==1B25	;INHIBIT LOAD ICPC
TX.UPE==1B26	;MP ERROR
TX.MPE==1B27	;MEM PARITY ERROR
TX.NXM==1B28	;NXM
TX.STA==1B29	;STATUS AVAILABLE
TX.CLR==1B31	;CLEAR
TX.CON==1B32	;CONTINUE

;SENSE BYTE DEFINITIONS

LSNS==^D24	;NUMBER OF SENSE BYTES
SB1==4		;OFFSET INTO CHSNS FOR BYTE 1
SB17TK==1B11	;DRIVE IS 7-TK
;STATUS BITS IN DSR/CSR

DS.UCH==1B6		;UNIT CHECK
DS.UEX==1B7		;UNIT EXCEPTION

CS.SLE==1B11		;SELECTION ERROR
CS.SQE==1B12		;SEQUENCE ERROR
CS.DPE==1B13		;DEVICE PARITY ERROR
CS.LNE==1B14		;LENGTH ERROR
CS.DSF==1B17		;DSR FLAG

CS.NFG==1B18		;SENSE AND/OR STATUS NO GOOD
CS.INC==1B19		;OP INCOMPLETE

CS.STE==1		;ENDING STATUS
CS.STC==2		;CU INITIATED STATUS

;DATA MODES

TX.7TK==3		;7 TRACK CORE DUMP
TX.9TK==0		;9 TRACK CORE DUMP

TX.D72==063		;200 BPI + ODD PARITY
TX.D75==163		;556 BPI + ODD PARITY
TX.D78==263		;800 BPI + ODD PARITY
>; END IFN FTDX10
;TX02/DX20 DEVICE-DEPENDENT PARAMETERS

IFN FTDX20,<
;RH20 CONI/CONO BITS

D2.ATN==1B28		;ATTENTION
D2.CLR==5010		;BITS TO CLEAR ERRORS

;RH20 DATAI/DATAO BITS

D2.SCR==71B5		;RH20 SECONDARY COMMAND REGISTER
	D2.LDR==1B6	;LOAD REGISTER ON DATAO
	D2.RCP==1B7	;RESET COMMAND LIST POINTER
	D2.SCS==1B10	;STORE CHANNEL STATUS
	D2.DTE==1B19	;DISABLE TRANSFER ERROR STOP
	D2.TRA==1B0	;TRANSFER IN CHANNEL COMMAND LIST
	D2.RHJ==1B1	;JUMP WORD IN CHANNEL COMMAND LIST
	D2.HLT==1B1	;HALT CHANNEL WHEN COMBINED WITH D2.TRA

;DX20 DATAO/DATAI BITS

D2.CTR==0B5		;CONTROL REGISTER
	D2.REW==7	;REWIND OPERATION PLUS GO BIT
	D2.SFR==31	;SKIP FORWARD OPERATION PLUS GO BIT
	D2.SBR==33	;SKIP BACKWARD OPERATION PLUS GO BIT
	D2.SNS==45	;SENSE OPERATION PLUS GO BIT
	D2.RDF==71	;READ FORWARD PLUS GO BIT
D2.STR==1B5		;STATUS REGISTER
	D2.CER==1B21	;COMPOSITE ERROR
	D2.RUN==1B23	;MICROPROCESSOR IS RUNNING
D2.ERR==2B5		;ERROR REGISTER
	D2.HER==177B35	;HARD ERRORS
D2.MTR==3B5		;MAINTENANCE REGISTER
	D2.SCY==1B31	;SINGLE CYCLE
	D2.SMP==1B33	;START MICRO PROCESSOR
	D2.RES==1B34	;RESET MICRO PROCESSOR
D2.ASR==4B5		;ATTENTION SUMMARY REGISTER
D2.FCR==5B5		;FRAME COUNT REGISTER
D2.GP0==20B5		;STATUS INDEX/ENDING STATUS REGISTER
	D2.DVE==1B25	;DEVICE END
	D2.UCK==1B26	;UNIT CHECK
	D2.UEX==1B27	;UNIT EXCEPTION
	D2.RST==1B28	;REQUEST STATUS UPDATE
D2.GP1==21B5		;DRIVE NUMBER REGISTER
D2.GP4==24B5		;ASYNCHRONOUS STATUS REGISTER
D2.GP6==26B5		;EXTENDED STATUS REGISTER 0
D2.DR0==30B5		;DIAGNOSTIC REGISTER 0
D2.DR1==31B5		;DIAGNOSTIC REGISTER 1
	D2.IRE==1B20	;INSTRUCTION REGISTER ENABLE
	D2.MSE==1B21	;ENABLE MICRO-STORE LOAD FROM IR
	D2.PCE==1B22	;PC ENABLE
	D2.PCI==1B23	;PC AUTO INCREMENT
D2.DR7==37B5		;DIAGNOSTIC REGISTER 7
	D2.IRP==1B22	;IR PARITY ERROR

D2.DLR==004000,,0	;LOAD REGISTER
D2.DRE==000400,,0	;DISABLE REGISTER ACCESS ERROR STOP

;MISCELLANEOUS DEFINITIONS

D2.7TK==1B31		;DRIVE IS 7 TRACK IN SENSE BYTE 1
D2.SAD==1		;DX20 START ADDRESS
D2.C10==100		;REQUIRED CONTENTS OF CRAM LOCATION 10
D2.C11==042562		;REQUIRED CONTENTS OF CRAM LOCATION 11

;MAGIC ADDRESS AND VALUE

MAGICA==11		;ADDRESS WE MUST STORE MAGIC VALUE IN
MAGICV==42562		;THE MAGIC VALUE
>; END IFN FTDX20
;TM78 DEVICE-DEPENDENT PARAMETERS

IFN FTTM78,<

;DEVICE REGISTERS

T7.ICD==010000,,0	;INTERRUPT CODE
	.T7DCD==1		;DONE
	.T7SCD==21		;SHORT RECORD (OTHERWISE OK)
	.T7EOF==2		;EOF
T7.FMT==020000,,0	;FORMAT REGISTER
T7.ATR==040000,,0	;ATTENTION SUMMARY REGISTER
T7.BCT==050000,,0	;BYTE COUNT REGISTER
T7.NIC==130000,,0	;NON-DATA INTERRUPT CODE
T7.TMS==210000,,0	;STATUS REGISTER
	T7.TMC==40000		;TM CLEAR
	T7.TMR==100000		;TM READY

T7.DLR==004000,,0	;LOAD REGISTER FLAG

.T7DV0==14		;REGISTER FOR DRIVE 0


;FUNCTIONS

T7.FRW==7		;REWIND
T7.FSN==11		;SENSE
T7.FSR==21		;SKIP RECORD
T7.FBR==23		;BACKSPACE RECORD
T7.FRD==71		;READ
>; END IFN FTTM78
	SUBTTL	MACRO DEFINITIONS


; MACRO TO LOAD THE VECTOR
DEFINE	LV	(OFS,DAT),<
	.ORG	BTSVEC+.BT'OFS
	IRP DAT,<DAT>
>

;MACRO DEFINITIONS TO ALLOW ASSEMBLY TO BE PHASED STARTING AT .VBOOT
DEFINE	BLK(LABEL,SIZE),<LABEL:	  BLOCK	SIZE>


;MACRO TO BUILD THE BOOT VERSION STRING
DEFINE	VSTR(VER,EDT),<
ASCIZ/BOOT V'VER'(EDT)

/
	>


;MACRO TO CAUSE A FATAL ERROR TRAP AND RESTART BOOT.

DEFINE	ERROR(TEXT),<
	PUSHJ	P,FATERR
	JUMP	[ASCIZ |TEXT|]
>; END DEFINE ERROR
;MACROS TO HELP IN INSERTING ENTRIES INTO THE PAGE MAP

DEFINE	ONE41(FPAGE,LPAGE),<
	  ZZ==FPAGE
	  XLIST
	  REPEAT <LPAGE-FPAGE+1>,<
	    EXP <PM.DCD>B2+PM.WRT+ZZ
	    ZZ==ZZ+1
	  >
	  LIST
	>


DEFINE	INSLOC(FLOC,LLOC,INSTN),<
	  XLIST
	  REPEAT <LLOC-FLOC+1>,<
	    INSTN
	  >
	  LIST
	>


;MACRO TO CAUSE A PAUSE BETWEEN THE DATAO WHICH LOADS THE PREPARATION
;REGISTER AND THE DATAI WHICH READS THE VALUE FROM THE SPECIFIED
;REGISTER.

	DEFINE	STALL,<
	  IMULI	P,1
	  IFN FTKL10,<
	  XLIST
	  IMULI P,1
	  LIST
	  >
	>
;MACRO TO PUT TEXT IN FORMAT SO IT LOOKS LIKE 11 ASCII WHEN IT GET INTO
;20F FORMAT.  SEE RSXCMN.MAC IF YOU ABSOLUTELY NEED TO KNOW HOW THIS HAPPENS.
;(SIGH, IRPC WON'T DEAL WITH <CR><LF>, SO \| WILL HAVE TO DO)

IFN FTKL10,<
	DEFINE	ASCI11(A),<
	  ...Z1==0
	  ...Z2==0
	  IRPC	A,<
		...Z3==<"'A'">
		IFE ...Z3-"\",<...Z3==15>
		IFE ...Z3-"|",<...Z3==12>
		IFE <...Z2-0>,<...Z1==...Z3>
		IFE <...Z2-1>,<...Z1==<...Z3_^D8>!...Z1>
		IFE <...Z2-2>,<...Z1==<...Z3_^D16>!...Z1>
		IFE <...Z2-3>,<EXP <...Z3_^D24>!...Z1
			       ...Z2==-1>
		...Z2==...Z2+1>
	  IFN	...Z2,<EXP ...Z1>
			>
>;FTKL10

IFN FTKS10,<			;IF A KS10, IT'S ASCIZ AFTER ALL!
	DEFINE	ASCI11(A),<
	  ...Z1==0
	  ...Z2==0
	  IRPC	A,<
		...Z3==<"'A'">
		IFE ...Z3-"\",<...Z3==15>
		IFE ...Z3-"|",<...Z3==12>
		IFE <...Z2-0>,<...Z1==<...Z3>B6>
		IFE <...Z2-1>,<...Z1==<...Z3>B13!...Z1>
		IFE <...Z2-2>,<...Z1==<...Z3>B20!...Z1>
		IFE <...Z2-3>,<...Z1==<...Z3>B20!...Z1>
		IFE <...Z2-4>,<EXP <...Z3>B27!...Z1
			       ...Z2==-1>
		...Z2==...Z2+1>
	  IFN	...Z2,<EXP ...Z1>
			>
>;FTKS10
	SUBTTL	MICROCODE LOADER


	RELOC	0

LOADER:	JFCL			;NO CCL
	RESET			;STOP I/O
	SETOM	USRFLG		;REMEMBER TO DO USER MODE I/O TO THE TTY
	MOVE	P,[IOWD PDLLEN,BTSPDL] ;SET UP A PUSH DOWN LIST
	PUSHJ	P,DELPGS	;KILL USELESS PAGES

GO:
LOADR1:	PUSHJ	P,QINIT		;INIT QUESTION BUFFER
	MOVEI	T1,[ASCIZ/Create binary output files/]
	PUSHJ	P,QTEXT		;STORE IN BUFFER
	PUSHJ	P,QYNT		;APPEND [Y/N] AND TERMINATE BUFFER
	MOVEI	T2,[ASCIZ/No/]	;DEFAULT ANSWER
	PUSHJ	P,ASKYN		;ASK
	  JRST	LOADR1		;CONFUSED USER
	  TDZA	T1,T1		;USER SAID NO
	MOVEI	T1,1		;USER SAID YES
	MOVEM	T1,BINFLG	;SAVE FLAG
	JUMPN	T1,LOADR3	;SKIP DDT QUESTION IF WRITING FILES

LOADR2:	SKIPN	.JBDDT		;DDT LOADED?
	JRST	LOADR3		;NO
	PUSHJ	P,QINIT		;INIT QUESTION BUFFER
	MOVEI	T1,[ASCIZ/Preserve EDDT and symbols/]
	PUSHJ	P,QTEXT		;STORE IN BUFFER
	PUSHJ	P,QYNT		;APPEND [Y/N] AND TERMINATE BUFFER
	MOVEI	T2,[ASCIZ/No/]	;DEFAULT ANSWER
	PUSHJ	P,ASKYN		;ASK
	  JRST	LOADR2		;CAN'T DECIDE
	  PUSHJ	P,DELDDT	;ZAP OLD LOADER+DDT+SYMBOLS

LOADR3:	PUSHJ	P,HIADDR	;FIND HIGHEST ADDRESS IN USE
	MOVEM	T1,UCODSA	;SAVE AS UCODE STARTING ADDRESS
	MOVEM	T1,LOADFF	;SAVE FIRST FREE LOCATION
	MOVSI	U,-UCDNUM	;FOR INDEXING INTO UCODE TABLES

LOADR4:	SKIPN	UCDTXT(U)	;THIS A REAL ENTRY?
	JRST	LOADR5		;NO
	PUSHJ	P,QINIT		;INIT QUESTION BUFFER
	MOVEI	T1,[ASCIZ/Load /]
	PUSHJ	P,QTEXT		;STORE IN BUFFER
	MOVE	T1,UCDTXT(U)	;GET TEXT
	PUSHJ	P,QTEXT		;STORE IN BUFFER
	PUSHJ	P,QYNT		;APPEND [Y/N] AND TERMINATE BUFFER
	MOVEI	T2,[ASCIZ/No/]	;DEFAULT ANSWER
	PUSHJ	P,ASKYN		;ASK
	  JRST	LOADR4		;CONFUSED USER
	  JRST	LOADR5		;DON'T WANT IT
	PUSHJ	P,LODFIL	;LOAD A FILE
	  JRST	LOADR4		;GIVE THE GUY A CHANCE TO FIX THINGS

LOADR5:	AOBJN	U,LOADR4	;LOOP BACK FOR ANOTHER UCODE
	SKIPN	BINFLG		;WRITING BINARY FILES?
	JRST	LOADR6		;NO
	EXIT	1,		;DONE
	JRST	LOADER		;THE FOOL TYPED CONTINUE

LOADR6:	PUSHJ	P,MEMMAP	;DISPLAY MEMORY MAP
	DMOVE	T1,.JBSYM	;GET POINTER TO SYMBOL TABLES
	DMOVEM	T1,BTSVEC+.BTSYM ;SAVE FOR DEBUGGING
	MOVEI	T1,BOOT		;GET START ADDRESS
	HRRM	T1,.JBSA	;STORE IT
IFN FTKL10,<
	PUSHJ	P,EXBFIL	;WRITE AN EXB FILE FOR RSX-20F
>; END IFN FTKL10
	MOVSI	T1,SAVBLT	;WHERE THE FINAL INSTRUCTIONS LIVE
	HRRI	T1,.JBBLT	;AND WHERE THEY'RE MOVING TO
	BLT	T1,.JBBLT+3	;MOVE SAVE. UUO INTO PLACE
	MOVSI	17,SAVCOD	;POINT TO CODE THAT RUNS IN THE ACS
	BLT	17,17		;LOAD THE ACS
	JRST	SAVGO		;DELETE LOADER, DO SAVE, AND EXIT
SUBTTL	FILE LOADERS -- DISPATCH


LODFIL:	SETZM	UCODWD		;CLEAR WORD COUNT
	SETZM	UCODCK		;AND THE CHECKSUM
	SETZM	UCODVR		;AND THE VERSION NUMBER
	MOVSI	T1,UCODBF	;POINT TO START OF TEMP STORAGE
	HRRI	T1,UCODBF+1	;MAKE A BLT POINTER
	SETZM	UCODBF		;CLEAR FIRST WORD
	BLT	T1,UCODBF+UCDSIZ-1 ;CLEAR TEMP STORAGE
	MOVE	T1,UCDNAM(U)	;GET FILE NAME
	HLLZ	T2,UCDEXT(U)	;GET EXTENSION
	MOVE	T3,UCDMOD(U)	;GET I/O MODE
	PUSHJ	P,SETIO		;SET UP FOR I/O
	MOVEI	T1,.FORED	;FILOP FUNCTION
	PUSHJ	P,FILOP		;DO IT
	  JRST	OPNERR		;FAILED
	MOVSI	T1,-FMTLEN	;-LENGTH OF TABLE
	HRRI	T1,FMTTAB	;MAKE AN AOBJN POINTER
LODFI1:	HLLZ	T2,(T1)		;GET AN EXTENSION
	CAME	T2,UCDEXT(U)	;A MATCH?
	AOBJN	T1,LODFI1	;NO
	SKIPL	T1
	HALT	.
	HRRZ	T2,(T1)		;GET DISPATCH ADDRESS
	PUSHJ	P,(T2)		;LOAD FILE
	  JRST	LODFI4		;FAILED
	SKIPE	BINFLG		;WRITING BINARY FILES?
	JRST	LODFI2		;YES
	PUSHJ	P,GETCOR	;ALLOCATE CORE
	  JRST	LODFI4		;FAILED--ALL DONE HERE
	MOVE	T1,UCDPTR(U)	;GET UCODE POINTER INTO VECTOR
	MOVE	T2,UCODWD	;GET WORD COUNT
	AOS	T2		;PLUS ONE FOR THE VERSION WORD
	MOVE	T3,LOADFF	;AND LOAD ADDRESS
	SUBI	T3,BTSVEC	;OFFSET FROM THE START OF THE VECTOR
	DMOVEM	T2,(T1)		;SAVE IN VECTOR
	MOVE	T1,UCODVR	;GET THE VERSION
	MOVEM	T1,@LOADFF	;SAVE
	AOS	LOADFF		;ADVANCE
	MOVSI	T1,UCODBF	;POINT TO TEMP STORAGE
	HRR	T1,LOADFF	;AND TO PERMANENT STORAGE
	MOVE	T2,UCODWD	;GET WORD COUNT
	ADD	T2,LOADFF	;COMPUTE END OF BLT
	BLT	T1,-1(T2)	;COPY
	MOVE	T1,UCODWD	;GET WORD COUNT AGAIN
	ADDM	T1,LOADFF	;UPDATE FIRST FREE LOCATION
	JRST	LODFI3		;FINISH UP
LODFI2:	RELEAS	IOC,		;RELEASE CHANNEL
	PUSHJ	P,WRTBIN	;WRITE OUT BINARY FILE
	  POPJ	P,		;FAILED

LODFI3:	AOS	(P)		;SKIP
LODFI4:	RELEAS	IOC,		;RELEASE CHANNEL
	POPJ	P,		;AND RETURN
FMTTAB:	XWD	'A8 ',A8L	;A8  FORMAT LOADER
	XWD	'ADX',ADX	;ADX FORMAT LOADER
	XWD	'ULD',ULD	;ULD FORMAT LOADER
FMTLEN==.-FMTTAB		;LENGTH OF TABLE


LODER2:	PUSHJ	P,PRCRLF	;START WITH A CRLF
	MOVEI	T1,[ASCIZ/? Input error reading /]
	PUSHJ	P,PRMSG		;TYPE TEXT
	PUSHJ	P,PRFILE	;PRINT FILESPEC
	PUSHJ	P,PRCRLF	;FINISH WITH A CRLF
	JRST	LODFI4		;GO EXIT THROUGH COMMON CLEANUP CODE

FMTERR:	MOVEI	T1,[BYTE (7).CHCRT,.CHLFD,"?"," ",0]
	PUSHJ	P,PRMSG		;START ERROR MESSAGE
	HLLZ	T1,UCDEXT(U)	;GET UCODE EXTENSION
	PUSHJ	P,PRSIX		;PRINT IT
	MOVEI	T1,[ASCIZ / file format error reading /]
	PJRST	FILERR		;PRINT FILESPEC AND RETURN

OPNERR:	MOVEI	T1,[ASCIZ /Open failed for /]
	JRST	IOEERR		;ENTER COMMON CODE
INPERR:	MOVEI	T1,[ASCIZ /Input error reading /]
	JRST	IOEERR		;ENTER COMMON CODE
OUTERR:	MOVEI	T1,[ASCIZ /Output error writing /]
	JRST	IOEERR		;ENTER COMMON CODE
UEFERR:	MOVEI	T1,[ASCIZ /Unexpected EOF reading /]
	JRST	IOEERR		;ENTER COMMON CODE
CHKERR:	MOVEI	T1,[ASCIZ /File data checksum error reading /]
IOEERR:	PUSH	P,T1		;SAVE T1
	MOVEI	T1,[BYTE (7).CHCRT,.CHLFD,"?"," ",0]
	PUSHJ	P,PRMSG		;START ERROR MESSAGE
	POP	P,T1		;GET START OF TEXT
FILERR:	PUSHJ	P,PRMSG		;PRINT TEXT
	PUSHJ	P,PRFILE	;PRINT FILESPEC
	PJRST	PRCRLF		;END WITH A CRLF
SUBTTL	FILE LOADERS -- A8 FORMAT


A8L:	MOVSI	T1,(POINT 7,)	;BYTE POINTER
	PUSHJ	P,SETBUF	;SET UP BUFFERS
	MOVE	T1,[BYTE (12)7402,7402,7402] ;PDP-8 HALT INSTRUCTIONS
	MOVEM	T1,UCODBF	;SAVE IN BUFFER
	MOVE	T1,[UCODBF,,UCODBF+1] ;SET UP BLT
	BLT	T1,UCODBF+<10000/3>-1 ;FILL ENTIRE BUFFER
A8L1:	PUSHJ	P,WCREAD	;GET WORD COUNT IN WC
	JUMPE	T1,A8L3		;ALMOST DONE IF ZERO
	MOVE	T4,T1
	PUSHJ	P,WDREAD	;GET DATA WORD
	PUSH	P,T2
	IDIVI	T1,3
	ADDI	T1,UCODBF	;INDEX INTO BUFFER
	MOVE	T3,T1		;COPY ADDRESS
	IMULI	T2,^D12
	MOVEI	T1,^D36
	SUB	T1,T2
	LSH	T1,^D12
	IORI	T1,^D12_6
	HRLM	T1,T3		;FORM BYTE PNTR
	POP	P,T2		;RESTORE
A8L2:	PUSHJ	P,WDREAD	;GET WORD
	IDPB	T1,T3		;STASH WORD
	SOJG	T4,A8L2		;LOOP THROUGH ALL WORDS
	PUSHJ	P,CHREAD	;READ AND VERIFY CHECKSUM
	JRST	A8L1		;GET NEXT RECORD
A8L3:	MOVEI	T1,<10000/3>	;NUMBER OF PDP-10 WORDS
	MOVEM	T1,UCODWD	;SAVE FOR CORE ALLOCATOR
	LDB	T1,[POINT 12,UCODBF+1,11] ;GET VERSION NUMBER
	DPB	T1,[POINT 9,UCODVR,11] ;SAVE
	JRST	CPOPJ1		;RETURN


;ROUTINE TO READ THE CHECKSUM FROM FILE AND THE CRLF
;CHECK THAT CHECKSUM IS CORRECT
CHREAD:	PUSHJ	P,GET2W		;GET A WORD
	CAIE	T2,.CHCRT	;TERMINATOR BETTER BE CR
	PJRST	FMTERR		;FORMAT ERROR
	ADD	T1,UCODCK	;ADD COMPUTED CHECKSUM
	ANDI	T1,7777		;MASK DOWN
	JUMPN	T1,CHKERR	;JUMP IF CHECKSUM ERROR
	PUSHJ	P,GETBYT	;GET A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
	CAIE	T1,.CHLFD	;DOUBLE CHECK CRLF
	PJRST	FMTERR		;FORMAT ERROR
	POPJ	P,		;RETURN
;PDP-8 A8 UTILITIES

GET2W:	PUSH	P,[0]		;INIT ANSWER
	PUSHJ	P,GETA8		;GET FIRST CHAR
	  JRST	GET2X		;EXIT IF NOT DIGIT
	MOVEM	T1,0(P)		;STASH ON PDL
	PUSHJ	P,GETA8		;GET NEXT
	  JRST	GET2X		;MUST BE SINGLE DIGIT
	EXCH	T1,0(P)		;NEW LOW ORDER BYTE
	LSH	T1,6		;MAKE HIGH ORDER BYTE
	IORM	T1,0(P)		;COMBINE
	PUSHJ	P,GETBYT	;GET A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
GET2X:	MOVE	T2,T1		;RETURN BREAK CHAR IN T2
	POP	P,T1		;RESTORE WORD TO T1
	POPJ	P,		;RETURN

;GET NEXT FILE CHAR AND RETURN LOW 6 BITS
GETA8:	PUSHJ	P,GETBYT	;GET A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
	CAIE	T1,","		;CHECK TERMINATOR
	CAIN	T1,.CHCRT	;CARRIAGE RETURN?
	POPJ	P,		;NON SKIP RETURN
	ANDI	T1,77		;TRIM TO LOW ORDER 6-BIT
	JRST	CPOPJ1		;RETURN

;GET WORD COUNT FFROM FILE

WCCOMM:	PUSHJ	P,SKPCOM	;SKIP COMMENT
WCREAD:	PUSHJ	P,GETBYT	;READ A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
	CAIE	T1,"8"		;CHECK VALIDITY
	JRST	WCCOMM		;SKIP COMMENT AND TRY AGAIN
	PUSHJ	P,GETBYT	;GET A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
	CAIE	T1," "		;BETTER BE A SPACE
	PJRST	FMTERR		;FORMAT ERROR
	SETZM	UCODCK		;INIT CHECKSUM

WDREAD:	PUSHJ	P,GET2W		;GET 12 BIT NUMBER
	ADDM	T1,UCODCK	;ADD TO CHECKSUM
	CAIE	T2,","		;NEED A COMMA
	PJRST	FMTERR		;FORMAT ERROR
	POPJ	P,		;RETURN (ANSWER IN T1)

;ROUTINE TO SKIP COMMENTS
SKPCOM:	CAIE	T1,";"		;VALID COMMENT CHAR?
	PJRST	FMTERR		;FORMAT ERROR
SKPCM1:	PUSHJ	P,GETBYT	;GET A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
	CAIE	T1,.CHLFD	;LINE FEED?
	JRST	SKPCM1		;NO - LOOP
	POPJ	P,		;YES - RETURN
SUBTTL	UCODE FILE PROCESSING -- ADX FORMAT


	CRDAT==UCODBF		;CRAM - 2K*16 BITS
	DRDAT==CRDAT+2000	;DRAM - 1K*8 BITS
	ADXWC==DRDAT+400	;LOAD ADDRESS,,WORD COUNT
	ADXDAT==ADXWC+1		;DATA WORDS

ADX:	MOVSI	T1,(POINT 7,)	;BYTE POINTER
	PUSHJ	P,SETBUF	;SET UP BUFFERS
ADX1:	PUSHJ	P,ADXLIN	;READ A LINE
	JUMPE	T1,ADX4		;DONE?
	MOVNS	T1		;NEGATE WORD COUNT
	HRLZS	T1		;MAKE AN AOBJN POINTER
	SKIPN	T3		;SKIP IF CRAM
	JRST	ADX2		;DRAM
	ROT	T2,-1
	TLZN	T2,400000
	TLOA	T2,442200
	TLO	T2,222200
	ADDI	T2,CRDAT	;FORM LOAD ADDRESS
	JRST	ADX3		;ENTER STORAGE LOOP
ADX2:	IDIVI	T2,4		;COMPUTE STARTING BYTE
	ADD	T2,ADXTAB(T3)	;FORM BYTE POINTER
ADX3:	MOVE	T3,ADXDAT(T1)	;GET A DATA WORD
	IDPB	T3,T2		;STORE
	AOBJN	T1,ADX3		;LOOP THROUGH THIS LINE
	JRST	ADX1		;GO GET ANOTHER LINE
ADX4:	LDB	T1,[POINT 10,CRDAT,17] ;GET EDIT LEVEL
	LDB	T2,[POINT 6,CRDAT,7] ;GET VERSION NUMBER
	LSH	T2,30		;POSITION
	IOR	T1,T2		;FORM STANDARD DEC-10 VERSION NUMBER
	MOVEM	T1,UCODVR	;SAVE
	MOVEI	T1,2000+400	;CRAM + DRAM SIZE
	MOVEM	T1,UCODWD	;SAVE WORD COUNT
	JRST	CPOPJ1		;RETURN

ADXTAB:	POINT	8,DRDAT,	;BYTE 0
	POINT	8,DRDAT,7	;BYTE 1
	POINT	8,DRDAT,15	;BYTE 2
	POINT	8,DRDAT,23	;BYTE 3
;ADXLIN - READS IN A LINE OF DATA WORDS TO BE LOADED INTO CRAM OR
; WORKING MEMORY
;
;	CALL ADXLIN
;
; RETURN+1: ALWAYS
; LINDAT IS THE TALBE WHICH HAS THE CONVERTED DATA WORDS
; T1/ WORD COUNT OF DATA WORDS IN THE TABLE
; T2/ LOAD ADDR
; T3/ 0 FOR WORKING MEMORY, 1 FOR CRAM

ADXLIN:	SETZM	UCODCK		;RESET CHECKSUM
	SETZM	ADXWC		;RESET WORD COUNT
	MOVE	T2,[ADXDAT,,ADXDAT+1] ;INITIALIZE WORK AREA
	SETZM	ADXDAT		;CLEAR FIRST WORD
	BLT	T2,ADXWC+^D32-1	;ZERO LINE BUFFER
	MOVEI	T3,^D32*5	;MAXIMUN NUMBER OF CHARACTERS
	MOVEI	T4,0		;FLAG WORKING MEMORY
	PUSHJ	P,GETBYT	;READ A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
	CAIN	T1,";"		;IS IT COMMENT LINE?
	JRST	ADXLI5		;YES, IGNORE IT
	CAIE	T1,"C"		;CRAM LOAD LINE?
	JRST	ADXLI1		;NO, SEE IF WM LOAD LINE
	MOVEI	T4,1		;SET FLAG FOR CRAM
	JRST	ADXLI2		;JUMP AROUND

ADXLI1:	CAIE	T1,"W"		;WM LOAD LINE?
	PJRST	FMTERR		;FORMAT ERROR

ADXLI2:	PUSHJ	P,GETBYT	;GET A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
	CAIE	T1," "		;MUST BE BLANK
	PJRST	FMTERR		;FORMAT ERROR
	PUSHJ	P,ADXWRD	;GET NEXT WORD
	  PJRST	FMTERR		;FORMAT ERROR
	MOVEM	T1,ADXWC	;SAVE WORD COUNT FOR THE LINE
	MOVEM	T1,UCODCK	;INITIALIZE CHECKSUM FOR THE LINE
	PUSHJ	P,ADXWRD	;GET NEXT WORD
	  PJRST	FMTERR		;FORMAT ERROR
	ADDM	T1,UCODCK	;UPDATE CHKSUM
	DPB	T1,[POINT 16,ADXWC,19]	;SAVE LOAD ADDR.
	MOVSI	T3,-^D32	;SETUP LOOP INDEX FOR SUBSEQUENT WORDS
ADXLI3:	PUSHJ	P,ADXWRD	;GET NEXT WORD
	  JRST ADXLI4		;LAST WORD, CHECKSUM, READ IN T1
	ADDM	T1,UCODCK	;UPDATE CHECKSUM
	MOVEM	T1,ADXDAT(T3)	;SAVE DATA WORD
	AOBJN	T3,ADXLI3	;LOOP BACK
	PJRST	FMTERR		;FORMAT ERROR

ADXLI4:	MOVEM	T1,ADXDAT(T3)	;SAVE EVEN CHECKSUM
	ADD	T1,UCODCK	;ADD CHECKSUM INTO T1
	TRNE	T1,177777	;CHECKSUM SHOULD BE 0
	PJRST	CHKERR		;CHECKSUM RROR
	LDB	T1,[POINT 16,ADXWC,35]	;WC IN T1
	LDB	T2,[POINT 16,ADXWC,19]	;LOAD ADDR. IN T2
	MOVE	T3,T4		;GET CRAM/WORKING MEMORY FLAG
	POPJ	P,		;NONSKIP RETURN

ADXLI5:	PUSHJ	P,GETBYT	;GET A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
	CAIE	T1,.CHLFD	;LINE FEED?
	JRST	ADXLI5		;FLUSH CHARACTER
	JRST	ADXLIN		;ELSE GO PROCESS NEW LINE
;ADXWRD - GET A DATA WORD FROM DATLIN WHICH IS A CHAR. STRING
; CONVERT THE ASCIIZED DATA WORD INTO BINARY
;
;	CALL ADXWRD
;
; RETURN+1: DATA WORD DELIMITED BY CR
; RETURN+2: DATA WORD DELIMITED BY ,
; T1/ CONVERTED DATA WORD

ADXWRD:	SETZ	T2,		;INIT RESULT
ADXWR1:	PUSHJ	P,GETBYT	;GET A BYTE
	  PJRST	UEFERR		;UNEXPECTED EOF
	CAIN	T1,","		;SKIP IF NOT COMMA
	JRST	ADXWR2		;GOT THE DATA WORD
	CAIN	T1,.CHCRT	;SKIP IF NOT CR
	JRST	ADXWR1		;CR, THROW IT AWAY AND LOOK FOR LF
	CAIN	T1,.CHLFD	;LINE FEED?
	JRST	ADXWR3		;GOT LAST DATA WORD IN LINE
	LSH	T2,6		;MAKE ROOM
	CAIE	T1," "		;SKIP IF BLANK
	DPB	T1,[POINT 6,T2,35] ;PUT IN T2, UNASCIIZED THE BYTE
	JRST	ADXWR1		;GET NEXT CHAR.
ADXWR2:	AOS	(P)		;SKIP
ADXWR3:	MOVE	T1,T2		;GET RESULT
	POPJ	P,		;AND RETURN
SUBTTL	UCODE FILE PROCESSING -- ULD FORMAT


; MACRO TO BUILD A BYTE POINTER TO ULD FILE DATA
DEFINE	ULDPNT	(SS,YY,PP),<
	AA==YY*^D60+^D<PP>
	WW==AA/^D36
	XX==AA-<WW*^D36>
	POINT	^D<SS>,UCODBF+WW,XX
	PURGE	AA,WW,XX
>

ULD:	MOVSI	T1,(POINT 7,)	;BYTE POINTER
	PUSHJ	P,SETBUF	;SET UP BUFFERS
ULD1:	PUSHJ	P,GETBYT	;GET A BYTE
	  JRST	ULDEOF		;EOF
	CAIE	T1,"["		;DATA?
	JRST	ULD3		;NO--SKIP REMAINDER OF LINE
	PUSHJ	P,OCTIN		;READ AN OCTAL DOUBLEWORD
	  PJRST	UEFERR		;FORMAT ERROR
	JUMPN	T1,FMTERR	;CHECK FOR FORMAT ERRORS
	CAIL	T2,0
	CAILE	T2,10000-1
	PJRST	FMTERR		;FORMAT ERROR
	MOVE	T3,T2		;SAVE LOW WORD
	MOVE	T1,LSTBYT	;GET LAST BYTE READ
	CAIE	T1,"]"		;END?
	PJRST	FMTERR		;NO--FORMAT ERROR
	PUSHJ	P,GETBYT	;GET A BYTE
	  JRST	ULDEOF		;EOF
	CAIE	T1,"="		;DATA ON THE WAY?
	PJRST	FMTERR		;NO--FORMAT ERROR
	PUSHJ	P,OCTIN		;READ AN OCTAL DOUBLEWORD
	  PJRST	FMTERR		;FORMAT ERROR
	IMULI	T3,^D60		;60 BITS PER ENTRY
	IDIVI	T3,^D36		;36 BITS PER WORD
	MOVNS	T4		;COUNT BITS FROM RIGHT
	ADDI	T4,^D36
	LSH	T4,^D30
	TLO	T4,^D12*100
	ADDI	T4,UCODBF(T3)	;OFFSET TO APPROPRIATE WORD
	MOVEI	T3,^D60/^D12	;NUMBER OF DPB'S TO DO
	ROTC	T1,^D12		;FLUSH NOISE BITS
ULD2:	ROTC	T1,^D12		;GET NEXT 12 BITS
	IDPB	T2,T4
	SOJN	T3,ULD2		;LOOP
	MOVE	T1,LSTBYT	;GET LAST BYTE READ AGAIN

;HERE TO EAT THE REST OF THE LINE
ULD3:	CAIN	T1,.CHLFD	;LINE FEED?
	JRST	ULD1		;YES--GO TRY FOR MORE DATA
	PUSHJ	P,GETBYT	;GET A BYTE
	  JRST	ULDEOF		;EOF
	JRST	ULD3		;FLUSH

;HERE ON EOF
ULDEOF:	LDB	T1,[ULDPNT (03,136,17)] ;MAJOR VERSION
	DPB	T1,[POINT 9,UCODVR,11]
	LDB	T1,[ULDPNT (06,136,23)] ;MINOR VERSION
	DPB	T1,[POINT 6,UCODVR,17]
	LDB	T1,[ULDPNT (10,137,23)] ;EDIT LEVEL
	HRRM	T1,UCODVR
	MOVEI	T1,<<10000*^D60+^D35>/^D36> ;WORD COUNT
	MOVEM	T1,UCODWD	;SAVE
	JRST	CPOPJ1		;RETURN
WRTBIN:	MOVE	T1,UCDNAM(U)	;GET FILE NAME
	MOVSI	T2,'BIN'	;GET EXTENSION
	MOVEI	T3,.IODMP	;DUMP MODE
	PUSHJ	P,SETIO		;SET UP FOR I/O
	MOVE	T1,UCODVR	;GET UCODE VERSION NUMBER
	MOVEM	T1,LEB+.RBVER	;SAVE
	MOVEI	T1,.FOWRT	;FILOP FUNCTION
	PUSHJ	P,FILOP		;DO IT
	  PJRST	OPNERR		;FAILED
	MOVN	T1,UCODWD	;GET -WORD COUNT
	SOS	T1		;ACCOUNT FOR VERSION WORD TOO
	HRLI	T1,UCODVR-1	;POINT TO START OF BUFFER
	MOVSS	T1		;MAKE AN IOWD
	SETZ	T2,		;TERMINATE LIST
	OUT	IOC,T1		;WRITE IT OUT
	SKIPA			;NO PROBLEMS
	PJRST	OUTERR		;REPORT ERROR
	PUSHJ	P,PRLBKT	;START MESSAGE WITH A BRACKET
	MOVEI	T1,[ASCIZ /Microcode version /]
	PUSHJ	P,PRMSG		;PRINT TEXT
	MOVE	T1,UCODVR	;GET VERSION
	PUSHJ	P,PRVRSN	;PRINT IT
	MOVEI	T1,[ASCIZ / written to /]
	PUSHJ	P,PRMSG		;PRINT TEXT
	PUSHJ	P,PRFILE	;PRINT FILESPEC
	PUSHJ	P,PRRBCR	;FINISH WITH A TRAILING BRACKET AND CRLF
	JRST	CPOPJ1		;RETURN
DELPGS:	MOVNI	T2,<<BTSVEC-LOADEN>_-11> ;PAGES TO KILL
	MOVEI	T3,<<LOADEN+PAGSIZ>_-11> ;STARTING PAGE NUMBER
	PUSHJ	P,KILPGS	;DELETE PAGES
	PUSHJ	P,HIPAGE	;GET THE HIGHEST PAGE IN BOOT
	MOVE	T2,T1		;COPY PAGE NUMBER
	ADD	T2,[-1000]	;PAGES TO KILL
	MOVE	T3,T1		;STARTING PAGE NUMBER
	PUSHJ	P,KILPGS	;DELETE PAGES
	POPJ	P,		;RETURN

DELDDT:	PUSHJ	P,HIPAGE	;GET HIGHEST PAGE IN USE
	MOVEI	T2,<<DDT##+PAGSIZ>_-11> ;STARTING PAGE NUMBER
	MOVE	T3,T2		;COPY
	SUBI	T2,(T1)		;PAGES TO KILL
	PUSHJ	P,KILPGS	;DELETE PAGES
	MOVEI	T1,0		;DDT IS GONE
	SETDDT	T1,		;ZERO DDT START ADDRESS
	MOVSI	T1,(JFCL)	;NO-OP
	HLLM	T1,BTSVEC+.BTDDT ;CAN'T ENTER DDT THE NORMAL WAY
	HLLM	T1,BTSVEC+.BTBPT ; OR BY TYPING CONTROL-D
	SETZM	.JBBPT		;ZERO UNSOLICITED BREAKPOINT ADDRESS
	SETZM	.JBSYM		;ZERO SYMBOL TABLE POINTER
	SETZM	.JBUSY		;ZERO UNDEFINED SYMBOL TABLE POINTER
	POPJ	P,		;RETURN

KILPGS:	MOVE	T1,[.PAGCD,,T2]	;SET UP UUO AC
	TLO	T3,(PA.GAF!PA.GDC) ;DELETE PAGES, OK OF NON-EXISTANT
	PAGE.	T1,		;DELETE THEM
	  HALT	.
	POPJ	P,		;RETURN
; COMPUTE THE HIGHEST ADDRESS OR PAGE IN BOOT (AND POSSIBLY DDT)
HIADDR:	TDZA	T3,T3		;ADDR ENTRY POINT
HIPAGE:	MOVEI	T3,1		;PAGE ENTRY POINT
	MOVEI	T1,BTSEND	;HIGHEST ADDRESS
	SKIPN	.JBDDT		;DDT LOADED?
	JRST	HIEXIT		;FINISH UP
	MOVEI	T1,<DDTEND##!<PAGSIZ-1>> ;HIGHEST ADDRESS
	SKIPN	T2,.JBSYM	;SYMBOLS LOADED?
	JRST	HIEXIT		;FINISH UP
	HLRE	T1,T2		;GET -LENGTH OF SYMBOL TABLE
	MOVNS	T1		;MAKE POSITIVE
	ADDI	T1,(T2)		;POINT TO END OF SYMBOL TABLE
HIEXIT:	JUMPE	T3,CPOPJ	;RETURN IF NO CONVERSION NEEDED
	ADDI	T1,PAGSIZ	;ROUND UP
	LSH	T1,-11		;CONVERT TO A PAGE NUMBER
	POPJ	P,		;RETURN

; ROUTINE TO ALLOCATION PAGES FOR MICROCODE STORAGE
GETCOR:	MOVE	T1,[.PAGCD,,T2]	;SET UP UUO TO CREATE NECESSARY PAGES
	MOVN	T2,UCODWD	;GET WORDS NEEDED
	SOS	T2		;PLUS (MINUS) ONE WORD FOR THE VERSION
	SUBI	T2,PAGSIZ	;ROUND UP (DOWN?)
	ASH	T2,W2PLSH	;CONVERT TO -NUMBER OF PAGES NEEDED
	MOVE	T3,LOADFF	;GET FIRST FREE LOCATION
	LSH	T3,W2PLSH	;CONVERT TO A PAGE NUMBER
	TLO	T3,(PA.GDC)	;DON'T CARE IF PAGES ALREADY EXIST
	PAGE.	T1,		;CREATE SOME PAGES
	  CAIA			;FAILED
	JRST	CPOPJ1		;RETURN
	PUSHJ	P,PRCRLF	;START WITH A CRLF
	MOVEI	T1,[ASCIZ/? PAGE. UUO error (/]
	PUSHJ	P,PRMSG		;TYPE TEXT
	POP	P,T1		;GET ERROR CODE
	PUSHJ	P,PROCT		;TYPE IT
	MOVEI	T1,[ASCIZ/) creating pages/]
	PUSHJ	P,PRMSG		;TYPE TEXT
	PJRST	PRCRLF		;END WITH A CRLF AND RETURN
MEMMAP:	MOVEI	T1,MEMTX1	;POINT TO HEADER TEXT
	PUSHJ	P,PRMSG		;TYPE IT
	MOVEI	T4,BTSVEC	;GET START ADDRESS OF BOOT
	PUSHJ	P,PRHWDR	;TYPE IT
	PUSHJ	P,SPACES	;SPACE OVER
	SKIPN	T4,.JBDDT	;GET DDT STARTING ADDRESS (IF ANY)
	MOVE	T4,UCODSA	;GET UCODE STARTING ADDRESS
	HRRZS	P1,T4		;SAVE ADDR
	SUBI	T4,1		;BACK OFF BY ONE FOR BOOTSTRAP END ADDRESS
	PUSHJ	P,PRHWDR	;TYPE ENDING BOOTSTRAP ADDRESS
	PUSHJ	P,SPACES	;SPACE OVER
	MOVEI	T4,-BTSVEC(P1)	;COMPUTE BOOTSTRAP LENGTH
	PUSHJ	P,PRHWDR	;TYPE IT
	PUSHJ	P,SPACES	;SPACE OVER
	MOVE	T1,BTSVEC+.BTVER ;GET OUR VERSION
	PUSHJ	P,PRVRSN	;PRINT IT
	PUSHJ	P,PRCRLF	;END LINE
	SKIPN	.JBDDT		;EDDT LOADED?
	JRST	MEMMA1		;NO
	MOVEI	T1,[ASCIZ/EDDT + symbol table  /]
	PUSHJ	P,PRMSG		;TYPE TEXT
	HRRZ	T4,.JBDDT	;GET START ADDRESS
	MOVE	P1,T4		;COPY
	PUSHJ	P,PRHWDR	;TYPE IT
	PUSHJ	P,SPACES	;SPACE OVER
	MOVE	T2,.JBSYM	;GET POINTER TO SYMBOL TABLE
	HLRE	T4,T2		;GET -VE LENGTH
	MOVNS	T4		;MAKE POSITIVE
	ADDI	T4,-1(T2)	;GET END ADDRESS
	PUSH	P,T4		;SAVE A BIT
	PUSHJ	P,PRHWDR	;TYPE IT
	PUSHJ	P,SPACES	;SPACE OVER
	POP	P,T4		;RESTORE END ADDRESS
	SUBI	T4,(P1)		;COMPUTE LENGTH
	PUSHJ	P,PRHWDR	;TYPE IT
	PUSHJ	P,SPACES	;SPACE OVER
	MOVE	T1,[%%DDT##]	;GET DDT VERSION
	PUSHJ	P,PRVRSN	;PRINT IT
	PUSHJ	P,PRCRLF	;END LINE
MEMMA1:	MOVSI	U,-UCDNUM	;FOR INDEXING INTO UCODE TABLES

MEMMA2:	SKIPE	P1,UCDPTR(U)	;GET STORAGE ADDRESS/COUNT POINTER
	SKIPN	0(P1)		;LENGTH SET?
	JRST	MEMMA3		;UCODE ISN'T INCLUDED
	MOVE	T1,UCDTXT(U)	;GET TEXT
	PUSHJ	P,PRMSG		;TYPE IT
	PUSHJ	P,SPACES	;SPACE OVER
	MOVE	T4,1(P1)	;GET UCODE OFFSET
	ADDI	T4,BTSVEC	;PLUS THE ORIGIN
	PUSHJ	P,PRHWDR	;TYPE IT
	PUSHJ	P,SPACES	;SPACE OVER
	MOVE	T4,0(P1)	;GET UCODE LENGTH
	ADD	T4,1(P1)	;FIND STARTING OFFSET
	ADDI	T4,BTSVEC-1	;AND THE ADDRESS
	PUSHJ	P,PRHWDR	;TYPE IT
	PUSHJ	P,SPACES	;SPACE OVER
	MOVE	T4,0(P1)	;GET LENGTH AGAIN
	PUSHJ	P,PRHWDR	;TYPE IT
	PUSHJ	P,SPACES	;SPACE OVER
	MOVE	T1,1(P1)	;GET UCODE OFFSET
	ADDI	T1,BTSVEC	;PLUS THE ORIGIN
	MOVE	T1,(T1)		;GET UCODE VERSION
	PUSHJ	P,PRVRSN	;PRINT IT
	PUSHJ	P,PRCRLF	;END LINE

MEMMA3:	AOBJN	U,MEMMA2	;LOOP
	MOVEI	T1,MEMTX2	;POINT TO SUMMARY TEXT
	PUSHJ	P,PRMSG		;TYPE IT
	MOVE	T4,LOADFF	;POINT TO LAST WORD+1 USED
	SUBI	T4,BTSVEC	;COMPUTE TOTAL LENGTH
	HRRZM	T4,BTSVEC+.BTSIZ ;SAVE IN VECTOR
	MOVEI	T1,PAGSIZ(T4)	;COPY LENGTH AND ROUND UP A PAGE
	LSH	T1,W2PLSH	;CONVERT TO PAGES
	MOVNS	T1		;NEGATE
	HRLM	T1,BTSVEC+.BTSIZ ;SAVE -SIZE IN PAGES
	PUSHJ	P,PRHWDR	;TYPE IT
	PUSHJ	P,PRCRLF	;TYPE A CRLF
	PJRST	PRCRLF		;ONE MORE AND RETURN
MEMTX1:	ASCIZ	/

     Memory  map      From     To     Size    Version
                     ------  ------  ------  ---------
Bootstrap            /


MEMTX2:	ASCIZ	/
Total size                           /
SPACES:	MOVEI	T1,[ASCIZ /  /]
	PJRST	PRMSG		;SPACE OVER

QINIT:	MOVEI	T1,<QWDS*5>-1	;MAXIMUM CHARACTER COUNT
	MOVEM	T1,QCTR		;SAVE
	MOVEI	T1,QBUF		;POINT TO BUFFER
	HRLI	T1,(POINT 7,)	;MAKE A BYTE POINTER
	MOVEM	T1,QPTR		;SAVE
	POPJ	P,		;RETURN

QTEXT:	HRLI	T1,(POINT 7,)	;MAKE A BYTE POINTER
QTEXT1:	ILDB	T2,T1		;GET A CHARACTER
	JUMPE	T2,CPOPJ	;RETURN IF END OF STRING
	IDPB	T2,QPTR		;PUT A CHARACTER
	JRST	QTEXT1		;LOOP

QYNT:	MOVEI	T1,[ASCIZ\ [Y/N]: \]
	PUSHJ	P,QTEXT		;APPEND TO QUESTION BUFFER
	MOVEI	T1,.CHNUL	;GET A NUL
	IDPB	T1,QPTR		;TERMINATE BUFFER
	MOVEI	T1,QBUF		;POINT TO BUFFER
	POPJ	P,		;AND RETURN
DEFINE	X	(L,PFX,NAM,EXT,TXT,MOD,SIZ),<<SIXBIT /NAM/>>
UCDNAM:	UCODES

DEFINE	X	(L,PFX,NAM,EXT,TXT,MOD,SIZ),<<SIXBIT /EXT/>>
UCDEXT:	UCODES

DEFINE	X	(L,PFX,NAM,EXT,TXT,MOD,SIZ),<
	IFE <L>,<EXP 0>
	IFN <L>,<EXP BTSVEC+.BTUCD+.BT'PFX>
>
UCDPTR:	UCODES

DEFINE	X	(L,PFX,NAM,EXT,TXT,MOD,SIZ),<
	IFE <L>,<EXP 0>
	IFN <L>,<EXP [ASCIZ |TXT|]>
>
UCDTXT:	UCODES

DEFINE	X	(L,PFX,NAM,EXT,TXT,MOD,SIZ),<EXP	MOD>
UCDMOD:	UCODES
	SUBTTL	GENERATE .EXB FILE FOR RSX-20F

IFN FTKL10,<
EXBFIL:	MOVE	T1,['BOOT  ']	;FILE NAME
	MOVSI	T2,'EXB'	;EXTENSION
	MOVEI	T3,.IOIMG	;I/O MODE
	PUSHJ	P,SETIO		;SET UP I/O AND OPEN CHANNEL
	MOVEI	T1,.FOWRT	;WRITE FUNCTION
	PUSHJ	P,FILOP		;CREATE THE FILE
	  HALT	.
	MOVSI	T1,(POINT 18,)	;BYTE POINTER FOR BUFFERED MODE
	PUSHJ	P,SETBUF	;SET UP BUFFERS
	MOVEI	T1,BTSVEC	;POINT TO START OF BOOTSTRAP
	MOVEM	T1,EXBPTR	;SAVE
	SETZB	P1,EXBSTA	;INIT BYTE STORAGE AND START ADDRESS FLAG
EXBFI1:	PUSHJ	P,EXBREC	;BUILD A RECORD
	  JRST	EXBFI3		;RAN OUT OF DATA
	MOVE	T1,RECCNT	;GET RECORD BYTE COUNT
	PUSHJ	P,EXBPU2	;WRITE IT OUT
	  HALT	.
EXBFI2:	SOSGE	RECCNT		;COUNT BYTES
	JRST	EXBFI1		;GO DO ANOTHER RECORD
	ILDB	T1,RECPTR	;GET A BYTE
	PUSHJ	P,EXBPUT	;WRITE IT OUT
	  HALT	 .
	JRST	EXBFI2		;LOOP BACK FOR ANOTHER BYTE
EXBFI3:	SKIPL	T1,P1		;ONE MORE BYTE TO OUTPUT?
	JRST	EXBFI4		;NO
	PUSHJ	P,PUTBYT	;WRITE IT OUT
	  HALT	.
EXBFI4:	RELEAS	IOC,		;CLOSE AND RELEASE CHANNEL
	POPJ	P,		;RETURN
; EXB RECORD GENERATOR
EXBREC:	SKIPE	EXBSTA		;HAVE WE WRITTEN THE START ADDRESS YET?
	POPJ	P,		;YES--DONE
	MOVSI	T1,(POINT 8,)	;8-BIT BYTES
	HRRI	T1,RECBUF	;POINT TO RECORD BUFFER
	MOVEM	T1,RECPTR	;SAVE
	SETZM	RECCNT		;RESET BYTE COUNT
	PUSHJ	P,EXBDAT	;GET AOBJN POINTER TO DATA
	  SKIPA	T1,BTSVEC+.BTSTA ;ALL THAT'S LEFT IS THE START ADDRESS
	JRST	EXBRE1		;GOT ONE
	HRLI	T1,-1		;MAKE AN AOBJN POINTER
	MOVNI	T2,5		;FUDGE BYTE COUNT
	MOVEM	T2,RECCNT	; JUST A LITTLE BIT
	SETOM	EXBSTA		;INDICATE WRITING START ADDRESS
EXBRE1:	HRRZM	T1,EXBLDA	;SAVE LOAD ADDRESS
	ADJSP	T1,-1		;COMPENSATE FOR AOBJN LATER ON
	PUSH	P,T1		;SAVE LOAD ADDRESS ON STACK
	MOVEI	T1,EXBLDA	;POINT TO LOAD ADDRESS STORAGE
	TDZA	T3,T3		;PROCESSING BYTE COUNT AND ADDRESS NOW
EXBRE2:	MOVEI	T3,1		;PROCESSING DATA NOW
	LDB	T2,[POINT 8,(T1),35] ;PDP-11 BYTE #0
	IDPB	T2,RECPTR
	LDB	T2,[POINT 8,(T1),27] ;PDP-11 BYTE #1
	IDPB	T2,RECPTR
	LDB	T2,[POINT 8,(T1),19] ;PDP-11 BYTE #2
	IDPB	T2,RECPTR
	LDB	T2,[POINT 8,(T1),11] ;PDP-11 BYTE #3
	IDPB	T2,RECPTR
	JUMPE	T3,EXBRE3	;JUMP IF NOT PROCESSING DATA
	LDB	T2,[POINT 4,(T1),03] ;OVERFLOW HALF-BYTE
	IDPB	T2,RECPTR
	AOSA	EXBPTR		;ADVANCE LOAD ADDRESS WORD
EXBRE3:	POP	P,T1		;GET BACK AOBJN POINTER
	MOVEI	T2,4(T3)	;MUST ACCOUNT FOR ALL BYTES PROCESSED
	ADDM	T2,RECCNT	;ACCUMULATE
	AOBJN	T1,EXBRE2	;GO BACK FOR ANOTHER WORD
	MOVSI	T1,(POINT 8,)	;BYTE POINTER FOR
	HRRI	T1,RECBUF	; READING DATA
	MOVEM	T1,RECPTR	;SAVE IT
	JRST	CPOPJ1		;RETURN
; GENERATE AOBJN POINTER TO EXB DATA
EXBDAT:	MOVEI	T1,0		;INIT WORD COUNT
	MOVE	T2,EXBPTR	;GET STARTING LOAD ADDRESS
EXBDA1:	CAMLE	T2,LOADFF	;END OF BOOTSTRAP?
	POPJ	P,		;YES
	SKIPN	(T2)		;ZERO?
	AOJA	T2,EXBDA1	;YES--COMPRESS ZEROS
	MOVEM	T2,EXBPTR	;UPDATE LOAD ADDRESS
EXBDA2:	CAMG	T2,LOADFF	;END OF BOOTSTRAP?
	SKIPN	(T2)		;NEED TO ZERO COMPRESS?
	JRST	EXBDA3		;YES
	AOS	T2		;ADVANCE POINTER
	CAMLE	T1,[-EXBMAX]	;WILL THIS FILL UP THE RECORD?
	SOJA	T1,EXBDA2	;NO--KEEP COUNTING
EXBDA3:	HRL	T1,EXBPTR	;GET LOAD ADDRESS
	MOVSS	T1		;MAKE AN AOBJN POINTER
	JRST	CPOPJ1		;AND RETURN
; STORE BYTES IN THE EXB FILE
EXBPUT:	ANDI	T1,377		;SMALL MACHINES USE SMALL BYTES
	JUMPL	P1,EXBPU1	;BYTE LEFT OVER FROM BEFORE?
	TLO	T1,400000	;INDICATE INCOMPLETE 16-BIT BYTE
	MOVE	P1,T1		;SAVE BYTE
	JRST	CPOPJ1		;RETURN
EXBPU1:	LSH	T1,10		;SHIFT NEW BYTE TO HIGH BYTE
	IOR	T1,P1		;PUT IN THE LOW BYTE FROM LAST CALL
	MOVEI	P1,0		;RESET OLD BYTE FOR NEXT TIME
EXBPU2:	EXCH	T1,P1		;SAVE NEW BYTE, GET OLD ONE
	JUMPGE	T1,EXBPU3	;JUMP IF NO BYTE LEFT OVER FROM BEFORE
	PUSHJ	P,PUTBYT	;STORE IN FILE
	  HALT	.	
EXBPU3:	MOVE	T1,P1		;GET NEW BYTE BACK
	MOVEI	P1,0		;RESET OLD BYTE FOR NEXT TIME
	PUSHJ	P,PUTBYT	;STORE NEW BYTE IN FILE
	  HALT	.
	JRST	CPOPJ1		;AND RETURN
>; END IFN FTKL10
; SET UP FOR I/O
; CALL:	MOVE	T1, FILE NAME
;	MOVE	T2, EXTENSION
;	MOVE	T3, I/O MODE BITS
;	PUSHJ	P,SETIO

SETIO:	PUSH	P,T1		;SAVE FILE NAME
	PUSH	P,T2		;SAVE EXTENSION
	MOVSI	T1,F.ZBEG	;FIRST CLEAR
	HRRI	T1,F.ZBEG+1	; THE FILE
	SETZM	F.ZBEG		;  STORAGE
	BLT	T1,F.ZEND-1	;   AREA
	MOVSI	T1,<(FO.PRV)>!IOC ;PRIV BIT + CHANNEL NUMBER
	MOVEM	T1,FOP+.FOFNC
	MOVEM	T3,FOP+.FOIOS	;SAVE I/O MODE
	MOVSI	T1,'DSK'	;DEVICE
	MOVEM	T1,FOP+.FODEV
	MOVSI	T1,OBR		;OUTPUT BUFFER RING HEADER
	HRRI	T1,IBR		;INPUT BUFFER RING HEADER
	ANDI	T3,17		;KEEP ONLY THE MODE
	CAIE	T4,.IODMP	;DUMP MODE?
	MOVEM	T1,FOP+.FOBRH	;NO--MUST SAVE RING HEADER POINTERS
	MOVEI	T1,LEB		;POINT TO LOOKUP/ENTER BLOCK
	MOVEM	T1,FOP+.FOLEB
	MOVE	T1,[.FOFMX,,FSP] ;POINT TO RETURNED FILESPEC BLOCK
	MOVEM	T1,FOP+.FOFSP
	MOVEI	T1,.RBMAX	;LENGTH OF LOOKUP/ENTER BLOCK
	MOVEM	T1,LEB+.RBCNT
	MOVE	T1,.JBVER	;SET OUR VERSION NUMBER ON ALL FILES CREATED
	MOVEM	T1,LEB+.RBVER
	POP	P,LEB+.RBEXT	;SAVE EXTENSION
	POP	P,LEB+.RBNAM	;SAVE FILE NAME
	POPJ	P,		;RETURN
SETBUF:	PUSH	P,T1		;SAVE BYTE POINTER
	MOVSI	T1,(BF.IOU)	;BUFFER USE BIT
	HRRI	T1,OBF+.BFHDR	;GET ADDRESS OF NEXT OUTPUT BUFFER
	MOVEM	T1,OBR+.BFADR	;STORE IN OUTPUT BUFFER CONTROL BLOCK
	HLLZ	T1,(P)		;BYTE POINTER
	MOVEM	T1,OBR+.BFPTR	;STORE IN OUTPUT BUFFER CONTROL BLOCK
	MOVSI	T1,201		;NUMBER OF DATA WORDS IN A BUFFER
	HRRI	T1,OBF+.BFHDR	;GET ADDRESS OF NEXT OUTPUT BUFFER
	MOVEM	T1,OBF+.BFHDR	;RING LOOPS ON ITSELF
	MOVSI	T1,(BF.IOU)	;BUFFER USE BIT
	HRRI	T1,IBF+.BFHDR	;GET ADDRESS OF NEXT INPUT BUFFER
	MOVEM	T1,IBR+.BFADR	;STORE IN INPUT BUFFER CONTROL BLOCK
	HLLZ	T1,(P)		;BYTE POINTER
	MOVEM	T1,IBR+.BFPTR	;STORE IN INPUT BUFFER CONTROL BLOCK
	MOVSI	T1,201		;NUMBER OF DATA WORDS IN A BUFFER
	HRRI	T1,IBF+.BFHDR	;GET ADDRESS OF NEXT INPUT BUFFER
	MOVEM	T1,IBF+.BFHDR	;RING LOOPS ON ITSELF
	POP	P,(P)		;TRIM STACK
	POPJ	P,		;RETURN
FILOP:	MOVE	T2,T1		;COPY FUNCTION CODE FOR LATER
	HRRM	T1,FOP+.FOFNC	;COMPLETE FUNCTION WORD
	MOVEI	T1,FOP		;POINT TO ARGUMENT BLOCK
	HRLI	T1,2		;ASSUME I/O CALL (LENGTH=2)
	CAIE	T2,.FORED	;READ?
	CAIN	T2,.FOWRT	;WRITE?
	HRLI	T1,.FOMAX	;USE A FULL ARGUMENT BLOCK
	FILOP.	T1,		;DO SOMETHING
	  POPJ	P,
	CAIE	T2,.FORED	;READ?
	CAIN	T2,.FOWRT	;WRITE?
	SKIPA			;YES TO EITHER
	JRST	CPOPJ1		;ALL DONE
	MOVSI	T1,FSP+.FOFDV	;POINT TO START OF RETURNED FILESPEC
	HRRI	T1,DEV		;WHERE TO PUT IT
	BLT	T1,EXT		;COPY DEVICE, FILE NAME, AND EXTENSION
	MOVSI	T1,FSP+.FOFPP	;POINT TO START OF PATH
	HRRI	T1,PTHBLK	;WHERE TO PUT IT
	BLT	T1,PTHBLK+7-1	;COPY PATH
	JRST	CPOPJ1		;RETURN
GETBYT:	SOSGE	IBR+.BFCTR	;COUNT BYTES
	JRST	GETBY1		;BUFFER EMPTY
	ILDB	T1,IBR+.BFPTR	;GET A BYTE
	MOVEM	T1,LSTBYT	;SAVE AS LAST BYTE
	JRST	CPOPJ1		;AND RETURN
GETBY1:	IN	IOC,		;READ A BUFFER IN
	JRST	GETBYT		;LOOP BACK
	GETSTS	IOC,T1		;GET CHANNEL STATUS
	TRNE	T1,IO.EOF	;END OF FILE?
	POPJ	P,		;YES
	PJRST	INPERR		;ELSE INPUT ERROR

PUTBYT:	SOSGE	OBR+.BFCTR	;COUNT BYTES
	JRST	PUTBY1		;BUFFER FULL
	IDPB	T1,OBR+.BFPTR	;SAVE A BYTE
	JRST	CPOPJ1		;AND RETURN
PUTBY1:	OUT	IOC,		;WRITE BUFFER OUT
	JRST	PUTBYT		;LOOP BACK
	GETSTS	IOC,T1		;GET CHANNEL STATUS
	HALT	.


OCTIN:	PUSH	P,T3		;SAVE T3
	PUSH	P,T4		;SAVE T4
	SETZB	T3,T4		;INIT RESULT
OCTIN1:	PUSHJ	P,GETBYT	;GET A CHARACTER
	  JRST	OCTIN3		;EOF
	CAIL	T1,"0"		;RANGE
	CAILE	T1,"7"		; CHECK
	JRST	OCTIN2		;ALMOST DONE
	LSHC	T3,3		;SHIFT
	ADDI	T4,-"0"(T1)	;INCLUDE DIGIT
	JRST	OCTIN1		;LOOP
OCTIN2:	DMOVE	T1,T3		;GET DOUBLEWORD RESULT
OCTIN3:	POP	P,T4		;RESTORE T4
	POP	P,T3		;RESTORE T3
	JRST	CPOPJ1		;RETURN
SAVBLT:	PHASE	.JBBLT
	SAVE.	0,		;(.JBBLT+0) SAVE PROGRAM
	  HALT	.		;(.JBBLT+1) FAILED
	EXIT			;(.JBBLT+2) RETURN TO MONITOR
	DEPHASE

SAVCOD:	PHASE	0
	XWD	.PAGCD,PAGBLK	;(00) PAGE. UUO AC
SAVGO:!	PAGE.	0,		;(01) DELETE UCODE LOADER
	  HALT	.		;(02) FAILED
	MOVEI	0,SAVBLK	;(03) POINT TO SAVE. UUO ARGUMENT
	JRST	.JBBLT		;(04) DO SAVE AND EXIT
	EXP	0		;(05) FREE
PAGBLK:!EXP	-<LOADPG-1>	;(06) PAGE. UUO ARGUMENT (KEEP PAGE 0)
	EXP	PA.GAF+1	;(07) PAGE. UUO ARGUMENT
SAVBLK:!SIXBIT	/DSK/		;(10) DEVICE
	SIXBIT	/BOOT/		;(11) FILE NAME
	SIXBIT	/EXE/		;(12) EXTENSION
	EXP	0		;(15) MBZ
	EXP	0		;(16) PPN
	EXP	0		;(17) CORE
	DEPHASE
LOADFF:	BLOCK	1		;ADDRESS OF FIRST FREE LOCATION
BINFLG:	BLOCK	1		;BINARY FILE OUTPUT FLAG
UCODSA:	BLOCK	1		;UCODE STARTING ADDRESS
UCODWD:	BLOCK	1		;UCODE WORD COUNT
UCODCK:	BLOCK	1		;UCODE CHECKSUM
UCODVR:	BLOCK	1		;UCODE VERSION NUMBER (TEMPORARY)
UCODBF:	BLOCK	UCDSIZ		;UCODE STORAGE BUFFER (TEMPORARY)
QPTR:	BLOCK	1		;BYTE POINTER TO QUESTION BUFFER
QCTR:	BLOCK	1		;BYTE COUNTER TO QUESTION BUFFER
QBUF:	BLOCK	QWDS		;QUESTION BUFFER
LSTBYT:	BLOCK	1		;SAVE BYTE READ FROM FILE
F.ZBEG:!			;START OF FILE AREA TO CLEAR
FOP:	BLOCK	.FOMAX		;FILOP BLOCK
LEB:	BLOCK	.RBMAX		;LOOKUP/ENTER BLOCK
FSP:	BLOCK	.FOFMX		;RETURNED FILESPEC BLOCK
OBR:	BLOCK	3		;OUTPUT BUFFER RING HEADER
IBR:	BLOCK	3		;INPUT BUFFER RING HEADER
OBF:	BLOCK	203		;OUTUT DISK BLOCK
IBF:	BLOCK	203		;INPUT DISK BLOCK
F.ZEND:!			;END OF FILE AREA TO CLEAR
EXBSTA:	BLOCK	1		;EXB START ADDRESS FLAG
EXBLDA: BLOCK	1		;EXB LOAD ADDRESS
EXBPTR:	BLOCK	1		;EXB CORE IMAGE BYTE POINTER
RECPTR:	BLOCK	1		;EXB RECORD BUFFER BYTE POINTER
RECCNT:	BLOCK	1		;EXB RECORD BYTE COUNT
RECBUF:	BLOCK	EXBWDS		;EXB RECORD BUFFER
LDRLIT:	LIT
LOADEN:!			;END OF THE LOADER
LOADSZ==<LOADEN-LOADER>+.JBDA	;LOADER SIZE IN WORDS
LOADPG==<LOADSZ+PAGSIZ-1>/PAGSIZ ;LOADER SIZE IN PAGES
	SUBTTL	DATA AREAS


;THE DATA AREA MUST BE THE FIRST THING IN THIS PROGRAM THAT GENERATES
;CODE TO INSURE THAT IT STARTS ON A PAGE BOUNDARY.  IN ADDITION,
;THE EPT MUST BE THE FIRST THING IN THE DATA AREA FOLLOWED IMMEDIATELY
;BY THE BLOCKS FOR HOM, RIB, AND BUF, FOR THE SAME REASON.  NOTE
;THAT IF ANY OF THE LAST THREE BLOCKS ARE SPLIT ACROSS A PAGE BOUNDARY
;THE I/O SUBROUTINES WILL NOT (NECESSARILY) WORK.

	RELOC	.VBOOT-.JBDA

BTSVEC:
LV (NAM,<SIXBIT/BOOT/>)		;IDENTIFIER
LV (VER,<%%BTS>)		;BOOT VERSION
LV (STA,<JRST BOOT>)		;BOOT START ADDRESS (FOR DEBUGGING)
LV (DDT,<JRST DDT##>)		;DDT START ADDRESS
LV (BPT,<JSR $0BPT##>)		;DDT ENTRY VIA UNSOLICITED BREAKPOINT
LV (DSP,<SUBR-BTSVEC>)		;SUBROUTINE OFFSET FROM ORIGIN
LV (SAV,<.BTSVE-.BTSVB>)	;NUMBER OF SAVED DATA ITEMS
LV (DAT,<<-DATLEN,,<SUBDAT-BTSVEC>>>) ;-LENGTH,,OFFSET TO DATA FOR SUBR
LV (XPC,<0,0,1B6,0>)		;XPCW ENTRY POINT
LV (SSL,<<-^D36,,.BTSSL+1>>)	;-LENGTH,,OFFSET TO THE SSL
LV (ASL,<<-^D8,,.BTASL+1>>)	;-LENGTH,,OFFSET TO THE ASL
LV (SDL,<<-^D36,,.BTSDL+1>>)	;-LENGTH,,OFFSET TO THE SDL
LV (MSZ,<MEMPSZ-BTSVEC>)	;OFFSET TO MEMORY SIZE IN P
LV (NXM,<<-NXMLEN,,<NXMTAB-BTSVEC>>>)	;-LENGTH,,OFFSET TO NXMTAB

	.ORG	BTSVEC+<.BTVLN*PAGSIZ> ;ROUND UP TO THE NEXT PAGE BOUNDRY

EPTABS:				;UNMAPPED ADDRESS OF EPT
EPTOFS==EPTABS-.VBOOT		;EPT OFFSET FROM BOOT ORIGIN IN WORDS
EPTPAG==EPTOFS/PAGSIZ		;EPT OFFSET FROM BOOT ORIGIN IN PAGES
BLK(EPT,0)			;PUT THIS HERE SO IT STARTS ON A PAGE BOUNDARY
	ONE41	(0,417)		;0-417=PAGES 0-417 IN EXEC MAP
	BLOCK	1		;420=UNUSED ON KL OR KS
	JFCL			;421=ARITHMETIC OVERFLOW TRAP INSTRUCTION
	JRST	TRAP		;422=PDL OVERFLOW TRAP INSTRUCTION
	JRST	TRAP		;423=TRAP 3 TRAP INSTRUCTION
	BLOCK	4		;424-427 MUUO LOCATIONS
	INSLOC	(430,437,<EXP TRAP>) ;430-437=MUUO NEW PC WORDS
	...Z4==.
CPYRIT:!CPYTXT			;PUT THE COPYRIGHT TEXT HERE
	.ORG	...Z4
	BLOCK	40		;440-477=UNUSED
	BLOCK	2		;500-501=PAGE FAIL LOCATIONS ON KL AND KS
	EXP	PFTRAP		;502=NEW PC WORD ON KL AND KS
	EXP	PFTRAP		;503=REAL PAGE FAIL NEW PC WITH KL PAGING
	ONE41	(504,537)	;504-537=PAGES 504-537 IN EXEC MAP
	ONE41	(EPTABS/PAGSIZ,EPTABS/PAGSIZ) ;540=POINTER TO SECTION 0 PAGE TABLE
	ONE41	(541,777)	;541-777=PAGES 541-777 IN EXEC MAP
DATA:!			;START OF IMPURE DATA STORAGE

R.BEG:!			;FIRST ADDRESS OF DATA TO ZERO ON RESTART

BLK(HOM,BLKSIZ)		;HOM BLOCK FOR CURRENT UNIT
BLK(RIB,BLKSIZ)		;RIB BLOCK FOR CURRENT FILE
BLK(BUF,BLKSIZ)		;WORK BUFFER
BLK(SCR,BLKSIZ)		;REBOOT SCRATCH BUFFER

SWTVLV:
BLK(SWTVAL,0)		;START OF BLOCK OF SWITCH VALUES
BLK(STSA,1)		;START ADDRESS GIVEN IN /START
SWTVLL==.-SWTVLV

IFN FTTAPE,<
BLK(TAPIDX,1)		;MAGTAPE UNIT INDEX
BLK(TAPUNI,1)		;MAGTAPE UNIT NUMBER
BLK(TAPDEN,1)		;MAGTAPE DENSITY CODE (1=200 BPI, ..., 5=6250 BPI)
>; END IFN FTTAPE

R.END:!			;LAST ADDRESS TO ZERO ON RESTART

BLK(FILSPC,0)		;FIRST WORD CLEARED EACH TIME THROUGH PARSE
BLK(DEV,1)		;DEVICE NAME
BLK(FILNAM,1)		;FILENAME
BLK(EXT,1)		;EXTENSION
BLK(PTHBLK,7)		;PATH BLOCK
BLK(CPEBR,1)		;ARGUMENT TO CHANGE THE EPT TO IT'S CURRENT VALUE
BLK(CPCLL,1)		;CACHE STRATEGY FROM KLI/MONITOR (KL ONLY)
IFN FTTAPE,<
BLK(NOTAPE,1)		;FLAG NON-ZERO IF MAGTAPE DRIVERS HAVE BEEN DISCARDED
>; END IFN FTTAPE

Z.BEG:!			;FIRST ADDRESS TO ZERO AT INITIALIZATION
BLK(EPTADR,1)		;PHYSICAL ADDRESS OF OUR EPT
BLK(BTBOT,1)		;FIRST PHYSICAL ADDRESS USED BY BOOT
BLK(BTTOP,1)		;FIRST PHYSICAL ADDRESS BEYOND TOP OF BOOT
BLK(SUBREL,1)		;SUBROUTINE RELOCATION
BLK(SUBDAT,DATLEN)	;SUBROUTINE DATA STORAGE
BLK(ERRFLG,1)		;SUBROUTINE ERROR OCCURED IF NON-ZERO
BLK(CPUBR,1)		;ARGUMENT TO RESTORE THE UPT AS IT WAS ON ENTRY
IFN FTKL10,<
BLK(CPDTE,1)		;CONI DTE, ON SUBROUTINE CALLS
>
IFN FTKS10,<
BLK(CPHSB,1)		;RDHSB ON SUBROUTINE CALLS
BLK(CPAPR,1)		;CONI APR, ON SUBROUTINE CALLS
>
BLK(MEMPSZ,1)		;NUMBER OF PAGES IN MEMORY
BLK(TRPADR,1)		;ADDRESS OF WHERE TO GO ON A TRAP
BLK(LUNPOS,1)		;LOGICAL UNIT NUMBER WITHIN STR
BLK(DRVBPC,1)		;BLOCKS/CYLINDER ON THIS UNIT \*** KEEP
BLK(DRVBPT,1)		;BLOCKS/TRACK ON THIS UNIT    /*** TOGETHER
BLK(SDLPOS,1)		;POSITION IN SYSTEM DUMP LIST
BLK(BLKCNT,1)		;NUMBER BLOCKS LEFT IN THIS GROUP
BLK(BLKADR,1)		;CURRENT BLOCK ADDRESS
BLK(BLKNUM,1)		;CURRENT RELATIVE BLOCK NUMBER IN FILE
BLK(SAVFIR,1)		;COPY OF RIBFIR FROM CURRENT RIB
BLK(SAVSIZ,1)		;COPY OF RIBSIZ FROM CURRENT RIB
BLK(SAVEAC,20)		;SAVE AC'S HERE IN BUGDMP
IFN FTKL10,<
BLK(R2IOWD,R2IOWL)	;RH20 IOWDS
>
IFN FTKS10,<
BLK(MAPBLK,40)		;SAVE UBA MAP REGISTERS
>
BLK(USRFLG,1)		;USER MODE FLAG
BLK(CDFLG,1)		;CONTROL-D FLAG
BLK(CDSAV,20)		;SAVED ACS FOR CONTROL-D
BLK(CD112,1)		;SAVED MONITOR LOCATION 112
BLK(CD116,1)		;SAVED MONITOR LOCATION 116
BLK(CD117,1)		;SAVED MONITOR LOCATION 117
BLK(BTSPDL,PDLLEN)	;PUSH DOWN LIST
BLK(CMDPTR,1)		;BYTE POINTER TO COMMAND BUFFER
BLK(CMDBUF,LINBFL)	;COMMAND LINE BUFFER
BLK(BTXPTR,1)		;BYTE POINTER TO BOOTXT
BLK(AUTFLG,1)		;AUTO-BOOT FLAG
BLK(NXMFLG,1)		;NXMTAB VALID FLAG
BLK(NXMTAB,NXMLEN)	;OUR COPY OF NXMTAB

Z.END:!			;LAST ADDRESS TO ZERO AT INITIALIZATION
	SUBTTL	BOOTSTRAP INITIALIZATION

;HERE AFTER BEING LOADED INTO MEMORY.  WE ARE (PROBABLY) RUNNING
;UNPAGED AT THIS POINT SO WE MUST DO SOMETHING ABOUT THAT FIRST.

BOOT:
IFN FTKL10,<
	TDZA	S,S		;NO BITS SPECIFIED
	JFCL			;DON'T TOUCH - 20F SET UP S
				;PRESERVE S UNTIL WE CAN REFERENCE MEMORY
>
	CONO	APR,APRRST	;BLAST THE PROCESSOR
	CONO	PI,PI.CPI!PI.OFF ;BLAST THE PI SYSTEM

REPEAT 0,<
;THIS DOESN'T WORK AND SHOULD NEVER BE REQUIRED SINCE KLI ALREADY DID IT

IFN FTKLP,<
	CONO	PAG,0		;ZAP
	MOVSI	T1,(1B0+0B8+6B11) ;AC BLOCK 6
	JRSTF	@[4000,,.+1]	;MAKE SURE CAN ADDRESS PREVIOUS CONTEXT
	DATAO	PAG,T1		;PREVIOUS CONTEXT ACS
	EXCTUX	<SETZM 2>	;CLEAR CST BASE
>
>;END REPEAT 0

IFN FTKL10,<
	CONI	PAG,T3		;READ CACHE STRATEGY
	ANDI	T3,LG.CSL!LG.CSW ;ISOLATE CACHE STRATEGY BITS
	MOVEI	T1,XG.TEN!<EPTABS/PAGSIZ>!XG.KLP ;GET BITS TO SET THE EBR
	MOVSI	T4,(XG.LAB!LG.LPC!XG.LUB) ;FLAG BITS TO LOAD THE UBR
	HRRI	T4,LG.IAM!<EPTABS/PAGSIZ> ;AND THE PAGE NUMBER
	CONO	PAG,(T1)	;TURN ON PAGING, MAP US 1 FOR 1
	DATAO	PAG,T4		;SET THE UPT TO THE SAME PAGE
	CONO	DTE0,PILDEN!0	;TURN OFF DTE PIA
>
IFN FTKS10,<
	SETZB	T1,T3		;CLEAR AC, NO CACHE STRATEGY ON KS
	CONO	PAG,(T1)	;TURN OFF PAGING
	WRCSB	T1		;CLEAR CST BASE ADDRESS (REQUIRES UCODE 124)
	MOVEI	T1,XG.TEN!<EPTABS/PAGSIZ>!XG.KLP ;GET BITS TO SET THE EBR
	MOVSI	T4,(XG.LAB!XG.LUB) ;FLAG BITS TO LOAD THE UBR
	HRRI	T4,<EPTABS/PAGSIZ> ;AND THE PAGE NUMBER
	CONO	PAG,(T1)	;TURN ON PAGING, MAP US 1 FOR 1
	DATAO	PAG,T4		;SET THE UPT TO THE SAME PAGE
	MOVEI	T2,.EPHSB	;GET HALT STATUS BLOCK ADDRESS
	WRHSB	T2		;WRITE IT
>
	MOVEM	T1,CPEBR	;STORE BITS TO CHANGE EBR FOR LATER
	MOVEM	T3,CPCLL	;SAVE CACHE STRATEGY FROM KLI
	MOVSI	T2,(<PM.DCD>B2+PM.WRT) ;ACCESSIBLE AND WRITABLE
	MOVEM	T2,EPT+.MPAG0	;MAP PAGE 0
	MOVEM	T2,EPT+.MPAG0+1
	AOS	EPT+.MPAG0+1	;AND PAGE 1
	MOVEI	T2,.VBOOT	;GET STARTING PHYSICAL ADDRESS
	MOVEM	T2,BTBOT	;STORE AS BOTTOM OF BOOT
	HRRZ	T3,.VBOOT+.BTSIZ ;GET +SIZE IN WORDS
	ADD	T2,T3		;GET TOP+1
	MOVEM	T2,BTTOP	;STORE FOR LATER
	MOVEI	T2,EPTABS	;GET PHYSICAL ADDRESS OF OUR EPT
	MOVEM	T2,EPTADR	;STORE FOR LATER
	LSH	T2,W2PLSH	;CONVERT TO PAGE NUMBER
	HRLI	T2,(<PM.DCD>B2+PM.WRT) ;ACCESSIBLE + WRITABLE
	MOVEM	T2,EPT+540	;SETUP SECTION TABLE TO POINT AT SECTION 0 PT
IFN FTKL10,<SETZM EPT+DTEEPW>	;CLEAR EXAMINE/PROTECTION WORD
	MOVE	T2,CHGEBR	;GET INSTRUCTION TO CHANGE THE EBR
	MOVSI	T3,(JRST)	;SETUP JRST TO GET BACK AFTER
	HRRI	T3,MAPPED	;  WE'RE MAPPED
	JRST	T2		;CHANGE THE EBR, COME BACK MAPPED
;HERE WHEN THE .VBOOT ADDRESS SPACE HAS BEEN MAPPED TO DO SOME ONCE
;ONLY INITIALIZATION

MAPPED:	MOVEI	P,BTSPDL	;SETUP A PDL
IFN FTKL10,<
	SETZM	EPT+DTEEPW	;CLEAR DTE EXAMINE/PROTECTION WORD
	SETZM	EPT+DTEMTI	;CLEAR INPUT READY FLAG
	MOVSI	T3,DT.ESP	;BIT TO CAUSE -20F TO ENTER SECONDARY
	HRRI	T3,DTEFLG	;IN THIS WORD
	PUSHJ	P,DODTE		;EXECUTE THE COMMAND
	PUSHJ	P,ZAPICH	;FORCIBLY BLAST INTERNAL CHANNELS
>
	MOVE	T1,[Z.BEG,,Z.BEG+1] ;SET UP BLT
	SETZM	Z.BEG		;CLEAR FIRST WORD
	BLT	T1,Z.END-1	;CLEAR ENTIRE DATA BASE
IFN FTKS10,<
	SETZM	.VPAG0+CTYIWD	;CLEAR INPUT AVAILABLE WORD
	SETZM	.VPAG0+CTYOWD	;AND OUTPUT PRESENT WORD
	SETZM	.VPAG0+KLIIWD	;BE SURE KLINIK LINE COMMANDS
	SETZM	.VPAG0+KLIOWD	;CAN'T MAKE 8080 HANG IF TRASH FROM SAVE.
	HRRZ	S,.VPAG0+RLWORD	;GET FLAGS FROM 8080
	TRNE	S,FORREL	;IF FORCED RELOAD
	TLO	S,(KL.SIL!KL.DMP) ;WE WANT A DUMP/SILENT LOAD
	TRNE	S,AUTOBT	;IF AN AUTO-BOOT
	TLO	S,(KL.SIL)	;JUST LOAD SILENTLY
	HLLZS	S		;KEEP ONLY KL-STYLE FLAGS
>
	MOVEM	S,AUTFLG	;SAVE WHAT WE ARE TOLD
	MOVEI	S,0		;ZERO FLAGS
	PUSHJ	P,SUNXMT	;LOOK AT MEMORY AND SETUP NXMTAB
	MOVEI	T1,VERMSG	;POINT AT VERSION STRING
	PUSHJ	P,PRMSG		;TELL HIM THAT WE'RE HERE
	PUSHJ	P,COPDAT	;COPY DATA FROM OLD BOOT (SSL, ASL, SDL, ETC.)
	PUSHJ	P,FINDHI	;FIND PHYSICAL PAGE # OF TOP OF CORE
	PUSHJ	P,MOVBTS	;RELOCATE BOOT TO TOP OF PHYSICAL CORE
	MOVEI	T1,RESTAR	;GET RESTART ADDRESS
	HRRM	T1,BTSVEC+.BTSTA ;SAVE IT
	SETOM	CDFLG		;NOT A CONTROL-D
	PUSHJ	P,RICD		;ENTER DDT IF DEBUGGING
	SKIPN	T1,AUTFLG	;GET THE FLAGS FROM THE FE
	JRST	RESTAR		;IF NONE, ASK OPR
	PUSHJ	P,DEFSPC	;DEFAULT THE FILE-SPEC
	TLZE	T1,(KL.DMP)	;NEED A DUMP?
	PUSHJ	P,DODUMP	;YES -- DO ONE
	PUSHJ	P,DEFSPC	;RE-DEFAULT FOR LOAD
	MOVE	T1,[BTSVEC+.BTDEV,,DEV] ;SET UP BLT
	SKIPE	BTSVEC+.BTDEV	;HAVE A FILESPEC FROM BEFORE?
	BLT	T1,PTHBLK+6	;COPY IT
	.CREF	KL.SIL		;BIT WE'RE TESTING
	SKIPL	AUTFLG		;A SILENT LOAD?
	PJRST	RESTAR		;NO, ASK OPR
	PJRST	RLDMO2		;YES, DO SO
DEFSPC:	SETZM	R.BEG		;DEFAULT THE WORLD
	MOVE	T2,[R.BEG,,R.BEG+1] ;SET UP BLT
	BLT	T2,R.END-1	;ZERO DATA STORAGE
	MOVE	T2,[FILSPC,,FILSPC+1]
	SETZM	FILSPC
	BLT	T2,PTHBLK+6
	MOVSI	T2,'EXE'	;DEFAULT EXTENSION
	MOVEM	T2,EXT
	MOVE	T2,[XWD 1,4]	;DEFAULT PPN
	MOVEM	T2,PTHBLK
	MOVSI	S,(FL.WLD)	;ANY STRUCTURE
	POPJ	P,		;DONE
; SUBROUTINE ENTRY
SUBR:	MOVSI	17,(JRST (16))	;RETURN INSTRUCTION FOR JSR
	JSR	16		;FIND OUT WHERE WE ARE
	XMOVEI	17,0-.(16)	;OFFSET FOR RELOCATED LOADING TO ORIGINAL SPOT
	MOVEM	0,SAVEAC(17)	;SAVE CALLER'S AC 0
	MOVSI	0,1		;START WITH AC 1
	HRRI	0,SAVEAC+1(17)	;SET UP BLT
	MOVEI	16,SAVEAC+15(17) ;COMPUTE END OF BLT
	BLT	0,(16)		;SAVE CALLER'S ACS 1-15
	MOVE	R,17		;SET RELOCATION AC
	MOVEM	R,SUBREL(R)	;SAVE SUBROUTINE RELOCATION FOR RETURN
	JSP	P1,SAVHDW(R)	;SAVE HARDWARE STATUS
	JSP	P1,SETMAP(R)	;RESET POINTERS IN OUR EPT
	MOVE	T1,EPTADR(R)	;GET PHYSICAL EPT ADDRESS
	LSH	T1,W2PLSH	;CONVERT TO A PAGE NUMBER
	TRO	T1,XG.TEN!XG.KLP ;WORD TO CHANGE THE EBR
IFN FTKL10,<
	MOVEI	T4,LG.IAM(T1)	;GET UPT PAGE NUMBER AND FLAG
	HRLI	T4,(XG.LUB)	;FLAG BITS TO LOAD THE UBR
>
IFN FTKS10,<
	MOVE	T4,T1		;GET UPT PAGE NUMBER
	HRLI	T4,(XG.LAB!XG.LUB) ;FLAGS TO LOAD THE UBR
>
	MOVE	P1,CHGEBR(R)	;GET INSTRUCTION TO CHANGE THE EBR
	MOVE	P2,CHGUBR(R)	;GET INSTRUCTION TO CHANGE THE UBR
	MOVE	P3,[JRST @P4](R) ;SETUP JRST TO GET BACK AFTER WE'RE MAPPED
	MOVEI	P4,SUBR1	;RETURN TO 0,,SUBR1
	JRST	P1		;CHANGE THE EBR AND UBR, COME BACK MAPPED

SUBR1:	MOVE	P,[IOWD PDLLEN,BTSPDL] ;SET UP A STACK
	SETZM	ERRFLG		;CLEAR ERROR FLAG
	MOVE	T1,BTSVEC+.BTCPN ;GET NUMBER OF CPU WHICH INVOKED BOOT
	LDB	T1,BTYCST(T1)	;GET THAT CPU'S SAVED CACHE STRATEGY
	DPB	T1,[POINT 2,CPCLL,19] ;SAVE FOR POSSIBLE RELOAD
	PUSHJ	P,DEFSPC	;DEFAULT THE FILESPEC
	MOVE	T1,BTSVEC+.BTFNC ;GET FUNCTION CODE
	CAILE	T1,DISPLN	;KNOWN?
	MOVEI	T1,0		;NO--ERROR
	SKIPG	DISP(T1)	;PRESERVE NXMTAB?
	SETZM	NXMFLG		;NXMTAB NOT VALID (CAN'T TRUST MONITOR)
	PUSHJ	P,@DISP(T1)	;DISPATCH
	MOVE	R,SUBREL	;GET RELOCATION BACK
	MOVE	T1,CPEBR	;GET OLD EBR
	MOVE	T4,CPUBR	;AND OLD UBR
	MOVE	P1,CHGEBR	;GET INSTRUCTION TO CHANGE THE EBR
	MOVE	P2,CHGUBR	;GET INSTRUCTION TO CHANGE THE UBR
IFN FTKL10,<MOVE P3,[XJRST P4]>	;GET INSTRUCTION TO RETURN TO RELOCATED ADDRESS
IFN FTKS10,<MOVE P3,[JRST @P4]>	;GET INSTRUCTION TO RETURN TO RELOCATED ADDRESS
	MOVEI	P4,SUBR2(R)	;GET LOCAL RELOCATED ADDRESS
	HLL	P4,R		;MAKE IT GLOBAL
	JRST	P1		;CHANGE BACK TO OLD EBR AND UBR
SUBR2:	JSP	P1,RSTHDW(R)	;RESTORE THE STATE OF THE HARDWARE
	SKIPN	ERRFLG(R)	;ERROR ALONG THE WAY?
	AOS	BTSVEC+.BTXPC+1(R) ;NO--GIVE SKIP RETURN
	MOVE	17,R		;COPY RELOCATION
	MOVSI	15,SAVEAC(17)	;SET UP BLT
	BLT	15,15		;RESTORE ACS 0-15
	XJRSTF	BTSVEC+.BTXPC(17) ;RETURN TO CALLER

;BYTE POINTERS FOR SAVED CACHE STRATEGY

BTYCST:	POINT	2,BTSVEC+.BTSCS,35 ;FOR CPU0
	POINT	2,BTSVEC+.BTSCS,33 ;FOR CPU1
	POINT	2,BTSVEC+.BTSCS,31 ;FOR CPU2
	POINT	2,BTSVEC+.BTSCS,29 ;FOR CPU3
	POINT	2,BTSVEC+.BTSCS,27 ;FOR CPU4
	POINT	2,BTSVEC+.BTSCS,25 ;FOR CPU5

;SUBROUTINE DISPATCH TABLE

DISP:	XWD	400000,ILLFNC	;ILLEGAL FUNCTIONS
	XWD	400000,RESTAR	;FUNCTION 1 - BOOT RESTART (DO NOT LOAD)
	XWD	     0,DODUMP	;FUNCTION 2 - DUMP
	XWD	400000,RELOAD	;FUNCTION 3 - LOAD (READ BOOTXT)
	XWD	     0,SLFUNC	;FUNCTION 4 - SYSTEM SLEEP DUMP
	XWD	     0,PGFUNC	;FUNCTION 5 - PAGE REPLACE
DISPLN==.-DISP			;LENGTH OF TABLE


ILLFNC:	SETOM	ERRFLG		;FLAG THE ERROR
	MOVEI	T1,[ASCIZ /
?BOOT error; illegal function code 
/]
	PUSHJ	P,PRMSG		;PRINT TEXT
	MOVE	T1,BTSVEC+.BTFNC ;GET OFFENDING FUNCTION CODE
	PJRST	PROCT		;PRINT IT AND RETURN
; SAVE HARDWARE STATUS ON SUBROUTINE ENTRY
; CALL:	JSP	P1,SAVHDW(R)

SAVHDW:
IFN FTKL10,<
	SWPUA			;SWEEP CACHE
	CONSO	APR,LP.CSD	;DONE YET?
	JRST	.-1(R)		;NO--WAIT
	CONI	PAG,CPEBR(R)	;SAVE CURRENT EPT MAPPING
	DATAI	PAG,CPUBR(R)	;SAVE CURRENT UPT MAPPING
	CONI	DTE0,CPDTE(R)	;SAVE CURRENT DTE PIA
	CONO	DTE0,PILDEN!0	;ZAP DTE PIA
	SETZM	EPT+DTEEPW(R)	;AND THE EXAMINE/PROTECTION WORD
>
IFN FTKS10,<
	CONI	PAG,CPEBR(R)	;SAVE CURRENT EPT MAPPING
	DATAI	PAG,CPUBR(R)	;SAVE CURRENT UPT MAPPING
	CONI	APR,CPAPR(R)	;SAVE CURRENT APR PI ASSIGNMENT
	RDHSB	CPHSB(R)	;SAVE CURRENT HALT STATUS BLOCK
	HRLZ	T1,DVCTAB(R)	;UBA NUMBER FOR DISK
	MOVEI	T2,MAPBLK(R)	;ADDRESS OF SAVE AREA
	HRLI	T2,(POINT 18)	;MAKE A BYTE POINTER
SVMAP1:	TRNE	T1,100		;DONE?
	JRST	SVMAP2(R)	;YES
	RDIO	T3,SO.UPR(T1)	;READ MAP REGISTER
	LSHC	T3,-^D20	;CONVERT READ FORMAT TO WRITE
	LSH	T3,-4
	LSHC	T3,^D11
	IDPB	T3,T2		;STORE IT
	AOJA	T1,SVMAP1(R)	;LOOP
SVMAP2:
>
	JRST	(P1)		;RETURN
; RESTORE HARDWARE STATUS ON SUBROUTINE EXIT
; CALL:	JSP	P1,RSTHDW(R)

RSTHDW:
IFN FTKL10,<
	HRRZ	T1,CPDTE(R)	;RESTORE DTE PIA
	ANDI	T1,PI0ENB!PIA	;KEEP JUST USEFUL BITS
	CONO	DTE0,PILDEN(T1)
>
IFN FTKS10,<
	HRLZ	T1,DVCTAB(R)	;UBA NUMBER FOR DISK
	MOVEI	T2,MAPBLK(R)	;ADDRESS OF SAVE AREA
	HRLI	T2,(POINT 18)	;MAKE A BYTE POINTER
RSMAP1:	TRNE	T1,100		;DONE?
	JRST	RSMAP2(R)	;YES
	ILDB	T3,T2		;GET ORIGINAL VALUE
	WRIO	T3,SO.UPR(T1)	;PUT IT BACK
	AOJA	T1,RSMAP1(R)	;LOOP
RSMAP2:	MOVE	T1,CPHSB(R)	;GET HALT STATUS BLOCK ADDRESS
	WRHSB	T1		;RESTORE IT
	MOVE	T1,CPAPR(R)	;GET CONI APR,
	ANDI	T1,7		;KEEP JUST PI ASSIGNMENT
	CONO	APR,(T1)	;RESTORE APR PI ASSIGNMENT

>
	JRST	(P1)		;RETURN
; SET UP THE EPT/UPT ON SUBROUTINE ENTRY
; CALL:	JSP	P1,SETMAP(R)

SETMAP:	XMOVEI	T1,BTSVEC(R)	;GET CURRENT VIRTUAL ORIGIN
	MAP	T1,(T1)		;TRANSLATE TO PHYSICAL
IFN FTKL10,<TLZ	T1,(^-<LG.EPT*PAGSIZ+PAGSIZ-1>)> ;KEEP ONLY ADDRESS
IFN FTKS10,<TLZ	T1,(^-<SG.EPT*PAGSIZ+PAGSIZ-1>)> ;KEEP ONLY ADDRESS
	MOVEM	T1,BTBOT(R)	;SAVE PHYSICAL START OF BOOT
	HRRZ	T2,BTSVEC+.BTSIZ(R) ;GET SIZE IN WORDS
	ADD	T2,T1		;GET FIRST ADDRESS BEYOND BOOT
	MOVEM	T2,BTTOP(R)	;SAVE THAT
	ADDI	T1,EPTOFS	;OFFSET TO THE EPT
	MOVEM	T1,EPTADR(R)	;SAVE PHYSICAL ADDRESS OF THE OUR EPT
	LSH	T1,W2PLSH	;CONVERT TO A PAGE NUMBER
	HRRM	T1,EPT+540(R)	;SAVE SECTION 0 MAP POINTER
	SUBI	T1,EPTPAG	;BACK TO THE BOOT ORIGIN PAGE
	HLLZ	T2,BTSVEC+.BTSIZ(R) ;GET -LENGTH OF BOOT IN PAGES
	HRRI	T2,EPT+.MBOOT(R) ;MAKE AN AOBJN POINTER
	HRRM	T1,(T2)		;STUFF PAGE NUMBER IN MAP
	AOS	T1		;ADVANCE
	AOBJN	T2,.-2(R)	;LOOP FOR ALL OUR PAGES
	JRST	(P1)		;RETURN
	SUBTTL	PROCESS COMMAND

;ROUTINE TO PROMPT THE USER AND DUMP/LOAD/RELOAD THE MONITOR.  CALL
;AFTER SETTING UP THE MAP SO THAT WE ARE RUNNING IN THE .VBOOT ADDRESS
;SPACE.  EXITS TO THE START ADDRESS OF THE NEW MONITOR.

RESTAR:	SETZM	SUBDAT		;INVALIDATE POSSIBLE BOOTXT
	PUSHJ	P,DEFSPC	;DEFAULT THE FILESPEC
RELOAD:	MOVE	T1,[POINT 7,SUBDAT] ;POINT TO DATA BUFFER (COPY OF BOOTXT)
	MOVEM	T1,BTXPTR	;SAVE FOR PARSE
RELOA1:	SKIPN	SUBDAT		;HAVE ANY DATA?
RLDMON:	TLO	S,(FL.DEF!FL.CMD) ;NO DEFAULTS AND READ FROM COMMAND BUFFER
	TDZ	S,[FX.CLR]	;CLEAR LOTS OF BITS
	MOVEI	P,BTSPDL	;SETUP PDL AGAIN IN CASE OF TRAP
	SETZM	AUTFLG		;IF ERROR, ALLOW TALKING TO OPR
				;<MATCH ANGLE BRACKET ON NEXT LINE
	MOVEI	T1,[ASCIZ/BOOT>/] ;OUR PROMPT
	MOVEI	T2,[0]		;DEFAULT ANSWER IS CR
	TLNE	S,(FL.CMD)	;READING FROM COMMAND BUFFER?
	PUSHJ	P,REDLIN	;YES--PROMPT AND GET A COMMAND
	PUSHJ	P,PARSE		;PARSE THE COMMAND
	  JRST	RESTAR		;SYNTAX ERROR
IFN FTTAPE,<
	SKIPE	W,TAPIDX	;SET UP DEVICE INDEX FOR LATER USE IF MAGTAPE
	PUSHJ	P,@RESTAB(W)	;FIND AND RESET THE CONTROLLER
	TRNE	S,FR.TAB	;ANY TAPE ACTION BITS SET?
	JRST	TAPACT		;YES
>; END IFN FTTAPE
	TRNN	S,FR.DMP	;/DUMP SEEN?
	JRST	RLDMO1		;NO
IFN FTTAPE,<
	SKIPE	TAPIDX		;MAGTAPE UNIT SPECIFIED?
	JRST	NTDERR		;YES
>; END IFN FTTAPE
	TLZE	S,(FL.DDD)	;WANT TO SKIP /D?
	TLNE	S,(FL.CMD)	;AND READING FROM BOOTXT?
	PUSHJ	P,DODUMP	;NO TO EITHER, TAKE A DUMP
	TLNN	S,(FL.CMD)	;READING FROM BOOTXT?
	JRST	RELOA1		;YES--PERHAPS NOT DONE WITH BOOTXT YET
	JRST	RESTAR		;JUST RESTART THINGS CLEANLY
RLDMO1:	TRNE	S,FR.STA	;/START SEEN?
	TRNE	S,FR.ALL-FR.STA	;AND NOTHING ELSE?
	TLOA	S,(FL.CMD)	;NO, READ NO MORE COMMANDS FROM BOOTXT
	JRST	RLDMO3		;YES, JUST START UP MONITOR
				;FALL INTO RLDMO2
RLDMO2:	PUSHJ	P,DOLOAD	;LOAD NEW MONITOR
	  JRST	RESTAR		;ERROR DETECTED
	TRNE	S,FR.LOD	;/LOAD SPECIFIED?
	JRST	RLDMON		;YES, DON'T START
IFN FTTAPE,<
	SKIPE	TAPIDX		;DON'T POSITION TAPE UNLESS LOADED VIA TAPE
	TRNE	S,FR.NOR	;/NOREWIND?
	JRST	RLDMO3		;DON'T TOUCH TAPE
	PUSHJ	P,REWIND	;REWIND THE TAPE
	PUSHJ	P,SKPEOF	;SKIP ONE FILE
IFN FTKS10,<
	PUSHJ	P,SKPEOF	;SKIP A SECOND FILE ON THE KS
>; END IFN FTKS10
>; END IFN FTTAPE
RLDMO3:	TRNE	S,FR.RBT	;THIS A /REBOOT REQUEST?
	JRST	RLDMO4		;YES, DON'T CHANGE CORE
	MOVE	T1,[DEV,,BTSVEC+.BTDEV] ;SET UP BLT
	BLT	T1,BTSVEC+.BTPTH+6 ;COPY MONITOR FILESPEC INTO VECTOR
	MOVE	T1,EPT+.MBOOT	;GET MAP ENTRY FOR START OF BOOT
	LSH	T1,P2WLSH	;CONVERT TO A PHYSICAL ADDRESS
	MOVEM	T1,.VPAG0+BOOTSA ;SAVE FOR MONITOR
	APRID	T1		;READ SERIAL NUMBER
	ANDI	T1,ASNMSK	;MASK DOWN TO ONLY THE SERIAL NUMBER
	MOVEM	T1,.VPAG0+BOOTWD ;SAVE FOR MONITOR

RLDMO4:	PUSHJ	P,LISTEN	;GIVE ONE MORE CHANCE TO CONTROL-C OUT
IFN FTTAPE,<
	SKIPN	NOTAPE		;TAPE DRIVER CODE STILL PRESENT?
	PUSHJ	P,ZAPTAP	;YES, DELETE IT SINCE MONITOR HAS NO USE FOR
				; IT ONCE IT IS RUNNING
>; END IFN FTTAPE
	SKIPN	T4,STSA		;START ADDRESS SPECIFIED ON /START?
	HRRZ	T4,.VPAG0+.JBSA	;NO, USE ADDRESS FROM FILE
	HRLI	T4,(JRST)	;MAKE IT A JRST
	MOVE	T3,CHGEBR	;GET INSTRUCTION TO CHANGE THE EBR
	MOVE	T1,CPCLL	;GET CACHE STRATEGY BITS (KL), TURN OFF PAGING
	MOVE	S,AUTFLG	;PASS FLAGS TO MONITOR IN CASE IT CARES
	JRST	T3		;TURN OFF PAGING AND START NEW MONITOR
CHGEBR:	CONO	PAG,(T1)	;CHANGE THE EBR

CHGUBR:	DATAO	PAG,T4		;CHANGE THE UBR


;BUILD THE BOOT VERSION MESSAGE

VERMSG:	VSTR	(\BOOVER,\BOOEDT)
	SUBTTL	DUMP MONITOR


;ROUTINE TO DUMP THE SYSTEM. CALL WITH INITIAL FILESPEC ON
;WHICH TO DUMP IN THE FILESPEC AREA.  ASKS THE USER FOR A NEW
;FILESPEC IF ERRORS ARE DETECTED.
;CALL:	PUSHJ	P,DODUMP
;RETURN+1 ALWAYS

SLFUNC:	TLO	S,(FL.DEF!FL.SSD) ;NO DEFAULTS, SYSTEM-SLEEP DUMP
	PJRST	DODUMP		;BUT MOSTLY NORMAL

ASKSTR:	TDO	S,[FL.1CM!FR.DMP] ;FORCE PARSE FROM COMMAND BUFFER AND /DUMP
	MOVEI	T1,[ASCIZ/File on which to dump: /]
	MOVEI	T2,[ASCIZ/DSK:CRASH.EXE[1,4]/]
	TLNN	S,(FL.SSD)	;IF THIS IS FOR A NORMAL DUMP,
	TLZ	S,(FL.DEF)	;MAKE SURE DEFAULTS ARE ALLOWED
	PUSHJ	P,REDLIN	;ASK WHERE HE WANTS THE DUMP
	PUSHJ	P,PARSE		;PARSE THE COMMAND
	  JRST	ASKSTR		;TRY AGAIN
	TLZ	S,(FL.1CM)	;CLEAR COMMAND FLAG
	TRNN	S,FR.ALL-FR.DMP	;SEE ANYTHING AT ALL?
	POPJ	P,		;NO, LONE CR MEANS NO DUMP

DODUMP:	SKIPN	NXMFLG		;NXMTAB VALID?
	PUSHJ	P,SUNXMT	;MUST REBUILD IT
	PUSHJ	P,SDLCHK	;CHECK FOR THE SDL
	  SKIPA	P1,['DSKA  '-10000] ;GET DISK NAME TO INCREMENT TO DSKA
	MOVE	P1,T1		;GET PREDECREMENTED AOBJN POINTER
	MOVE	T1,[SIXBIT/CRASH/] ;FILENAME IS CRASH
	TRNN	S,FR.FIL	;SEE A FILE NAME?
	MOVEM	T1,FILNAM	;NO, USE DEFAULT
	TLNN	S,(FL.WLD)	;WILD STR?
	JRST	DODUM4		;NO, USE THE ONE HE SAID
DODUM1:	TRNE	S,FR.FRC	;/FORCE (IGNORE THE SDL)?
	JRST	DODUM2		;YES
	AOBJP	P1,DODUM6	;ADVANCE POINTER
	SKIPN	T1,(P1)		;GET A STRUCTURE NAME
	AOBJN	P1,.-1		;NONE THERE, TRY NEXT
	JUMPL	P1,DODUM3	;JUMP IF HAVE A STRUCTURE NAME
	JRST	DODUM6		;GIVE UP
DODUM2:	CAMN	P1,[SIXBIT/DSKZ/] ;LOOKED AT THE LAST ONE?
	JRST	DODUM6		;YES, GIVE UP
	ADDI	P1,10000	;STEP TO NEXT DISK NAME
	MOVE	T1,P1		;COPY STRUCTURE NAME
DODUM3:	MOVEM	T1,DEV		;ELSE STORE STR NAME TO TRY THIS TIME
DODUM4:	TLZA	S,(FL.OVW)	;DON'T ALLOW OVERWRITING
DODUM5:	TLO	S,(FL.OVW)	;OVERWRITE IF HE SAYS TO
	TLZ	S,FR.DMP	;CLEAR DUMP FLAG FOR NEXT TIME
	PUSHJ	P,DUMP		;TRY TO DUMP THE MONITOR
	  JRST	DMPERR		;FAILED, ANALYZE ERROR AND TRY TO RECOVER
	POPJ	P,		;COMPLETED SUCCESSFULLY, RETURN
DODUM6:	MOVEI	T1,[ASCIZ/?Unable to find a file on which to dump
/]
	PUSHJ	P,PRMSG		;PRINT MESSAGE
	TLNE	S,(FL.SSD)	;SYSTEM SLEEP DUMP?
	JRST	ASKSTR		;YES, DON'T GIVE THEM A CHANCE TO BLOW IT
	MOVEI	T1,[ASCIZ/Do you want to keep this dump? /]
	MOVEI	T2,[ASCIZ/No/]
	PUSHJ	P,ASKYN		;ASK HIM WITH DEFAULT ANSWER
	  JRST	DODUM6		;CONFUSED USER--ASK AGAIN
	  POPJ	P,		;HE SAYS NO
	JRST	ASKSTR		;ASK ON WHAT STR TO DUMP
; CHECK FOR THE EXISTANCE OF ANY STRUCTURES IN THE PRESERVED
; COPIES OF THE SYSTEM SEARCH LIST OR DUMP LIST
; CALL:	PUSHJ	P,SSLCHK/SDLCHK
;	  <NON-SKIP>		;TABLE EMPTY OR /FORCE SEEN
;	<SKIP>			;USE TABLE, T1 = PREDECREMENTED POINTER

SSLCHK:	SKIPA	T1,BTSVEC+.BTSSL ;AOBJN POINTER TO SSL
SDLCHK:	MOVE	T1,BTSVEC+.BTSDL ;AOBJN POINTER TO SDL
	ADDI	T1,BTSVEC	;OFFSET TO START OF DESIRED TABLE
	MOVE	T2,T1		;MAKE A WORKING COPY
	ADJSP	T1,-1		;PREDECREMENT AOBJN POINTER FOR CALLER
	TRNE	S,FR.FRC	;/FORCE SEEN?
	POPJ	P,		;YES
	SKIPN	(T2)		;NON-ZERO ENTRY?
	AOBJN	T2,.-1		;KEEP SEARCHING
	JUMPL	T2,CPOPJ1	;RETURN IF FOUND A STRUCTURE
	TRO	S,FR.FRC	;NO--MUST FORCE SCANNING OF DSKA-DSKZ
	POPJ	P,		;RETURN
;HERE IF AN ERROR IS DETECTED IN THE DUMP OR LOAD.  USE THE ERROR
;CODE RETURNED IN T1 TO INDEX INTO EMSTAB AND PRINT A MESSAGE.
;FOR DUMP, INDEX INTO DMPDSP AND DISPATCH TO THE ROUTINE TO
;HANDLE THE ERROR.

LODERR:	TLOA	S,(FL.CMD!FL.LDE) ;INSURE NEXT READ IS FROM TTY
DMPERR:	TLZ	S,(FL.LDE)	;CLEAR BIT FOR DUMP ERRORS
	TLNE	S,(FL.WLD)	;WILD STRUCTURE?
	TLNE	S,(FL.FFL)	;YES, DID WE FIND THE FILE ON THIS STR?
	JRST	DMPER1		;YES, PROCEED NORMALLY
	CAIG	T1,FNFOFS	;NO, IS THIS ERROR JUST FILE OR STR NOT FOUND?
	JRST	DMPER2		;YES, DON'T PRINT MESSAGE
DMPER1:	PUSH	P,T1		;SAVE CODE FOR LATER
	HRRZ	T1,EMSTAB(T1)	;GET MESSAGE ADDRESS
	PUSHJ	P,PRMSG		;PRINT IT
	PUSHJ	P,PRFILE	;PRINT FILENAME
	PUSHJ	P,PRCRLF	;END THE LINE
	POP	P,T1		;RESTORE ERROR CODE
DMPER2:
IFN FTKL10,<
	CONSZ	APR,LP.SBE!LP.NXM!LP.PAR ;NXM OR PARITY ERROR?
>
IFN FTKS10,<
	CONSZ	APR,SP.NXM!SP.HMP ;NXM OR PARITY ERROR?
>
	JRST	DMPER3		;YES
	TLNN	S,(FL.LDE)	;SKIP IF LOAD ERROR
	SKIPA	T1,DMPDSP(T1)	;GET DISPATCH ADDRESSES FOR DUMP
	MOVE	T1,LODDSP(T1)	;DITTO FOR LOAD
	TLNN	S,(FL.WLD)	;DOING WILD STR?
	MOVSS	T1		;YES, USE LH DISPATCH ADDRESSES
	JRST	(T1)		;GO RECOVER

;HERE ON A NXM OR PARITY ERROR DETECTED IN THE CONI APR TO PRINT THE
;APR STATUS AND GIVE UP.

DMPER3:	MOVEI	T1,[ASCIZ/?NXM or memory parity error detected/]
	PUSHJ	P,PRMSG		;TELL WHAT HAPPENED
	PUSHJ	P,PRTHDW	;PRINT APR, EBR, AND UBR STATUS
	CONO	APR,CLRAPR	;RESET THE BITS
	TLO	S,(FL.DEF!FL.CMD) ;NO DEFAULTS, READ FROM CTY
	POPJ	P,		;AND GIVE UP
;HERE ON A FATAL ERROR WHICH WILL RESTART BOOT AT "RESTAR"
;INVOKED VIA THE "ERROR" MACRO

FATERR:	MOVEI	T1,[ASCIZ /
%/]
	PUSHJ	P,PRMSG		;START ON A NEW LINE
	HRRZ	T1,@(P)		;GET TEXT ADDRESS
	PUSHJ	P,PRMSG		;PRINT IT
	PUSHJ	P,PRCRLF	;NEW LINE
	PJRST	RESTAR		;START OVER
;TABLE OF ERROR MESSAGES INDEXED BY THE ERROR CODE RETURNED IN T1.
;THE STRUCTURE NOT FOUND AND FILE NOT FOUND ERRORS MUST BE THE FIRST
;IN THE TABLE BEFORE THE LABEL FNFOFS SO THAT WE CAN AVOID PRINTING
;A FILE/STRUCTURE NOT FOUND MESSAGE FOR EVERY STRUCTURE WHEN THE
;OPERATOR SPECIFIES A WILD STRUCTURE NAME.

EMSTAB:	[ASCIZ/%Structure not found for /]
	[ASCIZ/%File not found /]
FNFOFS==.-EMSTAB-1
	[ASCIZ/%Unprocessed dump on /]
	[ASCIZ/%Unexpected end-of-file on /]
	[ASCIZ\%I/O error on \]
	[ASCIZ/%Bad directory format for /]
	[ASCIZ/%Memory configuration too complicated for /]
	[ASCIZ/%Not a REBOOTable dump /]
	[ASCIZ/%Monitor extends past beginning of BOOT for /]
EMSTBL==.-EMSTAB


;DISPATCH TABLES INDEXED BY ERROR CODE.  LH GIVES THE DISPATCH ADDRESS
;IF AN EXPLICIT STRUCTURE WAS GIVEN, RH GIVES THE DISPATCH ADDRESS IF
;THE STRUCTURE WAS WILD (DSKA-DSKZ)

DMPDSP:	XWD	ASKSTR,DODUM1	;STRUCTURE NOT FOUND
	XWD	ASKSTR,DODUM1	;FILE NOT FOUND
	XWD	STRFUL,DODUM1	;UNPROCESSED DUMP
	XWD	ASKSTR,DODUM1	;UNEXPECTED EOF
	XWD	ASKSTR,DODUM1	;I/O ERROR
	XWD	ASKSTR,DODUM1	;BAD DIRECTORY FORMAT
	XWD	ASKSTR,DODUM1	;MEMORY CONFIGURATION TOO COMPLICATED
	XWD	ASKSTR,DODUM1	;NOT A REBOOTABLE CRASH
	XWD	ASKSTR,DODUM1	;MONITOR EXTENDS BEYOND BEGINNING OF BOOT
DMPDSL==.-DMPDSP

LODDSP:	XWD	CPOPJ,DOLOA1	;STRUCTURE NOT FOUND
	XWD	CPOPJ,DOLOA1	;FILE NOT FOUND
	XWD	CPOPJ,DOLOA1	;UNPROCESSED DUMP
	XWD	CPOPJ,DOLOA1	;UNEXPECTED EOF
	XWD	CPOPJ,DOLOA1	;I/O ERROR
	XWD	CPOPJ,DOLOA1	;BAD DIRECTORY FORMAT
	XWD	CPOPJ,DOLOA1	;MEMORY CONFIGURATION TOO COMPLICATED
	XWD	CPOPJ,DOLOA1	;NOT A REBOOTABLE CRASH
	XWD	CPOPJ,DOLOA1	;MONITOR EXTENDS BEYOND BEGINNING OF BOOT
LODDSL==.-LODDSP


IF2 <IFN EMSTBL-DMPDSL+LODDSL-ERRTBL,<
PRINTX ?Discrepency in lengths of EMSTAB, DMPDSP, LODDSP, ERRTAB
>>
;HERE IF AN EXPLICIT STR WAS GIVEN AND AN UNPROCESSED DUMP WAS FOUND
;ON THAT STR.

STRFUL:	MOVEI	T1,[ASCIZ/Do you want to overwrite it? /]
	MOVEI	T2,[ASCIZ/No/]
	PUSHJ	P,ASKYN
	  JRST	STRFUL		;CONFUSED USER--ASK AGAIN
	  JRST	ASKSTR		;ANSWER WAS NO
	JRST	DODUM5		;OVERWRITE FILE
;ROUTINE TO DUMP THE MONITOR ONTO THE CRASH FILE SPECIFIED IN THE
;COMMAND STRING.  DOES 5 ONE BLOCK TRANSFERS TO WRITE THE 4 BLOCKS
;OF THE DIRECTORY PLUS WORDS 0-177 OF PAGE 0 (SINCE THE RH20 CAN'T
;READ/WRITE ADDRESS 0) AND THEN DOES AS FEW TRANSFERS AS NECESSARY
;FOR EACH GROUP POINTER IN THE RIB.  (GENERALLY ONLY 1).  CALL WITH
;STRUCTURE NAME IN DEV.
;CALL:	PUSHJ	P,DUMP
;RETURN+1 IF ERROR DETECTED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL

DUMP:	PUSHJ	P,SAVE2		;SAVE P1-P2
	PUSHJ	P,FNDFIL	;FIND CRASH FILE FOR THIS STR
	  POPJ	P,		;NOT FOUND
	TLNE	S,(FL.SSD)	;SUSPENDING?
	SKIPA	T1,[[ASCIZ /[Suspending system on /]] ;YES, DIFFERENT MESSAGE
	MOVEI	T1,[ASCIZ/[Dumping on /]
	PUSHJ	P,PRMSG		;TELL THE OPERATOR WHAT
	PUSHJ	P,PRFILE	;  WE'RE DOING
	PUSHJ	P,PRRBCR	;END THE LINE
	MOVEI	T1,RIPDMP	;GET "UNPROCESSED DUMP BIT"
	TLNN	S,(FL.OVW)	;DOES CALLER CARE?
	TDNN	T1,RIB+RIBSTS	;YES, IS BIT SET IN RIB?
	CAIA			;NO, OR DOESN'T CARE
	JRST	UPDERR		;YES, GIVE ERROR RETURN
	IORM	T1,RIB+RIBSTS	;SET BIT IN RIB
	PUSHJ	P,WRTRIB	;REWRITE RIB
	  POPJ	P,		;FAILED
	PUSHJ	P,CLRBUF	;CLEAR BUFFER AREA
	MOVSI	P3,-BLKSIZ	;MAKE AOBJP POINTER TO BUF
	MOVEI	P4,1		;FIRST FILE PAGE IS 1
	MOVEI	P2,0		;FIRST CORE PAGE IS 0
DUMP1:	PUSHJ	P,FNDPGS	;FIND NEXT GROUP OF CONTIGUOUS PAGES
	JUMPLE	P1,DUMP3	;DONE IF NONE FOUND
	MOVE	T1,P1		;COPY NUMBER OF PAGES TO T1
	SUBI	T1,1		;REPEAT COUNT FOR LAST HUNK
	ROT	T1,-^D9		;NUMBER OF 256K HUNKS+REPEAT COUNT IN LH
	MOVEI	T2,1(T1)	;T2:=NUMBER OF DESCRIPTORS
DUMP2:	AOBJP	P3,MCCERR	;GO IF TOO MANY DESCRIPTORS
	HRRZM	P4,BUF(P3)	;STORE FILE PAGE NUMBER IN BUF
	MOVEI	T3,(P2)		;COPY CORE PAGE NUMBER TO T3
	HRLI	T3,777000	;512 PAGES IN THIS HUNK
	AOBJP	P3,MCCERR	;GO IF TOO MANY DESCRIPTORS
	MOVEM	T3,BUF(P3)	;STORE IN BUFFER
	ADDI	P2,<^D256*^D1024>/PAGSIZ ;INCR CORE PAGE
	ADDI	P4,<^D256*^D1024>/PAGSIZ ;DITTO FOR FILE PAGE
	SOJG	T2,DUMP2	;LOOP FOR ALL DESCRIPTORS
	HLLM	T1,BUF(P3)	;CORRECT REPEAT COUNT IN LAST DESCRIPTOR
	LSH	T1,-<^D9+^D18>	;RIGHT JUSTIFY REPEAT COUNT
	MOVNI	T1,-777(T1)	;HAVE TO BACK OFF ON CORE AND FILE PAGE
	SUBI	P2,(T1)		;  NUMBERS TO REFLECT THE (POSSIBLY)
	SUBI	P4,(T1)		;  PARTIAL ALLOCATION IN THE LAST DESCRIPTOR
	JRST	DUMP1		;LOOP FOR MORE
DUMP3:	MOVE	T1,[SV.END,,1]	;GET END OF DESCRIPTOR MARKER
	AOBJP	P3,MCCERR	;GO IF TOO MANY DESCRIPTORS
	MOVEM	T1,BUF(P3)	;STORE IN BUFFER
	HRLI	P3,SV.DIR	;MAKE P3 BE 1ST WORD OF DIRECTORY
	MOVEM	P3,BUF		;AND STORE IT THERE
	PUSHJ	P,WRTBUF	;WRITE BUFFER TO FILE
	  POPJ	P,		;NO POINTERS OR WRITE FAILURE
	PUSHJ	P,CLRBUF	;CLEAR BUFFER AGAIN
	MOVEI	P1,3		;NEED TO WRITE 3 BLOCKS OF ZEROS
DUMP4:	PUSHJ	P,WRTBUF	;  TO COMPLETE DIRECTORY
	  POPJ	P,		;NO POINTERS OR WRITE FAILURE
	SOJG	P1,DUMP4	;LOOP FOR ALL
	MOVE	T1,[.VPAG0,,BUF] ;SETUP TO BLT WORD 0-177 TO BUF
	BLT	T1,BUF+BLKSIZ-1 ;DO SO
	PUSHJ	P,WRTBUF	;WRITE IT
	  POPJ	P,		;NO POINTERS OR WRITE FAILURE
	MOVEI	P2,0		;START WITH ADDRESS 0
DUMP5:	LSH	P2,W2PLSH	;CONVERT TO PAGE NUMBER
	PUSHJ	P,FNDPGS	;FIND NEXT GROUP OF CONTIGUOUS PAGES
	JUMPLE	P1,CPOPJ1	;DONE IF NO MORE
	LSH	P2,P2WLSH	;CONVERT BACK TO ADDRESS
	LSH	P1,P2BLSH	;CONVERT PAGES TO BLOCKS
	JUMPN	P2,DUMP6	;GO IF NOT DOING PAGE ZERO
	ADDI	P2,BLKSIZ	;COMPENSATE FOR WORDS 0-177
	SUBI	P1,1		;  WHICH WERE WRITTEN ABOVE
DUMP6:	JUMPLE	P1,DUMP5	;LOOP IF NO MORE BLOCKS IN THIS CHUNK
	PUSHJ	P,LISTEN	;CHECK FOR CONTROL-C
	MOVE	T1,P1		;COPY NUMBER OF BLOCKS WE WANT TO XFER
	PUSHJ	P,SELBLK	;SETUP TO DO THAT MANY
	  JRST	EOFERR		;RAN OUT OF POINTERS
	MOVE	R,P2		;START AT THIS ADDRESS
	MOVE	P1,T1		;COPY NUMBER LEFT INTO P1 FOR LOOP TEST
	MOVE	T1,M		;GET NUMBER OF BLOCKS WE CAN DO
	LSH	T1,B2WLSH	;CONVERT TO WORDS
	ADD	P2,T1		;INCREMENT ADDRESS FOR NEXT TIME
	PUSHJ	P,@WRTTAB(W)	;DO THE WRITE
	  JRST	IOFERR		;WRITE ERROR
	JRST	DUMP6		;LOOP FOR ALL OF CORE
	SUBTTL	RELOAD MONITOR


;ROUTINE TO RELOAD THE MONITOR FROM A FILE ON DISK.  CALL WITH
;THE FILESPEC FROM WHICH TO LOAD SETUP IN THE FILESPEC AREA.
;CALL:	PUSHJ	P,DOLOAD
;RETURN+1 IF ERRORS DETECTED WITH MESSAGE ALREADY ISSUED
;RETURN+2 IF LOAD WAS SUCCESSFUL

DOLOAD:	SKIPN	NXMFLG		;NXMTAB VALID?
	PUSHJ	P,SUNXMT	;MUST REBUILD IT
	PUSHJ	P,ZERCOR	;START OFF CLEAN BY ZEROING CORE
	PUSHJ	P,SSLCHK	;CHECK FOR THE SSL
	  SKIPA	P1,['DSKA  '-10000] ;GET DISK NAME TO INCREMENT TO DSKA
	MOVE	P1,T1		;GET PREDECREMENTED AOBJN POINTER
	MOVE	T1,[SIXBIT/SYSTEM/] ;DEFAULT FILENAME IS SYSTEM
	TRNE	S,FR.RBT	;UNLESS A /REBOOT REQUEST
	MOVE	T1,[SIXBIT/CRASH/] ;IN WHICH CASE FILENAME IS CRASH
	TRNN	S,FR.FIL	;SEE A FILENAME?
	MOVEM	T1,FILNAM	;NO, USE DEFAULT
	TLNN	S,(FL.WLD)	;WILD STR?
	JRST	DOLOA4		;NO, USE THE ONE HE GAVE
DOLOA1:	TRNE	S,FR.FRC	;/FORCE SEEN?
	JRST	DOLOA2		;YES
	AOBJP	P1,DOLOA5	;ADVANCE POINTER
	SKIPN	T1,(P1)		;GET A STRUCTURE NAME
	AOBJN	P1,.-1		;NONE THERE, TRY NEXT
	JUMPL	P1,DOLOA3	;JUMP IF HAVE A STRUCTURE NAME
	JRST	DOLOA5		;GIVE UP
DOLOA2:	CAMN	P1,[SIXBIT/DSKZ/] ;LOOKED AT THEM ALL?
	JRST	DOLOA5		;YES, GIVE UP
	ADDI	P1,10000	;STEP TO NEXT DISK NAME
	MOVE	T1,P1		;COPY STRUCTURE NAME
DOLOA3:	MOVEM	T1,DEV		;STORE STR NAME
DOLOA4:	PUSHJ	P,LOAD		;LOAD IT
	  JRST	LODERR		;GIVE ERROR MESSAGE AND RETURN
	JRST	CPOPJ1		;GIVE SKIP RETURN
DOLOA5:	MOVEI	T1,[ASCIZ/?No file found on any structure
/]
	PJRST	PRMSG		;GIVE ERROR MESSAGE AND RETURN
;ROUTINE TO LOAD A NEW MONITOR INTO CORE. CALL WITH THE FILESPEC AREA
;CONTAINING THE FILE TO BE LOADED.
;CALL:	PUSHJ	P,LOAD
;RETURN+1 IF ERROR DETECTED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL

LOAD:	PUSHJ	P,SAVE2		;SAVE P1-P2
	PUSHJ	P,FNDMON	;FIND THE MONITOR, READ EXE DIRECTORY
	  POPJ	P,		;FAILED, RETURN CODE IN T1
	TRNE	S,FR.RBT	;THIS A REBOOT?
	SKIPA	T1,[[ASCIZ/[Reloading from /]] ;YES, CHANGE THE MESSAGE
	MOVEI	T1,[ASCIZ/[Loading from /]
	PUSHJ	P,PRMSG		;TELL WHAT'S HAPPENING
	PUSHJ	P,PRFILE	;PRINT FILENAME
	PUSHJ	P,PRRBCR	;END THE LINE
	MOVEI	P3,0		;START WITH CORE ADDRESS OF ZERO
LOAD1:	LDB	P2,[POINT 9,1(P1),8] ;GET REPEAT COUNT FOR THIS ENTRY
	ADDI	P2,1		;MAKE IT TOTAL PAGE COUNT
	LSH	P2,P2BLSH	;COMPUTE BLOCK COUNT
	HRRZ	P4,0(P1)	;GET FILE PAGE NUMBER
	LSH	P4,P2BLSH	;COMPUTE FILE BLOCK NUMBER
	JUMPE	P4,[LSH  P2,B2WLSH ;IF ALLOCATED BUT ZERO PAGE, COMPUTE
		    ADD  P3,P2	;  NUMBER OF WORDS IN THIS DESCRIPTOR
		    JRST LOAD11]	;  UPDATE CORE ADDRESS AND DO NEXT ONE
	CAMGE	P4,BLKNUM	;PAGE NUMBERS IN THE EXE DIRECTORY MUST
	JRST	BDFERR		;  BE MONOTONICALLY INCREASING
LOAD2:	PUSHJ	P,POSFIL	;POSITION FILE TO THAT BLOCK
	  POPJ	P,		;HIT EOF
LOAD3:	HRRZ	P3,1(P1)	;GET CORE PAGE NUMBER
	LSH	P3,P2WLSH	;COMPUTE CORE ADDRESS
	JUMPN	P3,LOAD5	;GO IF NOT ZERO
	HRL	P4,P2		;REMEMBER NUMBER OF BLOCKS
	MOVEI	P2,PAGSIZ/BLKSIZ ;  AND READ ONE PAGE
LOAD4:	MOVEI	P3,PAGSIZ	;  STARTING AT 1000
LOAD5:	PUSHJ	P,LISTEN	;CHECK FOR CONTROL-C
	CAML	P3,BTTOP	;IS THERE ANY CHANCE OF HITTING BOOT?
	JRST	LOAD9		;NO, DON'T BOTHER ME
	CAML	P3,BTBOT	;YES, DO WE KNOW FOR SURE THAT IT WILL?
	JRST	LOAD6		;YES, HANDLE
	MOVE	T1,P2		;NO, COPY NUMBER OF BLOCKS TO TRANSFER
	LSH	T1,B2WLSH	;MAKE NUMBER OF WORDS
	ADD	T1,P3		;GET END+1 OF TRANSFER
	CAMG	T1,BTBOT	;WILL IT HIT BOOT?
	JRST	LOAD9		;NO, DON'T SWEAT IT
LOAD6:	TRNN	S,FR.RBT	;YES, ARE WE RELOADING A SLEEP DUMP?
	JRST	MEPERR		;NO, CAN'T DO IT
	CAML	P3,BTBOT	;ARE WE ABOUT TO CLOBBER BOOT?
	JRST	LOAD7		;YES, BE SELECTIVE
	MOVE	T1,BTBOT	;NO, GET START OF BOOT
	SUB	T1,P3		;FIND WORDS UNTIL BOOT
	LSH	T1,W2BLSH	;MAKE NUMBER OF BLOCKS
	SUB	P2,T1		;GET NUMBER OF BLOCKS TO CLOBBER
	MOVEM	P2,SCR		;SAVE REMAINDER
	MOVE	P2,T1		;COPY NUMBER OF 'SAFE' BLOCKS
	PUSHJ	P,REDBLK	;READ THEM IN
	  POPJ	P,		;PROPAGATE ERROR
	MOVE	P2,SCR		;GET REMAINING NUMBER TO TRANSFER
	JRST	LOAD5		;CHECK IT AGAIN
LOAD7:	MOVE	T1,P3		;YES, COPY PAGE NUMBER
	SUB	T1,BTBOT	;CONVERT TO OFFSET
	CAIL	T1,.BTSVB	;IS THIS IN THE RANGE
	CAIL	T1,.BTSVE	; THAT WE CARE ABOUT?
	JRST	LOAD8		;NO, DON'T BOTHER ME WITH IT
	PUSHJ	P,BLOAD		;YES, LOAD SCR WITH A BLOCK
	  POPJ	P,		;PROPAGATE FAILURE
	MOVE	T1,P3		;COPY PHYS. ADDRESS AGAIN
	SUB	T1,BTBOT	;CONVERT TO OFFSET
	MOVE	T2,T1		;COPY OFFSET
	MOVE	T3,T1		;AGAIN
	ANDI	T1,<BLKSIZ-1>	;KEEP OFFSET INTO BLOCK
	HRLI	T2,SCR(T1)	;GET SOURCE POINTER
	ADDI	T2,BTSVEC(T1)	;FORM XFER WORD
	MOVEI	T1,BTSVEC+BLKSIZ(T3) ;GET PRESUMED TERMINATION POINTER
	CAIGE	T3,.BTSVE	;UNLESS PARTIAL LAST BLOCK,
	MOVEI	T1,BTSVEC+.BTSVE ;THEN KEEP ONLY WHAT WE NEED
	BLT	T2,-1(T1)	;COPY THE DATA
				;FALL INTO LOAD8 TO TRY THE NEXT BLOCK

LOAD8:	ADDI	P3,BLKSIZ	;SKIPPING ONE BLOCK
	SOJE	P2,LOAD11	;TRY THE NEXT POINTER IF EXHAUSTED COUNT
	ADDI	P4,1		;NO, BUMP FILE BLOCK NUMBER
	PUSHJ	P,POSFIL	;GET THERE
	  POPJ	P,		;PROPAGATE ERROR
	JRST	LOAD5		;AND TRY ANOTHER BLOCK

LOAD9:	PUSHJ	P,REDBLK	;READ THE SPECIFIED BLOCKS
	  POPJ	P,		;FAILED
	HLRZ	P2,P4		;WERE WE READING 0-777
	JUMPE	P2,LOAD11	;  INTO 1000-1777?
	TRNN	S,FR.RBT	;DOING A REBOOT?
	JRST	LOAD10		;NO, CONTINUE
	SKIPN	.VPAG0+PAGSIZ+MBTCOM ;GET PAGE NUMBER OF COMM AREA
	JRST	NSSERR		;NOT A REBOOTABLE CRASH
IFN FTTAPE,<
	SKIPN	NOTAPE		;TAPE DRIVER CODE STILL PRESENT?
	PUSHJ	P,ZAPTAP	;DELETE IT NOW SO BOOT SIZE IS CORRECTED
> ;END IFN FTTAPE
	MOVE	T2,.VPAG0+PAGSIZ+MBTCOM ;GET PAGE NUMBER OF COMM AREA
	HLLZ	T1,T2		;GET -NUMBER OF PAGES IN LH
	HLLZ	T3,BTSVEC+.BTSIZ ;GET PAGES IN BOOT
	CAMLE	T1,T3		;MAKE SURE WE'LL FIT
	JRST	MCCERR		;COMPLAIN
	HRRZS	T3,T2		;CLEAR JUNK
	LSH	T3,P2WLSH	;CONVERT PAGE TO ADDRESS
	CAME	T3,.VPAG0+PAGSIZ+BOOTSA ;DOES IT MATCH THE BOOT ADDRESS?
	JUMPL	T1,NSSERR	;NO, CAN'T DO IT
	PUSHJ	P,MOVBTS	;MOVE US TO THOSE PAGES
	SKIPA	T1,[.VPAG0+PAGSIZ,,.VPAG0] ;SETUP TO BLT ENTIRE PAGE
LOAD10:	MOVE	T1,[.VPAG0+PAGSIZ+40,,.VPAG0+40] ;SETUP TO BLT 40-777
	BLT	T1,.VPAG0+PAGSIZ-1 ;MOVE THEM TO WHERE THEY BELONG
	HRRZS	P4		;CLEAR FLAG
	SUBI	P2,PAGSIZ/BLKSIZ ;COMPENSATE FOR WHAT WE READ
	JUMPG	P2,LOAD4	;DO THE REST IF MORE
LOAD11:	AOBJP	P1,.+1		;SKIP PAST FIRST OF 2 WORDS
	AOBJN	P1,LOAD1	;AND DO NEXT DESCRIPTOR
	JRST	CPOPJ1		;GIVE SKIP RETURN

BLOAD:	PUSHJ	P,SAVE4		;PRESERVE THESE FOR LATER
	MOVEI	P2,1		;ONLY READ ONE BLOCK
	MOVEI	P3,SCR-BTSVEC	;OFFSET TO SCRATCH BUFFER
	ADD	P3,BTBOT	;PHYSICAL ADDRESS FOR READ
	PJRST	REDBLK		;DO THE READ & PROPAGATE ITS RETURN
	SUBTTL	PARITY ERROR PAGE REPLACEMENT

;ROUTINE TO REPLACE A MONITOR HIGH SEGMENT PAGE FROM THE DISK COPY
;OF THE MONITOR ON PARITY ERRORS, ETC.
;CALL:
;	SUBDAT+0/EXEC VIRTUAL PAGE NUMBER
;	SUBDAT+1/PHYSICAL ADDRESS OF START OF THAT PAGE
;	PUSHJ	P,PGFUNC
;RETURN +1 ALWAYS, WITH PAGE REPLACED OR ERRFLG LIT

PGFUNC:	SKIPN	BTSVEC+.BTDEV	;DO WE KNOW WHERE TO FIND THE MONITOR?
	JRST	PGFUN3		;NO, COMPLAIN
	DMOVE	P2,SUBDAT	;YES, GET OUR ARGUMENTS
	SKIPE	P2		;IF EITHER THE PAGE NUMBER
	SKIPN	P3		;OR THE DESTINATION IS ZERO,
	JRST	PGFUN4		;WHINE
	MOVE	T1,[BTSVEC+.BTDEV,,DEV]
	BLT	T1,PTHBLK+6	;COPY THE MONITOR FILESPEC
	MOVEI	S,FR.DEV!FR.FIL!FR.EXT!FR.PTH ;WE HAVE EVERYTHING
	PUSHJ	P,FNDMON	;FIND FILE CONTAINING THE MONITOR
	  JRST	PGFUN5		;FAILED
	DMOVE	P2,SUBDAT	;GET ARGUMENTS AGAIN
PGFUN1:	HRRZ	P4,0(P1)	;GET FILE PAGE NUMBER OF NEXT DESCRIPTOR
	JUMPE	P4,PGFUN2	;NO GOOD IF ALLOCATED BUT ZERO PAGE
	HRRZ	T1,1(P1)	;GET CORE PAGE NUMBER OF DESCRIPTOR
	LDB	T2,[POINT 9,1(P1),8]  ;  AND REPEAT COUNT
	ADD	T2,T1		;CALCULATE LAST PAGE IN THIS DESCRIPTOR
	CAML	P2,T1		;IS DESIRED PAGE DESCRIBED BY
	CAMLE	P2,T2		;  THIS DESCRIPTOR?
	JRST	PGFUN2		;NO, CONTINUE
	SUB	P2,T1		;COMPUTE RELATIVE OFFSET OF DESIRED PAGE
	ADD	P4,P2		;AND FILE PAGE CONTAINING IT
	LSH	P4,P2BLSH	;COMPUTE FILE BLOCK NUMBER
	PUSHJ	P,POSFIL	;POSITION FILE TO THAT BLOCK
	  JRST	PGFUN5		;HIT EOF
	MOVEI	P2,PAGSIZ/BLKSIZ ;NUMBER OF BLOCKS TO TRANSFER
	PUSHJ	P,REDBLK	;READ PAGE INTO CORE
	  JRST	PGFUN5		;FAILED
	POPJ	P,		;RETURN WITH ERRFLG CLEAR (WINNITUDE)
PGFUN2:	AOBJP	P1,.+1		;LOOP FOR ALL DESCRIPTORS
	AOBJN	P1,PGFUN1	;WHICH ARE 2 WORDS LONG
	MOVEI	T1,[ASCIZ /% Can't find requested page in /]
	JRST	PGFUN6		;COMPLAIN ABOUT MISSING PAGE

PGFUN3:	MOVEI	T1,[ASCIZ /
? BOOT error; no saved monitor filespec
/]
	TRNA			;SKIP INTO FOLLOWING
PGFUN4:	MOVEI	T1,[ASCIZ /
? BOOT error; can't replace page zero
/]
	SETOM	ERRFLG		;RETURN ERROR TO TOP LEVEL
	PJRST	PRMSG		;TYPE TEXT AND RETURN
PGFUN5:	HRRZ	T1,EMSTAB(T1)	;CONVERT ERROR CODE TO STRING
PGFUN6:	PUSHJ	P,PRMSG		;TYPE THE ERROR TEXT
	PUSHJ	P,PRFILE	;AND THE FILESPEC
	PUSHJ	P,PRCRLF	;END THE LINE
	SETOM	ERRFLG		;RETURN BADNESS
	POPJ	P,		;GIVE UP
	SUBTTL	FILE SEARCH SUBROUTINES


;ROUTINE TO FIND THE FILE CONTAINING THE MONITOR SPECIFIED IN THE
;FILESPEC AREA, READ THE EXE DIRECTORY INTO BUF AND SETUP TO READ
;THE FILE.
;CALL:	PUSHJ	P,FNDMON
;RETURN+1 IF FAILED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL WITH
; P1/AOBJN POINTER TO EXE DIRECTORY DESCRIPTORS
;DESTROYS P3-P4
;FOR TAPES WE BRANCH TO SCAN TO SEARCH THE TAPE FOR THE T$FIL RECORD
;FOR THE DESIRED FILE, READ THE BLOCK CONTAINING THE DIRECTORY AND BLT
;THE DIRECTORY INTO BUF, THEN REJOIN THE CODE AT FNDMOE.

FNDMON:
IFN FTTAPE,<
	SKIPE	TAPIDX		;TAPE I/O?
	JRST	TAPSCN		;YES, SEARCH THE TAPE FOR T$FIL RECORD
>; END IFN FTTAPE
	PUSHJ	P,FNDFIL	;FIND THE FILE
	  POPJ	P,		;FILE NOT FOUND
	PUSHJ	P,REDBUF	;READ 1ST BLOCK OF EXE DIRECTORY
	  POPJ	P,		;FAILED
FNDMOE:	HLRZ	T1,BUF		;GET CODE
	HRRZ	P1,BUF		;AND LENGTH OF DIRECTORY
	CAIN	T1,SV.DIR	;THIS AN EXE FILE?
	CAILE	P1,BLKSIZ-1	;AND NOT TOO LONG?
	JRST	BDFERR		;NO, BAD DIRECTORY FORMAT
	MOVNI	P1,-1(P1)	;BUILD -VE COUNT FOR AOBJN POINTER
	HRLI	P1,BUF+1	;AND FIRST WORD
	MOVSS	P1		;MAKE IT AN AOBJN POINTER TO BUF
	JRST	CPOPJ1		;GIVE SKIP RETURN
;ROUTINE TO FIND A FILE AND SETUP ITS RIB IN RIB.  CALL WITH
;FILESPEC AREA SETUP.
;CALL:	PUSHJ	P,FNDFIL
;RETURN+1 IF NOT FOUND OR READ ERROR ON DIRECTORY WITH CODE IN T1
;RETURN+2 IF FILE FOUND
;DESTROYS P3-P4

FNDFIL:	TLZ	S,(FL.FFL)	;HAVEN'T FOUND FILE YET
	PUSHJ	P,SAVE2		;SAVE P1-P2
	PUSHJ	P,FNDMFD	;FIND THE MFD
	  JRST	SNTERR		;FAILED
	MOVEI	P1,0		;SETUP LOOP POINTER TO PTHBLK
FNDFI1:	SKIPN	P3,PTHBLK(P1)	;GET NEXT UFD/SFD FROM PATH BLOCK
	MOVE	P3,FILNAM	;FOUND END, USE FILENAME
	MOVEI	P4,'UFD'	;ASSUME EXTENSION IS UFD
	JUMPE	P1,FNDFI2	;GO IF CORRECT
	MOVEI	P4,'SFD'	;ASSUME SFD
	SKIPN	PTHBLK(P1)	;DONE WITH PATH BLOCK?
	HLRZ	P4,EXT		;YES, USE REAL EXTENSION
FNDFI2:	PUSHJ	P,SRCHFD	;SEARCH THE DIRECTORY
	  JRST	FNTERR		;FILE NOT FOUND
	PUSH	P,T2		;SAVE BLOCK IN UNIT OF RIB
	PUSHJ	P,FNDLUN	;FIND SPECIFIED UNIT
	  JRST	[POP	P,(P)	;FLUSH STACK
		 JRST	SNTERR]	;GIVE ERROR CODE AND RETURN
	POP	P,F		;RESTORE BLOCK OF RIB
	PUSHJ	P,REDRBP	;READ THE RIB OF THE FILE
	  JRST	FNTERR		;FAILED
	SKIPE	PTHBLK(P1)	;FOUND UFD, ALL SFD'S AND FILE?
	AOJA	P1,FNDFI1	;NO, TRY NEXT LEVEL
	TLO	S,(FL.FFL)	;INDICATE THAT WE FOUND THE FILE
	JRST	CPOPJ1		;GIVE SKIP RETURN, RIB SETUP
;ROUTINE TO FIND THE MFD FOR A STRUCTURE.  CALL WITH DEV CONTAINING
;THE STRUCTURE NAME.
;CALL:	PUSHJ	P,FNDMFD
;RETURN+1 IF FAILED
;RETURN+2 IF FOUND WITH MFD RIB IN RIB
;DESTOYS P3-P4

FNDMFD:	SETZM	LUNPOS		;FIND UNIT ZERO OF STRUCTURE
	PUSHJ	P,FNDUNI	;FIND IT
	  POPJ	P,		;FAILED, GIVE UP
	MOVE	T1,HOM+HOMMFD	;GET BLOCK IN STR CONTAINING MFD RIB
	MOVE	T2,HOM+HOMBSC	;GET BLOCKS/SUPERCLUSTER
	IMUL	T2,HOM+HOMSCU	;TIME SUPERCLUSTERS/UNIT
	IDIV	T1,T2		;T1=UNIT, T2=BLOCK IN UNIT OF RIB
	PUSH	P,T2		;SAVE BLOCK NUMBER
	JUMPE	T1,FNDMF1	;GO IF ON UNIT ZERO
	MOVEM	T1,LUNPOS	;STORE UNIT
	PUSHJ	P,FNDUNI	;FIND UNIT
	  JRST	TPOPJ		;FAILED
FNDMF1:	POP	P,F		;RESTORE BLOCK IN UNIT
	MOVE	P3,[1,,1]	;FILENAME IS [1,,1]
	MOVEI	P4,'UFD'	;EXTENSION IS UFD
	PJRST	REDRBP		;READ RIB OF MFD AND RETURN


;ROUTINE TO SEARCH A UFD OR SFD FOR A FILE.  CALL WITH RIB SETUP
;IN RIB.
;CALL:
;	P3/FILENAME,	P4/0,,EXTENSION
;	PUSHJ	P,SRCHFD
;RETURN+1 IF FILE NOT FOUND
;RETURN+2 IF FOUND
;RETURNS T1=UNIT IN STR, T2=BLOCK IN UNIT OF RIB FOR FILE.

SRCHFD:	PUSHJ	P,REDBUF	;READ THE NEXT BLOCK OF THE DIRECTORY
	  POPJ	P,		;EOF OR READ ERROR
	MOVSI	T1,-BLKSIZ	;BUILD AOBJN POINTER TO BLOCK
SRCHF1:	HLRZ	T2,BUF+1(T1)	;GET EXTENSION
	CAMN	P3,BUF(T1)	;FILENAMES MATCH?
	CAME	P4,T2		;YES, EXTENSIONS MATCH?
	AOBJN	T1,.+2		;NO, INCREMENT PAST FILENAME
	JRST	SRCHF2		;YES
	AOBJN	T1,SRCHF1	;LOOP FOR ALL OF THIS BLOCK
	JRST	SRCHFD		;TRY NEXT BLOCK
SRCHF2:	HRRZ	T1,BUF+1(T1)	;GET CFP FROM DIRECTORY
	IDIV	T1,HOM+HOMSCU	;T1=UNIT, T2=SUPERCLUSTER IN UNIT
	IMUL	T2,HOM+HOMBSC	;T2=BLOCK IN UNIT
	JRST	CPOPJ1		;GIVE SKIP RETURN
	SUBTTL	BLOCK READ/WRITE SUBROUTINES


;ROUTINE TO WRITE BUF/RIB TO THE OUTPUT FILE.  CALL WITH RIB OF FILE
;SETUP.
;CALL:	PUSHJ	P,WRTBUF  -OR-  PUSHJ P,WRTRIB
;RETURN+1 IF ERROR DETECTED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL

WRTRIB:	MOVEI	R,RIB		;POINT TO RIB
	AOS	SAVSIZ		;COMPENSATE FOR SELBLK DECREMENTING SAVSIZ
	TLZA	S,(FL.RIB)	;FORCE SELBLK TO WRITE THE RIB
WRTBUF:	MOVEI	R,BUF		;POINT TO BUF
	MOVEI	T1,1		;NUMBER OF BLOCKS IS 1
	PUSHJ	P,SELBLK	;SETUP TO DO THAT MANY
	  JRST	EOFERR		;FILE MUST BE REALLY SCREWED UP
	JUMPN	T1,EOFERR	;DITTO
	PUSHJ	P,VRTWRT	;WRITE THE BLOCK
	  JRST	IOFERR		;WRITE ERROR
	JRST	CPOPJ1		;GIVE SKIP RETURN


;ROUTINE TO READ ONE BLOCK FROM THE INPUT FILE INTO BUF.  CALL WITH
;RIB OF FILE SETUP.
;CALL:	PUSHJ	P,REDBUF
;RETURN+1 IF ERROR DETECTED WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL

REDBUF:	MOVEI	R,BUF		;POINT TO BUF
	MOVEI	T1,1		;NUMBER OF BLOCKS IS 1
	PUSHJ	P,SELBLK	;SETUP TO READ
	  JRST	EOFERR		;HIT EOF
	JUMPN	T1,EOFERR	;DITTO
	PUSHJ	P,VRTRED	;READ THE BLOCK
	  JRST	IOFERR		;READ ERROR
	JRST	CPOPJ1		;GIVE SKIP RETURN
;ROUTINE TO POSITION AN EXE FILE SO THAT THE NEXT READ WILL READ
;THE BLOCKS THAT WE WANT.
;CALL:
;	P4/DESIRED BLOCK IN FILE
;	PUSHJ	P,POSFIL
;RETURN+1 IF EOF ENCOUNTERED WITH ERROR CODE IN T1
;RETURN+2 WITH FILE POSITIONED CORRECTLY

POSFIL:	CAMN	P4,BLKNUM	;AT THE RIGHT BLOCK IN THE FILE NOW?
	JRST	CPOPJ1		;YES, GIVE SKIP RETURN
	MOVEI	T1,1		;DO ONE BLOCK
	PUSHJ	P,SELBLK	;USETI .+1
	  JRST	EOFERR		;CANNOT HAVE EOF HERE
	JRST	POSFIL		;TRY AGAIN


;ROUTINE TO READ ONE OR MORE BLOCKS FROM AN EXE FILE.
;CALL:	P2/NUMBER OF BLOCKS TO READ
;	P3/CORE ADDRESS OF WHERE TO READ FIRST BLOCK
;	P4/FILE BLOCK NUMBER OF FIRST BLOCK
;	PUSHJ	P,REDBLK
;RETURN+1 IF ERROR WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL WITH P3 AND P4 UPDATED TO REFLECT THE TRANSFER

REDBLK:
IFN FTTAPE,<
	SKIPE	TAPIDX		;TAPE I/O
	PJRST	REDTAP		;YES, DO IT OVER THERE
>; END IFN FTTAPE
REDBL1:	JUMPLE	P2,CPOPJ1	;READ ALL BLOCKS YET?
	MOVE	T1,P2		;NO, GET NUMBER OF BLOCKS TO TRANSFER
	PUSHJ	P,SELBLK	;SETUP TO DO THAT MANY
	  JRST	EOFERR		;CAN'T HAVE EOF
	MOVE	R,P3		;PUT CORE ADDRESS IN R
	MOVE	P2,T1		;COPY BLOCKS WE COULDN'T DO FOR NEXT TIME
	ADD	P4,M		;INCREMENT FILE BLOCK NUMBER
	MOVE	T1,M		;GET NUMBER OF BLOCKS TO DO
	LSH	T1,B2WLSH	;CONVERT TO WORDS
	ADD	P3,T1		;UPDATE CORE ADDRESS
	PUSHJ	P,@REDTAB(W)	;READ THE SPECIFIED BLOCKS
	  JRST	IOFERR		;I/O ERROR
	JRST	REDBL1		;CONTINUE FOR ALL
;ROUTINE TO FIND A UNIT AND READ IT'S HOM BLOCK. CALL WITH LUNPOS
;CONTAINING THE LOGICAL UNIT NUMBER AND DEV CONTAINING THE DEVICE
;NAME.
;CALL:
;	T1/LOGICAL UNIT IN STRUCTURE
;	PUSHJ	P,FNDLUN
;RETURN+1 IF NOT FOUND
;RETURN+2 IF FOUND WITH HOM BLOCK IN HOM

FNDLUN:	EXCH	T1,LUNPOS	;STORE UNIT, GET CURRENT
	CAMN	T1,LUNPOS	;SAME AS CURRENT ONE?
	JRST	CPOPJ1		;YES, ALREADY THERE
;;	PJRST	FNDUNI		;FALL INTO FNDUNI


;ROUTINE TO FIND A UNIT BY EXHAUSTIVE SEARCH.  CALL WITH LUNPOS
;CONTAINING THE LOGICAL UNIT NUMBER IN THE STRUCTURE, DEV CONTAINING
;THE STRUCTURE NAME AND SDLPOS CONTAINING THE POSITION IN THE SYSTEM
;DUMP LIST.
;CALL:	PUSHJ	P,FNDUNI
;RETURN+1 IF NOT FOUND
;RETURN+2 IF FOUND WITH HOM BLOCK IN HOM

FNDUNI:	MOVSI	J,-DVCTBL	;AOBJN POINTER TO DEVICE CODE TABLE
FNDUN1:	MOVSI	U,-MAXUNI	;AOBJN POINTER FOR EACH UNIT
FNDUN2:	HLRZ	W,DVCTAB(J)	;SETUP TYPE OFFSET
	PUSHJ	P,SETIOT	;SETUP I/O INSTRUCTIONS
	PUSHJ	P,REDHOM	;READ HOM BLOCK FOR UNIT
	  JRST	FNDUN3		;FAILED OR BAD
	MOVE	T1,HOM+HOMLUN	;GET LOGICAL UNIT NUMBER OF THIS STR
	MOVE	T2,HOM+HOMSNM	;GET STR NAME
	CAMN	T1,LUNPOS	;UNIT NUMBER MATCH?
	CAME	T2,DEV		;YES, DOES IT?
	JRST	FNDUN3		;NO
	JRST	CPOPJ1		;YES, GIVE SKIP RETURN
FNDUN3:	AOBJN	U,FNDUN2	;LOOP FOR NEXT UNIT
	AOBJN	J,FNDUN1	;LOOP FOR NEXT CONTROLLER
	POPJ	P,		;ERROR RETURN
;ROUTINE TO READ A HOM BLOCK.
;CALL:
;	U/PHYSICAL UNIT NUMBER
;	J/OFFSET INTO DEVICE CODE TABLE
;	W/OFFSET INTO TYPE TABLES
;	PUSHJ	P,REDHOM
;RETURN+1 IF ERROR
;RETURN+2 IF SUCCESSFUL WITH HOM BLOCK IN HOM

REDHOM:	MOVEI	F,LBNHOM	;ADDRESS OF FIRST HOM BLOCK ON UNIT
REDHO1:	MOVEI	R,HOM		;ADDRESS OF WHERE TO PUT IT
	MOVEI	M,1		;READ 1 BLOCK
	PUSHJ	P,VRTRED	;READ THE BLOCK
	  JRST	REDHO2		;FAILED, TRY SECOND
	MOVS	T1,HOM+HOMNAM	;GET FIRST WORD OF BLOCK
	MOVE	T2,HOM+HOMCOD	;GET WORD CONTAINING UNLIKELY CODE
	CAIN	T1,'HOM'	;NAME MUST BE HOM
	CAIE	T2,CODHOM	;AND MUST MATCH UNLIKELY CODE
	JRST	REDHO2		;ONE FAILED
	CAMN	F,HOM+HOMSLF	;SELF POINTER MUST MATCH
	SKIPE	HOM+HOMREF	;AND MUST NOT NEED REFRESHING
	JRST	REDHO2		;FAILED
	MOVEI	T1,T4		;SETUP HOMCLP AND
	HRRM	T1,HOM+HOMCLP	;  HOMCNP TO POINT
	HRRM	T1,HOM+HOMCNP	;  TO T4
	JRST	CPOPJ1		;GIVE SKIP RETURN
REDHO2:	CAIE	F,LBNHOM	;DOING FIRST HOM BLOCK?
	POPJ	P,		;NO, GIVE FAIL RETURN
	MOVEI	F,LB2HOM	;GET ADDRESS OF 2ND
	JRST	REDHO1		;AND TRY THAT ONE
;ROUTINE TO READ A RIB.
;CALL:
;	U/PHYSICAL UNIT NUMBER
;	J/OFFSET INTO DEVICE CODE TABLE
;	W/OFFSET INTO TYPE TABLES
;	F/BLOCK IN UNIT
;	PUSHJ	P,REDRIB
;RETURN+1 IF READ OR RIB ERROR
;RETURN+2 IF SUCCESSFUL WITH RIB IN RIB
;CALL REDRBP IF FILENAME AND EXTENSION ALREADY IN P3,P4
;DESTROYS P3-P4

REDRIB:	MOVE	P3,FILNAM	;GET FILENAME
	HLRZ	P4,EXT		;AND EXT
REDRBP:	MOVEI	R,RIB		;ADDRESS OF WHERE TO READ IT
	MOVEI	M,1		;READ 1 BLOCK
	PUSHJ	P,VRTRED	;READ THE BLOCK
	  POPJ	P,		;FAILED
	MOVE	T1,RIB+RIBCOD	;GET WORD CONTAINING UNLIKELY CODE
	CAIN	T1,CODRIB	;MUST MATCH
	SKIPL	T1,RIB+RIBFIR	;POINTER MUST BE NEGATIVE
	POPJ	P,		;FAILED
	MOVEM	T1,SAVFIR	;SAVE FOR SELBLK
	MOVE	T1,RIB+RIBNAM	;GET FILENAME FROM RIB
	CAMN	T1,P3		;MATCH WITH WHAT WE WANT?
	CAME	F,RIB+RIBSLF	;SELF POINTER MUST MATCH
	POPJ	P,		;ELSE ERROR
	HLRZ	T1,RIB+RIBEXT	;GET EXTENSION FROM RIB
	MOVE	T2,PTHBLK	;GET PPN FROM PATH BLOCK
	CAIN	P4,'UFD'	;READING A UFD?
	MOVE	T2,[1,,1]	;YES, PPN IS 1,1
	CAMN	T1,P4		;EXTENSION MATCH?
	CAME	T2,RIB+RIBPPN	;  ALONG WITH PPN?
	POPJ	P,		;NO, ERROR
	TLO	S,(FL.RIB)	;TELL SELBLK THAT FIRST BLOCK IS A RIB
	SETOM	BLKCNT		;AND NO BLOCKS LEFT IN GROUP
	MOVE	T1,RIB+RIBSIZ	;GET RIBSIZ FROM RIB
	ADDI	T1,BLKSIZ-1	;ROUND UP TO A BLOCK
	LSH	T1,W2BLSH	;CONVERT TO BLOCKS
	TLZE	S,(FL.EXR)	;READING EXTENDED RIB?
	JRST	CPOPJ1		;YES, GIVE SKIP RETURN
	MOVEM	T1,SAVSIZ	;NO, SAVE SIZE FOR SELBLK
	SETZM	BLKNUM		;AND ZERO RELATIVE BLOCK IN FILE
	JRST	CPOPJ1		;AND GIVE SKIP RETURN
;ROUTINE TO SETUP A TRANSFER TO/FROM DISK.
;CALL:
;	T1/NUMBER OF BLOCKS DESIRED TO TRANSFER
;	PUSHJ	P,SELBLK
;RETURN+1 IF EOF DETECTED
;RETURN+2 IF SOME TRANSFER IS POSSIBLE
;RETURNS M/NUMBER OF BLOCKS POSSIBLE, T1/NUMBER OF BLOCKS IN REQUEST
;	 THAT COULDN'T BE TRANSFERED, F/BLOCK ON UNIT OF FIRST BLOCK.
;PRESERVES P3-P4

SELBLK:	TLNN	S,(FL.RIB)	;WANT TO SKIP FIRST RIB BLOCK?
	JRST	SELBL1		;NO
	PUSHJ	P,SAVE2		;SAVE P1-P2
	MOVE	P1,T1		;SAVE REQUESTED TRANSFER IN P1
	MOVEI	T1,1		;AND MAKE IT LOOK LIKE 1 BLOCK
SELBL1:	SKIPLE	BLKCNT		;AND MORE BLOCKS LEFT IN GROUP?
	JRST	SELBL4		;YES, USE THEM
SELBL2:	SKIPL	T2,SAVFIR	;RUN OUT OF POINTERS?
	JRST	SELBL5		;YES, CHECK FOR EXTENDED RIBS
	MOVE	T4,RIB(T2)	;GET NEXT POINTER
	AOBJN	T2,.+1		;INCREMENT POINTER TO POINTERS
	MOVEM	T2,SAVFIR	;STORE POINTER BACK
	LDB	T2,HOM+HOMCNP	;GET CLUSTER COUNT FROM THIS POINTER
	JUMPN	T2,SELBL3	;GO IF NON-ZERO
	TRZN	T4,RIPNUB	;UNIT CHANGE POINTER?
	POPJ	P,		;NO, THAT'S AN EOF POINTER
	PUSH	P,T1		;SAVE ARGUMENT
	MOVE	T1,T4		;COPY NEW UNIT NUMBER
	PUSHJ	P,FNDLUN	;FIND IT AND SETUP HOM BLOCK
	  JRST	TPOPJ		;NOT THERE, SIMULATE EOF
	POP	P,T1		;RESTORE ARGUMENT
	JRST	SELBL2		;TRY WITH NEXT POINTER
SELBL3:	IMUL	T2,HOM+HOMBPC	;COMPUTE NUMBER OF BLOCKS IN GROUP
	SKIPL	SAVFIR		;DOING LAST POINTER IN THIS RIB?
	SUBI	T2,1		;YES, DON'T OVERWRITE SPARE RIB
	TLNE	S,(FL.RIB)	;SKIPPING A RIB?
	AOS	SAVSIZ		;YES, FILE IS 1 MORE BLOCK LONG
	CAMLE	T2,SAVSIZ	;MORE THAN AMOUNT REMAINING IN FILE?
	MOVE	T2,SAVSIZ	;YES, USE THAT
	MOVEM	T2,BLKCNT	;STORE IT
	LDB	T2,HOM+HOMCLP	;GET CLUSTER ADDRESS OF 1ST CLUSTER IN GROUP
	IMUL	T2,HOM+HOMBPC	;COMPUTE BLOCK ADDRESS
	MOVEM	T2,BLKADR	;STORE ADDRESS OF BLOCK


				;CONTINUED ON THE NEXT PAGE
SELBL4:	MOVN	M,T1		;GET -VE NUMBER OF BLOCKS IN REQUEST
	SUB	T1,BLKCNT	;SUBTRACT AMOUNT LEFT IN GROUP
	SKIPLE	T1		;REQUEST LARGER THAN AMOUNT WE HAVE?
	MOVN	M,BLKCNT	;YES, USE WHAT WE HAVE
	ADDM	M,BLKCNT	;DECREASE BLKCNT BY APPROPRIATE AMOUNT
	ADDM	M,SAVSIZ	; AND SIZE OF FILE
	MOVNS	M		;SET M TO AMOUNT TO TRANSFER
	MOVE	F,BLKADR	;START AT THIS BLOCK
	ADDM	M,BLKADR	;INCREMENT BLOCK ADDRESS FOR NEXT CALL
	TLNN	S,(FL.RIB)	;SKIPING A RIB?
	ADDM	M,BLKNUM	;NO, UPDATE RELATIVE FILE BLOCK
	SKIPGE	T1		;CAN WE DO THE WHOLE REQUEST?
	MOVEI	T1,0		;YES, RETURN ZERO AS REMAINDER
	TLZN	S,(FL.RIB)	;SKIPPING 1 BLOCK FOR RIB?
	JRST	CPOPJ1		;NO, RETURN TO CALLER
	MOVE	T1,P1		;RESTORE ORIGINAL REQUEST
	JRST	SELBL1		;AND DO THE REAL REQUEST
SELBL5:	SKIPN	RIB+RIBXRA	;EXTENDED RIB POINTER?
	POPJ	P,		;NO, GIVE EOF RETURN
	PUSH	P,T1		;SAVE ARGUMENT
	PUSH	P,P3		;AND QUASI-PRESERVED REGISTERS
	PUSH	P,P4		;SMASHED BY REDRIB
	LDB	T1,DEYRBU	;GET UNIT ON WHICH NEXT RIB EXISTS
	PUSHJ	P,FNDLUN	;FIND UNIT, SETUP HOM BLOCK
	  JRST	SELBL6		;FAILED GIVE EOF RETURN
	LDB	F,DEYRBA	;GET CLUSTER ADDRESS ON THAT UNIT
	IMUL	F,HOM+HOMBPC	;CONVERT TO BLOCK ADDRESS
	TLO	S,(FL.EXR)	;DON'T CHANGE SAVSIZ FOR EXTENDED RIBS
	PUSHJ	P,REDRIB	;READ NEW RIB
	  JRST	SELBL6		;FAILED, GIVE EOF RETURN
	POP	P,P4		;RESTORE P4 AND
	POP	P,P3		;  P3
	POP	P,T1		;RESTORE ARGUMENT
	JRST	SELBLK		;AND TRY NEW POINTER FROM THIS RIB
SELBL6:	TLZ	S,(FL.EXR)	;MAKE SURE THIS FLAG IS OFF
	ADJSP	P,-3		;BRING STACK INTO SYNC
	POPJ	P,		;AND GIVE NON-SKIP RETURN
	SUBTTL	SUPPORT SUBROUTINES


;ROUTINE TO CLEAR BUF.
;CALL:	PUSHJ	P,CLRBUF	
;RETURN+1 ALWAYS

CLRBUF:	SETZM	BUF		;CLEAR FIRST WORD
	MOVE	T1,[BUF,,BUF+1]	;SETUP FOR BLT
	BLT	T1,BUF+BLKSIZ-1 ;CLEAR IT ALL
	POPJ	P,		;RETURN


;ROUTINE TO STORE A DEVICE CODE IN ALL I/O INSTRUCTIONS.
;CALL:
;	J/OFFSET INTO DEVICE CODE TABLE
;	PUSHJ	P,SETIOT
;OR (KL ONLY):
;	T1/DEVICE CODE
;	PUSHJ	P,SETIOC
;RETURN+1 ALWAYS

SETIOT:
IFN FTKL10,<
	HRRZ	T1,DVCTAB(J)	;GET DEVICE CODE
SETIOC:	MOVSI	T2,-IOTTBL	;BUILD AOBJN POINTER TO IOTTAB
	DPB	T1,[POINT 7,IOTTAB(T2),9] ;STORE DEVICE CODE IN INSTN.
	AOBJN	T2,.-1		;DO THEM ALL
>
	POPJ	P,		;RETURN


;RETURN POINTS TO SET T1 TO AN ERROR CODE AND NON-SKIP RETURN

ERRTAB:
SNTERR:	JSP	T1,ALLERR	;STRUCTURE NOT FOUND
FNTERR:	JSP	T1,ALLERR	;FILE NOT FOUND
UPDERR:	JSP	T1,ALLERR	;UNPROCESSED DUMP
EOFERR:	JSP	T1,ALLERR	;UNEXPECTED EOF
IOFERR:	JSP	T1,ALLERR	;I/O ERROR
BDFERR:	JSP	T1,ALLERR	;BAD DIRECTORY FORMAT
MCCERR:	JSP	T1,ALLERR	;MEM CONFIG TOO COMPLICATED
NSSERR:	JSP	T1,ALLERR	;NOT SYSTEM SLEEP DUMP
MEPERR:	JSP	T1,ALLERR	;MONITOR EXTENDS PAST BEGINNING OF BOOT
ERRTBL==.-ERRTAB
ALLERR:	SUBI	T1,ERRTAB+1	;COMPUTE ERROR CODE
	TLZ	T1,-1		;CLEAR LH JUNK
	POPJ	P,		;RETURN
;ROUTINE TO READ DATA INTO A VIRTUAL ADDRESS.
;CALL:
;	R/VIRTUAL ADDRESS
;	M/NUMBER OF BLOCKS TO TRANSFER
;	F/BLOCK ON UNIT
;	U/PHYSICAL UNIT
;	W/OFFSET INTO TYPE TABLE
;	J/OFFSET INTO DEVICE CODE TABLE
;	PUSHJ	P,VRTRED
;RETURN+1 IF ERROR
;RETURN+2 IF SUCCESSFUL

VRTRED:	PUSHJ	P,MAPADR	;CONVERT VIRTUAL TO PHYSICAL ADDRESS
	PJRST	@REDTAB(W)	;DO THE TRANSFER


;ROUTINE TO WRITE DATA FROM A VIRTUAL ADDRESS.  CALL WITH SAME ARGUMENTS
;AS VRTRED.
;CALL:	PUSHJ	P,VRTWRT
;RETURN+1 IF ERROR
;RETURN+2 IF SUCCESSFUL

VRTWRT:	PUSHJ	P,MAPADR	;CONVERT VIRTUAL TO PHYSICAL ADDRESS
	PJRST	@WRTTAB(W)	;DO THE TRANSFER


;ROUTINE TO CONVERT A VIRTUAL ADDRESS TO A PHYSICAL ADDRESS.
;CALL:
;	R/VIRTUAL ADDRESS
;	PUSHJ	P,MAPADR
;RETURN+1 ALWAYS WITH PHYSICAL ADDRESS IN R

MAPADR:	MAP	R,(R)		;CONVERT TO PHYSICAL ADDRESS
IFN FTKL10,<
	TLZ	R,(^-<LG.EPT*PAGSIZ+PAGSIZ-1>) ;KEEP ONLY ADDRESS
>
IFN FTKS10,<
	TLZ	R,(^-<SG.EPT*PAGSIZ+PAGSIZ-1>) ;KEEP ONLY ADDRESS
>
	POPJ	P,		;AND RETURN
;ROUTINE TO SAVE P1 AND P2 AND CALL THE CALLER AS A COROUTINE
;WHICH RESTORES P1 AND P2 WHEN THE CALLER RETURNS.
;CALL:	PUSHJ	P,SAVE2
;RETURN+1 ALWAYS

SAVE2:	EXCH	P1,(P)		;GET RETURN, SAVE P1
	PUSH	P,P2		;SAVE P2
	MOVEM	P1,1(P)		;SAVE RETURN
	MOVE	P1,-1(P)	;RESTORE P1
	PUSHJ	P,@1(P)		;CALL CALLER
	  CAIA			;NON SKIP
	AOS	-2(P)		;SKIP RET
	POP	P,P2		;RESTORE P2
	POP	P,P1		;RESTORE P1
	POPJ	P,		;RETURN


;ROUTINE TO SAVE P1-P4 AND CALL THE CALLER AS A COROUTINE
;WHICH RESTORES P1-P4 WHEN THE CALLER RETURNS.
;CALL:	PUSHJ	P,SAVE4
;RETURN+1 ALWAYS

SAVE4:	EXCH	P1,(P)		;GET RETURN, SAVE P1
	PUSH	P,P2		;SAVE P2
	PUSH	P,P3		;AND P3
	PUSH	P,P4		;AND EVEN P4
	MOVEM	P1,1(P)		;SAVE RETURN
	MOVE	P1,-3(P)	;RESTORE P1
	PUSHJ	P,@1(P)		;CALL CALLER
	  CAIA			;NON SKIP
	AOS	-4(P)		;SKIP RET
	DMOVE	P1,-3(P)	;RESTORE P1 AND P2
	DMOVE	P3,-1(P)	;RESTORE P3 AND P4
	ADJSP	P,-4		;TRIM STACK
	POPJ	P,		;RETURN


;ROUTINE TO SAVE F AND R AND CALL THE CALLER AS A COROUTINE
;WHICH RESTORES F AND R WHEN THE CALLER RETURNS.
;CALL:	PUSHJ	P,SAVFR
;RETURN+1 ALWAYS
SAVFR:	EXCH	F,(P)		;GET RETURN, SAVE F
	PUSH	P,R		;SAVE R
	MOVEM	F,1(P)		;SAVE RETURN
	MOVE	F,-1(P)		;RESTORE F
	PUSHJ	P,@1(P)		;CALL CALLER
	  CAIA			;NON SKIP
	AOS	-2(P)		;SKIP RET
	POP	P,R		;RESTORE R
	POP	P,F		;RESTORE F
	POPJ	P,		;RETURN
	SUBTTL	COPY ENTRY VECTOR DATA FROM PREVIOUS MONITOR


; ROUTINE TO CAUSE SSL, ASL, SDL, ETC. TO BE PRESERVED ACROSS
; MONITOR RELOADS.  DATA IS COPIED FROM THE PREVIOUS BOOT'S
; ENTRY VECTOR INTO OURS.  THIS DEPENDS ON PHYSICAL ADDRESS
; 20 CONTAINING THE ADDRESS OF THE OLD BOOT'S ENTRY VECTOR.

COPDAT:	SKIPN	P1,.VPAG0+BOOTSA ;GET VECTOR ADDRESS
	POPJ	P,		;OLD STYLE BOOTSTRAP
	LSH	P1,W2PLSH	;CONVERT TO A PAGE NUMBER
	PUSHJ	P,REFMEM	;MAKE SURE PAGE EXISTS
	  JFCL			;INTERLEAVING ERROR??
	  POPJ	P,		;NXM--CAN'T COPY DATA
	HRRM	P1,EPT+.MVECT	;MAKE PAGE ADDRESSABLE
	CLRPT	.VVECT		;FLUSH PAGE TABLE FOR VECTOR PAGE
	MOVEI	T1,.VVECT	;POINT TO OLD VECTOR
	MOVE	T2,BTSVEC+.BTNAM ;GET IDENTIFIER
	CAMN	T2,.BTNAM(T1)	;SAME?
	SKIPL	.BTSIZ(T1)	;-PAGE LENGTH SETUP?
	POPJ	P,		;NO
	SKIPN	T2,.BTSAV(T1)	;ANY SAVED DATA?
	POPJ	P,		;NO
	MOVSI	T3,.BTSVB(T1)	;POINT TO START OF SAVED DATA
	HRRI	T3,BTSVEC+.BTSVB ;DESTINATION ADDRESS
	BLT	T3,BTSVEC+.BTSVB-1(T2) ;COPY PRESERVED VECTOR DATA
	POPJ	P,		;RETURN
	SUBTTL	MOVE BOOT TO TOP OF MEMORY AND ZERO CORE


;ROUTINE TO MOVE BOOT TO THE TOP OF CORE SO THAT A NEW MONITOR
;CAN BE LOADED.  ALSO CALLED ON A REBOOT REQUEST TO MOVE BOOT
;TO THE COMMUNICATION REGION SPECIFIED BY BOOTSA IN THE DUMP.
;CALL:
;	T2/PHYSICAL PAGE NUMBER OF WHERE TO MOVE BOOT
;	PUSHJ	P,MOVBTS
;RETURN+1 ALWAYS

MOVBTS:	LSH	T2,P2WLSH	;CONVERT PAGE NUMBER TO ADDRESS
	MOVE	T1,EPTADR	;GET OUR EPT ADDRESS
	SUBI	T1,EPTOFS	;COMPUTE PHYSICAL BOOT ORIGIN
	CAMN	T2,T1		;MOVING TO THE SAME SPOT?
	POPJ	P,		;YES, JUST RETURN
	ADDI	T2,EPTOFS	;COMPUTE NEW PHYSICAL EPT ADDRESS
	MOVEM	T2,EPTADR	;STORE PHYSICAL ADDRESS OF NEW EPT
	SUBI	T2,EPTOFS	;BACK TO NEW ORIGIN
	MOVEM	T2,BTBOT	;STORE NEW START OF BOOTSTRAP
	HRRZ	T1,BTSVEC+.BTSIZ ;GET +SIZE IN WORDS
	ADD	T1,T2		;GET NEW FIRST-FREE
	MOVEM	T1,BTTOP	;SAVE IT
	LSH	T2,W2PLSH	;CONVERT ORIGIN BACK TO PAGE NUMBER
	HLLZ	T1,BTSVEC+.BTSIZ ;GET -SIZE IN PAGES
	MOVE	T3,T2		;FIRST PHYSICAL PAGE
	HRLI	T3,(<PM.DCD>B2+PM.WRT) ;BITS
	MOVEM	T3,EPT+.MMOVE(T1) ;STORE NEXT POINTER
	AOS	T3		;NEXT PHYSICAL PAGE
	AOBJN	T1,.-2		;SETUP POINTERS FOR ALL PAGES
	MOVE	T1,CPEBR	;GET CURRENT MAPPING
	XCT	CHGEBR		;CAUSE THE PAGE TABLE TO BE FLUSHED
	PUSH	P,T1		;SAVE MAPPING
	HRRZ	T1,BTSVEC+.BTSIZ ;GET SIZE IN WORDS
	ADDI	T1,.VMOVE	;COMPUTE END BLT ADDRESS
	MOVE	T4,[.VBOOT,,.VMOVE] ;SETUP BLT WORD TO MOVE IT ALL
	BLT	T4,-1(T1)	;DO SO
	HRR	T3,T2		;FIRST PHYSICAL PAGE + BITS
	ADDI	T3,EPTPAG	;OFFSET TO THE EPT
	MOVEM	T3,.VMOVE+EPTOFS+540 ;POINTER TO SECTION 0 MAP
	HLLZ	T4,BTSVEC+.BTSIZ ;GET -SIZE IN PAGES
	SUBI	T3,EPTPAG	;BACK TO THE NEW ORIGIN PAGE
	MOVEM	T3,.VMOVE+.MBOOT+EPTOFS(T4) ;STORE NEXT POINTER
	AOS	T3		;NEXT PHYSICAL PAGE
	AOBJN	T4,.-2		;SETUP POINTERS FOR ALL PAGES
	ADDI	T2,EPTPAG	;OFFSET TO THE EPT PAGE AGAIN
	POP	P,T1		;RESTORE MAPPING
IFN FTKL10,<
	TRZ	T1,LG.EPT	;CLEAR OLD PAGE NUMBER
	MOVEI	T4,LG.IAM(T2)	;GET ARGUMENT TO CHANGE
	HRLI	T4,(XG.LAB!LG.LPC!XG.LUB) ; UBR ALSO
>
IFN FTKS10,<
	TRZ	T1,SG.EPT	;CLEAR OLD PAGE NUMBER
	MOVEI	T4,(T2)		;GET ARGUMENT TO CHANGE
	HRLI	T4,(XG.LAB!XG.LUB) ; UBR ALSO
>
	IORI	T1,(T2)		;INSERT NEW EPT PAGE NUMBER
	MOVEM	T1,.VMOVE+CPEBR-.VBOOT ;STORE NEW MAPPING
	XCT	CHGEBR		;CONTINUE EXECUTION AT TOP OF CORE
	XCT	CHGUBR		;CHANGE UPT ALSO
IFN FTTAPE,<
	SKIPE	NOTAPE		;MAGTAPE DRIVERS PRESENT?
	POPJ	P,		;NO, THAT'S ALL WE NEED TO DO
	PUSH	P,R		;SAVE R A BIT
	MOVEI	R,TAPBUF	;GET MAGTAPE BUFFER ADDRESS
	PUSHJ	P,MAPADR	;CONVERT TO A PHYSICAL ADDRESS
	MOVEM	R,TAPBFA	;SAVE FOR USE BY READ ROUTINES
IFN FTDX10,<
	MOVEI	R,CHPRG		;GET DX10 CHANNEL PROGRAM BUFFER ADDRESS
	PUSHJ	P,MAPADR	;CONVERT TO A PHYSICAL ADDRESS
	MOVEM	R,CHPRGA	;SAVE
	MOVEI	R,CHSNS		;GET DX10 SENSE BUFFER ADDRESS
	PUSHJ	P,MAPADR	;CONVERT TO A PHYSICAL ADDRESS
	MOVEM	R,CHSNSA	;SAVE
>; END IFN FTDX10
	POP	P,R		;RESTORE R
>; END IFN FTTAPE
	POPJ	P,		;RETURN
; HERE TO ZERO CORE.

ZERCOR:	HLRE	T1,BTSVEC+.BTSIZ ;GET -SIZE IN PAGES
	MOVNS	T1		;MAKE POSITIVE
	PUSH	P,T1		;SAVE FOR COMPARE
	MOVE	T2,EPTADR	;GET OUR EPT ADDRESS
	LSH	T2,W2PLSH	;CONVERT TO A PAGE NUMBER
	MOVEI	T4,-EPTPAG(T2)	;GET BOOT ORIGIN PAGE NUMBER
	MOVE	T2,MEMPSZ	;GET NUMBER OF PAGES DESCRIBED BY NXMTAB
	SUBI	T2,1		;CALCULATE THE HIGHEST PAGE # IN CORE
ZERCO1:	MOVEI	T1,(T4)		;GET PAGE NUMBER
	ADD	T1,(P)		;POINT PAST THE END OF BOOT
	CAIL	T2,(T4)		;IS THIS PAGE
	CAILE	T2,-1(T1)	; OCCUPIED BY BOOT?
	PUSHJ	P,CHKNXM	;NO, DOES IT EXIST?
	  JRST	ZERCO2		;NO, TRY NEXT
	HRLI	T1,(<PM.DCD>B2+PM.WRT) ;ACCESS BITS
	HRR	T1,T2		;PAGE NUMBER
	MOVEM	T1,EPT+.MZERO	;SETUP MAPPING TO ZERO THE PAGE
	CLRPT	.VZERO		;FLUSH PAGE TABLE FOR THAT PAGE
	MOVE	T3,[.VZERO,,.VZERO+1] ;SETUP BLT POINTER
	SKIPN	T2		;ABOUT TO DO PAGE 0?
	ADJSP	T3,40		;YES, DON'T CLEAR 0-37
	SETZM	-1(T3)		;CLEAR FIRST WORD OF PAGE
	BLT	T3,.VZERO+PAGSIZ-1 ;DO IT ALL
ZERCO2:	SOJGE	T2,ZERCO1	;LOOP IF MORE TO DO
	POP	P,(P)		;PHASE STACK
	POPJ	P,		;RETURN
;HERE TO DESTROY MAGTAPE DRIVERS BY MOVING MICROCODES, ETC., DOWNWARD.

IFN FTTAPE,<
ZAPTAP:	HLRZ	T1,BTSVEC+.BTDDT ;GET DDT ENTRY INSTRUCTION
	CAIE	T1,(JFCL)	;EDDT LOADED?
	POPJ	P,		;YES, DON'T BOTHER
	SETOM	NOTAPE		;REMEMBER THEY'RE GONE
	HRRZ	T1,BTSVEC+.BTSIZ ;GET SIZE IN WORDS
	SUBI	T1,BTSEND-BTSVEC ;COMPUTE NUMBER OF WORDS TO MOVE
	JUMPE	T1,ZAPTP1	;JUMP IF NOTHING TO MOVE
	ADDI	T1,TAPBEG	;ADD IN DESTINATION ADDRESS
	MOVE	T2,[BTSEND,,TAPBEG] ;SET UP BLT TO OVERWRITE TAPE DRIVERS
	BLT	T2,-1(T1)	;MOVE IT ALL
ZAPTP1:	HRRZ	T1,BTSVEC+.BTSIZ ;GET SIZE IN WORDS AGAIN
	SUBI	T1,<BTSEND-TAPBEG> ;AMOUNT WE'VE SHRUNK BY
	HRRM	T1,BTSVEC+.BTSIZ ;SAVE NEW SIZE
	ADDI	T1,PAGSIZ-1	;ROUND UP TO A PAGE BOUNDARY
	LSH	T1,W2PLSH	;CONVERT TO NUMBER OF PAGES
	MOVNS	T1		;NEGATE IT
	HRLM	T1,BTSVEC+.BTSIZ ;SAVE NEW -VE SIZE IN PAGES
	MOVNI	T1,BTSEND-TAPBEG ;AMOUNT TO ADJUST MICROCODE POINTERS BY
	MOVSI	T2,-UCDNUM	;GET A POINTER TO MICROCODE STORAGE
ZAPTP2:	SKIPE	BTSVEC+.BTUCD(T2) ;IS THERE A MICROCODE HERE?
	ADDM	T1,BTSVEC+.BTUCD+1(T2) ;YES, ADJUST THE POINTER
	AOBJN	T2,.+1		;ADVANCE POINTER
	AOBJN	T2,ZAPTP2	;LOOP FOR ALL
;MUST MOVE TO TOP OF CORE HERE
	POPJ	P,		;FOR NOW
>; END IFN FTTAPE
	SUBTTL	NXMTAB HANDLING ROUTINES


;ROUTINE TO FIND MBTPGS CONTIGUOUS PAGES STARTING AT THE TOP OF
;CORE SO THAT WE CAN MOVE BOOT THERE.
;CALL:	PUSHJ	P,FINDHI
;RETURN+1 ALWAYS WITH STARTING PAGE NUMBER IN T2

FINDHI:	MOVE	T2,MEMPSZ	;GET NUMBER OF PAGES IN CORE
FINDH1:	HLRE	T1,BTSVEC+.BTSIZ ;GET -SIZE IN PAGES
	MOVNS	T1		;MAKE POSITIVE
FINDH2:	SOS	T2		;DECREMENT PAGE NUMBER
	PUSHJ	P,CHKNXM	;DOES THIS PAGE EXIST?
	  JRST	FINDH1		;NO, RESET COUNT AND TRY AGAIN
	SOJG	T1,FINDH2	;YES, DECREMENT PAGE AND CHECK IT
	POPJ	P,		;FOUND THEM, RETURN PAGE # IN T2


;ROUTINE TO FIND A CONTIGUOUS GROUP OF PAGES WHICH EXIST BY LOOKING
;THROUGH NXMTAB.  I KNOW THAT THIS ISN'T PARTICULARLY FAST BUT I WAS
;IN A HURRY.
;CALL:
;	P2/PAGE NUMBER OF WHERE TO START
;	PUSHJ	P,FNDPGS
;RETURN+1 ALWAYS
;RETURNS P1=COUNT OF PAGES
;	 P2=STARTING PAGE NUMBER

FNDPGS:	MOVEI	P1,0		;START WITH NO PAGES FOUND
	SOS	P2		;TAKE A RUNNING START AT THE LOOP
FNDPG1:	AOS	T2,P2		;INCREMENT PAGE NUMBER, COPY TO T2
	CAML	T2,MEMPSZ	;OFF THE END OF MEMORY?
	POPJ	P,		;YES, RETURN WITH P1=0
	PUSHJ	P,CHKNXM	;DOES THAT PAGE EXIST?
	  JRST	FNDPG1		;NO, LOOP FOR NEXT
FNDPG2:	CAMGE	T2,MEMPSZ	;OFF THE END OF MEMORY?
	PUSHJ	P,CHKNXM	;NO, DOES THIS PAGE EXIST?
	  POPJ	P,		;NO, RETURN
	AOS	P1		;INCREMENT COUNT OF PAGES
	AOJA	T2,FNDPG2	;INCREMENT PAGE NUMBER AND LOOP
;ROUTINE TO CHECK NXMTAB TO SEE IF A PAGE EXISTS.
;CALL:
;	T2/PHYSICAL PAGE NUMBER
;	PUSHJ	P,CHKNXM
;RETURN+1 IF MARKED AS NXM
;RETURN+2 IF NOT
;PRESERVES T2, DESTROYS T3

CHKNXM:	PUSH	P,T2		;SAVE PAGE NUMBER
	IDIVI	T2,^D36		;DIVIDE BY THE NUMBER OF BITS PER WORD
	MOVE	T2,NXMTAB(T2)	;GET THE WORD CONTAINING THE BIT
	LSH	T2,(T3)		;SHIFT NXM BIT TO 1B0
	SKIPL	T2		;MARKED AS A NXM?
	AOS	-1(P)		;NO, GIVE SKIP RETURN
	POP	P,T2		;RESTORE T2
	POPJ	P,		;RETURN


;ROUTINE TO BUILD NXMTAB BY TOUCHING EVERY POSSIBLE PAGE IN MEMORY
;TO SEE IF IT EXISTS.
;CALL:	PUSHJ	P,SUNXMT
;RETURN+1 ALWAYS

SUNXMT:	PUSHJ	P,SAVE2		;SAVE P1-P2
	JRST	SUNXM2		;SKIP AOUND ERROR RECOVERY CODE
SUNXM1:	MOVEI	T1,[ASCIZ /%Memory interleaved wrong/]
	PUSHJ	P,PRMSG		;PRINT WARNING
	PUSHJ	P,PRCRLF	;END LINE
	MOVEI	T1,[ASCIZ /Type RETURN when ready to proceed: /]
	MOVEI	T2,[0]		;DEFAULT ANSWER IS CR
	PUSHJ	P,REDLIN	;READ ANSWER
SUNXM2:	SETZM	NXMTAB		;ZERO FIRST WORD OF NXMTAB
	MOVE	T1,[NXMTAB,,NXMTAB+1] ;GET BLT POINTER
	BLT	T1,NXMTAB+NXMLEN-1 ;ZERO IT ALL
	MOVSI	P1,-MAXPGS	;GET LOOP COUNT FOR ALL POSSIBLE PAGES
	MOVEI	P2,0		;P2 WILL BE HIGHEST PAGE SEEN
	MOVE	T2,[POINT 1,NXMTAB] ;GET BYTE POINTER TO NXMTAB
	MOVEI	T3,1		;AND A BIT TO USE
SUNXM3:	IBP	T2		;STEP BYTE POINTER TO NEXT BIT
	PUSHJ	P,REFMEM	;TOUCH THAT PAGE
	  JRST	SUNXM1		;INTERLEAVING ERROR
	  SKIPA			;NXM
	  SKIPA	P2,P1		;EXISTS, MOVE NUMBER TO P2
	DPB	T3,T2		;SET THE BIT FOR THIS PAGE
	AOBJN	P1,SUNXM3	;LOOP FOR ALL PAGES
	ADDI	P2,1		;P2:=NUMBER OF PAGES IN MEMORY
	HRRZM	P2,MEMPSZ	;STORE FOR LATER
SUNXM4:	IDPB	T3,T2		;STORE 1'S IN THE REST
	TLNE	T2,(77B5)	;  OF THE FINAL
	JRST	SUNXM4		;  WORD
	SETOM	NXMFLG		;NXMTAB IS VALID
	POPJ	P,		;AND RETURN
;ROUTINE TO DETERMINE IF A PAGE EXISTS IN MEMORY BY TOUCHING
;THAT PAGE.  NOTE THAT THE PAGE FAIL TRAP ADDRESS IN THE UPT HAS
;BEEN CHANGED TO POINT AT REFTRP BY THE CALLER.
;CALL:
;	P1/PHYSICAL PAGE NUMBER
;	PUSHJ	P,REFMEM
;RETURN+1 IF INTERLEAVING ERROR
;RETURN+2 IF PAGE DOES NOT EXIST
;RETURN+3 IF PAGE EXISTS

REFMEM:	PUSH	P,T1		;SAVE T1
	PUSH	P,T2		;SAVE T2
	PUSH	P,EPT+.LMPFN+1	;SAVE PAGE FAIL NEW PC
	MOVEI	T1,REFTRP	;NEED NEW PC SINCE NXM'S SOMETIMES
	MOVEM	T1,EPT+.LMPFN+1	;  CAUSE AR/ARX PARITY ERRORS
	CONO	APR,CLRAPR	;CLEAR APR ERRORS
	MOVE	T1,P1		;PAGE NUMBER
	HRLI	T1,(<PM.DCD>B2+PM.WRT) ;ACCESS BITS
	MOVEM	T1,EPT+.MZERO	;USE .VZERO AS TEMPORARY PAGE
	CLRPT	.VZERO		;FLUSH THE PAGE TABLE FOR THAT PAGE
	MOVSI	T1,-MEMITL	;INTERLEAVE COUNTER
	SETZ	T2,		;CLEAR A FLAG

REFME1:	MOVES	.VZERO(T1)	;TOUCH THE PAGE

REFTRP:
IFN FTKL10,<CONSZ APR,LP.NXM>	;SEE A NXM?
IFN FTKS10,<CONSZ APR,SP.NXM>	;SEE A NXM?
	AOS	T2		;YES--COUNT IT
	AOBJN	T1,REFME1	;LOOP BACK FOR MORE
	SKIPN	T2		;ALL ADDRS REFERENCED OK?
	AOSA	-3(P)		;EITHER REAL NXM OR GOOD ADDRESS
	CAIN	T2,MEMITL	;ALL ADDRS GIVE NXM IF INTERLEAVING OK
	AOS	-3(P)		;REAL NXM
	POP	P,EPT+.LMPFN+1	;RESTORE OLD PAGE FAIL TRAP ADDRESS
	POP	P,T2		;RESTORE T2
	POP	P,T1		;RESTORE T1
	CONO	APR,CLRAPR	;CLEAR APR ERRORS
	POPJ	P,		;RETURN
	SUBTTL	TRAP HANDLING


;HERE ON A TRAP OTHER THAN A PAGE FAIL.

TRAP:	MOVEI	T1,[ASCIZ/?Trap other than page fail
MUUO Flags, Opcode, AC = /]
	PUSHJ	P,PRMSG
	MOVE	T4,EPT+.UPMUO	;GET MUUO
	PUSHJ	P,PRHWD		;PRINT AS HALF WORDS
	MOVEI	T1,[ASCIZ/
MUUO PC = /]
	PUSHJ	P,PRMSG
	MOVE	T4,EPT+.UPMUP	;GET OLD PC WORD
	PUSHJ	P,PRHWD		;PRINT AS HALF WORDS
	MOVEI	T1,[ASCIZ/
MUUO EA = /]
	PUSHJ	P,PRMSG
	MOVE	T4,EPT+.UPMUE	;GET MUUO EFFECTIVE ADDRESS
	PUSHJ	P,PRHWD		;PRINT AS HALF WORDS
	JRST	PFTRA1		;JOIN COMMON EXIT CODE
;HERE ON A PAGE FAIL TRAP

PFTRAP:	MOVEI	T1,[ASCIZ/?Page fail trap
PFW = /]
	PUSHJ	P,PRMSG		;PRINT ERROR MESSAGE
	MOVE	T4,EPT+.LMPFW	;GET PAGE FAIL WORD
	PUSHJ	P,PRHWD		;PRINT AS HALF-WORDS
	MOVEI	T1,[ASCIZ/
PF Flags = /]
	PUSHJ	P,PRMSG
	MOVE	T4,EPT+.LMPFP	;GET PC FLAGS
	PUSHJ	P,PRHWD		;PRINT AS HALF-WORDS
	MOVEI	T1,[ASCIZ/
PF PC = /]
	PUSHJ	P,PRMSG	
	MOVE	T4,EPT+.LMPFP+1	;GET PC OF FAILURE
	PUSHJ	P,PRHWD		;PRINT IT AS HALF WORDS
PFTRA1:	PUSHJ	P,PRTHDW	;PRINT APR, EBR, AND UBR STATUS
	JRST	RESTAR		;RESTART AT THE BEGINNING
; ROUTINE TO PRINT THE HARDWARE STATUS (APR, RDERA, EBR, AND UBR)
; CALL:	PUSHJ	P,PRTHDW
; RETURN+1 ALWAYS

PRTHDW:	MOVEI	T1,[ASCIZ/
CONI APR, = /]
	PUSHJ	P,PRMSG
	CONI	APR,T4		;GET CONI APR
	PUSHJ	P,PRHWD		;PRINT AS HALF WORDS
IFN FTKL10,<
	MOVEI	T1,[ASCIZ/
RDERA = /]
	PUSHJ	P,PRMSG
	RDERA	T4		;GET ERA
	PUSHJ	P,PRHWD		;PRINT AS HALF WORDS
>
	MOVEI	T1,[ASCIZ/
CONI PAG, = /]
	PUSHJ	P,PRMSG
	CONI	PAG,T4		;GET EBR
	PUSHJ	P,PRHWD		;PRINT AS HALF-WORDS
	MOVEI	T1,[ASCIZ/
DATAI PAG, = /]
	PUSHJ	P,PRMSG
	DATAI	PAG,T4		;GET UBR
	PUSHJ	P,PRHWD		;PRINT AS HALF-WORDS
	PJRST	PRCRLF		;END LINE AND RETURN
	SUBTTL	COMMAND PARSING


;ROUTINE TO PARSE A COMMAND LINE. CALL WITH FL.CMD OR FL.1CM SET
;RETURNS WITH THE FILESPEC VARIABLE AND BITS IN S SETUP.
;CALL:	PUSHJ	P,PARSE
;RETURN+1 IF ERROR DETECTED AND MESSAGE ISSUED
;RETURN+2 IF NO ERRORS DETECTED

PARSE:	SETZM	R.BEG		;CLEAR FIRST WORD OF FILESPEC
	MOVE	T1,[R.BEG,,R.BEG+1] ;SETUP FOR BLT
	BLT	T1,R.END-1	;CLEAR IT ALL
	TDZA	S,[FX.CLR-FR.DMP] ;CLEAR FLAG BITS AND GET FIRST ATOM
PARSE1:	TDZA	T1,T1		;CLEAR ATOM, SKIP CALL TO GETSIX
PARSE2:	PUSHJ	P,GETSIX	;GET SIXBIT ATOM IN T1
	MOVSI	T2,-TRMTBL	;-VE LENGTH OF TERMINATING CHAR TABLE
PARSE3:	HLRZ	T4,TRMTAB(T2)	;GET NEXT POSSIBLE CHARACTER FROM TABLE
	CAIE	T4,(T3)		;MATCH WITH THE ONE WE SAW?
	AOBJN	T2,PARSE3	;NO, LOOP
	HRRZ	T4,TRMTAB(T2)	;GET DISPATCH ADDRESS FOR ATOM
	JUMPL	T2,(T4)		;GO TO ROUTINE IF MATCH FOUND
CMDERR:	MOVEI	T1,[ASCIZ/%Syntax error
/]
	PJRST	PRMSG		;TELL OF ERROR AND RETURN

IFN FTTAPE,<
TAPERR:	MOVEI	T1,[ASCIZ/%Tape drivers not present
/]
	PJRST	PRMSG		;TELL OF ERROR AND RETURN
>; END IFN FTTAPE


;TABLE OF LEGAL CHARACTERS TERMINATING COMMAND STRING ATOMS AND
;THE CORRESPONDING DISPATCH ADDRESSES.  FORMAT IS:
;	XWD	CHAR,ADDRESS

TRMTAB:	XWD	":",CMDDEV	;DEVICE SEEN
	XWD	".",CMDFIL	;FILENAME SEEN
	XWD	"[",CMDPTH	;START OF PATCH SEEN
	XWD	"/",CMDSWT	;SWITCH SEEN
	XWD	.CHCRT,CMDEOL	;END OF LINE SEEN
	XWD	0,BTXEOL	;END OF BOOTXT (ASCIZ)
TRMTBL==.-TRMTAB		;LENGTH OF TABLE
;HERE TO PROCESS DEVICE IN COMMAND STRING

CMDDEV:	TRON	S,FR.DEV	;ALREADY HAVE A DEVICE?
	SKIPN	T1		;NO, DEVICE NULL?
	JRST	CMDERR		;YES, ERROR
	MOVEM	T1,DEV		;STORE DEVICE
	JRST	PARSE2		;AND GET NEXT ATOM


;HERE TO PROCESS FILENAME IN COMMAND STRING

CMDFIL:	JSP	T2,STOFIL	;STORE FILENAME AS NECESSARY
	TROE	S,FR.EXT	;FLAG AN EXTENSION SEEN
	JRST	CMDERR		;ERROR IF MORE THAN ONE
	PUSHJ	P,GETSIX	;GET EXTENSION
	HLLZM	T1,EXT		;STORE IT
	JRST	PARSE1		;GET NEXT ATOM


;HERE TO PROCESS PATH SPEC IN COMMAND STRING

CMDPTH:	JSP	T2,STOFIL	;STORE FILENAME AS NECESSARY
	PUSHJ	P,GETOCT	;GET OCTAL PROJECT NUMBER
	JUMPE	T1,CMDERR	;NONE IS ILLEGAL
	TRON	S,FR.PTH	;ALREADY SEEN A PATH?
	CAIE	T3,","		;MUST HAVE BROKEN ON A COMMA
	JRST	CMDERR		;ELSE ERROR
	HRLZM	T1,PTHBLK	;STORE IN PATH BLOCK
	PUSHJ	P,GETOCT	;GET PROGRAM NUMBER
	JUMPE	T1,CMDERR	;NONE IS ILLEGAL
	HRRM	T1,PTHBLK	;STORE IN PATH BLOCK
	MOVSI	W,-LIMLVL	;SETUP AOBJN POINTER TO SFD'S
CMDPT1:	CAIE	T3,","		;SFD COMMING?
	JRST	CMDPT2		;NO, OR NONE ALLOWED
	PUSHJ	P,GETSIX	;GET SFD NAME
	JUMPE	T1,CMDERR	;MUST NOT BE NULL
	MOVEM	T1,PTHBLK+1(W)	;STORE IN NEXT SLOT IN PATH BLOCK
	AOBJN	W,CMDPT1	;LOOP FOR NEXT
CMDPT2:	CAIN	T3,"]"		;TERMINATE WITH RIGHT BRACKET?
	JRST	PARSE2		;YES, GET NEXT ATOM
	JRST	PARSE1		;NO, WORRY ABOUT THE CHARACTER
;HERE TO PROCESS THE END OF THE COMMAND LINE

BTXEOL:	TLO	S,(FL.CMD)	;FORCE NEXT READ FROM TERMINAL
CMDEOL:	JSP	T2,STOFIL	;STORE FILENAME AS NECESSARY
	TRNE	S,FR.DMP!FR.RBT	;/DUMP SEEN?
	JRST	CMDEO1		;YES--DON'T TOUCH FILESPEC
	TRNN	S,FR.DEV!FR.FIL!FR.EXT!FR.PTH ;ANYTHING TYPED?
	SKIPN	BTSVEC+.BTDEV	;HAVE A FILESPEC FROM BEFORE?
	JRST	CMDEO1		;YES--LEAVE FILESPEC ALONE
	MOVE	T1,[BTSVEC+.BTDEV,,DEV] ;SET UP BLT
	BLT	T1,PTHBLK+6	;COPY IT
	TRO	S,FR.DEV!FR.FIL!FR.EXT!FR.PTH ;DEFAULT EVERYTHING ON
CMDEO1:	SKIPN	T1,DEV		;GET DEVICE NAME
	MOVSI	T1,'DSK'	;DEFAULT
	MOVEM	T1,DEV		;UPDATE
	CAMN	T1,['DSK   ']	;GENERIC?
	TLO	S,(FL.WLD)	;YES, FLAG IT
	MOVSI	T1,'EXE'	;DEFAULT EXTENSION IS EXE
	TRNN	S,FR.EXT	;EXTENSION SEEN?
	MOVEM	T1,EXT		;NO, USE DEFAULT
	MOVE	T1,[1,,4]	;DEFAULT DIRECTORY IS [1,4]
	SETZ	T2,		;PATH TERMINATOR
	TRNN	S,FR.PTH	;PATH SEEN?
	DMOVEM	T1,PTHBLK	;NO, STORE DEFAULT
IFN FTTAPE,<
	TRNE	S,FR.TSB	;ANY TAPE-SPECIFIC BITS?
	SKIPE	TAPIDX		;YES, YOU'D BETTER HAVE SPEC'D A TAPE UNIT
	SKIPA			;WE'LL LET YOU BY THIS TIME
	JRST	CMDERR		;BAD BOY, THAT'S AN ERROR
	SKIPE	TAPIDX		;LIKEWISE, IF A TAPE WAS SPECIFIED
	SKIPN	NOTAPE		; DRIVERS MUST STILL BE PRESENT
	SKIPA			;NO SWEAT
	JRST	TAPERR		;NOPE
>; END IFN FTTAPE
	MOVEI	T1,SYSDDT	;GET ADDRESS OF EDDT START
	TRNE	S,FR.DDT	;USER SPECIFY /EDDT?
	SKIPE	STSA		;  AND NO ADDRESS ON /START?
	JRST	CPOPJ1		;NO TO FIRST OR YES TO SECOND
	MOVEM	T1,STSA		;FORCE A STARTING ADDRESS
	JRST	CPOPJ1		;GIVE SKIP RETURN
;HERE TO PROCESS A SWITCH IN THE COMMAND STRING

CMDSWT:	JSP	T2,STOFIL	;STORE FILENAME AS NECESSARY
	PUSHJ	P,GETSIX	;GET THE SWITCH
	MOVE	T2,T1		;COPY IT TO T2
	SETOM	W		;SET FULL WORD MASK
CMDSW1:	LSH	W,-6		;SHIFT MASK 6
	LSH	T2,6		;AND WORD BY SAME AMOUNT
	JUMPN	T2,CMDSW1	;UNTIL IT'S NULL
	MOVSI	T4,-SWTTBL	;GET -VE LENGTH OF SWITCH TABLE
CMDSW2:	MOVE	T2,SWTTAB(T4)	;GET NEXT ENTRY IN SWITCH TABLE
	TDZ	T2,W		;MASK TO SAME SIZE AS WHAT USER TYPED
	CAME	T1,T2		;MATCH?
	AOBJN	T4,CMDSW2	;NO, LOOP FOR NEXT
	TLZN	T4,-1		;CLEAR LH.  FIND MATCH?
	JRST	CMDERR		;NO
	CAIL	T4,SWTTBS	;IS THIS A SPECIAL PROCESSING SWITCH?
	JRST	CMDSWS		;YES
	MOVEI	T1,FR.1ST	;GET FIRST SWITCH BIT IN S
	LSH	T1,(T4)		;SHIFT BY OFFSET INTO SWITCH TABLE
	IORI	S,(T1)		;SET SWITCH BIT IN S
	CAIE	T3,":"		;SWITCH HAVE A VALUE?
	JRST	PARSE1		;NO, GET NEXT ATOM
	CAIL	T4,SWTVLL	;CAN THIS SWITCH LEGALLY HAVE A VALUE?
	JRST	CMDERR		;NO
	PUSHJ	P,GETOCT	;GET OCTAL VALUE FOR SWITCH
	MOVEM	T1,SWTVAL(T4)	;STORE VALUE IN TABLE
	JRST	PARSE1		;AND GET NEXT ATOM

CMDSWS:
IFN FTTAPE,<
	CAIL	T4,SWTTBU	;MAGTAPE UNIT IDENTIFIER?
	JRST	CMDSWU		;YES
>; END IFN FTTAPE
	JRST	@SWTDSP-SWTTBS(T4) ;DISPATCH FOR THIS SPECIAL SWITCH

IFN FTTAPE,<
CMDSWU:	HRROI	T1,-SWTTBU(T4)	;GET OFFSET INTO READ/WRITE TABLES
	MOVEM	T1,TAPIDX	;SAVE UNIT TYPE INDEX
	SETZM	TAPUNI		;ASSUME DEFAULT UNIT SELECTION
	CAIE	T3,":"		;SWITCH HAVE A VALUE?
	JRST	PARSE1		;NO, GET NEXT ATOM
	PUSHJ	P,GETOCT	;GET OCTAL VALUE FOR SWITCH
	MOVEM	T1,TAPUNI	;SAVE FOR LATER
	JRST	PARSE1		;GET NEXT ATOM
>; END IFN FTTAPE
;TABLE OF LEGAL SWITCHES.  NOTE THAT ALL SWITCHES THAT MAY HAVE
;AN OCTAL VALUE MUST OCCUR POSITIONALLY BEFORE THE SWTVLL'TH
;LOCATION IN THE TABLE.  FURTHER NOTE THAT ALL MAGTAPE UNIT
;IDENTIFIERS APPEAR LAST IN THE TABLE.

SWTTAB:	SIXBIT/START/		;/START:N
	SIXBIT/EDDT/		;/EDDT
	SIXBIT/LOAD/		;/LOAD
	SIXBIT/DUMP/		;/DUMP
	SIXBIT/REBOOT/		;/REBOOT
	SIXBIT/FORCE/		;/FORCE
IFN FTTAPE,<
	SIXBIT/REWIND/		;/REWIND
	SIXBIT/SKIP/		;/SKIP
	SIXBIT/NOREWI/		;/NOREWIND
>; END IFN FTTAPE
SWTTBS==.-SWTTAB		;INDEX FOR FIRST SPECIAL PROCESSING SWITCH
IFN FTTAPE,<
	SIXBIT/DENSIT/		;/DENSITY:N
>; END IFN FTTAPE
IFN FTTAPE,<
SWTTBU==.-SWTTAB		;INDEX FOR FIRST MAGTAPE UNIT IDENTIFIER
IFN FTDX10,<
	SIXBIT	/DX10/		;/DX10
>; END IFN FTDX10
IFN FTTM02,<
	SIXBIT	/TM02/		;/TM02
>; END IFN FTTM02
IFN FTDX20,<
	SIXBIT	/DX20/		;/DX20
>; END IFN FTDX20
IFN FTTM78,<
	SIXBIT	/TM78/		;/TM78
>; END IFN FTTM78
>; END IFN FTTAPE
SWTTBL==.-SWTTAB

;PARALLEL DISPATCH TABLE FOR SPECIAL PROCESSING SWITCHES.  MUST
;BE IN SAME ORDER AS ENTRIES IN SWTTAB STARTING AT OFFSET SWTTBS.

SWTDSP:
IFN FTTAPE,<
	EXP	SWTDEN		;/DENSITY
>; END IFN FTTAPE
;PROCESS /DENSITY SWITCH

IFN FTTAPE,<
SWTDEN:	CAIE	T3,":"		;MUST HAVE A VALUE
	JRST	CMDERR		;NOPE
	PUSHJ	P,GETSIX	;READ THE ATOM
	MOVE	T2,T1		;COPY IT TO T2
	SETOM	W		;SET FULL WORD MASK
SWTDN1:	LSH	W,-6		;SHIFT MASK 6
	LSH	T2,6		;AND WORD BY SAME AMOUNT
	JUMPN	T2,SWTDN1	;UNTIL IT'S NULL
	MOVSI	T4,-DENTBL	;GET -VE LENGTH OF DENSITY TABLE
SWTDN2:	MOVE	T2,DENTAB(T4)	;GET NEXT ENTRY IN DENSITY TABLE
	TDZ	T2,W		;MASK TO SAME SIZE AS WHAT USER TYPED
	CAME	T1,T2		;MATCH?
	AOBJN	T4,SWTDN2	;NO, LOOP FOR NEXT
	TLZN	T4,-1		;CLEAR LH.  FIND MATCH?
	JRST	CMDERR		;NO
	MOVEI	T1,1(T4)	;YES, MAKE DENSITY CODE 1-BASED
	MOVEM	T1,TAPDEN	;SAVE IT
	JRST	PARSE1		;DONE

;TABLE OF LEGAL DENSITY VALUES

DENTAB:	SIXBIT/200/		;200 BPI
	SIXBIT/556/		;556 BPI
	SIXBIT/800/		;800 BPI
	SIXBIT/1600/		;1600 BPI
	SIXBIT/6250/		;6250 BPI
DENTBL==.-DENTAB
>; END IFN FTTAPE
	SUBTTL	COMMAND	INPUT


;ROUTINE TO STORE A FILENAME IF REQUIRED.
;CALL:
;	T1/FILENAME OR 0
;	JSP	T2,STOFIL
;RETURN+1 IF NO ERRORS

STOFIL:	JUMPE	T1,(T2)		;DON'T DO ANYTHING IF NOTHING TO STORE
	TROE	S,FR.FIL	;ALREADY SEEN A FILENAME?
	JRST	CMDERR		;YES, ERROR
	MOVEM	T1,FILNAM	;STORE FILENAME
	JRST	(T2)		;AND RETURN


;ROUTINE TO READ A SIXBIT NAME FROM THE COMMAND STRING.
;CALL:	PUSHJ	P,GETSIX
;RETURN+1 ALWAYS
;RETURNS NAME IN T1, BREAK CHARACTER IN T3
;DESTROYS T2

GETSIX:	MOVEI	T1,0		;START WITH NULL NAME
	MOVE	T2,[POINT 6,T1]	;GET BYTE POINTER FOR ATOM
GETSI1:	PUSHJ	P,GETCHR	;GET NEXT CHARACTER FROM COMMAND
	CAIL	T3,"A"		;LETTER?
	CAILE	T3,"Z"		; ??
	CAIA			;NO, CHECK DIGITS
	JRST	GETSI2		;YES
	CAIL	T3,"0"		;NUMBER?
	CAILE	T3,"9"		; ??
	POPJ	P,		;NO, RETURN
GETSI2:	TRC	T3,"A"-'A'	;CONVERT ASCII TO SIXBIT
	TLNE	T2,770000	;TOO MANY?
	IDPB	T3,T2		;NO, STORE IN T1
	JRST	GETSI1		;AND LOOP FOR NEXT


;ROUTINE TO RETURN AN OCTAL NUMBER FROM THE COMMAND STRING.
;CALL:	PUSHJ	P,GETOCT
;RETURN+1 ALWAYS
;RETURNS NUMBER IN T1, BREAK CHARACTER IN T3

GETOCT:	MOVEI	T1,0		;START WITH NO NUMBER
GETOC1:	PUSHJ	P,GETCHR	;GET NEXT CHARACTER FROM COMMAND
	CAIL	T3,"0"		;NUMBER?
	CAILE	T3,"7"		;  OCTAL THAT IS?
	POPJ	P,		;NO, RETURN
	LSH	T1,3		;MAKE ROOM FOR IT
	IORI	T1,-"0"(T3)	;INCLUDE IN TOTAL
	JRST	GETOC1		;LOOP FOR NEXT
;ROUTINE TO RETURN THE NEXT CHARACTER FROM THE COMMAND STREAM.
;CONVERTS LOWER TO UPPER CASE.
;CALL:	PUSHJ	P,GETCHR
;RETURN+1 ALWAYS WITH CHARACTER IN T3

GETCHR:	TLNN	S,(FL.1CM!FL.CMD) ;WANT TO READ FROM COMMAND BUFFER?
	ILDB	T3,BTXPTR	;NO, READ FROM BOOTXT
	TLNE	S,(FL.1CM!FL.CMD) ;SAME QUESTION
	ILDB	T3,CMDPTR	;ONLY THIS TIME READ FROM COMMAND BUFFER
	CAIE	T3," "		;SPACE?
	CAIN	T3,.CHTAB	;  OR TAB?
	MOVEI	T3,.CHCRT	;YES, RETURN CR
	CAIL	T3,"a"		;LOWER CASE?
	CAILE	T3,"z"		;??
	POPJ	P,		;NO
	SUBI	T3,"a"-"A"	;YES, CONVERT TO UPPER
	POPJ	P,		;AND RETURN


;ROUTINE TO ASK A QUESTION AND GIVE SKIP RETURN IF ANSWER WAS YES.
;CALL:
;	T1/ADDRESS OF QUESTION STRING
;	T2/ADDRESS OF DEFAULT ANSWER STRING
;	PUSHJ	P,ASKYN
;RETURN+1 IF NEITHER YES OR NO
;RETURN+2 IF ANSWER WAS NO
;RETURN+3 IF ANSWER WAS YES

ASKYN:	TLZ	S,(FL.DEF)	;WE DO WANT TO ALLOW DEFAULTING
	PUSHJ	P,REDLIN	;ASK QUESTION, READ ANSWER
	TLO	S,(FL.1CM)	;FORCE READ FROM COMMAND BUFFER
	PUSHJ	P,GETCHR	;GET FIRST CHARACTER
	SKIPE	USRFLG		;USER MODE?
	CLRBFI			;YES--ZAP REMAINDER OF INPUT BUFFER
	TLZ	S,(FL.1CM)	;CLEAR FLAG
	CAIN	T3,"N"		;NO?
	JRST	CPOPJ1		;GIVE SKIP
	CAIE	T3,"Y"		;YES?
	POPJ	P,		;USER DOESN'T KNOW WHAT'S GOING ON
CPOPJ2:	AOS	0(P)		;DOUBLE SKIP
CPOPJ1:	AOS	0(P)		;YES, GIVE SKIP RETURN
CPOPJ:	POPJ	P,		;RETURN
;ROUTINE TO PRINT A PROMPT STRING, AND READ A COMMAND LINE INTO
;CMDBUF.  DOES LOCAL EDITING OF RUBOUT AND ^U AND DEFAULT STRING IF
;THE OPERATOR DOESN'T ANSWER OR SCHED IS 400.
;CALL:
;	T1/ADDRESS OF PROMPT STRING
;	T2/ADDRESS OF DEFAULT ANSWER STRING
;	PUSHJ	P,REDLIN
;RETURN+1 ALWAYS WITH LINE IN CMDBUF


REDLIN:	PUSHJ	P,SAVE2		;SAVE P1-P2
	PUSH	P,T1		;SAVE ADDRESS OF PROMPT STRING
	HRLI	T2,(POINT 7,0)	;MAKE BYTE POINTER TO DEFAULT STRING
	PUSH	P,T2		; AND SAVE IT
REDLI1:	MOVE	T1,-1(P)	;RESTORE ADDRESS FOR SUBSEQUENT TIMES
	PUSHJ	P,PRMSG		;TYPE PROMPT STRING
	MOVE	P1,[POINT 7,CMDBUF] ;GET POINTER TO BUFFER
	MOVEM	P1,CMDPTR	;SAVE FOR CALLER
	SETZM	CMDBUF		;SET TO CLEAR BUFFER
	MOVE	T1,[CMDBUF,,CMDBUF+1] ;SETUP FOR BLT
	BLT	T1,CMDBUF+LINBFL-1 ;ZERO IT ALL
	TLZ	S,(FL.RUB)	;CLEAR RUBOUT FLAG
	MOVEI	P2,<LINBFL*5>-5 ;MAX CHARACTERS
REDLI2:	PUSHJ	P,TYI		;READ A CHARACTER
	  ILDB	T3,0(P)		;TIMED OUT, GET ONE FROM DEFAULT STRING
	CAIE	T3,.CHCNH	;BACKSPACE?
	CAIN	T3,.CHDEL	; OR RUBOUT?
	JRST	REDRUB		;YES
	CAIN	T3,.CHCNU	;^U?
	JRST	REDCNU		;YES
	CAIN	T3,.CHCNR	;^R?
	 JRST	REDCNR		;YES
	JUMPN	T3,REDLI3	;READ LAST CHARACTER OF DEFAULT STRING?
	MOVEI	T1,[ASCIZ/	;Default answer/] ;TELL HIM WHAT HAPPENED
	PUSHJ	P,PRMSG		;FOR POST MORTUM
	MOVEI	T3,.CHCRT	;AND TURN IT INTO A CR
REDLI3:	CAIE	T3,.CHCRT	;END OF LINE?
	SOSL	P2		;IGNORE IF TOO MANY
	IDPB	T3,P1		;STASH CHAR
	TLZE	S,(FL.RUB)	;POST PROCESS RUBOUT
	PUSHJ	P,PRBSL		;BY PRINTING BACKSLASH
	LDB	T3,P1		;GET CHAR BACK
	SKIPN	USRFLG		;MONITOR DOES ECHOING IN USER MODE
	PUSHJ	P,ECHO		;AND ECHO CHARACTER
	LDB	T3,P1		;ONCE MORE
	CAIE	T3,.CHCRT	;END-OF LINE?
	JRST	REDLI2		;NO, LOOP
	POP	P,(P)		;FLUSH STACK
TPOPJ:	POP	P,T1		;RESTORE T1
	POPJ	P,		;AND RETURN
;HERE TO PROCESS RUBOUTS

REDRUB:	CAIN	P2,<LINBFL*5>-5	;CHECK FOR BEGINNING OF LINE
	JRST	REDRU1		;YES
	TLON	S,(FL.RUB)	;CHECK HERE BEFORE?
	PUSHJ	P,PRBSL		;NO, TYPE BACKSLASH
	LDB	T3,P1		;GET CHAR
	PUSHJ	P,ECHO		;PRINT IT
	SETZ	T3,		;KEEP BUFFER ASCIZ
	DPB	T3,P1		;FOR ^R
	MOVNI	T3,1		;WANT TO BACKUP POINTER BY
	EXCH	T3,P1		;BY 1 BYTE POSITION
	ADJBP	P1,T3		;DO IT THE EASY WAY
	AOJA	P2,REDLI2	;GET NEXT CHAR

;HERE TO PROCESS BEGINNING OF LINE ON RUBOUT

REDRU1:	TLZE	S,(FL.RUB)	;NEED TO TYPE A BACKSLASH?
	PUSHJ	P,PRBSL		;YES, DO SO
	JRST	REDCU1		;JOIN COMMON CODE

;HERE TO PROCESS ^U

REDCNU:	PUSHJ	P,ECHO		;ECHO AS UPARROW U
REDCU1:	PUSHJ	P,PRCRLF	;TYPE CRLF
	JRST	REDLI1		;RETYPE PROMPT AND TRY AGAIN

;HERE TO PROCESS ^R

REDCNR:	PUSHJ	P,PRCRLF	;ECHO AS <CR><LF>
	MOVE	T1,-1(P)	;GET PROMPT ADDRESS
	PUSHJ	P,PRMSG		;ECHO IT BACK
	MOVEI	T1,CMDBUF	;GET ADDRESS OF TYPEIN
	PUSHJ	P,PRMSG		;THUS
	TLZ	S,(FL.RUB)	;NOT IN \ ANY MORE
	JRST	REDLI2		;ONWARD
	SUBTTL	COMMAND OUTPUT


;ROUTINES TO PRINT SELECTED CHARACTERS.
;
;	PRCRLF	- PRINT CRLF
;	PRBSL	- PRINT BACKSLASH
;	PRCOMA	- PRINT COMMA
;	PRLBKT	- PRINT LEFT BRACKET
;	PRRBKT	- PRINT RIGHT BRACKET
;	PRRBCR	- PRINT RIGHT BRACKET AND CRLF

PRRBCR:	PUSHJ	P,PRRBKT	;PRINT RIGHT BRACKET AND FALL INTO PRCRLF
PRCRLF:	MOVEI	T3,.CHCRT	;GET A CR
	PUSHJ	P,TYO
	MOVEI	T3,.CHLFD	;GET A LF
	PJRST	TYO		;TYPE IT AND RETURN

PRDOT:	SKIPA	T3,["."]	;GET A PERIOD
PRCOL:	MOVEI	T3,":"		;GET A COLON
	PJRST	TYO		;TYPE IT AND RETURN
PRBSL:	SKIPA	T3,["\"]	;GET A BACKSLASH
PRCOMA:	MOVEI	T3,","		;GET A COMMA
	PJRST	TYO		;TYPE IT AND RETURN
PRLBKT:	SKIPA	T3,["["]	;GET A LEFT BRACKET
PRRBKT:	MOVEI	T3,"]"		;GET A RIGHT BRACKET
	PJRST	TYO		;TYPE IT AND RETURN


;ROUTINE TO PRINT AN ASCIZ MESSAGE ON THE CTY.
;CALL:
;	T1/ADDRESS OF ASCIZ STRING
;	PUSHJ	P,PRMSG
;RETURN+1 ALWAYS
;DESTROYS T1,T3

PRMSG:	HRLI	T1,(POINT 7,)	;FORM 7 BIT BYTE POINTER
PRMSG1:	ILDB	T3,T1		;GET NEXT CHARACTER
	JUMPE	T3,CPOPJ	;RETURN ON NULL
	PUSHJ	P,TYO		;TYPE CHARACTER
	JRST	PRMSG1		;LOOP FOR NEXT
;ROUTINE TO PRINT A SIXBIT WORD ON THE CTY.
;CALL:
;	T1/SIXBIT WORD
;	PUSHJ	P,PRSIX
;RETURN+1 ALWAYS
;DESTROYS T1,T2,T3

PRSIX:	LSHC	T1,-^D36	;MOVE WORD TO T2, CLEAR T1
	LSHC	T1,6		;MOVE NEXT BYTE TO T1
	MOVEI	T3,"A"-'A'(T1)	;CONVERT TO ASCII AND COPY TO T3
	PUSHJ	P,TYO		;PUT IT OUT
	SKIPE	T1,T2		;MOVE REMAINDER BACK TO T1, SKIP IF DONE
	JRST	PRSIX		;LOOP FOR REST
	POPJ	P,		;RETURN


;ROUTINE TO PRINT AN OCTAL NUMBER ON THE CTY.
;CALL:
;	T1/NUMBER TO PRINT
;	PUSHJ	P,PROCT
;RETURN+1 ALWAYS
;DESTROYS T1,T2,T3

PROCT:	IDIVI	T1,^D8		;DIVIDE BY RADIX, REMAINDER IN T2
	HRLM	T2,0(P)		;STORE ON STACK
	SKIPE	T1		;DONE?
	PUSHJ	P,PROCT		;NO, LOOP
	HLRZ	T3,0(P)		;GET DIGIT FROM STACK
	ADDI	T3,"0"		;CONVERT TO ASCII
	PJRST	TYO		;OUTPUT IT AND RETURN TO CALLER


;ROUTINE TO PRINT A WORD AS TWO 6 DIGIT OCTAL NUMBERS SEPARATED
;BY TWO COMMAS.
;CALL:
;	T4/WORD
;	PUSHJ	P,PRHWD
;RETURN+1 ALWAYS

PRHWD:	PUSHJ	P,PRHWD1	;PRINT LEFT HALF
	MOVEI	T1,[ASCIZ/,,/]	;FOLLOWED BY
	PUSHJ	P,PRMSG		;  TWO COMMAS
	JRST	PRHWD1		;GO PRINT RH
PRHWDR:	HRLZS	T4		;PUT WORD IN LH
PRHWD1:	MOVEI	T1,6		;LOOP COUNT IS 6
PRHWD2:	MOVE	T3,T4		;MOVE WORD TO T3
	LSHC	T3,-^D33	;KEEP 1 DIGIT, CLEAR REST OF T3
	ADDI	T3,"0"		;CONVERT TO ASCII
	PUSHJ	P,TYO		;PUT IT OUT
	SOJG	T1,PRHWD2	;LOOP FOR ALL
	POPJ	P,		;RETURN
;ROUTINE TO PRINT A WORD AS A STANDARD FORMAT VERSION NUMBER.
;CALL:
;	T1/WORD
;	PUSHJ	P,PRVRSN
;RETURN+1 ALWAYS

PRVRSN:	MOVE	T4,T1		;PUT IN SAFE PLACE
	LDB	T1,[POINT 9,T4,11] ;GET MAJOR VERSION
	SKIPE	T1		;IF NON-ZERO,
	PUSHJ	P,PROCT		;PRINT IN OCTAL
	LDB	T1,[POINT 6,T4,17] ;GET MINOR VERSION
	JUMPE	T1,PRVRS2	;IF NON-ZERO,
	SOS	T1		;  PRINT IN MODIFIED
	IDIVI	T1,^D26		;  RADIX 26 ALPHA
	JUMPE	T1,PRVRS1	;  JUMP IF ONE CHAR
	MOVEI	T3,"A"-1(T1)	;  ISSUE FIRST OF TWO
	PUSHJ	P,TYO		;  CHARACTERS
PRVRS1:	MOVEI	T3,"A"(T2)	;  ISSUE "UNITS"
	PUSHJ	P,TYO		;  CHARACTER
PRVRS2:	HRRZ	T1,T4		;GET EDIT NUMBER
	JUMPE	T1,PRVRS3	;IF NON-ZERO,
	MOVEI	T3,"("		;  ISSUE
	PUSHJ	P,TYO		;  AS OCTAL
	HRRZ	T1,T4		;  WITHIN
	PUSHJ	P,PROCT		;  PARENTHESES
	MOVEI	T3,")"		;  ..
	PUSHJ	P,TYO		;  ..
PRVRS3:	LDB	T2,[POINT 3,T4,2] ;GET "WHO" FIELD
	JUMPE	T2,CPOPJ	;IF NON-ZERO,
	MOVEI	T3,"-"		;  PRINT -
	PUSHJ	P,TYO		;  AND THEN
	MOVE	T1,T2		;  THE FIELD
	PJRST	PROCT		;  AS OCTAL


;ROUTINE TO PRINT ONE CHARACTER IN (POSSIBLY) UP-ARRROW FORMAT.
;CALL:
;	T3/CHARACTER TO ECHO
;	PUSHJ	P,ECHO
;RETURN+1 ALWAYS
;DESTROYS T3

ECHO:	CAIE	T3,.CHTAB	;TAB?
	CAIL	T3," "		;NO, CONTROL CHARACTER?
	PJRST	TYO		;NO, JUST PRINT IT
	CAIN	T3,.CHCRT	;END-OF-LINE?
	PJRST	PRCRLF		;YES, ECHO CRLF
	PUSH	P,T3		;SAVE CHAR
	MOVEI	T3,"^"		;PRINT CTRL CHAR
	PUSHJ	P,TYO		;...
	POP	P,T3		;RESTORE CHARACTER
	ADDI	T3,"A"-1	;CONVERT TO PRINTING CHARACTER
	PJRST	TYO		;PRINT IT AND RETURN
;ROUTINE TO PRINT THE CURRENT FILESPEC FROM THE DATA BASE.
;CALL:	PUSHJ	P,PRFILE
;RETURN+1 ALWAYS
;DESTROYS T1-T4

PRFILE:	SKIPE	USRFLG		;USER MODE?
	JRST	PRFIL2		;YES, DIFFERENT PLACE
	MOVE	T1,DEV		;GET DEVICE NAME
	PUSHJ	P,PRSIX		;PRINT IT
	PUSHJ	P,PRCOL		;PRINT A COLON
	MOVE	T1,FILNAM	;GET THE FILENAME
	PUSHJ	P,PRSIX		;PRINT IT
	PUSHJ	P,PRDOT		;PRINT A DOT
	HLLZ	T1,EXT		;GET EXTENSION
	PUSHJ	P,PRSIX		;PRINT IT
	PUSHJ	P,PRLBKT	;PRINT LEFT BRACKET
	HLRZ	T1,PTHBLK	;GET PROJECT NUMBER
	PUSHJ	P,PROCT		;PRINT IT
	PUSHJ	P,PRCOMA	;PRINT COMMA
	HRRZ	T1,PTHBLK	;GET PROGRAMMER NUMBER
	PUSHJ	P,PROCT		;PRINT IT
	MOVEI	T4,1		;OFFSET INTO PTHBLK OF FIRST SFD
PRFIL1:	SKIPN	T1,PTHBLK(T4)	;NEXT SFD NON-NULL?
	PJRST	PRRBKT		;NO, PRINT RIGHT BRACKET AND RETURN
	PUSHJ	P,PRCOMA	;PRINT COMMA
	PUSHJ	P,PRSIX		;PRINT SFD NAME
	AOJA	T4,PRFIL1	;LOOP FOR NEXT SFD

PRFIL2:	MOVE	T1,FOP+.FODEV	;GET DEVICE
	PUSHJ	P,PRSIX		;PRINT IT
	PUSHJ	P,PRCOL		;PRINT A COLON
	MOVE	T1,LEB+.RBNAM	;GET THE FILENAME
	PUSHJ	P,PRSIX		;PRINT IT
	PUSHJ	P,PRDOT		;PRINT A DOT
	HLLZ	T1,LEB+.RBEXT	;GET EXTENSION
	PJRST	PRSIX		;PRINT IT AND RETURN
	SUBTTL	LOWEST LEVEL CTY INPUT/OUTPUT ROUTINES


;ROUTINE TO TYPE ONE CHARACTER ON THE CTY.
;CALL:
;	T3/CHARACTER TO TYPE
;	PUSHJ	P,TYO
;RETURN+1 ALWAYS
;DESTROYS T3.

TYO:	SKIPN	USRFLG		;USER MODE?
	JRST	TYO0		;EXEC MODE
	OUTCHR	T3		;TYPE ON THE TERMINAL
	POPJ	P,		;RETURN

TYO0:
IFN FTKL10,<
	MOVSI	T3,DT.MTO(T3)	;GET CHAR IN LOW ORDER 8 BITS, COMMAND IN NEXT FOUR
	HRRI	T3,DTEMTD	;PUT WORD OFFSET IN RH
DODTE:	SETZM	EPT(T3)		;CLEAR DONE FLAG
	HLRZM	T3,EPT+DTECMD	;PUT INTO COMMAND LOCATION
	CONO	DTE0,TO11DB	;RING DOORBELL
	SKIPN	EPT(T3)		;WAIT TILL MONITOR OUTPUT DONE
	JRST	.-1		;LOOP
	POPJ	P,0		;DONE.
>;END IFN FTKL10

IFN FTKS10,<
	SKIPE	.VPAG0+CTYOWD	;CAN WE SEND NEXT CHAR?
	JRST	.-1		;NOT YET
	IORI	T3,CTYOVL	;SIGNAL VALID
	MOVEM	T3,.VPAG0+CTYOWD ;PUT IT UP FOR THE 8080 TO FIND IT
	CONO	APR,SP.SSF!SP.IFE ;WAKE THE 8080
	POPJ	P,0		;DONE
>;END IFN FTKS10
;ROUTINE TO READ ONE CHARACTER FROM THE CTY.
;CALL:	PUSHJ	P,TYI
;RETURN+1 IF THE OPERATOR DID NOT ANSWER OR SCHED WAS 400
;RETURN+2 WITH CHARACTER IN T3
;DESTROYS T1

TYI:	TLNE	S,(FL.NOP)	;NO OPERATOR IN ATTENDANCE?
	TDZA	T1,T1		;YES, USE SHORT TIMEOUT COUNT
	MOVSI	T1,WATTIM	;ELSE USE 30 SECONDS OR SO
	SKIPN	USRFLG		;USER MODE?
	JRST	TYI0		;NO
	INCHWL	T3		;READ A CHARACTER IN LINE MODE
	JRST	TYI2		;AND ENTER COMMON CODE

TYI0:
IFN FTKL10,<SKIPN EPT+DTEMTI>	;INPUT READY?
IFN FTKS10,<SKIPN .VPAG0+CTYIWD>;INPUT READY?
	SOJGE	T1,.-1		;NO, LOOP BUT NOT TOO LONG
	JUMPGE	T1,TYI1		;GO IF DIDN'T TIME OUT
	TLNE	S,(FL.DEF)	;WANT TO DO DEFAULTING?
	JRST	TYI		;NO, WAIT FOR TYPEIN
	TLO	S,(FL.NOP)	;SET NO OPERATOR FLAG
	POPJ	P,		;AND GIVE NON-SKIP RETURN
TYI1:
IFN FTKL10,<
	MOVE	T3,EPT+DTEF11	;GET CHARACTER
	SETZM	EPT+DTEMTI	;FLAG WE GOT IT
>;END IFN FTKL10

IFN FTKS10,<
	MOVEI	T3,0		;SET TO GET CHAR AND CLEAR WORD
	EXCH	T3,.VPAG0+CTYIWD ;GET CHARACTER AND CLEAR
>;END IFN FTKS10

TYI2:	ANDI	T3,177		;KEEP ONLY 7 BITS
	JUMPE	T3,TYI		;IGNORE NULLS
	CAIN	T3,.CHCNC	;CONTROL-C?
	JRST	RICC		;YES
	CAIN	T3,.CHCND	;CONTROL-D?
	JRST	RICD		;YES
	MOVEI	T1,1		;GET A BIT TO SHIFT
	LSH	T1,(T3)		;SHIFT BY VALUE OF CHARACTER
	TDNE	T1,BRKTAB	;BREAK CHARACTER?
	MOVEI	T3,.CHCRT	;YES, CONVERT TO CR
	JRST	CPOPJ1		;GIVE SKIP RETURN
; HERE TO CHECK FOR INPUT WITHOUT BLOCKING
LISTEN:	PUSH	P,S		;SAVE S
	PUSH	P,T1		;PRESERVE T1
	PUSH	P,T3		;PRESERVE T3
	MOVSI	S,(FL.NOP)	;NO DEFAULTING, NO OPERATOR
	MOVEI	T1,0		;SHORT TIMEOUT
	PUSHJ	P,TYI0		;TRY TO GET A CHARACTER
	  JFCL			;OK IF NONE THERE
	POP	P,T3		;RESTORE T3
	POP	P,T1		;RESTORE T1
	POP	P,S		;RESTORE S
	POPJ	P,		;RETURN
; HERE ON CONTROL-C
RICC:	MOVEI	T1,[ASCIZ/
^C
/]
	PUSHJ	P,PRMSG		;PRINT MESSAGE
	JRST	RESTAR		;AND RESTART BOOT


; HERE ON A CONTROL-D
RICD:	MOVEM	0,CDSAV		;SAVE AC 0
	MOVE	0,[1,,CDSAV+1]	;SET UP BLT
	BLT	0,CDSAV+17	;SAVE ACS 1-17
	MOVEI	T1,0		;PREPARE TO CLEAR
	EXCH	T1,.VPAG0+.JBEDV ;GET MONITOR'S EDV POINTER
	MOVEM	T1,CD112	;SAVE SINCE MONITOR MAY AHVE EDDT LOADED TOO
	DMOVE	T1,.VPAG0+.JBSYM ;GET ADDITIONAL MONITOR WORDS
	DMOVEM	T1,CD116	;SAVE THEM
	DMOVE	T1,BTSVEC+.BTSYM ;GET SYMBOL TABLE POINTERS
	DMOVEM	T1,.VPAG0+.JBSYM ;SET UP SYMBOL TABLE FOR EDDT
	DMOVE	T1,CDSAV+T1	;RESTORE T1 AND T2
	XCT	BTSVEC+.BTBPT	;ENTER DDT IF DEBUGGING
	MOVE	T1,CD112	;GET MONITOR'S EDV POINTER
	MOVEM	T1,.VPAG0+.JBEDV ;RESTORE IT
	DMOVE	T1,CD116	;GET SAVED LOCATIONS
	DMOVEM	T1,.VPAG0+.JBSYM ;RESTORE THEM
	MOVSI	17,CDSAV	;SET UP BLT
	BLT	17,17		;RESTORE ACS 0-17
	SKIPN	CDFLG		;ENTERED DDT FROM STARTUP?
	JRST	TYI0		;NO--GO BACK AND TRY FOR MORE INPUT
	SETZM	CDFLG		;CLEAR INCASE RESTARTED
	POPJ	P,		;RETURN

BRKTAB:	1_.CHBEL!1_.CHTAB!1_.CHLFD!1_.CHVTB!1_.CHFFD!1_.CHCNZ!1_.CHESC!1_" "
	SUBTTL	DISK SUPPORT SUBROUTINES


IFE FTKS10,<
;ROUTINE TO READ A MASSBUS REGISTER AND RETURN THE VALUE.
;CALL WITH:
;	T1/DATAO WORD
;	PUSHJ	P,REDREG
;RETURN+1 ALWAYS WITH FULL 36 BIT DATA IN T1

REDREG:	XCT	DODATO		;TELL THE DEVICE WHICH REGISTER
	STALL			;WAIT AWHILE
	XCT	DODATI		;READ THE DATA
	POPJ	P,		;RETURN
>;END IFE FTKS10


;ROUTINE TO READ AND CHECK THE DRIVE TYPE REGISTER FOR A DEVICE AGAINST
;THOSE DRIVE TYPES THAT WE KNOW ABOUT.
;CALL:
;	T1/DATAO WORD TO READ DRIVE TYPE REGISTER
;	PUSHJ	P,DRVTYP
;RETURN+1 IF NO MATCH
;RETURN+2 IF MATCH WITH DRVBPC, DRVBPT SETUP

DRVTYP:
IFE FTKS10,<
	PUSHJ	P,REDREG	;READ THE REGISTER
>
IFN FTKS10,<
	TRNN	T1,SI.DSK	;THIS A DISK UNIT?
	POPJ	P,		;NO
>
	ANDI	T1,777		;KEEP ONLY 9 BITS
	MOVSI	T2,-DRTTBL	;GET AOBJN POINTER TO DRIVE TYPE TABLE
DRVTY1:	CAME	T1,DRTTAB(T2)	;MATCH WITH THIS ONE?
	AOBJN	T2,DRVTY1	;NO, LOOP
	JUMPGE	T2,CPOPJ	;FAIL IF NO MATCH
	MOVE	T1,BPCTAB(T2)	;GET BLOCKS/CYLINDER
	MOVE	T2,BPTTAB(T2)	;  AND BLOCKS/TRACK
	DMOVEM	T1,DRVBPC	;STORE VALUES
	JRST	CPOPJ1		;GIVE SKIP RETURN
;TABLES DEFINING THE DRIVE TYPES OF THE DRIVES WE KNOW ABOUT AND
;THE CORRESPONDING VALUES OF BLOCKS/CYLINDER AND BLOCKS/TRACK FOR
;EACH DRIVE.  THESE ARE PARALLEL TABLES AND THUS ARE ORDER SENSITIVE.
;
;TABLE GIVING THE DRIVE TYPES THAT WE KNOW ABOUT.

DRTTAB:	EXP	20		;RP04
	EXP	22		;RP06
	EXP	24		;RM03
	EXP	42		;RP07
DRTTBL==.-DRTTAB


;TABLE GIVING THE NUMBER OF BLOCKS/CYLINDER FOR EACH DRIVE.

BPCTAB:	DEC	380		;RP04
	DEC	380		;RP06
	DEC	150		;RM03
	DEC	1376		;RP07


;TABLE GIVING THE NUMBER OF BLOCKS/TRACK FOR EACH DRIVE.

BPTTAB:	DEC	20		;RP04
	DEC	20		;RP04
	DEC	30		;RM03
	DEC	43		;RP07
	SUBTTL	BYTE POINTERS INTO DATA STRUCTURES


DESRBU==^D4	;SIZE OF UNIT NUMBER FIELD IN RIBXRA
DENRBU==^D12	;BIT POSITION OF UNIT NUMBER FIELD IN RIBXRA
DESRBA==^D23	;SIZE OF CLUSTER ADDRESS FIELD IN RIBXRA
DENRBA==^D35	;BIT POSITION OF CLUSTER ADDRESS FIELD IN RIBXRA

DEYRBU:	POINT	DESRBU,RIB+RIBXRA,DENRBU
		;UNIT ON WHICH NEXT EXTENDED RIB EXISTS
DEYRBA:	POINT	DESRBA,RIB+RIBXRA,DENRBA
		;CLUSTER ADDRESS ON UNIT ON WHICH NEXT EXTENDED
		;RIB EXISTS
	SUBTTL	TABLES DRIVING DEVICE DEPENDENT I/O


;TABLE GIVING DEVICE CODES OF CONTROLLERS THAT WE CAN TALK TO.
;TABLE IS ORDERED (HOPEFULLY) SO THAT WE WILL FIND THE FILE IN THE
;LEAST DISK ACCESSES.
;FORMAT IS:
;	XWD	<OFFSET INTO TYPE TABLES>,<DEVICE CODE>_-2

DEFINE	DCODE(CODE,OFS,FTS),<
	IFN	FTS,<
	XWD	OFS,CODE_-2
	>
>

DVCTAB:	DCODE	(540,R20OFS,FTKL10)	;RH20 0 ON KL
	DCODE	(544,R20OFS,FTKL10)	;RH20 1 ON KL
	DCODE	(550,R20OFS,FTKL10)	;RH20 2 ON KL
	DCODE	(554,R20OFS,FTKL10)	;RH20 3 ON KL
	DCODE	(270,R10OFS,FTKL10)	;RH10 0 ON KL
	DCODE	(274,R10OFS,FTKL10)	;RH10 1 ON KL
	DCODE	(560,R20OFS,FTKL10)	;RH20 4 ON KL
	DCODE	(564,R20OFS,FTKL10)	;RH20 5 ON KL
	DCODE	(570,R20OFS,FTKL10)	;RH20 6 ON KL
	DCODE	(574,R20OFS,FTKL10)	;RH20 7 ON KL
	DCODE	(360,R10OFS,FTKL10)	;RH10 2 ON KL
	DCODE	(364,R10OFS,FTKL10)	;RH10 3 ON KL
	DCODE	(<1_2>,R11OFS,FTKS10)	;RH11 UBA 1 ON KS
DVCTBL==.-DVCTAB


;TABLE OF I/O INSTRUCTIONS.  DEVICE CODES FILLED IN BEFORE USE.

IOTTAB:
IFN FTKL10,<
DODATO:	DATAO	0,T1
DODATI:	DATAI	0,T1
DOCONI:	CONI	0,T1
DOCONO:	CONO	0,(T1)
DOCNSO:	CONSO	0,(T1)
>;END IFN FTKL10
IOTTBL==.-IOTTAB
;THE FOLLOWING TABLES GIVE THE DISPATCH ADDRESSES FOR THE DISK CONTROLLER
;DEPENDENT READ AND WRITE ROUTINES.  ALL ARE CALLED WITH THE FOLLOWING
;AC'S SETUP:
;
; J = INDEX INTO DEVICE CODE TABLE
; U = PHYSICAL UNIT NUMBER
; W = OFFSET INTO TABLES BELOW
; R = PHYSICAL MEMORY ADDRESS OF START OF TRANSFER
; F = BLOCK ON UNIT OF FIRST BLOCK TO TRANSFER
; M = NUMBER OF CONTIGUOUS BLOCKS TO TRANSFER
;
;ALL CONTROLLER DEPENDENT ROUTINES MUST PRESERVE F AND R WITH
;A CALL TO SAVFR.
;
;**** THE RH10 AND RH20 ENTRIES IN THE FOLLOWING TABLES MUST BE
;**** THE FIRST AND SECOND ENTRIES IN THE TABLES AND MUST REMAIN
;**** IN THE SAME RELATIVE ORDER.


DEFINE	DADDR(ADDR,OFS,FTS),<
	IFN	FTS,<
	OFS==.-REDTAB
	EXP	ADDR
	>
>


;TABLE OF ADDRESSES OF CONTROLLER READ ROUTINES INDEXED BY CONTROLLER
;TYPE.

REDTAB:	DADDR	(R12RED,R10OFS,FTKL10)
	DADDR	(R12RED,R20OFS,FTKL10)
	DADDR	(R11RED,R11OFS,FTKS10)


DEFINE	DADDR	(ADDR,FTS),<
	IFN	FTS,<
	EXP	ADDR
	>
>


;TABLE OF ADDRESSES OF CONTROLLER WRITE ROUTINES INDEXED BY CONTROLLER
;TYPE.

WRTTAB:	DADDR	(R12WRT,FTKL10)
	DADDR	(R12WRT,FTKL10)
	DADDR	(R11WRT,FTKS10)
	SUBTTL	RH10/RH20 DEVICE DEPENDENT ROUTINES

IFN FTKL10,<

;ROUTINES TO READ FROM/WRITE TO A DRIVE ON AN RH10/RH20. CALL WITH THE
;STANDARD AC'S SETUP.  TRANSLATES THE DEVICE INDEPENDENT TRANSFER
;REQUEST INTO AS MANY TRANSFERS AS NECESSARY TO MAKE THE RH10/RH20 HAPPY.
;CALL:	PUSHJ	P,R12RED -OR- PUSHJ   P,R12WRT
;RETURN+1 IF I/O ERRORS
;RETURN+2 IF TRANSFER WAS SUCCESSFUL

R12WRT:	TLOA	S,(FL.IO)	;SET FLAG FOR OUTPUT
R12RED:	TLZ	S,(FL.IO)	;CLEAR FLAG FOR INPUT
	PUSHJ	P,SAVFR		;SAVE F AND R
	PUSHJ	P,R12INI	;INITIALIZE THE RH10/RH20
	  POPJ	P,		;FAILED
R12XFR:	JUMPLE	M,CPOPJ1	;DONE WHEN TRANSFERED ALL BLOCKS
	TLNE	S,(FL.IO)	;WRITING?
	CAILE	F,LB2HOM+LBOBAT	;YES, ON HOM OR BAT BLOCKS?
	CAIA			;NO
	HALT	.		;YES,  DON'T MAKE THINGS WORSE
	PUSHJ	P,R12CLR	;MAKE SURE THE RH10/RH20 IS CLEARED
	PUSHJ	P,R12SET	;MAKE IOWDS, TELL DRIVE WHERE TO START
IFN FTKL10,<
	JUMPE	W,R10XFR	;DIFFERENT IF RH10
	MOVSI	T1,<(DO.2ST)>(U) ;TALK TO STCR AND SPECIFIED DRIVE
	DPB	T4,[POINT 10,T1,29] ;STORE -VE BLOCKCOUNT
	JRST	R12XF1		;JOIN COMMON CODE
>
R10XFR:	MOVSI	T1,<(DO.1CR)>(U) ;TALK TO COMMAND REGISTER AND SPECIFIED DRIVE
	HRRI	T1,<BOOTWD_6>	;SET INITIAL CONTROL WORD ADDRESS
R12XF1:	TLNN	S,(FL.IO)	;DOING OUTPUT?
	TROA	T1,DO.XRD	;NO, SET READ FUNCTION CODE
	TRO	T1,DO.XWT	;YES, SET WRITE FUNCTION CODE
	XCT	DODATO		;START THE TRANSFER
	PUSHJ	P,R12WAT	;WAIT FOR IT TO COMPLETE
	PUSHJ	P,R12CHK	;CHECK FOR ERRORS
	  POPJ	P,		;GIVE NON-SKIP RETURN IF ERRORS OR TIMED OUT
	JRST	R12XFR		;DO MORE IF ANY BLOCKS LEFT
;ROUTINE TO SETUP THE CHANNEL COMMAND LIST FOR THIS TRANSFER AND
;TELL THE DRIVE WHERE TO START THE TRANSFER.  CALL WITH THE STANDARD
;AC'S SETUP.
;CALL:	PUSHJ	P,R12SET
;RETURN+1 ALWAYS
;RETURNS WITH M, R, AND F UPDATED TO REFLECT THIS TRANSFER AND
;	 T4/NEGATIVE BLOCKCOUNT FOR THIS TRANSFER

R12SET:	MOVEI	T4,0		;INITIALIZE BLOCK COUNT TO 0
IFN FTKL10,<
	JUMPE	W,R12SE2	;NO LOGOUT AREA FOR RH10'S
	HRRZ	T1,DVCTAB(J)	;GET DEVICE CODE FOR THIS DEVICE
	LSH	T1,2		;TIMES 2
	SUBI	T1,540		;COMPUTE OFFSET IN EPT OF LOGOUT AREA
	MOVE	T2,EPTADR	;GET PHYSICAL ADDRESS OF THE EPT
	ADDI	T2,R2IOWD-EPT	;ADD OFFSET TO FIRST IOWD
	TLO	T2,(RH2JMP)	;MAKE IT A JUMP WORD
	MOVEM	T2,EPT(T1)	;STORE JUMP WORD IN LOGOUT AREA
	MOVSI	T1,-<R2IOWL-1>	;MAKE AOBJN POINTER TO IOWD LIST
R12SE1:	JUMPLE	M,R12SE5	;STOP WHEN DONE ENTIRE TRANSFER
>
R12SE2:	MOVEI	T2,(M)		;ASSUME LESS THAN MAX
	CAMLE	M,[R1BCNT
		   R2BCNT](W)	;ARE WE CORRECT?
	MOVE	T2,[R1BCNT
		    R2BCNT](W)	;NO, MAKE IT THE MAX POSSIBLE IN 1 IOWD
	SUBI	M,(T2)		;DECREMENT BLOCKS REMAINING
	SUBI	T4,(T2)		;AND BLOCKS DONE
	LSH	T2,B2WLSH	;CONVERT TO WORDS
IFN FTKL10,<
	JUMPE	W,R12SE3	;GO IF RH10
	LSH	T2,^D18+4	;POSITION IN IOWD
	TLO	T2,(RH2TRA)	;MAKE THE OPCODE A TRANSFER
	IOR	T2,R		;STORE PHYSICAL ADDRESS
	MOVEM	T2,R2IOWD(T1)	;STORE IN CHANNEL COMMAND LIST
	ADDI	R,R2WCNT	;INCREMENT CORE ADDRESS FOR NEXT TIME
	JRST	R12SE4		;JOIN COMMON CODE
>
R12SE3:	MOVNS	T2		;RH10'S WANT A NEGATIVE WORDCOUNT
	LSH	T2,^D18		;MOVE TO LH
	XCT	DOCONI		;GET CONI FOR DRIVE
	TLNE	T1,(CI.122)	;SKIP IF 18 BIT DF10
	LSH	T2,4		;DF10C'S ONLY HAVE 14 BITS OF WORDCOUNT
	IOR	T2,R		;STORE PHYSICAL ADDRESS
	SUBI	T2,1		;AND ADDRESS-1
	MOVEM	T2,.VPAG0+BOOTWD ;STORE IOWD IN LOW CORE
	SETZM	.VPAG0+BOOTWD+1 ;INSURE IOWD TERMINATION
	ADDI	R,R1WCNT	;INCREMENT CORE ADDRESS FOR NEXT TIME
IFN FTKL10,<
	JRST	R12SE6		;DO ONLY ONE IOWD FOR AN RH10
R12SE4:	AOBJN	T1,R12SE1	;DO AS MANY AS POSSIBLE
R12SE5:	SETZM	R2IOWD(T1)	;STORE HALT IOWD TO TERMINATE LIST
>
R12SE6:	MOVE	T1,F		;COPY BLOCK ADDRESS
	SUB	F,T4		;UPDATE FOR AMOUNT OF THIS TRANSFER
	IDIV	T1,DRVBPC	;T1=CYLINDER, T2=REMAINDER
	HRLI	T1,<(DO.XDC)>(U) ;STORE IN DESIRED CYLINDER REGISTER
	XCT	DODATO		;TELL THE DRIVE
	IDIV	T2,DRVBPT	;T2=TRACK, T3=SECTOR
	DPB	T2,[POINT 8,T3,27] ;POSITION CORRECTLY
	MOVSI	T1,<(DO.XDS)>(U) ;TALK TO THE BLOCK ADDRESS REGISTER
	HRRI	T1,(T3)		;STORE ADDRESS
	XCT	DODATO		;TELL THE DRIVE
	POPJ	P,		;RETURN
;ROUTINE TO INITIALIZE THE RH10/RH20 FOR A TRANSFER.  ACTS AS A COROUTINE
;IF NO ERRORS ARE DETECTED SO THAT THE CONI STATE MAY BE RESTORED
;WHEN THE CALLER RETURNS
;CALL:	PUSHJ	P,R12INI
;RETURN+1 IF INITIALIZATION FAILED
;RETURN+2 IF SUCCESSFUL

R12INI:	XCT	DOCONI		;GET CONI IN T1
	PUSH	P,T1		;SAVE IT FOR LATER
	MOVEI	T1,1		;WRITE THE PIA
	XCT	DOCONO
	XCT	DOCONI		;AND READ IT BACK
	JUMPLE	T1,TPOPJ	;0 - NO RH10/20, SIGN BIT - KLIPA/KLNI
	MOVE	T1,[DO.1IA	;READ INTERRUPT ADDRESS REGISTER
		    DO.2IV](W)	; OR INTERRUPT VECTOR INDEX REGISTER
	PUSHJ	P,REDREG
	PUSH	P,T1		;SALT IT AWAY FOR LATER
	PUSHJ	P,R12CLR	;BLAST THE RH10/RH20 INTO A KNOWN STATE
	MOVSI	T1,<(DO.XDT)>(U) ;NEED DRIVE TYPE REGISTER FOR THIS DRIVE
	PUSHJ	P,DRVTYP	;READ AND CHECK IT
	  JRST	R12IN1		;NO MATCH
	MOVSI	T1,<(DO.XCR)>(U) ;POINT TO DRIVE CONTROL REGISTER
	HRRI	T1,DO.XCL	;FUNCTION IS DRIVE CLEAR
	XCT	DODATO		;CLEAR THE DRIVE
	HRRI	T1,DO.XRP	;FOLLOWED BY A READIN
	XCT	DODATO		;  PRESET
	MOVSI	T1,<(DO.XSR)>(U) ;SETUP TO READ STATUS REGISTER
	PUSHJ	P,REDREG	;DO SO
	ANDI	T1,DI.XSM	;MASK, IGNORING WRITE LOCK, PGM
	CAIE	T1,DI.XSB	;IS IT OK?
	JRST	R12IN1		;NO
	MOVE	T1,-1(P)	;GET THE CONI BITS
	EXCH	T1,-2(P)	;SWAP WITH CALLER'S PC
	POP	P,-1(P)		;MOVE DATAI BITS DOWN ONE ON STACK
	PUSHJ	P,1(T1)		;CALL THE CALLER
	  CAIA			;PROPAGATE NON-SKIP
	AOS	-2(P)		;SET FOR SKIP RETURN
R12IN1:	PUSHJ	P,R12CLR	;BLAST THE RH10/RH20 AGAIN
	POP	P,T1		;RESTORE THE IA/IVIR CONTENTS
	TLO	T1,(DO.LDR)	;SET LOAD REGISTER
	XCT	DODATO		;RELOAD THE IA/IVIR
	POP	P,T1		;RESTORE THE CONI BITS
	IOR	T1,[CO.1AE
		    CO.2ME](W)	;FORCE CORRECT BITS FOR CONTROLLER TYPE
	AND	T1,[CO.1RB
		    CO.2RB](W)	;BUT KEEP ONLY THE IMPORTANT ONES
	XCT	DOCONO		;RESTORE THE PIA, AIE, ETC.
	POPJ	P,		;RETURN
;ROUTINE TO CHECK THE RH10/RH20 FOR ERRORS IN THE LAST TRANSFER.
;CALL:	PUSHJ	P,R12CHK
;RETURN+1 IF ERRORS DETECTED
;RETURN+2 IF NO ERRORS

R12CHK:	MOVSI	T1,<(DO.XSR)>(U) ;SET TO READ STATUS REGISTER
	PUSHJ	P,REDREG	;DO SO
	TRNE	T1,DI.XCE	;COMPOSITE ERROR?
	POPJ	P,		;YES, GIVE ERROR RETURN
	MOVE	T1,[CI.1ER
		    CI.2ER](W)	;GET CONI ERROR BITS FOR CONTROLLER
	XCT	DOCNSO		;ANY SET?
	JRST	CPOPJ1		;NO, GIVE SKIP RETURN
	POPJ	P,		;YES
;ROUTINE TO WAIT FOR THE RH10/RH20 TO FINISH A TRANSFER.
;CALL:	PUSHJ	P,R12WAT
;RETURN+1 IF SUCCESSFUL
;RETURN+2 IF TIMED OUT

R12WAT:	MOVSI	T2,10		;LOOP COUNT = ABOUT 7 SECONDS
	MOVE	T1,[CI.1RA!CI.XDN
		    CI.2RA!CI.XDN](W) ;WAIT FOR DONE OR RAE TO COME UP
	XCT	DOCNSO		;IN THE CONI
	SOJG	T2,.-1		;HASN'T YET, WAIT FOR IT
	JUMPLE	T2,CPOPJ1	;GIVE SKIP RETURN IF TIMED OUT
	POPJ	P,		;RETURN


;ROUTINE TO FORCE THE RH10/RH20 INTO A KNOWN STATE FOR A TRANSFER.
;CALL:	PUSHJ	P,R12CLR
;RETURN+1 ALWAYS

R12CLR:	MOVEI	T1,CO.XMI	;DO A
	XCT	DOCONO		;  MASSBUS INIT
	MOVEI	T1,CO.XSX	;THEN A
	XCT	DOCONO		;  STOP TRANSFER
	MOVEI	T1,CO.XDN	;THEN A
	XCT	DOCONO		;  CLEAR DONE
	MOVEI	T1,CO.2ME	;AND FINALLY A
	XCT	DOCONO		;  MASSBUS ENABLE
	POPJ	P,
	SUBTTL	INTERNAL CHANNEL DEVICE DEPENDENT ROUTINERS


;ROUTINE TO FORCIBLY HALT ALL INTERNAL CHANNEL DEVICES.
;CALL:
;	PUSHJ	P,ZAPICH
;RETURN+1 ALWAYS

ZAPICH:	PUSH	P,P1		;SAVE AN AC
	MOVEI	P1,FSTICD/4	;GET FIRST INTERNAL CHANNEL DEVICE CODE
ZAPIC1:	MOVE	T1,P1		;GET DEVICE CODE IN T1
	PUSHJ	P,SETIOC	;SET UP I/O INSTRUCTIONS
	XCT	DOCONI		;READ CONI
	JUMPE	T1,ZAPIC3	;JUMP IF NON-EXISTANT
	JUMPL	T1,ZAPIC2	;JUMP IF IPA DEVICE (CI20 OR NIA20)
	PUSHJ	P,R12CLR	;CLEAR THE RH20
	JRST	ZAPIC3		;CONTINUE

ZAPIC2:	MOVEI	T1,CO.CPT	;BIT TO CLEAR THE PORT
	XCT	DOCONO		;HALT THE MICROPROCESSOR
ZAPIC3:	CAIGE	P1,LSTICD/4	;DONE THEM ALL?
	AOJA	P1,ZAPIC1	;NO, LOOP FOR OTHERS
	POP	P,P1		;RESTORE THE AC
	POPJ	P,		;RETURN


>;END IFN FTKL10
	SUBTTL	RH11 DEVICE DEPENDENT ROUTINES

IFN FTKS10,<

;ROUTINES TO READ FROM/WRITE TO A DRIVE ON AN RH11.  CALL WITH THE
;STANDARD AC'S SETUP.  TRANSLATES DEVICE INDEPENDENT TRANSFER REQUEST
;TO AS MANY TRANSFERS AS NECESSARY TO MAKE THE RH11 HAPPY.
;CALL:	PUSHJ	P,R11RED -OR- PUSHJ	P,R11WRT
;RETURN+1 IF I/O ERRORS
;RETURN+2 IF TRANSFER WAS SUCCESSFUL

R11WRT:	TLOA	S,(FL.IO)	;SET FLAG FOR OUTPUT
R11RED:	TLZ	S,(FL.IO)	;CLEAR FLAG FOR INPUT
	PUSHJ	P,SAVFR		;SAVE F AND R
	HRLZ	T4,DVCTAB(J)	;SET T4=UBA,,0
	PUSHJ	P,R11INI	;INITIALIZE THE RH11
	  POPJ	P,		;FAILED
R11XFR:	JUMPLE	M,CPOPJ1	;DONE WHEN TRANSFERED ALL BLOCKS
	TLNE	S,(FL.IO)	;WRITING?
	CAILE	F,LB2HOM+LBOBAT ;YES, ON HOM OR BAT BLOCKS?
	CAIA			;NO
	HALT	.		;YES, DON'T MAKE THINGS WORSE
	PUSHJ	P,R11CLR	;CLEAR THE RH11
	WRIO	U,SO.CS2(T4)	;SELECT DRIVE
	PUSH	P,T4		;SAVE T4
	PUSHJ	P,R11SET	;SET UBA MAP SLOTS, DRIVE LBN
	POP	P,T4		;RESTORE T4
	MOVEI	T1,SO.WRT	;ASSUME WRITING
	TLNN	S,(FL.IO)	;ARE WE CORRECT?
	MOVEI	T1,SO.RED	;NO, SET READING
	WRIO	T1,SO.CS1(T4)	;START THE TRANSFER
	MOVSI	T2,2		;LOOP COUNT
R11XF1:	RDIO	T1,SO.CS1(T4)	;READ STATUS REGISTER
	TRNN	T1,SI.RDY	;READY COME UP?
	SOJG	T2,R11XF1	;NO, LOOP
	JUMPLE	T2,CPOPJ	;ERROR RETURN IF TIMED OUT
	TRNE	T1,SI.S1E	;ERRORS?
	POPJ	P,		;YES
	JRST	R11XFR		;DO MORE IF ANY BLOCKS LEFT
;ROUTINE TO SETUP THE UBA MAPPING REGISTERS, AND THE DRIVE REGISTERS
;FOR THIS TRANSFER.  CALL WITH THE STANDARD AC'S SETUP.
;CALL:
;	T4/UBA,,0
;	PUSHJ	P,R11SET
;RETURN+1 ALWAYS
;RETURNS WITH M, R, AND F UPDATED TO REFLECT THIS TRANSFER.
;DESTROYS T4

R11SET:	MOVEI	T1,(R)		;GET ADDRESS OF FIRST WORD TO TRANSFER
	ANDI	T1,PAGSIZ-1	;ISOLATE OFFSET OF FIRST WORD IN PAGE
	LSH	T1,2		;MAKE IT A BYTE OFFSET
	WRIO	T1,SO.BA(T4)	;SET THE BUS ADDRESS REGISTER
	MOVE	T1,F		;COPY LBN OF FIRST BLOCK TO TRANSFER
	IDIV	T1,DRVBPC	;T1=CYLINDER, T2=BLOCK IN CYLINDER
	WRIO	T1,SO.DC(T4)	;SET DESIRED CYLINDER REGISTER
	IDIV	T2,DRVBPT	;T2=TRACK, T3=BLOCK IN TRACK
	DPB	T2,[POINT 8,T3,27] ;POSITION TRACK NUMBER
	WRIO	T3,SO.DA(T4)	;TELL DRIVE
	MOVEI	T1,(M)		;ASSUME WE CAN DO ALL OF TRANSFER
	CAILE	T1,RSBCNT	;LARGER THAN MAX?
	MOVEI	T1,RSBCNT	;YES, USE MAX
	SUBI	M,(T1)		;ADJUST M FOR NEXT TIME
	ADDI	F,(T1)		;ADVANCE TO FIRST BLOCK OF NEXT TRANSFER
	MOVE	T2,R		;COPY CORE ADDRESS OF FIRST WORD
	LSH	T1,B2WLSH	;COMPUTE WORD COUNT
	ADD	R,T1		;ADVANCE CORE ADDRESS FOR NEXT TIME
	LSH	T1,1		;COMPUTE PDP11 WORD COUNT
	MOVNS	T1		;MAKE IT NEGATIVE
	WRIO	T1,SO.WC(T4)	;SET WORD COUNT REGISTER
	LSH	T2,W2PLSH	;COMPUTE PAGE NUMBER OF 1ST PAGE
	MOVE	T1,R		;GET ADDRESS OF FIRST WORD OF NEXT TRANSFER
	SUBI	T1,1		;MAKE IT LAST ADDRESS OF THIS TRANSFER
	LSH	T1,W2PLSH	;COMPUTE PAGE NUMBER
	SUBI	T1,-1(T2)	;COMPUTE NUMBER OF PAGES TO MAP
	MOVNS	T1		;MAKE IT NEGATIVE
	HRL	T2,T1		;AND MAKE AN AOBJN POINTER
	TRO	T2,SO.VFT	;SET VALID AND FAST TRANSFER
R11SE1:	WRIO	T2,SO.UPR(T4)	;MAP ONE PAGE
	ADDI	T4,1		;INCREMENT UBA MAP ADDRESS
	AOBJN	T2,R11SE1	;LOOP FOR ALL
	POPJ	P,		;RETURN
;ROUTINE TO INITIALIZE THE RH11 FOR A TRANSFER.  ACTS AS A COROUTINE
;IF NO ERRORS ARE DETECTED SO THAT THE UBA STATUS REGISTER AND
;CONTROL STATUS REGISTER 1 MAY BE RESTORED WHEN THE CALLER RETURNS.
;CALL:
;	T4/UBA,,0
;	PUSHJ	P,R11INI
;RETURN+1 IF INITIALIZATION FAILED
;RETURN+2 IF SUCCESSFUL

R11INI:	RDIO	T1,SO.USR(T4)	;READ UBA STATUS REGISTER
	TRNE	T1,SI.UER	;ANY ERRORS?
	POPJ	P,		;YES, ERROR
	RDIO	T2,SO.CS1(T4)	;READ CS REGISTER 1
	HRL	T1,T2		;T1=CSR 1,,UBA SR
	PUSH	P,T1		;SAVE FOR RESTORE
	PUSHJ	P,R11CLR	;CLEAR THE RH11
	WRIO	U,SO.CS2(T4)	;SELECT DRIVE
	RDIO	T1,SI.DT(T4)	;READ DRIVE TYPE REGISTER
	PUSHJ	P,DRVTYP	;CHECK IT
	  JRST	R11IN1		;FAILED
	MOVEI	T1,SO.DCL	;GET DRIVE CLEAR FUNCTION
	WRIO	T1,SO.CS1(T4)	;DO IT
	MOVEI	T1,SO.RIP	;GET READIN PRESET FUNCTION
	WRIO	T1,SO.CS1(T4)	;DO IT
	RDIO	T1,SO.DS(T4)	;READ DRIVE STATUS REGISTER
	ANDI	T1,SO.DSM	;MASK, IGNORING WRITE LOCK, PGM
	CAIE	T1,SO.DSB	;IS IT OK?
	JRST	R11IN1		;NO
	MOVE	T1,-1(P)	;GET CALLERS RETURN ADDRESS
	POP	P,-1(P)		;MOVE STATE BITS DOWN ONE ON THE STACK
	PUSHJ	P,1(T1)		;CALL THE CALLER
	  CAIA			;PROPAGATE NON-SKIP
	AOS	-1(P)		;GIVE SKIP RETURN
R11IN1:	PUSHJ	P,R11CLR	;CLEAR THE RH11 AGAIN
	POP	P,T1		;GET BACK CS1,,UBA SR
	AND	T1,[SO.RBT]	;KEEP ONLY IMPORTANT BITS
	WRIO	T1,SO.USR(T4)	;RESTORE UBA STATUS REGISTER
	MOVSS	T1		;PUT CS1 BITS IN RH
	WRIO	T1,SO.CS1(T4)	;RESTORE CS1 BITS
	POPJ	P,		;RETURN


;ROUTINE TO FORCE THE RH11 INTO A KNOWN STATE.
;CALL:
;	T4/UBA,,0
;	PUSHJ	P,R11CLR
;RETURN+1 ALWAYS

R11CLR:	MOVEI	T1,SO.UBI	;UBA INIT
	WRIO	T1,SO.USR(T4)	;CLEAR THE UBA/DRIVES
	RDIO	T1,SO.ASR(T4)	;READ ATTENTION SUMMARY
	WRIO	T1,SO.ASR(T4)	;CLEAR ANYBODY WHO'S STILL ON
				;CAN HAPPEN IF DUAL PORTED
	POPJ	P,		;RETURN


>;END IFN FTKS10
	SUBTTL	LITERALS


BTSLIT:	LIT
	SUBTTL	MAGTAPE-SPECIFIC CODE


;MAGTAPE-SPECIFIC CODE RESIDES HERE (AFTER LITERALS) SO IT CAN BE THROWN
;AWAY AFTER LOADING A MONITOR.

IFN FTTAPE,<

TAPBEG:!			;START OF MAGTAPE-SPECIFIC CODE


;TAPE ACTION COMMAND PROCESSING (GET HERE FROM RLDMO2)

TAPACT:	TRNE	S,FR.SKP	;/SKIP SEEN?
	JRST	TAPSKP		;YES
	TRNE	S,FR.REW	;/REWIND SEEN?
	JRST	TAPREW		;YES
;PROCESS ANY OTHER TAPE ACTION BITS
	JRST	RESTAR		;PARSE NEXT COMMAND

TAPSKP:	PUSHJ	P,SKPEOF	;SKIP TO END OF FILE
	JRST	RESTAR		;PARSE NEXT COMMAND

TAPREW:	PUSHJ	P,REWIND	;REWIND THE TAPE
	PUSHJ	P,CHKREW	;WAIT FOR COMPLETION
	JRST	RESTAR		;PARSE NEXT COMMAND

MUSERR:	SKIPA	T1,[[ASCIZ /%Magtape unit specification required/]]
NTDERR:	MOVEI	T1,[ASCIZ /%Dumping to magtape is not supported/]
	PUSHJ	P,PRMSG		;PRINT MESSAGE
	PJRST	PRCRLF		;END THE LINE AND RETURN
	SUBTTL	SCAN TAPE FOR SPECIFIED FILE


;THIS ROUTINE IS LIKE FNDMON, FNDMFD, ET AL FOR TAPES.  IT SEARCHES
;THE TAPE FOR THE SPECIFIED FILE AND WHEN FOUND READS THE DIRECTORY
;OF THE .EXE FILE INTO BUF.  FLOW THEN BRANCHES BACK TO FNDMON.

TAPSCN:	MOVE	T1,DEV		;GET WHAT THEY TYPED
	MOVEM	T1,SAVDEV	;SAVE IT FOR LATER

TAPSC1:	PUSHJ	P,READBL	;READ TAPE BLOCK
	  JRST	.-1		;IGNORE EOF
	MOVE	T1,TAPBUF+G$TYPE ;GET RECORD TYPE WORD
	SKIPLE	T1		;CHECK FOR LEGAL RECORD TYPE
	CAILE	T1,T$MAX	;...
	JRST	TAPSC6		;NOT A BACKUP RECORD, IGNORE THIS FILE
	CAIN	T1,T$FIL	;FILE RECORD?
	JRST	TAPSC3		;YES
	CAIN	T1,T$END	;END OF SAVESET?
	JRST	TAPSCE		;YES, FILE NOT FOUND
	JRST	TAPSC1		;NO, KEEP LOOKING FOR T$FIL OR T$END

TAPSC3:	MOVE	T1,TAPBUF+G$FLAG ;GET FLAGS WORD
	TLNN	T1,(GF$SOF)	;START OF A FILE?
	JRST	TAPSC1		;NO, KEEP LOOKING
	MOVEI	P1,TAPBUF+MTHLEN+1 ;POINT AT DATA AREA
	TLZ	S,(FL.EXS)	;NO EXTENSION SEEN YET
TAPSC4:	PUSHJ	P,FDCODE	;PICK UP NEXT SUB-BLOCK
	  JRST	TAPSC5		;DONE, SEE IF WE WON
	CAIL	T1,.FCDIR	;DIRECTORY INFORMATION?
	SUBI	T1,<.FCDIR-.FCEXT>-1 ;YES, REMOVE OFFSET
	CAIN	T1,.FCDEV	;DEVICE?
	TLNN	S,(FL.WLD)	;YES, WILD STRUCTURE?
	SKIPA			;NO
	MOVEM	T2,DEV		;OVER-RIDE WHATEVER JUNK IS THERE
	CAME	T2,FILSPC-1(T1)	;COMPARE WITH WHAT USER TYPED
	JRST	TAPSC1		;DIDN'T MATCH, KEEP LOOKING
	JRST	TAPSC4		;OK SO FAR, TRY NEXT SUB-BLOCK

TAPSC5:	TLNN	S,(FL.EXS)	;DID WE GET AN EXTENSION?
	SKIPN	EXT		;NO, WAS ONE SPECIFIED?
	JRST	FOUND		;WE WON
	JRST	TAPSC1		;CLOSE, BUT NO CIGAR

TAPSC6:	PUSHJ	P,SKPEOF	;SKIP TO END OF (TAPE) FILE
	JRST	TAPSC1		;START WITH NEW FILE

TAPSCE:	MOVE	T1,SAVDEV	;GET SAVED DEV
	MOVEM	T1,DEV		;AS YOU WERE
	TLZ	S,(FL.WLD)	;NO LONGER A WILD STRUCTURE
	PUSHJ	P,REWIND	;REWIND THE TAPE
;	PUSHJ	P,CHKREW	;MIGHT BE USEFUL TO WAIT
	JRST	FNTERR		;GIVE FILE NOT FOUND ERROR
;HERE WHEN THE DESIRED FILE WAS FOUND.

FOUND:	SETZM	BLKNUM		;START AT BEGINNING OF THE FILE
	PUSHJ	P,RDNXTB	;READ NEXT TAPE BLOCK
	MOVSI	T1,TAPBUF+MTHLEN ;"FROM" ADDRESS
	HRRI	T1,BUF		;"TO" ADDRESS
	BLT	T1,BUF+BLKSIZ-1	;COPY ONE BLOCK
	JRST	FNDMOE		;CONTINUE LIKE DISK FILE
;ROUTINE TO GET THE NEXT SUB-BLOCK FROM THE TAPE BUFFER.
;CALL WITH P1 POINTING AT NEXT SUB-BLOCK, RETURNS SUB-BLOCK
;TYPE IN T1 AND SUB-BLOCK CONTENTS IN T2, AND P1 UPDATED.

FDCODE:	HLRZ	T1,(P1)		;GET TYPE CODE
	JUMPE	T1,CPOPJ	;DONE IF ZERO
	CAIG	T1,.FCEXT	;DEVICE, NAME, OR EXTENSION?
	JRST	FDCOD1		;YES
	CAIGE	T1,.FCDIR	;DIRECTORY?
	POPJ	P,		;NO
FDCOD1:	CAIN	T1,.FCEXT	;EXTENSION?
	TLO	S,(FL.EXS)	;YES, REMEMBER THAT
	HRRZ	P2,(P1)		;GET WORD COUNT
	SUBI	P2,1		;WHICH INCLUDES WORD COUNT WORD
	MOVEI	P1,1(P1)	;POINT AT DATA
	HRLI	P1,(POINT 7)	;IT'S ASCII DATA
	SETZB	T2,T3		;T2 GETS THE ANSWER IF SIXBIT, T3 IF PPN
	CAIE	T1,.FCDIR	;PPN?
	MOVE	T3,[POINT 6,T2]	;NO, EVERYTHING ELSE IS SIXBIT
FDCOD2:	TLNN	P1,760000	;DONE WITH THIS WORD?
	SOJLE	P2,FDCOD5	;YES, GO IF WORD COUNT EXHAUSTED
	ILDB	T4,P1		;GET NEXT CHARACTER
	JUMPE	T4,FDCOD5	;DONE IF NULL
	CAIN	T1,.FCDIR	;PPN?
	JRST	FDCOD3		;YES
	SUBI	T4," "-' '	;MAKE SIXBIT
	TLNE	T3,770000	;WORD FULL?
	IDPB	T4,T3		;NO, STORE THIS BYTE
	JRST	FDCOD2		;LOOP FOR MORE

FDCOD3:	CAIN	T4,"_"		;DONE WITH PROJECT?
	JRST	FDCOD4		;YES
	ROT	T4,-3		;ACCUMULATE IN ANSWER
	LSHC	T3,3
	JRST	FDCOD2		;LOOP FOR MORE

FDCOD4:	HRL	T2,T3		;PROJECT IN LH
	SETZ	T3,		;START WITH ZERO PROGRAMMER NUMBER
	JRST	FDCOD2		;LOOP FOR THAT

FDCOD5:	CAIN	T1,.FCDIR	;PPN?
	HRR	T2,T3		;YES, GET PROGRAMMER NUMBER
	AOJA	P1,CPOPJ1	;POINT AT NEXT WORD AND EXIT
	SUBTTL	MAGTAPE EQUIVALENT TO REDBLK

;ROUTINE TO READ ONE OR MORE BLOCKS OF AN EXE FILE FROM A MAGTAPE.
;CALL:	P2/NUMBER OF BLOCKS TO READ
;	P3/CORE ADDRESS OF WHERE TO READ FIRST BLOCK
;	P4/FILE BLOCK NUMBER OF FIRST BLOCK
;	PUSHJ	P,REDTAP
;RETURN+1 IF ERROR WITH ERROR CODE IN T1
;RETURN+2 IF SUCCESSFUL WITH P3 AND P4 UPDATED TO REFLECT THE TRANSFER.

REDTAP:	TRNE	P2,3		;MUST BE A MULTIPLE OF 4 BLOCKS
	HALT	.		;NOT TOO GOOD
	JUMPLE	P2,CPOPJ1	;READ ALL BLOCKS YET?
	PUSHJ	P,RDNXTB	;READ NEXT TAPE BLOCK
	MOVE	T1,P3		;COPY ADDRESS
	LSH	T1,W2PLSH	;BACK TO A PAGE NUMBER
	HRRM	T1,EPT+.MMOVE	;SET UP MAPPING
	CLRPT	.VMOVE		;MAKE NEW MAPPING VISIBLE
	MOVE	T1,[TAPBUF+MTHLEN,,.VMOVE] ;SET UP A BLT
	BLT	T1,.VMOVE+PAGSIZ-1 ;TRANSFER THE PAGE
	ADDI	P3,PAGSIZ	;ACCOUNT FOR THE PAGE JUST READ
	ADDI	P4,PAGSIZ/BLKSIZ ;...
	SUBI	P2,PAGSIZ/BLKSIZ ;...
	JRST	REDTAP		;CONTINUE FOR ALL
;ROUTINE TO READ NEXT TAPE BLOCK FOR A FILE
;CALL:	PUSHJ	P,RDNXTB
;RETURN+1 ALWAYS

RDNXTB:	PUSHJ	P,READBL	;READ A TAPE BLOCK
	  ERROR	(<Tape mark in middle of file>)
	MOVE	T1,TAPBUF+G$TYPE ;GET RECORD TYPE
	MOVE	T2,TAPBUF+G$FLAG ;GET RECORD FLAGS
	CAIN	T1,T$FIL	;STILL A FILE RECORD?
	TLNN	T2,(GF$SOF)	;YES, START OF NEXT FILE?
	JRST	RDNXT1		;NO, ALL IS WELL
	ERROR	(<BACKUP file inconsistant>)
RDNXT1:	TLNE	T2,(GF$RPT)	;REPEATER RECORD?
	JRST	RDNXTB		;YES, WE WON ON THE ORIGINAL
	MOVE	T1,TAPBUF+G$SIZ	;GET DATA SIZE
	CAIE	T1,PAGSIZ	;SOMETHING WE DON'T KNOW ABOUT?
	ERROR	(<BACKUP file inconsistant>)
	MOVEI	T1,PAGSIZ/BLKSIZ ;NUMBER OF BLOCKS WE READ
	ADDM	T1,BLKNUM	;WHERE WE ARE POSITIONED NOW
	POPJ	P,		;RETURN
;ROUTINE TO READ NEXT BLOCK FROM A TAPE.  CALLS DEVICE DEPENDENT DRIVER
;TO PERFORM THE ACTUAL I/O.

READBL:	SETZM	EOF		;CLEAR END OF FILE FLAG
	PUSHJ	P,CHKREW	;MAKE SURE NOT REWINDING
	MOVEI	M,ERRTRY	;NUMBER OF RETRIES ON READ ERROR
READB1:	PUSHJ	P,@RTRTAB(W)	;READ THE NEXT RECORD
	  JRST	READE		;ERROR
READB2:	SKIPN	EOF		;DID WE ENCOUNTER END OF FILE?
	AOS	(P)		;NO, SET FOR SKIP RETURN
	POPJ	P,		;RETURN

;HERE ON A READ ERROR

READE:	CAIN	M,ERRTRY	;FIRST RETRY?
	JRST	READE3		;YES
READE1:
IFN FTDX10,<
	HRRZ	T1,W		;GET TYPE INDEX
	CAIN	T1,DX1OFS	;IF A TU70, THE DX10 HAS ALREADY RETRIED
	JRST	READE2		; THE OPERATION, SO JUST GIVE UP
>; END IFN FTDX10
	PUSHJ	P,BACKSP	;REPOSITION
	SOJG	M,READB1	;TRY AGAIN
	PUSHJ	P,SKIPRC	;SKIP BAD RECORD
READE2:	ERROR	(<Tape read error>)
READE3:	MOVEI	M,1		;COUNT OF RECORDS READ
	PUSHJ	P,@RTRTAB(W)	;READ THE NEXT RECORD
	  AOJA	M,.-1		;THAT ONE'S BAD TOO
	MOVE	T1,TAPBUF+G$FLAG ;GET FLAGS WORD
	TLNE	T1,(GF$RPT)	;REPEAT OF A BAD RECORD?
	JRST	READB2		;YES, WE WON
	PUSHJ	P,BACKSP	;NO, REPOSITION
	SOJG	M,.-1		; TO THE ORIGINAL BAD RECORD
	MOVEI	M,ERRTRY	;RESET COUNTER
	JRST	READE1		;AND RETRY IT
	SUBTTL	MISCELLANEOUS MAGTAPE ROUTINES


;ROUTINE TO REWIND THE TAPE.
;CALL:	PUSHJ	P,REWIND
;RETURN+1 ALWAYS

REWIND:	PUSHJ	P,CHKREW	;MAKE SURE NOT ALREADY REWINDING
	TLO	S,(FL.REW)	;REMEMBER WE ARE REWINDING
	PJRST	@REWTAB(W)	;CALL DEVICE DRIVER


;ROUTINE TO CHECK IF REWINDING AND WAIT FOR COMPLETION.
;CALL:	PUSHJ	P,CHKREW
;RETURN+1 ALWAYS

CHKREW:	TLZN	S,(FL.REW)	;ARE WE REWINDING?
	POPJ	P,		;NO, RETURN
	PJRST	@CHKTAB(W)	;CALL DEVICE DRIVER, RETURN WHEN REWIND COMPLETED


;ROUTINE TO SKIP TO END OF FILE.
;CALL:	PUSHJ	P,SKPEOF
;RETURN+1 ALWAYS

SKPEOF:	SETZM	EOF		;GUARANTEE WE SEE A LATER ONE
	PUSHJ	P,SKIPRC	;SKIP A RECORD
	SKIPN	EOF		;EOF YET?
	JRST	SKPEOF		;NO, LOOP
	POPJ	P,		;YES, RETURN


;ROUTINE TO SKIP FORWARD OR BACKWARD ONE RECORD.
;CALL:	PUSHJ	P,SKIPRC/BACKSP
;RETURN+1 ALWAYS

SKIPRC:	TDZA	T4,T4		;REMEMBER FORWARD SPACE
BACKSP:	MOVEI	T4,1		;REMEMBER BACK SPACE
	PUSH	P,T4		;SAVE ENTRY FLAG
	PUSHJ	P,CHKREW	;MAKE SURE NOT REWINDING
	POP	P,T4		;RESTORE FLAG
	JRST	@SKPTAB(W)	;CALL DEVICE DRIVER


;ROUTINE TO WAIT FOR UNIT TO SHOW DESIRED STATUS
;CALL:	PUSHJ	P,TWAIT
;	<INSTR TO EXECUTE>   ;SKIP WHEN SUCCESSFUL

TWAIT:	MOVSI	T1,(1B12)	;TIME TO WAIT FOR STATUS
	XCT	@(P)		;EXECUTE INSTR
	SOJG	T1,.-1		;'ROUND
	JUMPN	T1,CPOPJ1	;SUCCESS
	ERROR	(<No magtape status>)
;I/O INSTRUCTIONS, ROUTINE TO READ REGISTER, ETC.

TAPCNO:	CONO	0,(T2)		;CONO
TAPDTO:	DATAO	0,T2		;DATAO
	STALL			;WAIT A WHILE
TAPDTI:	DATAI	0,T2		;DATAI
	ANDI	T2,177777	;ONLY 16 BITS OF INTEREST
	POPJ	P,		;RETURN
	SUBTTL	TABLES DRIVING DEVICE DEPENDENT MAGTAPE I/O


;THE FOLLOWING TABLES CONTROL MAGTAPE I/O AND POSITIONING.
;ALL ARE INDEXED BY CONTROLLER TYPE.

DEFINE	DADDR(ADDR,OFS,FTS),<
	IFN	FTS,<
	OFS==.-RESTAB
	EXP	ADDR
	>
>


;ROUTINE TO FIND AND RESET THE CONTROLLER

RESTAB:	DADDR	(DX1RES,DX1OFS,FTDX10)
	DADDR	(TM2RES,TM2OFS,FTTM02)
	DADDR	(DX2RES,DX2OFS,FTDX20)
	DADDR	(T78RES,T78OFS,FTTM78)


DEFINE	DADDR(ADDR,FTS),<
	IFN	FTS,<
	EXP	ADDR
	>
>

;ROUTINE TO READ ONE TAPE RECORD INTO TAPBUF

RTRTAB:	DADDR	(DX1RED,FTDX10)
	DADDR	(TM2RED,FTTM02)
	DADDR	(DX2RED,FTDX20)
	DADDR	(T78RED,FTTM78)


;ROUTINE TO SKIP A TAPE RECORD (T4=0 IF FORWARD, =1 IF BACKWARD)

SKPTAB:	DADDR	(DX1SKR,FTDX10)
	DADDR	(TM2SKR,FTTM02)
	DADDR	(DX2SKR,FTDX20)
	DADDR	(T78SKR,FTTM78)


;ROUTINE TO REWIND THE TAPE

REWTAB:	DADDR	(DX1REW,FTDX10)
	DADDR	(TM2REW,FTTM02)
	DADDR	(DX2REW,FTDX20)
	DADDR	(T78REW,FTTM78)


;ROUTINE TO CHECK IF REWINDING

CHKTAB:	DADDR	(DX1CHK,FTDX10)
	DADDR	(TM2CHK,FTTM02)
	DADDR	(DX2CHK,FTDX20)
	DADDR	(T78CHK,FTTM78)
	SUBTTL	DX10/TX01 ROUTINES


IFN FTDX10,<

;DX10 RESET ROUTINE

DX1RES:	CONO	PDC,1		;SELECT A PI ASSIGNMENT
	CONI	PDC,T1		;READ IT BACK
	CONO	PDC,0		;CLEAR PI ASSIGNMENT
	TRNN	T1,7		;DEVICE PRESENT?
	ERROR	(<No DX10 present>)
;DID WE JUST CLOBBER THIS BIT ABOVE?
	TLNE	T1,(TX.RUN)	;'8 RUNNING?
	JRST	DX1IN2		;YES - PROCEDE
	PUSHJ	P,UPRES		;NO - RESET
	PUSHJ	P,LODX10	;LOAD DX10
	PUSHJ	P,UPHALT	;MAKE SURE HALTED
	MOVSI	T4,-UPMTBL 	;CHECK MAGIC LOCS
DX1IN1:	HLRZ	T3,UPMTAB(T4)	;GET ADDRESS
	PUSHJ	P,UPMRD		;READ CONTENTS
	HRRZ	T3,UPMTAB(T4)	;GET EXPECTED VALUE
	CAME	T2,T3		;MATCH?
TX.NRN:	ERROR	(<Cannot start DX10>)
	AOBJN	T4,DX1IN1	;YES - TRY MORE
TX.IST:	MOVEI	T3,UP.SA	;SET START ADDRS
	PUSHJ	P,UPSTRT	;START IT
DX1IN2:	PUSHJ	P,CLRICP	;CLEAR ICPC AREA
	PUSHJ	P,CLRCHN	;CLEAR CHL & SET ICPC
	CONI	PDC,T1		;GET STATUS
	TLNN	T1,(TX.RUN)	;STILL RUNNING
	JRST	TX.NRN		;NO - INFORM USER
	MOVEI	J,CHPRG		;SET UP PNTR TO PROGRAM
	MOVEI	T1,TX.NOP	;DEVICE COMMAND NOOP
	PUSHJ	P,TX.CMD	;BUILD A DEVICE COMMAND
	MOVSI	T1,(CH.STS!CH.FRC);FORCE SENSE BYTES
	MOVEM	T1,CHPRG+1	;STORE IN CHL PROG
	PUSHJ	P,TX.SXS	;START CHL ETC.
	PUSHJ	P,TWAIT		;WAIT FOR DONE
	  CONSO	PDC,TX.STA	;STATUS AVAILABLE
	PUSHJ	P,CLRSTA	;CLR STATUS AVAIL NOW
	MOVE	T1,CHSNS+SB1	;GET SENSE BYTE 1
	MOVEI	T2,5		;ASSUME 9-TK
	TLNE	T1,(SB17TK)	;TEST FOR 7-TK
	HRROI	T2,6		;IT IS , SET 6 BYTE/WD
	MOVEM	T2,TX.MOD	;SAVE IN MODE WORD
	POPJ	P,		;RETURN
;READ ROUTINE

DX1RED:	MOVEI	J,CHPRG		;SET UP CHL PGM PNTR
	SKIPGE	TX.MOD		;7-TK DRIVE?
	PUSHJ	P,TX.7MD	;SET 7 TRACK MODE
	MOVEI	T1,TX.FRD	;FWD READ CODE
	PUSHJ	P,TX.CMD	;BUILD COMMAND
	MOVEI	T1,TX.9TK	;ASSUME 9 TRACK MODE
	SKIPG	TX.MOD		;IS IT?
	MOVEI	T1,TX.7TK	;NO - USE DIFFERENT MODE
	DPB	T1,[POINT 2,0(J),6] ;SET INTO COMMAND
	MOVSI	T1,-LNMTBF	;GET LENGTH OF BUFFER
	HRRZ	T2,TX.MOD	;GET MODE WORD
	IMUL	T1,T2		;GET BYTE COUNT IN LH
	LSH	T1,4		;POSITION
	ADD	T1,TAPBFA	;ADD IN PHYSICAL ADDRESS OF TAPE BUFFER
	MOVEM	T1,1(J)		;STORE IN CHL PGM
	MOVSI	T1,(CH.STS!CH.FRC)
	MOVEM	T1,2(J)		;STORE STATUS & SENSE BYTES

TX.XFR:	PUSHJ	P,TX.SXS	;SET UP XS AREA & START XFR
	PUSHJ	P,TWAIT		;NOW WAIT TILL DONE
	  CONSO	PDC,TX.STA
	PUSHJ	P,DX1CKE	;CHECK FOR CHL ERRORS
	PUSHJ	P,CLRSTA	;CLEAR STATUS AVAIL NOW
	TLNN	T3,(CS.DSF)	;DSR FLAG?
	JRST	CPOPJ1		;NO - EVERTHING OK
	TLNN	T3,(DS.UEX)	;UNIT EXCEPTION?
	POPJ	P,		;NO - JUST ERROR
	SETOM	EOF		;YES - MUST BE EOF
	TLNN	T3,(DS.UCH!CS.DPE) ;UNIT CHECK ALSO
	AOS	0(P)		;NO - OK RETURN
	POPJ	P,		;ERROR ALSO

;SET UP XS AREA AND START XFER

TX.SXS:	MOVSI	T1,-LSNS_4	;CONSTRUCT XFER FOR SENSE BYTES
	ADD	T1,CHSNSA	;PHYSICAL ADDRS OF XS AREA
	MOVEM	T1,ICPC+3	;STORE IN ICPC AREA
	JRST	TX.GO		;START CHL

UPMTAB:	XWD	17,4756
	XWD	200,5210
	XWD	210,6007
	XWD	211,3777
	XWD	212,3774
	XWD	215,6502

UPMTBL==.-UPMTAB
;REWIND ROUTINE

DX1REW:	MOVEI	J,CHPRG		;ADDRS OF CHL PROG
	MOVEI	T1,TX.REW	;REWIND CMD
	PUSHJ	P,TX.CMD	;BUILD IT
	MOVSI	T1,(CH.STS)	;CHL TERMINATION WORD
	MOVEM	T1,1(J)		;STASH IN PRG
	SETZM	ICPC+3		;NO SENSE BYTES
	PUSHJ	P,TX.GO		;START CHL
	PUSHJ	P,TWAIT		;NOW WAIT TILL STARTED
	  CONSO	PDC,TX.STA
	PUSHJ	P,DX1CKE	;CHECK CORRECT STATUS
	JRST	CLRSTA		;AND CLEAR STATUS AVAIL.


;SKIP RECORD ROUTINE

DX1SKR:	MOVEI	J,CHPRG		;ADDRS OF CHL PROG
	SKIPG	TX.MOD		;CHECK FOR 7TK
	PUSHJ	P,TX.7MD	;YES - SET UP MODE SET STUFF
	MOVE	T1,[TX.FSR
		    TX.BSR](T4)	;SET CORRECT CMD
	PUSHJ	P,TX.CMD	;...
	MOVSI	T1,(CH.STS!CH.FRC)
	MOVEM	T1,1(J)		;FORCE SENSE
	PUSHJ	P,TX.XFR	;SET XS AND START CHL
	  JFCL			;IGNORE ERRORS
	POPJ	P,		;EXIT


;WAIT FOR REWIND TO COMPLETE

DX1CHK:	CONSO	PDC,TX.STA	;WAIT FOR STATUS AVAIL
	JRST	.-1
	LDB	T1,[POINT 2,ICPC+1,10]
	CAIE	T1,CS.STC	;CHECK CU STATUS
	ERROR	(<Not CU status>)
CLRSTA:	CONO	PDC,TX.ILI!TX.STA ;CLEAR STATUS AVAIL
	POPJ	P,		;RETURN
;ROUTINE TO CHECK ON CHL ERRORS
;RETURNS C(T3) := CSR/DSR

DX1CKE:	MOVE	T3,ICPC+1	;GET ST1
	CONI	PDC,T2		;GET CONI STATUS
	TRNN	T2,TX.UPE!TX.MPE!TX.NXM
	TLNE	T3,(CS.SLE!CS.SQE)
TX.LOS:	ERROR	(<Fatal DX10 error or drive off-line>)
	LDB	T1,[POINT 2,ICPC+1,10]
	CAIE	T1,CS.STE	;GRNTEE ENDING STATUS
	ERROR	(<Not ending status>)
	TRNE	T3,CS.NFG!CS.INC
	JRST	TX.LOS		;SOMETHING WORSE COULDN'T HAPPEN
	POPJ	P,		;RETURN
;DX10 UTILITIES FOR THE PDP8

UPHALT:	MOVEI	T2,DO.UC0	;SELECT CTL 0
	PUSHJ	P,UPRSEL	;...
	MOVEI	T2,DU0HLT	;SET HALT
	DATAO	PDC,T2		;...
	POPJ	P,

UPRES:	MOVSI	T2,(DO.RES)	;ISSUE RESET CMD
	DATAO	PDC,T2
	POPJ	P,		;RETURN

UPSTRT:	MOVEI	T2,DO.UC1	;SELECT CTL 1
	PUSHJ	P,UPRSEL	;...
	ANDI	T3,7777		;VALIDATE ADDRS
	DATAO	PDC,T3		;SEND ADDRS
	MOVEI	T2,DO.UC0	;SELECT CTL 0
	PUSHJ	P,UPRSEL	;...
	MOVEI	T2,DU0CON	;SET CONTINUE
	DATAO	PDC,T2		;...
	POPJ	P,		;RETURN

UPRSEL:	TLO	T2,(DO.LRS)	;LOAD REG SELECT BIT
	DATAO	PDC,T2		;SELECT REGISTER
	POPJ	P,		;RETURN

;READ MEMORY LOC IN DX10
;C(T3) := ADDRS , RESULT INTO T2

UPMRD:	MOVEI	T2,DO.UC1	;SELECT CTL 1
	PUSHJ	P,UPRSEL	;...
	ANDI	T3,7777		;GRNTEE VALID ADDRS
	DATAO	PDC,T3		;SEND IT OUT
	MOVEI	T2,DO.UC0	;SELECT CTL 0
	PUSHJ	P,UPRSEL	;...
	MOVEI	T2,DU0EXM	;EXAMINE ENABLE
	DATAO	PDC,T2		;SEND IT OUT
	DATAI	PDC,T2		;READ REG
	ANDI	T2,7777		;ONLY BITS OF INTEREST
	POPJ	P,		;RETURN
;ROUTINE TO CLEAR ICPC AREA

CLRICP:	SETZM	ICPC		;CLEAR 1ST WORD
	SETZM	ICPC+1
	SETZM	ICPC+2
	SETZM	ICPC+3		;THROUGH 4TH WORD
	POPJ	P,		;RETURN

;ROUTINE TO SET UP CHL STUFF

CLRCHN:	MOVEI	T1,ICPC		;ADDRS OF CHL AREA
	LSH	T1,^D9		;PROPER POSITION
	IORI	T1,TX.UPE!TX.MPE!TX.NXM!TX.STA
	CONO	PDC,(T1)	;CLEAR ERROR FLGS & SET ICPC
	POPJ	P,		;RETURN

;ROUTINE TO SETUP CHL COMMAND C(T1) := CMD

TX.CMD:	SETZM	0(J)		;CLEAR CMD WORD
	DPB	T1,[POINT 8,0(J),23] ;SET CMD IN PLACE
	MOVSI	T1,(CH.COP)	;SAY ITS A CHL OPR
	IORM	T1,0(J)		;PUT INTO CMD
	MOVE	T1,TAPUNI	;GET UNIT #
	DPB	T1,[POINT 8,0(J),35]
	POPJ	P,		;RETURN

;ROUTINE TO START CHL

TX.GO:	MOVE	T1,CHPRGA	;GET PHYSICAL ADDRESS OF CHANNEL PROGRAM
	TLO	T1,(CH.JMP!CH.GO) ;BUILD JUMP CCW
	MOVEM	T1,ICPC		;PUT IN ICPC
	CONSZ	PDC,TX.STA	;THIS BETTER NOT BE ON
	ERROR	(<Channel synchronization error>)
	CONO	PDC,TX.ILI!TX.CON!TX.CLR
	POPJ	P,		;START AND RETURN

;ROUTINE TO SETUP 7 TRACK MODE SET CMD

TX.7MD:	SKIPE	T1,TAPDEN	;SEE IF DENSITY SPECIFIED
	CAILE	T1,3		;CHECK MAX ALLOWED
	MOVEI	T1,3		;ELSE USE DEFAULT
	MOVE	T1,TX.DTB(T1)	;GET DENSITY CMD
	PUSHJ	P,TX.CMD	;FINISH COMMAND
	AOJA	J,CPOPJ		;ADVANCE CHL PGM POINTER AND RETURN

;TX01/DX10 DENSITY TABLE

TX.DTB:	TX.D78		;800 BPI DEFAULT
	TX.D72		;200
	TX.D75		;556
	TX.D78		;800
;ROUTINE TO LOAD THE DX10 MICROCODE.
;CALL:	PUSHJ	P,LODX10
;DOESN'T RETURN IF MICROCODE NOT PRESENT IN BOOT
;RETURN+1 IF MICROCODE LOADED

LODX10:	PUSHJ	P,SAVE2		;FREE UP P1 AND P2
	DMOVE	P1,BTSVEC+.BTUCD+.BTTX1 ;GET POINTERS TO DX10 MICROCODE
	SKIPN	P1		;MICROCODE PRESENT?
	ERROR	(<DX10 microcode not present>)
	SUBI	P1,1		;DON'T INCLUDE VERSION WORD IN WORD COUNT
	IMULI	P1,3		;CONVERT WORD COUNT TO NUMBER OF 12-BIT BYTES
	ADDI	P2,BTSVEC+1	;CHANGE OFFSET INTO ADDRESS, SKIP VERSION WORD
	HRLI	P2,(POINT 12)	;MAKE A 12-BIT BYTE POINTER
	DATAO	PDC,[DO.LRS!DO.UC1] ;SELECT CPMA ON IBUS
	DATAO	PDC,[0]		;LOAD ADDRESS 0
	DATAO	PDC,[DO.LRS!DO.UC0] ;SELECT 8A CONTROL REGISTER
LDX101:	ILDB	T1,P2		;GRAB A BYTE
	TRO	T1,DU0DEP	;SET ENABLE DEPOSIT BIT
	DATAO	PDC,T1		;WRITE WORD INTO MEMORY
	SOJGE	P1,LDX101	;WRITE ALL WORDS

	MOVEI	T1,[ASCIZ /[TX01 microcode %/]
	PUSHJ	P,PRMSG		;PRINT MESSAGE
	MOVE	T1,BTSVEC+.BTUCD+.BTTX1+1 ;GET OFFSET TO MICROCODE
	MOVE	T1,BTSVEC(T1)	;GET VERSION WORD
	PUSHJ	P,PRVRSN	;PRINT IT
	MOVEI	T1,[ASCIZ / loaded on DX10 /]
	PUSHJ	P,PRMSG		;MORE NOISE
	MOVEI	T1,PDC		;DEVICE CODE
	PUSHJ	P,PROCT		;PRINT IT
	PUSHJ	P,PRRBKT	;PRINT RIGHT BRACKET
	PJRST	PRCRLF		;PRINT CRLF AND RETURN
>; END IFN FTDX10
	SUBTTL	TM02 ROUTINES


IFN FTTM02,<

;TM02/RH10/RH20 (TU16/TU45) READ ROUTINES

IFN FTKL10,<			;THIS VERSION FOR THE KL

;FIND AND RESET CONTROLLER

TM2RES:	MOVEI	T1,270/4	;SEARCH FOR RIGHT DEVICE CODE
	SETZ	J,		;ASSUME RH10
TM2RS1:	DPB	T1,[POINT 7,TAPDTO,9] ;TRY THIS CONTROLLER
	DPB	T1,[POINT 7,TAPDTI,9]
	DPB	T1,[POINT 7,TAPCNO,9]
	JUMPE	J,TM2RS2	;IF AN RH20,
	MOVEI	T2,CO.2ME	;MASSBUS ENABLE
	XCT	TAPCNO
TM2RS2:	MOVE	T2,TAPUNI	;UNIT WE'RE TALKING TO
	HRLI	T2,(T2.DTC!T2.DLR) ;SET TO TALK TO IT
	XCT	TAPDTO		;TELL TAPE CONTROL REG
	MOVSI	T2,(DO.XDT)	;READ DRIVE TYPE REGISTER
	PUSHJ	P,TAPDTO
	MOVE	T3,T2		;PRESERVE DT REG
	ANDI	T2,770		;MASK DRIVE TYPE
	CAIE	T2,TY.T3L	;IS IT A TM03?
	CAIN	T2,TY.T2L	; NO, IS IT A TM02?
	JRST	TM2RS3		;YES, WE'RE THERE
	ADDI	T1,1		;NO, TRY NEXT CONTROL
	CAIN	T1,300/4	;AFTER 274 IS 360
	MOVEI	T1,360/4
	CAIG	T1,374/4	;TRIED LAST RH10 DEV CODE?
	JRST	TM2RS1		;NO, TRY THIS ONE
	MOVEI	J,1		;TRY THE RH20'S
	CAIG	T1,LSTICD/4
	JRST	TM2RS1		;UNLESS WE TRIED ALL OF THEM
	ERROR	(<No RH20 for TM02>)
TM2RS3:	DPB	T1,[POINT 7,TM2CSO,9] ;SET DEV CODE IN CONSO INSTRUCTION
	TRNE	T3,10000	;IS IT 9-TRACK?
	HRROS	J		;NO, 7-TRACK
	LSH	T1,2		;COMPUTE INITIAL CNTRL WRD ADDRESS
	ADDI	T1,EPT-540	; IF THIS IS AN RH20
	HRRM	T1,TM2.IC
	POPJ	P,		;AND RETURN
;READ ROUTINE

TM2RED:	PUSHJ	P,TM2STC	;SET UP TAPE CONTROL REG
	MOVEI	T2,515410	;CLEAR ERRORS, MASSBUS ENABLE
	XCT	TAPCNO		;CLEAR THE RH20
	MOVEI	T2,LNMTBF	;BUFFER SIZE
	MOVEI	T3,5		;COMPUTE FRAME COUNT
	SKIPGE	J		;9-TRACK?
	ADDI	T3,1		;NO
	IMULI	T2,(T3)
	ANDI	T2,177777	;TELL FRAME-COUNT REG
	HRLI	T2,(T2.DFC!T2.DLR)
	XCT	TAPDTO
	MOVE	T1,TAPBFA	;GET PHYSICAL ADDRESS OF TAPE BUFFER
	TRNN	J,1		;RH20?
	JRST	TM2RH1		;NO
	TLO	T1,600000+<LNMTBF_4> ;SET TRA+LAST AND WORD COUNT
	MOVE	T2,[200000,,BOOTWD] ;JUMP TO IOWD
TM2.IC:	MOVEM	T2,.		;STORE INITIAL JUMP (ADDR PATCHED)
	JRST	TM2RD2		;CONTINUE
TM2RH1:	SUBI	T1,1		;MAKE RH-10 STYLE CCW
	TLO	T1,-<LNMTBF_4>	;SET -VE WORD COUNT
TM2RD2:	MOVEM	T1,BOOTWD	;SAVE IOWD
	SETZM	BOOTWD+1	;TERMINATE IO LIST
	TRNE	J,1		;IF AN RH20
	SKIPA	T2,[716200,,377000!T2.RDF] ;READ RH20-STYLE
	MOVE	T2,[T2.DRH!T2.DLR+BOOTWD_6!T2.RDF] ;READ RH10-STYLE
	XCT	TAPDTO		;START THE OPERATION
	PUSHJ	P,TWAIT		;WAIT TILL JOB DONE COMES UP
TM2CSO:	  CONSO	,T2.DON
TM2.RB:	MOVSI	T2,(T2.DSR)	;READ STATUS REG
	PUSHJ	P,TAPDTO
	TRNE	T2,T2.SEF	;EOF?
	SETOM	EOF		;YES
	TRNN	T2,T2.SER	;ERROR?
	JRST	TM2RD3		;NO, WE WON
	MOVE	T1,T2		;PRESERVE STATUS REG
	MOVSI	T2,(T2.DER)	;READ THE ERROR REG
	PUSHJ	P,TAPDTO
	TRNE	T1,T2.SPE	;PE MODE?
	TRZ	T2,T2.NER	;YES, THESE AREN'T ERRORS
	TRNN	T2,T2.ERR	;ERROR?
TM2RD3:	AOS	(P)		;NO ERROR, SKIP-RETURN
	MOVE	T2,[T2.DLR+T2.DCF] ;CLEAR OUT THE DRIVE
	XCT	TAPDTO		; IN CASE OF ANY ERRORS LEFT
	POPJ	P,		;AND RETURN
;REWIND

TM2REW:	PUSHJ	P,TM2STC	;TALK TO RIGHT DRIVE
	MOVE	T2,[T2.DLR+T2.RWF] ;FUNCTIN=REWIND
	XCT	TAPDTO		;DO IT
	PUSHJ	P,TWAIT		;WAIT TILL STARTED
	  PUSHJ	P,T2.RWC
	POPJ	P,		;AND RETURN


;SKIP RECORD ROUTINE

TM2SKR:	PUSHJ	P,TM2STC	;SET TO TALK TO RIGHT DRIVE
	MOVE	T2,[T2.DFC!T2.DLR+177777]
	XCT	TAPDTO		;SET FRAME-COUNT = 1
	MOVE	T2,[T2.DLR+T2.SFF ;GET RIGHT FUNCTION
		   T2.DLR+T2.SBF](T4)
	XCT	TAPDTO		;START THE OPERATION
	PUSHJ	P,TM2CK1	;WAIT FOR DRIVE-READY
	PUSHJ	P,TM2.RB	;CHECK FOR ERRS
	  JFCL
	POPJ	P,		;AND RETURN


;WAIT FOR REWIND TO COMPLETE

TM2CHK:	PUSHJ	P,TM2STC	;TALK TO RIGHT DRIVE
TM2CK1:	PUSHJ	P,TWAIT		;WAIT
	  PUSHJ	P,T2.RDC	; TILL DRIVE READY IS UP
	POPJ	P,		;AND RETURN


;ROUTINES TO WAIT

T2.RWC:	MOVEI	T4,T2.SPP!T2.SBT ;WAIT FOR BOT OR POSITION IN PROGRESS
	CAIA
T2.RDC:	MOVEI	T4,T2.SRY	;WAIT FOR DRIVE READY
	MOVSI	T2,(T2.DSR)	;READ STATUS REG
	PUSHJ	P,TAPDTO
	TRNE	T2,(T4)		;RIGHT BIT UP?
	AOS	(P)		;YES, SKIP
	POPJ	P,		;AND RETURN
;ROUTINE TO SET UP THE TAPE-CONTROL REGISTER

TM2STC:	SKIPL	T2,J		;9-TRACK?
	TDZA	T2,T2		;9-TRACK CORE DUMP
	MOVEI	T2,T2.M7T	;NO, 7-TRACK CORE DUMP
	MOVEI	T3,4		;4 OR 5 FRAMES PER WORD
	SKIPGE	J
	SUBI	T3,1
	SKIPE	T1,TAPDEN	;GET DENSITY
	CAILE	T1,(T3)
	MOVEI	T1,(T3)		;1=200BPI,...4=1600
	ADD	T2,TM2DTB(T1)	;SET DENSITY IN DATAO
	ADD	T2,TAPUNI	;PLUS UNIT NUMBER
	HRLI	T2,(T2.DTC!T2.DLR) ;TELL TAPE CNTRL REG
	XCT	TAPDTO		;NOW WE'RE TALKING TO DRIVE
	POPJ	P,		;AND RETURN
>; END IFN FTKL10
;TM02/RH11 READ ROUTINES

IFN FTKS10,<			;THIS VERSION FOR THE KS

;FIND AND RESET CONTROLLER

TM2RES:	SETZ	J,		;ASSUME 9-TRACK
	MOVE	T4,[TRHBAS]	;BASE UBA ADDRESS FOR THE TAPE RH11
	MOVEI	T1,C2.CLR	;CONTROLLER CLEAR
	WRIO	T1,MTCS2(T4)	;DO IT
	MOVE	T1,TAPUNI	;UNIT TO TALK TO
	WRIO	T1,MTTC(T4)	;SELECT IT
	RDIO	T2,MTDT(T4)	;GET DRIVE TYPE REGISTER
	MOVE	T3,T2		;SAVE A COPY HERE
	ANDI	T2,770		;MASK DRIVE TYPE
	CAIE	T2,TY.T3L	;IS IT A TM03?
	CAIN	T2,TY.T2L	; NO, IS IT A TM02?
	JRST	TM2RS1		;YES--PROCEED
	ERROR	(<No TM02/TM03 found>)
TM2RS1:	TRNE	T3,10000	;IS IT 9-TRACK?
	SETO	J,		;NO--7-TRACK, SET FLAG
	POPJ	P,		;RETURN
;READ ROUTINE

TM2RED:	PUSHJ	P,TM2STC	;SET UP TAPE CONTROL REGISTER
	MOVNI	T2,LNMTBF	;-VE WORD COUNT
	MOVEI	T3,5		;COMPUTE FRAME COUNT
	SKIPGE	J		;9-TRACK?
	ADDI	T3,1		;NO
	IMULI	T2,(T3)
	WRIO	T2,MTFC(T4)	;SET FRAME COUNT REG
	PUSH	P,P1		;FREE UP AN AC
	HLLZ	P1,T4		;PICK UP UBA NUMBER
	HRRI	P1,SO.UPR	;FORM UBA ADDRESS TO FIRST MAP REGISTER
	MOVE	T1,TAPBFA	;ADDRESS OF FIRST WORD IN BUFFER
	ANDI	T1,777		;PAGE OFFSET OF STARTING ADDRESS
	LSH	T1,2		;CONVERT TO -11 BYTE ADDRESS
	WRIO	T1,MTBA(T4)	;SET IN BUS ADDRESS REGISTER
	MOVNI	T2,LNMTBF_1	;-VE WORD COUNT TIMES 2 GIVES -11 WORD COUNT
	WRIO	T2,MTWC(T4)	;SET IN WORD COUNT REGISTER
	MOVE	T2,TAPBFA	;PHYSICAL ADDRESS OF TAPE BUFFER
	LSH	T2,W2PLSH	;CONVERT TO ITS PAGE NUMBER
	TRO	T2,40000	;SET THE VALID BIT FOR UBA PAGER
	MOVNI	T3,LNMTBF	;-VE WORD COUNT
	LSH	T1,-2		;PAGE OFFSET OF STARTING ADDRESS
	SUBI	T1,PAGSIZ-1	;-NUMBER OF BUFFER WORDS IN 1ST PAGE
	SKIPN	T1		;IF ZERO, THEN IT'S THE WHOLE PAGE
TM2RS2:	MOVNI	T1,PAGSIZ	;-SIZE OF A PAGE
	SUB	T3,T1		;ACCOUNT FOR NO. OF WORDS MAPPED BY THIS REGISTER
	WRIO	T2,(P1)		;SET THE MAP REGISTER ACCORDINGLY
	JUMPGE	T3,TM2RS3	;QUIT IF DONE
	AOS	T2		;NEXT PAGE IN MEMORY
	AOJA	P1,TM2RS2	;NEXT MAP REGISTER TO SET, AND CONTINUE
TM2RS3:	POP	P,P1		;RESTORE AC
	MOVEI	T2,T2.RDF	;READ FORWARD FUNCTION
	WRIOB	T2,MTCS1(T4)	;START THE TRANSFER
	MOVEI	T3,C1.RDY	;READY BIT
	TION	T3,MTCS1(T4)	;TEST IT AND
	JRST	.-1		; WAIT TILL IT'S DONE
TMH.RB:	RDIO	T2,MTDS(T4)	;GET THE DRIVE STATUS REG
	TRNE	T2,DS.TM	;EOF?
	SETOM	EOF		;YES--SET FLAG
	TRNN	T2,DS.ERR	;ERROR?
	JRST	TM2RS4		;NO
	RDIO	T1,MTER(T4)	;GET ERROR REGISTER
	TRNE	T2,DS.PES	;PHASE ENCODED MODE?
	TRZ	T1,ER.COR+ER.CS+ER.LRC ;YES, THESE AREN'T ERRORS
	TRNN	T1,176377	;ERROR?
TM2RS4:	AOS	(P)		;NO ERROR, SKIP RETURN
	MOVEI	T2,T2.DCF	;DRIVE CLEAR FUNCTION
	WRIOB	T2,MTCS1(T4)	;DO IT
	POPJ	P,		;RETURN
;REWIND

TM2REW:	PUSHJ	P,TM2STC	;TALK TO RIGHT DRIVE
	MOVEI	T1,T2.RWF	;REWIND FUNCTION
	WRIOB	T1,MTCS1(T4)	;DO IT
	PUSHJ	P,TWAIT		;WAIT TILL STARTED
	  PUSHJ	P,TH.RWC
	POPJ	P,		;RETURN


;ROUTINE TO SKIP RECORD

TM2SKR:	PUSH	P,T4		;SAVE FUNCTION INDEX
	PUSHJ	P,TM2STC	;SET UP TAPE CTRL REGISTER
	SETO	T2,		;-1
	WRIO	T2,MTFC(T4)	;SET IN FRAME COUNT REGISTER
	POP	P,T2		;GET BACK FUNCTION INDEX
	MOVE	T2,[T2.SFF	;GET RIGHT FUNCTION CODE
		    T2.SBF](T2)
	WRIOB	T2,MTCS1(T4)	;START OPERATION
	PUSHJ	P,TM2CK1	;WAIT FOR DRIVE READY
	PUSHJ	P,TMH.RB	;CHECK FOR ERRORS
	  JFCL
	POPJ	P,		;RETURN


;WAIT FOR REWIND TO COMPLETE

TM2CHK:	PUSHJ	P,TM2STC	;TALK TO RIGHT DRIVE
TM2CK1:	PUSHJ	P,TWAIT		;WAIT TILL
	  PUSHJ	P,TH.RDC	; DRIVE READY IS UP
	POPJ	P,		;RETURN


;ROUTINES TO WAIT

TH.RWC:	SKIPA	T3,[DS.PIP+DS.BOT] ;WAIT FOR PIP OR BOT
TH.RDC:	MOVEI	T3,DS.DRY	;WAIT FOR DRIVE READY
	TIOE	T3,MTDS(T4)	;RIGHT BIT(S) UP?
	AOS	(P)		;YES--SKIP RETURN
	POPJ	P,		;RETURN
;ROUTINE TO SET THE TAPE CONTROL REGISTER

TM2STC:	MOVE	T4,[TRHBAS]	;BASE UBA ADDRESS FOR TAPE RH11
	SKIPL	T2,J		;9-TRACK?
	TDZA	T2,T2		;YES, 9-TRK CORE DUMP FORMAT
	MOVEI	T2,T2.M7T	;NO, 7-TRK CORE DUMP FORMAT
	MOVEI	T3,4		;4 OR 5 FRAMES PER WORD
	SKIPGE	J		;7-TRACK?
	SUBI	T3,1		;YES--MAX DENSITY POSSIBLE
	SKIPE	T1,TAPDEN	;GET DENSITY
	CAILE	T1,(T3)
	MOVEI	T1,(T3)
	ADD	T2,TM2DTB(T1)	;PUT IN DENSITY CODE
	ADD	T2,TAPUNI	;PUT IN SLAVE NUMBER
	WRIO	T2,MTTC(T4)	;SET TAPE CTRL REGISTER
	POPJ	P,		;RETURN
>;END IFN FTKS10

TM2DTB:	-1
	0B27		;200 BPI
	1B27		;556
	2B27		;800
	4B27		;1600
>;END IFN FTTM02
SUBTTL	DX20/TX02 ROUTINES


IFN FTDX20,<

;FIND AND RESET DX20 CONTROLLER

DX2RES:	MOVEI	T1,FSTICD/4	;START WITH FIRST INTERNAL CHANNEL
DX2RS1:	DPB	T1,[POINT 7,TAPDTO,9] ;STORE IN DATAO
	DPB	T1,[POINT 7,TAPDTI,9] ;  AND IN DATAI
	DPB	T1,[POINT 7,TAPCNO,9] ;  AND IN CONO
	MOVEI	T2,CO.2ME	;MASSBUS ENABLE
	XCT	TAPCNO		;DO IT
	MOVSI	T2,(DO.XDT)	;DRIVE TYPE REGISTER
	PUSHJ	P,TAPDTO	;READ IT
	ANDI	T2,777		;KEEP JUST DRIVE TYPE
	CAIN	T2,TY.DXA	;DX20?
	JRST	DX2RS2		;YES
	MOVEI	T2,CO.XMI	;RESET THE RH TO CLEAR RAE
	XCT	TAPCNO		;DO IT
	CAIGE	T1,LSTICD/4	;GONE PAST THE END?
	AOJA	T1,DX2RS1	;TRY NEXT RH
	ERROR	(<No RH20 for DX20>)
DX2RS2:	DPB	T1,[POINT 7,DX2CSO,9] ;SET DEVICE CODE IN CONSO INSTRUCTION
	LSH	T1,2		;MAKE IT 9 BIT DEVICE CODE (I.E. 540)
	ADDI	T1,EPT-540	;COMPUTE ADDR OF 1ST WORD OF LOGOUT
	HRRM	T1,DX2.IC	;AREA AND SAVE FOR LATER
	PUSHJ	P,DX2CLE	;CLEAR RH20
	MOVSI	T2,(D2.STR)	;POINT AT STATUS REGISTER
	PUSHJ	P,TAPDTO	;READ IT
	TRNE	T2,D2.RUN	;MICROPROCESSOR RUNNING?
	JRST	DX2.R3		;YES, LEAVE IT RUNNING
	PUSHJ	P,MPRES		;RESET THE MICROPROCESSOR
	PUSHJ	P,LODX20	;LOAD THE MICROCODE
	PUSHJ	P,MPCHK		;CHECK MICROSTORE INTEGRITY
DX2.NR:	ERROR	(<Cannot start DX20>)
	PUSHJ	P,MPSTRT	;START THE DX20
	MOVSI	T2,(D2.STR)	;POINT AT STATUS REGISTER AGAIN
	PUSHJ	P,TAPDTO	;READ IT
	TRNN	T2,D2.RUN	;STILL RUNNING?
	JRST	DX2.NR		;NO, TELL USER
DX2.R3:	PUSHJ	P,DX2CLE	;CLEAR RH20 AGAIN
	MOVE	T2,TAPUNI	;GET UNIT NUMBER
	HRLI	T2,(D2.GP1!D2.LDR) ;POINT AT DRIVE NUMBER REGISTER
	XCT	TAPDTO		;SELECT THE DRIVE
	MOVE	T2,[D2.CTR!D2.LDR!D2.SNS] ;GET FORCED SENSE FUNCTION
	XCT	TAPDTO		;ISSUE THE COMMAND
	PUSHJ	P,DX2WAT	;WAIT FOR COMMAND TO COMPLETE
	PUSHJ	P,RDSNS		;READ SENSE BYTES INTO T2
	MOVEI	J,5		;ASSUME 9 TRACK WITH 5 FRAMES/WORD
	TRNE	T2,D2.7TK	;IS IT 7 TRACK?
	HRROI	J,6		;YES, MAKE IT 6 FRAMES/WORD
	POPJ	P,		;RETURN
;DX20 READ ROUTINE

DX2RED:	PUSHJ	P,DX2CLE	;CLEAR RH20
	PUSHJ	P,DX2STC	;SELECT DRIVE, DENSITY, MODE
	MOVNI	T2,LNMTBF	;-VE WORD COUNT
	IMULI	T2,(J)		;COMPUTE FRAME COUNT
	ANDI	T2,177777	;JUST 16 BITS WORTH
	HRLI	T2,(D2.FCR!D2.LDR) ;POINT AT FRAME COUNT REGISTER
	XCT	TAPDTO		;TELL THE HARDWARE
	MOVE	T1,TAPBFA	;PHYSICAL ADDRESS OF TAPE BUFFER
	TLO	T1,600000+<LNMTBF_4> ;SET TRA+LAST AND WORD COUNT
	MOVEM	T1,BOOTWD	;SAVE CCW
	SETZM	BOOTWD+1
	MOVE	T1,[200000,,BOOTWD] ;JUMP TO IOWD
DX2.IC:	MOVEM	T1,.		;SAVE IN LOGOUT AREA (ADDR PATCHED)
	MOVE	T2,[D2.SCR!D2.LDR!D2.RCP!D2.SCS!D2.DTE!177700!D2.RDF]
	XCT	TAPDTO		;START THE TRANSFER
	MOVEI	T2,CO.XDN	;GET DONE BIT
	PUSHJ	P,TWAIT		;WAIT FOR DONE TO COME UP
	  XCT	DX2CSO		;IN THE CONI WORD

DX2XFR:	PUSHJ	P,DX2CKE	;CHECK FOR ERRORS, RETURN DEVICE STATUS IN T3
	  JRST	DX2CLE		;FOUND ERROR, CLEAR THEM AND RETURN
	TRNE	T3,D2.UEX	;EOF?
	SETOM	EOF		;YES, TELL UPPER LEVEL
	TRNN	T3,D2.UCK	;UNIT CHECK?
	AOS	(P)		;NO, GIVE GOOD RETURN
	JRST	DX2CLE		;CLEAR ANY SOFT ERRORS AND RETURN
;ROUTINE TO START REWIND ON A DX20

DX2REW:	PUSHJ	P,DX2CLE	;CLEAR RH20
	PUSHJ	P,DX2STC	;SELECT DRIVE
	MOVE	T2,[D2.CTR!D2.LDR!D2.REW] ;GET REWIND OP
	XCT	TAPDTO		;START THE REWIND
	JRST	DX2WAT		;WAIT FOR COMPLETION AND RETURN


;SKIP RECORD

DX2SKR:	PUSHJ	P,DX2CLE	;CLEAR RH20
	PUSHJ	P,DX2STC	;SELECT DRIVE
	MOVE	T2,[D2.FCR!D2.LDR!177777] ;FRAME COUNT REGISTER TO -1
	XCT	TAPDTO		;SET IT
	MOVE	T2,[D2.CTR!D2.LDR!D2.SFR
		    D2.CTR!D2.LDR!D2.SBR](T4) ;GET APPROPRIATE OP
	XCT	TAPDTO		;START THE OPERATION
	PUSHJ	P,DX2WAT	;WAIT FOR COMPLETION
	PUSHJ	P,DX2XFR	;CHECK FOR ERRORS
	  JFCL			;DON'T CARE
	POPJ	P,		;RETURN


;ROUTINE TO CHECK FOR REWIND DONE ON A DX20

DX2CHK:	MOVSI	T2,(D2.GP0)	;POINT AT DEVICE STATUS REGISTER
	PUSHJ	P,TAPDTO	;READ IT
	MOVEI	T3,(T2)		;SAVE FOR LATER TEST
	PUSHJ	P,DX2CLR	;CLEAR RH20/DX20
	TRNE	T3,D2.DVE	;ALREADY DONE REWINDING?
	POPJ	P,		;YES, RETURN
DX2CK1:	MOVSI	T2,(D2.GP4)	;POINT AT ASYNC STATUS REGISTER
	PUSHJ	P,TAPDTO	;READ IT
	JUMPE	T2,DX2CK1	;WAIT FOR IT TO SET
	ANDI	T2,377		;ISOLATE JUST THE DRIVE NUMBER
	CAME	T2,TAPUNI	;BETTER BE THE ONE WE WANT
	ERROR	(<Wrong drive interrupted>)
	POPJ	P,		;RETURN


;ROUTINE TO WAIT FOR A NON-DATA TRANSFER OPERATION TO COMPLETE.

DX2WAT:	MOVEI	T2,D2.ATN	;GET ATTENTION BIT IN CONI
	PUSHJ	P,TWAIT		;WAIT FOR IT TO COME UP
DX2CSO:	  CONSO	0,(T2)		;BY DOING A CONSO
	POPJ	P,		;IT DID, RETURN
;ROUTINE TO CLEAR ALL ERROR ASSOCIATED WITH THE DX20 AND RH20

DX2CLE:	PUSHJ	P,DX2CLR	;CLEAR RH20/DX20
	MOVSI	T2,(D2.GP4!D2.LDR) ;GET BITS TO CLEAR ASYNCHRONOUS STATUS
	XCT	TAPDTO		;REGISTER
	POPJ	P,		;RETURN

DX2CLR:	MOVEI	T2,D2.CLR!CO.2ME ;CLEAR RH20 AND ENABLE MASSBUS
	XCT	TAPCNO		;DO SO
	MOVE	T2,[D2.ASR!D2.LDR!177] ;SETUP TO CLEAR ATTENTIONS
	XCT	TAPDTO		;DO SO
	MOVSI	T2,(D2.ERR!D2.LDR) ;GET BITS TO CLEAR ERROR REGISTER
	XCT	TAPDTO		;DO SO
	POPJ	P,		;AND RETURN


;ROUTINE TO READ SENSE BYTES 0 AND 1 FOR A DRIVE INTO T2.

RDSNS:	PUSHJ	P,TWAIT		;WAIT FOR DX20 TO UPDATE SENSE BYTES
	  PUSHJ P,[MOVSI T2,(D2.GP0) ;BY READING EXTENDED STATUS
		   PUSHJ P,TAPDTO ;REGISTER AND WAITING
		   TRNN  T2,D2.RST   ;FOR REQUEST STATUS BIT TO
		   AOS   (P)	     ;CLEAR
		   POPJ  P,]
	MOVSI	T2,(D2.GP6)	;POINT AT EXTENDED STATUS REGISTER
	JRST	TAPDTO		;READ BYTES 0 AND 1 AND RETURN


;ROUTINE TO SETUP DRIVE NUMBER, DENSITY, AND MODE FOR A DX20

DX2STC:	MOVE	T2,TAPUNI	;GET UNIT NUMBER
	SKIPLE	T3,TAPDEN	;IF DENSITY <=0,
	CAILE	T3,D2.DTM	;  OR > MAX,
	MOVEI	T3,0		;  USE DEFAULT
	MOVE	T3,D2.DTB(T3)	;GET TABLE ENTRY FOR THIS DENSITY
	SKIPGE	J		;IF A 7 TRACK DRIVE,
	MOVSS	T3		;  USE LH OF ENTRY
	TRO	T2,(T3)		;SET MODE AND DENSITY
	HRLI	T2,(D2.GP1!D2.LDR) ;POINT AT CORRECT REGISTER
	XCT	TAPDTO		;TELL THE DX20
	POPJ	P,		;AND RETURN

;DENSITY/MODE TABLE FOR DX20'S.  LH IS FOR 7 TRACK, RH IS FOR 9 TRACK.

D2.DTB:	XWD	<3B23+3B27>,<1B23+13B27> ;DEFAULT 7TK=800, 9TK=800
	XWD	<3B23+1B27>,<1B23+13B27> ;200 BPI 7TK=200, 9TK=800
	XWD	<3B23+2B27>,<1B23+13B27> ;556 BPI 7TK=556, 9TK=800
	XWD	<3B23+3B27>,<1B23+13B27> ;800 BPI 7TK=800, 9TK=800
	XWD	<3B23+3B27>,<1B23+14B27> ;1600 BPI 7TK=800, 9TK=1600
D2.DTM==.-D2.DTB-1
;ROUTINE TO CHECK FOR ERRORS AFTER A DX20 OPERATION. RETURNS
;CPOPJ IF ERROR DETECTED, CPOPJ1 IF NONE, DIES IF REALLY BAD ERROR.
;RETURNS DEVICE STATUS BYTE IN T3

DX2CKE:	MOVSI	T2,(D2.GP0)	;POINT AT DEVICE STATUS REGISTER
	PUSHJ	P,TAPDTO	;READ IT
	MOVEI	T3,(T2)		;MOVE TO WHERE CALLER EXPECTS IT
	MOVSI	T2,(D2.STR)	;POINT AT STATUS REGISTER
	PUSHJ	P,TAPDTO	;READ IT
	TRNN	T2,D2.CER	;COMPOSITE ERROR UP?
	JRST	CPOPJ1		;NO, RETURN SUCCESS
	MOVSI	T2,(D2.ERR)	;POINT AT ERROR REGISTER
	PUSHJ	P,TAPDTO	;READ IT
	TRNE	T2,D2.HER	;ANY REALLY BAD ERRORS?
DX2CHE:	ERROR	(<Hard DX20 error>)
	LDB	T2,[POINT 4,T2,27] ;GET ERROR CODE
	JRST	DX2ETB(T2)	;DISPATCH BASED ON ERROR CODE

;ERROR DISPATCH TABLE BASED ON ERROR CODE

DX2ETB:	JRST	DX2CHE		;0 - UNKNOWN ERROR
	JRST	CPOPJ1		;1 - UNUSUAL DEVICE STATUS
	JRST	CPOPJ1		;2 - SHORT RECORD
	POPJ	P,		;3 - LONG RECORD
	JRST	DX2CHE		;4 - DRIVE SELECTION ERROR
	POPJ	P,		;5 - PARITY ERROR
	POPJ	P,		;6 - RECOVERABLE ERROR
	JRST	DX2CHE		;7 - NON-RECOVERABLE ERROR
	JRST	DX2CHE		;10- FATAL ERROR
;ROUTINE TO START THE DX20 MICROPROCESSOR.

MPSTRT:	PUSHJ	P,MPRES		;RESET THE MICROPROCESSOR
	MOVE	T2,[D2.DR1!D2.LDR!D2.IRE!D2.PCE!D2.PCI!D2.SAD] ;SET BITS
	XCT	TAPDTO		;TELL DX20 IT'S START ADDRESS
	MOVE	T2,[D2.MTR!D2.LDR!D2.SMP] ;GET START BIT
	XCT	TAPDTO		;START THE DX20
	POPJ	P,		;AND RETURN


;ROUTINE TO RESET THE DX20

MPRES:	MOVE	T2,[D2.MTR!D2.LDR!D2.RES] ;GET RESET BIT
	XCT	TAPDTO		;RESET THE DX20
	POPJ	P,		;AND RETURN


;ROUTINE TO CHECK THE VALIDITY OF THE DX20 CONTROL STORE.
;NON-SKIP RETURN IF BAD.

MPCHK:	MOVE	T2,[D2.DR1!D2.LDR!D2.IRE!D2.PCE!D2.PCI!7] ;GET PC TO READ
	XCT	TAPDTO		;TELL THE DX20
	MOVSI	T2,(D2.DR0)	;POINT AT DIAGNOSTIC REGISTER 0
	PUSHJ	P,TAPDTO	;READ THE CONTENTS
	PUSH	P,T2		;SAVE FOR COMPARE
	MOVSI	T2,(DO.XDT)	;POINT AT DRIVE TYPE REGISTER
	PUSHJ	P,TAPDTO	;READ THAT
	POP	P,T3		;RESTORE CRAM LOCATION 7
	CAME	T2,T3		;HAVE TO BE THE SAME
	  POPJ	P,		;ERROR IF NOT
	MOVSI	T2,(D2.DR7)	;POINT AT DIAGNOSTIC REGISTER 7
	PUSHJ	P,TAPDTO	;READ IT
	TRNE	T2,D2.IRP	;IR PARITY ERROR ON LAST READ?
	  POPJ	P,		;YES, THAT'S AN ERROR
	MOVSI	T2,(D2.DR0)	;POINT AT DIAGNOSTIC REGISTER 0 AGAIN
	PUSHJ	P,TAPDTO	;READ CRAM LOC 10 (PC AUTO INCR SET)
	CAIE	T2,D2.C10	;MUST BE THIS VALUE
	  POPJ	P,		;NOT, ERROR
	MOVSI	T2,(D2.DR7)	;POINT AT DIAGNOSTIC REGISTER 7
	PUSHJ	P,TAPDTO	;READ IT
	TRNE	T2,D2.IRP	;IR PARITY ERROR ON LAST READ?
	  POPJ	P,		;YES, ERROR
	MOVSI	T2,(D2.DR0)	;POINT AT DIAGNOSTIC REGISTER 0 ONCE MORE
	PUSHJ	P,TAPDTO	;READ CRAM LOCATION 11
	CAIE	T2,D2.C11	;MUST BE THIS VALUE
	  POPJ	P,		;NOT, ERROR
	MOVSI	T2,(D2.DR7)	;POINT AT DIAGNOSTIC REGISTER 7
	PUSHJ	P,TAPDTO	;READ IT
	TRNN	T2,D2.IRP	;IR PARITY ERROR ON LAST READ?
	  AOS	(P)		;NO, GIVE SKIP RETURN
	POPJ	P,		;   AND RETURN
;ROUTINE TO LOAD THE DX20 MICROCODE.
;CALL:	PUSHJ	P,LODX20
;DOESN'T RETURN IF MICROCODE NOT PRESENT IN BOOT
;RETURN+1 IF MICROCODE LOADED

LODX20:	PUSHJ	P,SAVE2		;FREE UP P1 AND P2
	DMOVE	P1,BTSVEC+.BTUCD+.BTTX2 ;GET POINTERS TO DX20 MICROCODE
	SKIPN	P1		;MICROCODE PRESENT?
	ERROR	(<DX20 microcode not present>)
	ADDI	P2,BTSVEC+1	;CHANGE OFFSET INTO ADDRESS, SKIP VERSION WORD
	HRLI	P2,(POINT 18)	;MAKE AN 18-BIT BYTE POINTER
	SETZ	P1,		;CURRENT ADDRESS
LDX201:	MOVE	T2,P1		;GET ADDRESS
	PUSHJ	P,PRECR		;SET UP PC FOR CRAM
	ILDB	T2,P2		;GET NEXT BYTE
	CAIN	P1,MAGICA	;MAGIC ADDRESS?
	MOVEI	T2,MAGICV	;YES
	TLO	T2,(D2.DR0)	;SELECT IR
	PUSHJ	P,WTREG		;LOAD CRAM FROM IR
	CAIGE	P1,3777		;DONE ALL OF CRAM?
	AOJA	P1,LDX201	;NO

	MOVE	T2,[D2.DR1+D2.IRE+D2.PCE] ;PC=0, SET FLAGS
	PUSHJ	P,WTREG		;SET PC
	MOVSI	T2,(D2.DR0)	;SELECT IR
	PUSHJ	P,RDREG		;READ IR FROM CRAM, PC=0
	PUSH	P,T2		;SAVE LOCATION 0
	MOVE	P2,BTSVEC+.BTUCD+.BTTX2+1 ;GET OFFSET TO MICROCODE
	ADDI	P2,BTSVEC+2000+1 ;CHANGE OFFSET TO ADDRESS, SKIP CRAM & VRSN WD
	HRLI	P2,(POINT 8)	;BUILD A BYTE POINTER
	SETZ	P1,		;ADDRESS OF ZERO
LDX202:	MOVE	T2,P1		;GET ADDRESS
	PUSHJ	P,PREWM		;SET UP MA TO LOAD DRAM
	ILDB	T1,P2		;GET NEXT BYTE
	TRO	T1,11400	;MAKE MICROINSTR. (MOVEI MEM MA+1)
	PUSHJ	P,XI		;EXECUTE IT
	CAIGE	P1,1777		;DONE ALL?
	AOJA	P1,LDX202	;NO

	MOVE	T2,[D2.DR1+D2.PCE+D2.MSE] ;SELECT PC, PC=0
	PUSHJ	P,WTREG		;SET PC
	POP	P,T2		;GET SAVED LOCATION 0
	TLO	T2,(D2.DR0)	;SELECT IR
	PUSHJ	P,WTREG		;WRITE CRAM FROM IR
	MOVEI	T1,[ASCIZ /[TX02 microcode %/]
	PUSHJ	P,PRMSG		;PRINT MESSAGE
	MOVE	T1,BTSVEC+.BTUCD+.BTTX2+1 ;GET OFFSET TO MICROCODE
	MOVE	T1,BTSVEC(T1)	;GET VERSION WORD
	PUSHJ	P,PRVRSN	;PRINT IT
	MOVEI	T1,[ASCIZ / loaded on RH20 /]
	PUSHJ	P,PRMSG		;MORE NOISE
	LDB	T1,[POINT 7,TAPDTO,9] ;PICK UP DEVICE CODE
	LSH	T1,2		;MAKE IT UNDERSTANDABLE
	PUSHJ	P,PROCT		;PRINT IT
	MOVEI	T1,[ASCIZ /, DX20 0/]
	PUSHJ	P,PRMSG		;MAKE IT LOOK LIKE USUAL BOOT MESSAGE
	PUSHJ	P,PRRBKT	;PRINT RIGHT BRACKET
	PJRST	PRCRLF		;PRINT CRLF AND RETURN
;PREWM - SETS UP THE LOAD ADDR. FOR WORKING MEMORY
;ALSO, SAVES LOC. 0 OF CRAM FOR MICROINSTR. EXECUTION
;CALL:	T2/LOAD ADDR
;	PUSHJ	P,PREWM
;RETURN+1 ALWAYS

PREWM:	PUSH	P,T2		;SAVE LOAD ADDR
	MOVE	T1,T2		;GET LOAD ADDR.
	ANDI	T1,377		;MAX. ADDR. 256
	TRO	T1,1000		;MAKE MICROINTR. (MOVEI LOAD MA)
	PUSHJ	P,XI		;SET MA REGISTER
	POP	P,T1		;GET LOAD ADDR AGAIN
	LSH	T1,-^D8		;KEEP 2 MAEX BITS
	TRO	T1,400		;MAKE MICROINTR. (MOVEI LOAD MAEX)
	JRST	XI		;SET MAEX BITS AND RETURN


;PRECR - SETS UP PC FOR LOADING OR VERIFYING CRAM
;CALL:	MOVE	T2,LOAD ADDR
;	PUSHJ	P,PRECR
;RETURN+1 ALWAYS

PRECR:	ANDI	T2,7777		;MAKE SURE 12 BITS PC
	TRO	T2,D2.MSE+D2.PCE+D2.PCI ;SET BITS
	TLO	T2,(D2.DR1)	;SELECT PC
	JRST	WTREG		;WRITE PC AND RETURN

;XI - EXECUTE INSTR. IN T1
;CALL:	MOVE	T1/INSTR
;	PUSHJ	P,XI
;RETURN+1 ALWAYS
;CHANGES T2,T3,&T4
;PRESERVES T1

XI:	MOVE	T2,[D2.MTR+D2.SCY] ;SELECT MAINT. REG., CLEAR START & SET SINGLE CYCLE
	PUSHJ	P,WTREG		;STOP MICROPROCESSOR
	MOVE	T2,[D2.DR1+D2.PCE+D2.MSE] ;CLEAR PC AND SET BITS
	PUSHJ	P,WTREG		;DO IT
	MOVE	T2,T1		; AND LOAD IT IN LOC. 0, ALSO
	TLO	T2,(D2.DR0)
	PUSHJ	P,WTREG		;
	MOVE	T2,[D2.DR1+D2.IRE+D2.PCI] ;SET D2.IRE & D2.PCI BIT
	PUSHJ	P,WTREG		;PC HAS 0
	MOVE	T2,[D2.MTR+D2.SCY+D2.SMP] ;SET SINGLE STEP & START BITS
	PUSHJ	P,WTREG		;GO START MICROCONTROLLER
	MOVE	T2,[D2.MTR+D2.SCY] ;CLEAR START BIT
	JRST	WTREG		;DO IT AND RETURN
;WTREG - WRITES INTERNAL OR EXTERNAL REGISTER
;CALL:	T2/ REGISTER SELECT NUMBER AND CONTENTS TO WRITE
;	PUSHJ	P,WTREG
;RETURN+1 ALWAYS	
;DESTROYS T2

WTREG:	TLO	T2,(D2.DLR)	;SET LR LOAD	
	JUMPL	T2,WTREG1	;JUMP IF INTERNAL REG.
	TLO	T2,<(D2.DRE)>	;SET DRAES BIT & DRIVE NUMBER
				;DO.EP BIT 0 ALREADY
WTREG1:	XCT	TAPDTO		;WRITE IT
	POPJ	P,		;JUST RETURN


;RDREG - READS INTERNAL OR EXTERNAL REGISTER
;CALL:	MOVE	T3,REGISTER NUMBER
;	PUSHJ	P,RDREG
;RETURN1: ALWAYS
;T2 GETS VALUE

RDREG:	SETZ	T2,		;CLEAR THEM
	JUMPL	T2,TAPDTO	;JUMP ,IF INTERNAL
	TLO	T2,<(D2.DRE)>	;SET DRAES BIT & DRIVE NUMBER
				;DO.EP BIT 0 ALREADY
	PJRST	TAPDTO		;SET PREPARATION REGISTER, READ IT AND RETURN
>; END IFN FTDX20
	SUBTTL	TM78 ROUTINES


IFN FTTM78,<

;FIND AND RESET CONTROLLER, FILL IN CONX/DATAX INSTRUCTIONS

T78RES:	MOVEI	T1,FSTICD/4	;START AT RH 0
T78RS1:	DPB	T1,[POINT 7,TAPCNO,9]
	DPB	T1,[POINT 7,TAPDTO,9]
	DPB	T1,[POINT 7,TAPDTI,9]
	MOVEI	T2,CO.2ME	;MASSBUS ENABLE
	XCT	TAPCNO		;DO IT
	LDB	U,[POINT 3,TAPUNI,32] ;UNIT  (RH) NUMBER
	MOVSI	T2,<(DO.XDT)>(U) ;DATAO DRIVE-TYPE REGISTER
	PUSHJ	P,TAPDTO	;READ DRIVE TYPE
	ANDI	T2,777
	CAIN	T2,TY.T78	;TM78?
	JRST	T78RS2		;YES
	MOVEI	T2,CO.XMI	;RESET THE RH TO CLEAR RAE
	XCT	TAPCNO
	CAIGE	T1,LSTICD/4	;GONE PAST THE END?
	AOJA	T1,T78RS1	;TRY NEXT RH
	ERROR	(<No RH20 for TM78>)
T78RS2:	DPB	T1,[POINT 7,T78CSO,9]
	MOVEI	T2,7		;ISOLATE SLAVE NUMBER
	ANDB	T2,TAPUNI
	ADDI	T2,.T7DV0	;GET HDWRE UNIT-REGISTER (14=DRIVE 0, 15= DRV 1, ETC)
	LSH	T2,^D12		;POSITION IT TO DRIVE FIELD IN RH
	HRLS	U
	TLO	U,(T2)		;U=SLAVE-REGISTER+UNIT,,UNIT
	LSH	T1,2		;CONTROLLER (RH)
	ADDI	T1,EPT-540	;0 FOR RH0, 4 FOR RH1, ...
	HRRM	T1,T78.IC	;SAVE ICCW ADDRESS
	MOVE	T2,[T7.TMS+T7.DLR+T7.TMC]
	TLO	T2,(U)		;CLEAR TM78
	XCT	TAPDTO
	MOVEI	T1,40000
T78RS3:	MOVSI	T2,<(T7.TMS)>(U) ;READ STATUS REGISTER
	PUSHJ	P,TAPDTO
	TRNN	T2,T7.TMR	;WAIT FOR READY TO COME UP
	SOJG	T1,T78RS3
	JUMPG	T1,CPOPJ
	ERROR	(<TM78 won't start>)
;READ ROUTINE

T78RED:	MOVEI	T2,515410	;CLEAR ALL ERROR BITS
	XCT	TAPCNO
	LDB	T2,[POINT 4,U,5] ;GET SLAVE NUMBER + OFFSET
	SUBI	T2,.T7DV0	;CONVERT TO REAL NUMBER
	TDO	T2,[T7.FMT+T7.DLR+130004] ;CORE DUMP/SER/1 RECORD
	TLO	T2,(U)		;ADD UNIT, SLAVE
	XCT	TAPDTO		;TELL THE HARDWARE
	MOVEI	T2,LNMTBF*5	;BYTE COUNT
	HRLI	T2,<(T7.BCT+T7.DLR)>(U) ;WRITE BYTE COUNT REGISTER
	XCT	TAPDTO		;TELL THE HARDWARE
	MOVE	T1,TAPBFA	;PHYSICAL ADDRESS OF TAPE BUFFER
	TLO	T1,600000+<LNMTBF_4> ;SET TRA+LAST AND WORD COUNT
	MOVEM	T1,BOOTWD	;SAVE CCW
	SETZM	BOOTWD+1
	MOVE	T1,[200000,,BOOTWD] ;JUMP TO IOWD
T78.IC:	MOVEM	T1,.		;STORE INITIAL JUMP (ADDR PATCHED)
	MOVE	T2,[716600,,177700!T7.FRD]
	TLO	T2,(U)		;ADD THE UNIT NUMBER
	XCT	TAPDTO		;START THE READ
	PUSHJ	P,TWAIT		;WAIT FOR COMPLETION
T78CSO:	  CONSO	.-.,CI.XDN
	MOVSI	T2,<(T7.ICD)>(U) ;READ INTERRUPT CODE
	PUSHJ	P,TAPDTO
	ANDI	T2,37		;JUST THE CODE
	CAIE	T2,.T7DCD
	CAIN	T2,.T7SCD	;OK?
	JRST	T78RD4		;YES
	CAIE	T2,.T7EOF
	JRST	T78RD5		;ERROR
	SETOM	EOF		;EOF
T78RD4:	AOS	(P)
T78RD5:	MOVEI	T2,5410
	XCT	TAPCNO		;CLEAR DONE, ERRORS
	POPJ	P,		;AND RETURN
;TM78 REWIND ROUTINE

T78REW:	MOVEI	T2,T7.FRW	;FUNCTION
	PJRST	T78NDO		;DO IT AND RETURN WHEN STARTED


;SKIP RECORD

T78SKR:	MOVE	T2,[400+T7.FSR
		    400+T7.FBR](T4) ;FUNCTION
	PUSHJ	P,T78NDO	;DO IT
	MOVSI	T2,<(T7.NIC)>(U) ;READ THE STATUS REGISTER
	PUSHJ	P,TAPDTO
	ANDI	T2,37		;JUST THE CODE
	CAIN	T2,.T7EOF	;EOF?
	SETOM	EOF		;YES
	POPJ	P,


;WAIT FOR REWIND TO COMPLETE

T78CHK:	MOVEI	T2,T7.FSN	;SENSE
	PUSHJ	P,T78NDO
;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 MUST
;	BE REWINDING!
	JUMPE	T1,T78CHK
	POPJ	P,


;ROUTINE TO DO A NON-DATA OPERATION TO A TU78
;ENTER T2=FUNCTION, U=DRIVE+UNIT,,UNIT

T78NDO:	HLL	T2,U		;SLAVE REGISTER + RH UNIT NUMBER
	TLO	T2,(T7.DLR)	;TELL THE HARDWARE TO WRITE THE REGISTER
	XCT	TAPDTO		;DO THE FUNCTION
	MOVEI	T1,20000	;HOW LONG TO WAIT FOR COMPLETION
T78ND1:	MOVSI	T2,(T7.ATR)
	PUSHJ	P,TAPDTO	;READ THE ATTENTION SUMMARY REGISTER
	TRNN	T2,377		;ATTENTION UP?
	SOJG	T1,T78ND1
	JUMPE	T1,CPOPJ	;GO AWAY IF TIMED OUT
	MOVE	T2,[T7.ATR!T7.DLR+377] ;FINISHED. CLEAR THE ATTENTION
	XCT	TAPDTO
	POPJ	P,
>; END IFN FTTM78
	SUBTTL	MAGTAPE DRIVER DATA STORAGE AND LITERALS

TAPBUF:	BLOCK	LNMTBF		;THE BUFFER FOR BACKUP'ING INTO
TAPBFA:	BLOCK	1		;PHYSICAL ADDRESS OF ABOVE
EOF:	BLOCK	1		;END OF FILE FLAG
SAVDEV:	BLOCK	1		;SAVED DEV
IFN FTDX10,<
CHPRG:	BLOCK	4		;PLACE FOR CHANNEL PROGRAM
CHPRGA:	BLOCK	1		;PHYSICAL ADDRESS OF ABOVE
CHSNS:	BLOCK	12		;PLACE FOR EXTENDED STATUS
CHSNSA:	BLOCK	1		;PHYSICAL ADDRESS OF ABOVE
TX.MOD:	BLOCK	1		;MODE WORD
>; END IFN FTDX10

TAPLIT:	LIT
TAPEND==.-1			;THE END OF THE MAGTAPE CODE
>; END IFN FTTAPE
	SUBTTL	THE END


BTSEND:	END	LOADER