Google
 

Trailing-Edge - PDP-10 Archives - BB-4170G-SM - sources/kdpsrv.mac
There are 20 other files named kdpsrv.mac in the archive. Click here to see a list.
;<3A.MONITOR>KDPSRV.MAC.29,  9-Aug-78 10:16:56, Edit by KIRSCHEN
;LINE ID NEED NOT BE ASCIZ IN BTCLI
;<3A.MONITOR>KDPSRV.MAC.28, 20-Jun-78 12:39:20, Edit by MCCLURE
; Handle DTR whenn initiating or terminating protocol
;<3A.MONITOR>KDPSRV.MAC.27, 30-May-78 11:44:01, Edit by MCCLURE
; Only report dataset off transitions
;<3A.MONITOR>KDPSRV.MAC.26, 22-May-78 11:43:01, Edit by MCCLURE
; Fix don't shuffle in retransmitted
;<3A.MONITOR>KDPSRV.MAC.25, 18-May-78 09:50:29, Edit by MCCLURE
; Convert DUP to KDP
;<3.SM10-RELEASE-3>DUPSRV.MAC.24, 10-May-78 15:24:33, Edit by MCCLURE
; FIX BTIPR FOR .VNDDC
;<3.SM10-RELEASE-3>DUPSRV.MAC.22,  5-May-78 00:10:14, Edit by MCCLURE
; Fix .VNCNL & .VNCBL
;<3.SM10-RELEASE-3>DUPSRV.MAC.21,  1-May-78 12:57:24, Edit by MCCLURE
;<3A.MONITOR>DUPSRV.MAC.20, 11-Apr-78 15:53:00, Edit by MCCLURE
; Clear PGDLMX in DEDLIN
;<3A.MONITOR>DUPSRV.MAC.19,  6-Apr-78 16:23:44, Edit by MCCLURE
; Add new COMIOP u-code
;<3A.MONITOR>DUPSRV.MAC.18, 29-Mar-78 14:09:57, Edit by MCCLURE
; Have BTCLI and BTCPN believe KDP_0_#
;<3A.MONITOR>DUPSRV.MAC.17, 28-Mar-78 10:54:15, Edit by MCCLURE
;<3A.MONITOR>DUPSRV.MAC.16, 23-Mar-78 16:41:48, Edit by MCCLURE
; ADD THINGS WHICH GOT DROPPED
;<3A.MONITOR>DUPSRV.MAC.15, 15-Mar-78 12:20:42, Edit by MCCLURE
;<3A.MONITOR>DUPSRV.MAC.14,  9-Mar-78 11:08:40, Edit by MCCLURE
; ADD BTIPR, BTTPR, BTSTS, BTRLC, BTCLI, BTCPN
;<3A.MONITOR>DUPSRV.MAC.13,  3-Feb-78 03:38:55, Edit by MCCLURE
;<3A.MONITOR>DUPSRV.MAC.12, 31-Jan-78 03:09:20, Edit by MCCLURE
;<3A.MONITOR>DUPSRV.MAC.11, 29-Jan-78 16:36:30, Edit by MCCLURE
;<3.SM10-RELEASE-3>DUPSRV.MAC.9, 13-Jan-78 01:10:52, EDIT BY MCCLURE
;<3.SM10-RELEASE-3>DUPSRV.MAC.8, 12-Jan-78 17:27:05, EDIT BY MCCLURE
;<3.SM10-RELEASE-3>DUPSRV.MAC.7, 11-Jan-78 05:13:34, EDIT BY MCCLURE
;<3.SM10-RELEASE-3>DUPSRV.MAC.6,  3-Jan-78 10:14:36, EDIT BY MCCLURE
;<3.SM10-RELEASE-3>DUPSRV.MAC.5, 23-Dec-77 05:41:33, EDIT BY MCCLURE
;<3.SM10-RELEASE-3>DUPSRV.MAC.4, 22-Dec-77 02:56:16, EDIT BY MCCLURE
;<3.SM10-RELEASE-3>DUPSRV.MAC.3, 15-Dec-77 23:26:42, EDIT BY MCCLURE
;<3.SM10-RELEASE-3>DUPSRV.MAC.2, 14-Dec-77 09:55:45, EDIT BY MCCLURE
;<3.SM10-RELEASE-3>DUPSRV.MAC.1,  6-Dec-77 20:44:59, EDIT BY MCCLURE
;10-August-1977 DMCC

	SEARCH PROLOG,PROKS
	TTITLE KDPSRV

	EXTN <DEDMCB>
	EXTN <KDPLIM,KDPNLN,KDPN,KDPPAG,KDPTIM,KDPXPC>
	EXTN <KMCACS,KMCINQ,KMCIPL,KDPFLG,KMCPAG,KMCQLN>
	EXTN <NODINI,NSPQ,NSPSPC>

;THIS MODULE PROVIDES SUPPORT FOR DUP11'S WITH A KMC11 FOR NSPSRV ON A 2020

;THINGS TO CHECK
; 1) ERROR COUNTERS - SYSERR
; 2) COLLAPSE PAGES
	IFNDEF FTRACE,<FTRACE==-1>	;NONZERO TO TURN ON TRACE
;               TABLE OF CONTENTS FOR KDPSRV
;
;
;                        SECTION                                   PAGE
;    1. DEFINITIONS
;         1.1   STG...............................................   4
;         1.2   KMC11.............................................   5
;         1.3   DUP11.............................................   7
;         1.4   DDCMP.............................................   8
;    2. PROTOTYPE MESSAGES........................................   9
;    3. DUP11 COMIOP CODE FOR KMC11...............................  10
;    4. BOOT JSYS
;         4.1   PERFORM BOOTSTRAP FUNCTIONS FOR KMC11.............  11
;         4.2   SEND MOP MESSAGE..................................  13
;         4.3   INITIATE PROTOCOL.................................  14
;         4.4   TERMINATE PROTOCOL................................  15
;         4.5   RETURN PROTOCOL STATUS............................  16
;         4.6   RECEIVE MOP MESSAGE...............................  17
;         4.7   LOAD KMC11........................................  18
;         4.8   DUMP THE KMC11....................................  23
;         4.9   RETURN LINE COUNTERS..............................  25
;         4.10  CONVERT LINE-ID TO PORT NUMBER....................  26
;         4.11  CONVERT PORT NUMBER TO LINE-ID....................  27
;    5. HERE TO INITIALIZE THE KMC11..............................  28
;    6. KMC11 INTERRUPT LEVEL SERVICE.............................  32
;    7. DDCMP RECEIVER
;         7.1   DATA MESSAGE......................................  34
;         7.2   CONTROL MESSAGE...................................  35
;         7.3   ACK MESSAGE.......................................  36
;         7.4   NAK MESSAGE.......................................  38
;         7.5   REP MESSAGE.......................................  39
;         7.6   START MESSAGE.....................................  40
;         7.7   STACK MESSAGE.....................................  41
;         7.8   JUNK MESSAGE......................................  42
;    8. DDCMP TRANSMIT DONE.......................................  43
;    9. KMC11 CONTROL OUT INTERRUPT...............................  44
;   10. HERE FROM NSPSRV WITH OUTPUT MESSAGES.....................  45
;   11. HERE ONCE A SECOND TO CHECK THINGS........................  46
;   12. DDCMP TRANSMITTER
;        12.1   DATA MESSAGES.....................................  47
;        12.2   REP MESSAGE.......................................  48
;        12.3   ACK MESSAGE.......................................  49
;        12.4   NAK MESSAGE.......................................  50
;        12.5   CONTROL MESSAGE...................................  51
;        12.6   DATA MESSAGES.....................................  52
;   13. HERE TO ENABLE RECEIVER...................................  53
; P1 FOR LINE SPECIFIC CODE WILL CONTAIN THE ADDRESS OF THE LINES PAGE

; MESSAGE BLOCKS LIVE IN BLOCKS OF RESIDENT SPACE
	BLKSIZ=<MBKFRE*10>+1		;SIZE OF BLOCKS IN RESIDENT SPACE
;FORMAT OF EACH MESSAGE BLOCK
	MBKLNK==0	;LH = ADR OF NEXT MESSAGE BLOCK
			; RH = ADR OF MESSAGE
	MBKCOD==1	;DRIVER UNIQUE CODE
	MBKLEN==2	;LH IS DRIVER INT LOC
			; RH IS LENGTH OF MESSAGE IN BYTES
	;FOLLOWING VALID ONLY FOR LAST MSG BLOCK IN BLOCK
	MBKFRE==3	;LH = NUMBER OF FREE WORDS LEFT IN BLOCK
			; RH = ADR OF BLOCK

;KMCINQ - QUEUE OF MESSAGE TO BE GIVEN TO THE KMC11
; FIRST WORD IS USED TO PUT THINGS INTO THE QUEUE
; 2ND WORD IS USED TO TAKE ENTRIES FROM QUEUE
; QUEUE ENTRIES ARE 2 WORDS LONG
; RH OF 1ST WORD GOES TO BSEL2
; LH OF 2ND WORD GOES TO BSEL4
; RH OF 2ND WORD GOES TO BSEL6
	SUBTTL	DEFINITIONS -- STG

DEFINE X (A,B)<
A==Z
Z=Z+B
>
Z=0

;PAGE OFFSETS
X PGUBAD,1	;LH IS UNIBUS ADR OF PAGE
X PGDSTS,1	;DDCMP STATUS
    DEFSTR (DDSTA,PGDSTS(P1),35,3) ;DDCMP STATE
	STADWN==0		;KMC11 NOT RUNNING
	STAMAI==1		;MAINT MODE
	STASTR==2		;SENDING STARTS
	STASTK==3		;SENT STACK
	STARUN==4		;RUNNING
    DEFSTR (DDTIM,PGDSTS(P1),32,7)	;TIMER
	TIMSTR==5	;5 SECONDS BETWEEN STARTS
	TIMREP==3	;3 SECONDS BETWEEN REPS
	REPMAX==200	;MAXIMUM NUMBER OF REPS BEFORE DECLARING LINE DOWN
	DUPDSR==1B14		;DATASET READY
    DEFSTR (DDXAK,PGDSTS(P1),13,1)	;WANT TO SEND AN ACK
    DEFSTR (DDNCD,PGDSTS(P1),12,3)	;NAK CODE TO SEND
    DEFSTR (DDXRP,PGDSTS(P1),9,1)	;WANT TO SEND A REP
    DEFSTR (DCHNG,PGDSTS(P1),8,2)	;INFORMATION FOR NSPSRV (SWAPPABLE)
	DDUP==1		;DDCMP NOW UP
	DDOWN==2	;DDCMP DOWN
X PGDOMQ,1	;DDCMP OUTPUT MESSAGE QUEUE
		; LH IS ADR OF FIRST OUTPUT MESSAGE BLOCK
		; RH IS ADR OF LAST OUTPUT MESSAGE BLOCK
X PGDLMX,1	;RH IS ADR OF MESSAGE BLOCK FOR LAST MESSAGE TRANSMITTED
X PGFCOR,1	;RH & LH ARE ADR OF CORE BLOCKS FOR MESSAGE QUEUE
		;LH ASSIGNED FIRST, RH USED FIRST
X PGDMNM,1	;DDCMP MESSAGE NUMBERS
    DEFSTR (DDRMN,PGDMNM(P1),7,8)	;RECEIVED MESSAGE NUMBER (HIGHEST)
    DEFSTR (DDHXM,PGDMNM(P1),15,8)	;HIGHEST MESSAGE NUMBER TRANSMITTED
    DEFSTR (DDHMA,PGDMNM(P1),23,8)	;HIGHEST MESSAGE NUMBER ACKED
    DEFSTR (DDREPC,PGDMNM(P1),35,12)	;COUNTER FOR REPS
X PGKDPN,1	;DUP11 LINE NUMBER
X PGUBAM,1	;ADR OF UBA MAPPING REGISTER FOR PAGE
X PGZTIM,1	;TIME LAST ZEROED COUNTERS, TICKED ONCE PER SECOND
X PGCOCN,10	;CONTROL OUT COUNTS AS FOLLOWS
		;10 = INVALID DDCMP HEADER
		;12 = BAD CRC
		;14 = BUFFER NOT AVAILABLE
		;16 = DATASET READY TRANSITION
		;20 = NXM
		;22 = TRANSMIT UNDERRUN
		;24 = RECEIVER UNDERRUN
		;26 = KILL COMPLETE
X PGCOXX,1	;OTHER
X PGXMCN,1	;COUNT OF DDCMP MESSAGES TRANSMITTED
X PGNRNK,10	;COUNT OF RECEIVED NAKS
		; FIRST IS MISC NAKS, NEXT 7 ARE BY NAK CODE
X PGRMCN,1	;COUNT OF DDCMP MESSAGES RECEIVED
X PGNXNK,10	;COUNT OF TRNASMITTED NAKS
		; FIRST IS MISC NAKS, NEXT 7 ARE BY NAK CODE
X PGKMCR,2	;KMC11 REGISTERS WHEN KMC11 LAST HALTED
		; BSEL0,,BSEL2
		; BSEL4,,BSEL6
X PGLACK,2	;LAST DDCMP ACK,NAK OR DATA MESSAGE TO UPDATE ACKED MESSAGE
X PGXBD1,4	;1ST TRANSMIT BUFFER DESCRIPTOR LIST
X PGXMS1,140	;1ST XMIT MESSAGE BUFFER
X PGXBD2,4	;2ND TRANSMIT BUFFER DESCRIPTOR LIST
X PGXMS2,140	;2ND XMIT MESSAGE BUFFER
X PGRBD1,4	;1ST RECEIVE BUFFER DESCRIPTOR LIST
X PGRMS1,140	;1ST INPUT MESSAGE BUFFER
X PGRBD2,4	;2ND RECEIVE BUFFER DESCRIPTOR LIST
X PGRMS2,140	;2ND INPUT MESSAGE BUFFER
IFN FTRACE,<
X PGTPTR,1	;TRACE PUTTER
	Z=<Z+1>&<-2>	;TRACE MUST BEGIN ON AN EVEN WORD
X PGTRCE,1	;TRACE
>;IFN FTRACE
	PURGE Z,X
	SUBTTL	DEFINITIONS -- KMC11

;KMC11 REGISTER BIT DEFINITIONS

BSEL0==0
BSEL1==1
	KMCRUN==100000	;RUN FLOP
	KMCMCL==040000	;MASTER CLEAR
	KMCCWR==020000	;CRAM WRITE
	KMCSLU==010000	;STEP LINE UNIT
	KMCLUL==004000	;LINE UNIT LOOP
	KMCRMO==002000	;ROM OUTPUT
	KMCRMI==001000	;ROM INPUT
	KMCSUP==000400	;STEP u-PROCESSOR
	KMCRQI==000200	;REQUEST INPUT
	KMCIEO==000020	;INTERRUPT ENABLE OUTPUT
	KMCIEI==000001	;INTERRUPT ENABLE INPUT
BSEL2==2
BSEL3==3		;CONTAINS LINE NUMBER
	KMCRDO==000200	;READY FOR OUTPUT
	KMCRDI==000020	;READY FOR INPUT
	KMCIOT==000004	;SET FOR RECEIVE CLEARED FOR TRANSMIT
	KMCTYP==000003	;COMMAND TYPE
	 BASEIN==000003	;BASE IN
	 CNTLIN==000001	;CONTROL IN
	 BFADIN==000000	;BUFFER ADDRESS IN
	 CNTLOU==000001	;CONTROL OUT
	 BFADOU==000000	;BUFFER ADDRESS OUT
BSEL4==4
BSEL5==5
			;BUFFER DESCRIPTOR LIST ADDRESS (BUFFER ADR IN & OUT & CONTROL OUT)
BSEL6==6
BSEL7==7
		;140000	;ADR BITS 17 & 16 (BUFFER ADR IN & OUT & CONTROL OUT)
	BFREOM==010000	;END OF MESSAGE (BUFFER ADR OUT)
	BFRENB==020000	;BUFFER ENABLE (BUFFER ADR IN)
	BFRKIL==010000	;BUFFER KILL (BUFFER ADR IN)
	CSRMSK==017770	;MASK FOR DUP11 CSR ADR (BASE IN)
	CDDCMP==100000	;FLAG THIS A DDCMP LINE (CONTROL IN)
	CHALFD==020000	;FLAG THIS IS HALF DUPLEX (CONTROL IN)
		;010000	;ENABLE SECONDARY STATION (CONTROL IN)
		;001000	;CRC INHIBIT (CONTROL IN)
	CENABL==000400	;FLAG TO ENABLE LINE (CONTROL IN)
	COUERR==000377	;ERROR CODE (CONTROL OUT)

CRAMSZ==2000	;SIZE OF KMC11 CRAM
DRAMSZ==2000	;SIZE OF KMC11 DRAM
;BUFFER DESCRIPTOR LISTS ARE STRINGS OF 3 16 BIT WORDS
; 1ST WORD 16 BITS OF BUFFER ADDRESS
; 2ND WORD 16 BIT BYTE COUNT
; 3RD WORD
	BDLLDS==100000	;LAST DESCRIPTOR
	BDLRSY==010000	;RESYNC TRANSMITTER
	;==006000	;BUFFER ADDRESS 17 & 16
	BDLEOM==001000	;END OF MESSAGE
	BDLSOM==000400	;START OF MESSAGE

;MESSAGES TO THE KMC11
; BASEIN:	BSEL2/	<LINE #>*400+3
;		BSEL6/	<DUP11 ADR>&017770
; CONTROL IN:	BSEL2/	<LINE #*400+1
;		BSEL6/	FLAGS
; BF AD IN:	BSEL2/	<LINE NU>*400+0+<4 IF INPUT>
;		BSEL4/	BUFFER DESCRIPTOR LIST ADR
;		BSEL6/	FLAGS
; BF AD OUT:	BSEL2/	<LINE NU>*400+0+<4 IF RECEIVE>
;		BSEL4/	BUFFER DESCRIPTOR LIST ADR
;		BSEL6/	FLAGS
; CONTROL OUT:	BSEL2/	<LINE NU>*400+1+<4 IF RECEIVE>
;		BSEL4/	BUFFER DESCRIPTOR LIST ADR
;		BSEL6/	ERROR CODE
	SUBTTL	DEFINITIONS -- DUP11

	DUPADR==3760300	;ADDRESS OF 1ST DUP11
	DUPUBN==3	;UNIBUS ADAPTER NUMBER FOR DUP11

	DPRCSR==0	;RECEIVER CSR
		DPDTR==000002	;DATA TERMINAL READY
	DPRDBF==2	;(RO)RECEIVER DATA BUFFER
	DPPCSR==2	;(WO)PARAMETER CONTROL AND STATUS REGISTER
	DPTCSR==4	;TRANSMIT CONTROL AND STATUS REGISTER
		DPCBLP==010000	;EXTERNAL MAINTENCE MODE (CABLE LOOPBACK)
		DPCNLP==004000	;SYSTEMS TEST MODE (CONTROLLER LOOPBACK)
		DPMAIN==014000	;MAINTAINENCE MODE BITS
	DPTDBF==6	;TRANSMIT DATA BUFFER
	SUBTTL	DEFINITIONS -- DDCMP

	SYN==226
	IDLE==SYN	;NO SPECIAL IDLE CHARACTER
	ENQ==005	;1ST CHAR IN UNNUMBERED MESSAGES
	DLE==220	;1ST CHAR IN BOOTSTRAP MESSAGES
	SOH==201	;1ST CHAR IN NUMBERED MESSAGES

	MAXOUT==10	;MAXIMUM NUMBER OF DATA MESSAGES TO PUT IN PIPE

;NUMBERED MESSAGES
;	SOH CC1 CC2 QSYNC SELECT R N A0 BCC1 DATA BCC2
;	CC1&CC2 ARE TOTAL LENGTH OF DATA(BCC1 THRU BCC2 EXCLUSIVE)
;	CC1 IS LOWORDER 8BITS OF LENGTH
;	CC2 IS HIGH ORDER 6 BITS OF LENGTH
	QSYNC==100	;QSYNC BIT
	SELECT==200	;SELECT BIT
;	R IS # OF LAST GOOD MESSAGE RECEIVED
;	N IS THIS MESSAGE NUMBER
	A0==1	;A0 IS THE DESTINATION STATION ADR(ALWAYS 1)
;	BCC1 IS THE 16 BIT CRC ON SOH THROUGH A0 INCLUSIVE
;	DATA IS PASSED TO NCL
;	BCC2 IS THE 16BIT CRC OF DATA
;UNNUMBERED MESSAGES
	FILL==000		;FILL CHARACTER

;ACK:	ENQ	ACK	QSYNC SELECT FILL	MSG#	FILL	A0	BCC1	BCC2
	ACK==001
;	MSG# IS LAST GOOD MSG RECEIVED

;NAK:	ENQ	NAK	QSYNC SELECT RNAK	MSG#	FILL	A0	BCC1	BCC2
	NAK==002		;NETIVE ACKNOWLEDGE
;	RNAK IS NAK REASON AS FOLLOWS
	NCDHBC==1	;HEADER BCC ERROR
	NCDBCC==2	;DATA BCC ERROR
	NCDREP==3	;REP RESPONSE
	NCDBTU==4	;BUFFER TEMPORARILY UNAVAILABLE
	NCDROV==5	;RECEIVER OVERRUN
	NCDMTL==6	;MESSAGE TOO LONG
	NCDHFE==7	;HEADER FORMAT ERROR
;	MSG# IS LAST GOOD MSG RECEIVED

;REP:	ENQ	REP	QSYNC SELECT FILL	FILL	N	A0	BCC1	BCC2
	REP==003		;REPLY TYPE
;	N IS THE LAST MESSAGE# SENT

;RESET:	ENQ	RESET	QSYNC SELECT FILL	FILL	N	A0	BCC1	BCC2
;	RESET==4		;DC72 WILL NOT SEND THIS TYPE;WILL RESPOND WITH START

;RESAK:	ENQ	RESAK	QSYNC SELECT FILL	R	FILL	A0	BCC1	BCC2
	RESAK==5		;DC72 WILL NOT SEND THIS TYPE;WILL RESPOND WITH START

;START:	ENQ	STRT	QSYNC SELECT FILL	FILL	N	A0	BCC1	BCC2
	STRT==006		;START TYPE
;	N IS NEXT NUMBERED MESSAGE TO BE SENT

;STACK:	ENQ	STACK	QSYNC SELECT FILL	R	N	A0	BCC1	BCC2
	STACK==007		;START ACKNOWLEDGE
;	R IS NEXT EXPECTED MESSAGE # FOR RECPTION
;	N IS NEXT MESSAGE # FOR TRANSMISSION


MSNMAX==377		;MAXIMUM MESSAGE NUMBER

;WHEN A MSG IS RECEIVED CORRECTLY AN ACK IS SENT BACK;
; AN ACK IMPLIES ACK OF ALL LOWER NUMBERED MESSAGES
;WHEN A MSG IS RECEIVED INCORRECTLY A NAK MSG IS SENT BACK;
; A NAK IMPLIES ACK OF ALL LOWER NUMBERED MSGS.
	SUBTTL	PROTOTYPE MESSAGES

	RESCD
ACKMSG:	BYTE(18)ENQ+400*ACK,FILL+400*FILL,FILL+400*A0,FILL+400*FILL

NAKMSG:	BYTE(18)ENQ+400*NAK,FILL+400*FILL,FILL+400*A0,FILL+400*FILL

REPMSG:	BYTE(18)ENQ+400*REP,FILL+400*FILL,FILL+400*A0,FILL+400*FILL

STRTMS:	BYTE(18)ENQ+400*STRT,QSYNC+SELECT+FILL+400*FILL,FILL+400*A0,FILL+400*FILL

STCKMS:	BYTE(18)ENQ+400*STACK,QSYNC+SELECT+FILL+400*FILL,FILL+400*A0,FILL+400*FILL
	SUBTTL	DUP11 COMIOP CODE FOR KMC11

	SWAPCD
COMIOP:	BYTE(18)61220,61222,63234,63233,63224,16400,123600,60400
	BYTE(18)103412,100405,440,63225,74524,63220,60365,101427
	BYTE(18)63064,2777,4457,70000,76613,62614,114707,4003
	BYTE(18)10375,16451,16517,2777,123620,103163,10375,4003
	BYTE(18)140620,120440,103501,120440,103434,400,61222,2511
	BYTE(18)100434,2511,10377,50220,101434,55223,55224,55225
	BYTE(18)55226,55227,55222,10376,57221,43220,2517,767
	BYTE(18)60360,101474,406,62400,40361,101477,100500,2777

	BYTE(18)10375,123400,103105,2441,100434,2443,700,61231
	BYTE(18)100434,120400,103514,100451,3020,61202,102121,2524
	BYTE(18)100434,2531,600,100507,120440,103127,100533,120400
	BYTE(18)102121,120440,103034,2451,457,63225,123072,60532
	BYTE(18)70005,57233,47234,70213,14414,75231,56226,56227
	BYTE(18)70213,120440,102555,102272,100764,102254,400,61222
	BYTE(18)123620,116353,100434,521,61271,400,63232,73233
	BYTE(18)67234,100607,123620,116353,63072,420,60372,101436

	BYTE(18)4457,63220,60532,70000,57233,47234,70213,54620
	BYTE(18)43220,101572,62560,101172,76620,56224,56225,415
	BYTE(18)61230,43231,120600,102222,23421,60731,106750,23100
	BYTE(18)23417,103637,1400,106441,60617,107576,100572,402
	BYTE(18)62004,415,61230,120600,102243,23007,23030,60617
	BYTE(18)100632,110740,110470,110545,137140,14770,62660,56226
	BYTE(18)123160,740,62700,42227,401,62223,556,63236
	BYTE(18)405,114643,120560,102277,17400,76560,100702,136500

	BYTE(18)136500,422,76222,134560,2401,103707,2400,42223
	BYTE(18)421,61230,120600,102312,123560,103724,122142,2600
	BYTE(18)102722,2400,422,100732,2626,42222,2444,103331
	BYTE(18)2440,600,62263,736,63236,114645,120560,1400
	BYTE(18)103343,400,100746,410,63220,42700,76222,2633
	BYTE(18)120560,103753,2605,400,76223,136540,454,70013
	BYTE(18)2400,556,63236,114645,22144,22165,415,61230
	BYTE(18)120440,1400,102775,432,100776,411,60413,63226

	BYTE(18)120600,106000,23017,120560,113002,417,70006,43625
	BYTE(18)1400,107033,2440,70206,136500,136520,123160,700
	BYTE(18)60660,1400,1400,1400,1400,62620,60525,103556
	BYTE(18)434,63235,114450,500,62705,43225,403,70006
	BYTE(18)104414,60601,1400,107045,100634,404,62004,415
	BYTE(18)61230,120600,106051,20400,107456,100634,22106,22127
	BYTE(18)123220,501,63260,414,61311,454,70013,43620
	BYTE(18)113105,451,70013,40620,1400,107107,106100,100634

	BYTE(18)23140,770,62266,773,63677,62222,110520,20400
	BYTE(18)107116,20420,102634,3020,110515,103634,43620,106164
	BYTE(18)463,63236,445,114632,43621,76461,106152,62224
	BYTE(18)56225,414,63260,61070,400,62223,120600,106136
	BYTE(18)36002,22420,23140,402,62006,421,61230,120600
	BYTE(18)106147,100634,105155,14400,104561,560,63236,114743
	BYTE(18)400,76223,42222,104542,113040,20420,107573,62560
	BYTE(18)60611,1400,107120,401,62223,104542,404,70013

	BYTE(18)64214,57231,60610,117550,144620,2611,572,77236
	BYTE(18)104620,2615,572,77236,104620,106627,653,77236
	BYTE(18)74611,113545,43220,76607,43227,62600,160616,2605
	BYTE(18)435,63235,110635,2656,404,70013,456,62671
	BYTE(18)43231,601,60367,105653,405,60367,111545,620
	BYTE(18)60367,105653,114567,401,62711,110545,2663,407
	BYTE(18)70013,62607,110545,2677,410,70013,477,62667
	BYTE(18)63271,404,70013,700,60667,62711,110545,2701

	BYTE(18)110545,2703,110545,2717,74611,1400,106710,110545
	BYTE(18)40367,111545,404,70013,420,62711,110545,2721
	BYTE(18)100572,2727,107324,114555,60611,102172,104756,437
	BYTE(18)63236,114627,105334,104737,60611,103172,110545,405
	BYTE(18)70013,2743,100572,107356,114557,120600,106345,100572
	BYTE(18)3002,42722,706,63236,416,110722,2633,60611
	BYTE(18)107364,400,63235,110635,417,70013,57224,57223
	BYTE(18)57222,57221,57220,76604,76603,76602,76601,76600

	BYTE(18)60531,114762,120440,1400,112414,454,70013,43220
	BYTE(18)423,62700,601,110420,417,63235,114571,605
	BYTE(18)63222,426,63223,426,63235,110663,417,70006
	BYTE(18)2602,120560,1400,107005,100556,100572,114567,104732
	BYTE(18)60611,1400,113051,400,62222,2003,757,62660
	BYTE(18)104542,626,76222,401,76223,43221,62561,105142
	BYTE(18)451,70013,110446,105124,20420,113533,60600,112522
	BYTE(18)473,63235,110731,774,23140,62266,451,70013

	BYTE(18)43620,61620,107115,112127,100634,112541,2400,451
	BYTE(18)70013,40620,1400,107107,3000,410,60671,62302
	BYTE(18)621,104546,402,62223,652,63236,114645,454
	BYTE(18)70013,2423,100634,422,63223,473,63235,601
	BYTE(18)110734,62560,404,62223,104542,430,70013,43622
	BYTE(18)1400,113160,435,63235,571,63236,414,110722
	BYTE(18)563,63236,114631,111204,43622,112167,110577,572
	BYTE(18)63236,114615,60562,62226,14621,42222,61230,545

	BYTE(18)63235,120600,112201,110714,40620,112213,14000,14776
	BYTE(18)76662,62607,110627,616,63236,114615,74607,62223
	BYTE(18)42222,60602,112225,421,110626,621,61230,426
	BYTE(18)70013,745,63236,401,114741,426,70013,43622
	BYTE(18)112242,110654,645,63236,114615,74562,62226,42222
	BYTE(18)621,61230,120600,112252,420,63223,604,63222
	BYTE(18)411,60413,63226,70206,56226,56227,123220,501
	BYTE(18)63260,43221,414,60661,61311,406,70006,57220

	BYTE(18)43221,413,70006,56342,54441,76223,651,77236
	BYTE(18)40620,1400,117245,110740,400,63223,604,63222
	BYTE(18)411,110736,63223,3400,63221,63224,601,63222
	BYTE(18)110746,400,63223,600,63222,432,60413,63226
	BYTE(18)416,63236,70206,57220,57221,43224,10376,4003
	BYTE(18)50220,76612,76600,76601,62603,60602,112361,2400
	BYTE(18)110763,400,63223,77124,63124,63124,63524,76703
	BYTE(18)76602,10376,57220,40620,115410,60360,115412,10376

	BYTE(18)767,60360,115406,406,62400,174616,2517,174616
	BYTE(18)62600,110777,70200,3200,42700,174616,417,70006
	BYTE(18)64214,43620,117430,70206,432,63236,406,114741
	BYTE(18)60520,117435,737,62660,170615,677,62660,403
	BYTE(18)70006,57220,57221,57222,70206,76600,76601,62602
	BYTE(18)70206,56224,56225,401,63220,55310,120600,116056
	BYTE(18)37004,37025,465,63236,114721,37002,23023,36400
	BYTE(18)36420,76604,76605,476,63236,114721,23020,36420

	BYTE(18)76602,76603,76604,76605,43222,540,60662,62700
	BYTE(18)411,60413,60366,115543,74564,116126,62224,60605
	BYTE(18)62225,414,63260,61070,120600,116124,36420,16407
	BYTE(18)60617,1400,116542,2400,404,63717,62222,542
	BYTE(18)63236,114672,170615,754,43220,63260,62460,170615
	BYTE(18)117157,60530,117561,406,114562,410,114562,412
	BYTE(18)114562,424,63223,436,63235,605,110657,435
	BYTE(18)63235,64214,757,63677,62222,600,63236,114672

	BYTE(18)420,63717,62222,621,61230,54620,2633,1400
	BYTE(18)117212,2605,120600,116212,170615,56226,56227,123220
	BYTE(18)501,63260,414,63221,40661,61311,170616,407
	BYTE(18)114632,424,70013,43221,76561,115640,14000,170616
	BYTE(18)43221,76561,170616,3221,114647,402,3021,23140
	BYTE(18)62006,23160,62107,115255,114662,123220,404,63000
	BYTE(18)515,61271,123200,555,60660,60701,61230,120600
	BYTE(18)116267,160616,402,70013,56226,56227,123220,501

	BYTE(18)63260,414,61311,621,61230,114733,100572,460
	BYTE(18)73013,60013,115315,64214,100414,67114,400,73233
	BYTE(18)100414,402,23100,62004,23120,62105,123200,115336
	BYTE(18)416,63260,61070,120600,116333,174616,404,63000
	BYTE(18)114730,63220,56400,43220,76500,115347,164616,43220
	BYTE(18)404,62400,164616,500,61271,761,63236,420
	BYTE(18)110722,100434,117567,100572,0,0,0,0
	BYTE(18)0,0,0,0,0,0,0,0

COMIOE:	;END OF COMIOP CODE
	SUBTTL	BOOT JSYS -- PERFORM BOOTSTRAP FUNCTIONS FOR KMC11

;BOOT JSYS IS USED TO LOAD AND DUMP KMC11
; CALL	MOVEI AC1,<FUNCTION CODE>
;	MOVEI AC2,<ADR OF ARGUMENT BLOCK>
;	BOOT
;
;REG STRING IS BSEL0,BSEL2,BSEL4,BSEL6,MISC+NPR,INDATA,OUTDATA,INBA,OUTBA


; TABLE OF DISPATCH ADDRESSES

BOOTTB:	EXP BTERR		;(0) = ACTIVATE ROM
	EXP BTSMP		;(1) = SEND MOP MESSAGE
	EXP BTERR		;(2) = LOAD MEMORY
	EXP BTERR		;(3) = DUMP MEMORY
	EXP BTIPR		;(4) = INITIALIZE PROTOCOL
	EXP BTTPR		;(5) = TERMINATE PROTOCOL
	EXP BTSTS		;(6) = RETURN STATUS
	EXP BTERR		;(7) = WAIT FOR TO-10 DOORBELL
	EXP BTRMP		;(10) = READ MOP MESSAGE
	EXP BTKML		;(11) = LOAD KMC11
	EXP BTKMD		;(12) = DUMP KMC11
	EXP BTRLC		;(13) = RETURN LINE COUNTS
	EXP BTCLI		;(14) = CONVERT LINE-ID TO PORT NUMBER
	EXP BTCPN		;(15) = CONVERT PORT NUMBER TO LINE-ID
	BOOTLN==.-BOOTTB
;HERE ON A BOOT JSYS
.BOOT::	MCENT			;MONITOR CONTEXT ENTRY
	MOVE T1,CAPENB		;GET ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR!SC%MNT ;WHEEL, OPERATOR, OR MAINTENANCE ?
	ITERR (CAPX2)		;WHEEL, OPERATOR, or MAINTENANCE capability required
	UMOVE Q3,1		;GET FUNCTION CODE FROM USER
	CAIL Q3,.BTROM		;CHECK RANGE OF GIVEN
	CAIL Q3,.BTROM+BOOTLN	; FUNCTION CODE
BTERR:	ITERR (ARGX02)		;Invalid function

; VALIDATE KMC11 ADDRESS

	UMOVE Q1,2		;GET ADDRESS OF USER'S ARGUMENT BLOCK

; DISPATCH TO PROCESSING ROUTINE BASED ON REQUESTED FUNCTION

	CALL @BOOTTB-.BTROM(Q3)	;DISPATCH TO APPROPRIATE ROUTINE
	 ITERR ()		;FAILED, RETURN ERROR TO USER
	MRETNG			;SUCCESS, RETURN TO USER

;HERE TO GET KMC11 ADDRESS FROM ARGUMENT BLOCK
BTGKMA:	UMOVE Q2,.BTKMC(Q1)	;GET KMC11 ADDRESS FROM USER
	TRNE Q2,7		;BE SURE FIRST KMC11 ADR
	JRST BTDVX5		;GIVE USER ERROR
	MOVE T1,Q2		;COPY KMC11 ADR FOR UBGOOD
	LDB T2,[POINT 9,T1,22]	;GET UBA NUMBER & 5 BITS OF UNIBUS ADR
	CAIE T2,77		;1,,76#### ?
	CAIN T2,177		;OR 3,,76#### ?
	CALL UBGOOD		;SEE IF THAT ADDRESS EXISTS
BTDVX5:	ITERR (DEVX5)		;No such device
	RET

;HERE TO GET A PORT NUMBER ARGUMENT
; RETURN:	P1/ LINES PAGE
;		T4/ DUP11 HDW ADR
BTGPRT:	UMOVE P1,.BTPRT(Q1)	;GET PORT NUMBER FROM ARGUMENT BLOCK
	HRRZ T4,P1		;COPY ONLY PORT NUMBER
	CAML T4,KDPNLN		;IS ARGUMENT IN RANGE ?
	ITERR (ARGX19)		;Invalid unit number
	LSH T4,3		; *10
	ADD T4,[DUPADR]		;MAKES THIS DUP11'S ADR
	HRR P1,KDPPAG(P1)	;GET ADR OF LINES PAGE
	RET
	SUBTTL	BOOT JSYS -- SEND MOP MESSAGE

BTSMP:	CALL BTGPRT		;GET PORT NUMBER
	RETSKP
	SUBTTL	BOOT JSYS -- INITIATE PROTOCOL

BTIPR:	CALL BTGPRT		;GET PORT NUMBER
	MOVE T1,[EXP KMCADR]	;GET ADDRESS OF KMC11
	RDIO T1,(T1)		;GET STATUS FROM KMC11
	TRNN T1,KMCRUN		;IS KMC11 RUNNING ?
	RETBAD (KDPX01)		;KMC11 not running
	LOAD T1,DDSTA		;GET CURRENT LINE STATE
	UMOVE T2,.BTPRV(Q1)	;GET PROTOCOL VERSION NUMBER
	RDIO T3,DPTCSR(T4)	;GET CURRENT MAINTENANCE MODE BITS
	ANDI T3,DPMAIN		;LEAVE ONLY THE MAINTAINENCE MODE BITS
	CAIN T2,.VNDDC		;STARTING DDCMP ?
	JRST BTIDDC		;STARTING DDCMP
	CAIN T2,.VNCNL		;INITIATING CONTROLLER LOOPBACK ?
	 JRST BTICNL		;YES
	CAIN T2,.VNCBL		;INITIATING CABLE LOOPBACK ?
	 JRST BTICBL		;YES
	CAIE T2,.VNMOP		;STARTING DDCMP MAINTENANCE MODE ?
	JRST BTERR		;CAN'T DO THAT

;HERE TO INITIATE MAINTENANCE MODE ON LINE
BTIMOP:	MOVEI T1,DPMAIN		;DUP11 MAINTENANCE MODE BITS
	BCIO T1,DPTCSR(T4)	;CLEAR MAINTENANCE MODE
	MOVEI T1,STAMAI		;NOW AM IN MAINTENANCE MODE
	CALL DEDLIN		;DROP LINE
	RETSKP

;HERE TO INITIATE DDCMP ON LINE
BTIDDC:	SETZ T2,		;NO MAINTENANCE MODE BITS
	CAIE T1,STADWN		;IS THE LINE DOWN ?
	CAIN T1,STAMAI		;OR IS LINE IN MOP MODE ?
	 JRST BTIDC4		;GO TRY TO DDCMP START IT
	JUMPN T3,BTERR		;IF HDW LOOPED BACK LOSE
	RETSKP			;ALREADY RUNNING SO WIN
BTIDC4:	MOVEI T1,DPMAIN		;DUP11 MAINTENANCE MODE BITS
	BCIO T1,DPTCSR(T4)	;CLEAR MAINTENANCE MODE
	BSIO T2,DPTCSR(T4)	;SET NEW FORM OF MAINTAINENCE MODE
	MOVEI T1,DPDTR		;WANT DATA TERMINAL READY SET
	BSIO T1,DPRCSR(T4)	;SET IT
	MOVEI T1,STASTR		;NOW WANT TO SEND STARTS
	CALL DEDLIN		;DROP LINE
	RETSKP

;HERE TO INITIATE CONTROLLER LOOPBACK
BTICNL:	MOVEI T2,DPCNLP		;BIT FOR CONTROLLER LOOPBACK
	JRST BTILPB		;SET LOOPBACK

;HERE TO INITIATE CABLE LOOPBACK
BTICBL:	MOVEI T2,DPCBLP		;BIT FOR FOR CABLE LOOPBACK
BTILPB:	CAIE T1,STADWN		;IS THE LINE DOWN ?
	CAIN T1,STAMAI		;OR IS LINE IN MOP MODE ?
	 JRST BTIDC4
	CAMN T2,T3		;ALREADY THIS WAY ?
	 RETSKP			;ALREADY LOOPED BACK
	JRST BTERR		;LOSE
	SUBTTL	BOOT JSYS -- TERMINATE PROTOCOL

BTTPR:	CALL BTGPRT		;GET PORT NUMBER
	MOVEI T1,DPMAIN		;MAINTAINENCE MODE BITS
	BCIO T1,DPTCSR(T4)	;CLEAR MAINTAINENCE MODE BITS
	MOVEI T1,DPDTR		;NO LONGER TRYING
	BCIO T1,DPRCSR(T4)	;CLEAR DAT TERMINAL READY
	NOINT
	MOVEI T1,STADWN		;CODE FOR STOPPED
	CALL DEDLIN		;CLEAN UP LINE
	OKINT
	RETSKP
	SUBTTL	BOOT JSYS -- RETURN PROTOCOL STATUS

BTSTS:	CALL BTGPRT		;GET PORT NUMBER
	LOAD T1,DDSTA		;GET LINE STATE
	MOVEI T3,.VNMOP		;CALL IT MOP MODE
	CAIN T1,STAMAI		;MAINTENANCE MODE ?
	 JRST BTSTS9		;LINE IS IN MAINTAINENCE MODE
	SETOM T3		;ASSUME NOT RUNNING
	CAIN T1,STADWN		;IS THE LINE STOPPED
	 JRST BTSTS9		;LINE IS DOWN
	MOVEI T3,.VNDDC		;ASSUME RUNNING DDCMP
	RDIO T2,DPTCSR(T4)	;GET MAINTAINENCE MODE STATUS
	ANDI T2,DPMAIN		;STRIP EXTRA BITS
	JUMPE T2,BTSTS9		;IF NOT MAINTAINENCE THEN RUNNING
	SETOM T3		;IN CASE INTERNAL MAINTENANCE MODE
	CAIN T2,DPCNLP		;CONTROLLER LOOPBACK ?
	MOVEI T3,.VNCNL		;YES
	CAIN T2,DPCBLP		;CABLE LOOPBACK ?
	MOVEI T3,.VNCBL		;YES
BTSTS9:	UMOVEM T3,.BTPRV(Q1)	;GIVE STATE TO USER
	RETSKP
	SUBTTL	BOOT JSYS -- RECEIVE MOP MESSAGE

BTRMP:	CALL BTGPRT		;GET PORT NUMBER
	RETSKP
	SUBTTL	BOOT JSYS -- LOAD KMC11

BTKML:	CALL BTGKMA		;GET KMC11 ADR FROM ARGUMENT BLOCK
	CALL BTSTOP		;STOP THE KMC11 IF RUNNING
	MOVEI T1,KMCMCL		;TO CLEAR THE KMC11
	WRIO T1,BSEL0(Q2)	;RESET THE KMC11

;QUICK CHECK OF KMC11 INTEGRITY
	MOVEI T2,200		;BIT PATERN FOR FIRST REGISTER
	MOVE T4,Q2		;COPY KMC11 ADR
BTCHK0:	WRIO T2,@T4		;WRITE THE REGISTER
	RDIO T1,@T4		;THEN READ IT BACK
	CAME T2,T1		;DO THE BITS MATCH ?
	 JRST [	TXO T1,BT%RVE	;REGISTER VERIFY ERROR
		JRST KMCILL ]	;REPORT PROBLEM THEN QUIT,Q2
	JUMPE T2,BTCHK2		;DONE WITH REGISTER
	LSH T2,-1		;NEXT MASK TO TRY
	JRST BTCHK0		;TRY NEXT MASK
BTCHK2:	MOVEI T2,100000		;BIT PATERN FOR NEXT BSEL
	ADDI T4,2		;NEXT BSEL
	TRNE T4,7		;DONE ALL REGS YET ?
	JRST BTCHK0		;LOOP BACK FOR REST OF REGISTERS

;VERIFY DRAM IS OK
	CALL MARCLR		;INITIALIZE THE MAR
	MOVEI T4,DRAMSZ		;SIZE OF THE DRAM
	MOVEI T1,041222		;MOVE <MEM><BSEL2>
	CALL KMCXCT		;READ DRAM (TO RESTORE LATER)
	RDIO Q3,BSEL2(Q2)	;GET OLD CONTENTS
BTCKD0:	MOVEI T3,200		;PATERN FOR DRAM
BTCKD1:	WRIO T3,BSEL2(Q2)	;SO WE WRITE INTO DRAM
	MOVEI T1,122440		;MOVE <BSEL2><MEM>
	CALL KMCXCT		;WRITE DRAM
	SETZ T2,
	WRIO T2,BSEL2(Q2)	;CLEAR BSEL2
	MOVEI T1,041222		;MOVE <MEM><BSEL2>
	CALL KMCXCT
	RDIO T1,BSEL2(Q2)	;READ MEMORY
	CAME T1,T3		;RIGHT DATA ?
	 JRST [	TXO T1,BT%DVE	;DRAM VERIFY ERROR
		JRST KMCILL ]	;REPORT ERROR THEN QUIT
	JUMPE T3,BTCKD2
	LSH T3,-1		;NEXT PATERN FOR DRAM
	JRST BTCKD1		;TRY THAT ONE
BTCKD2:	WRIO Q3,BSEL2(Q2)	;OLD CONTENTS OF DRAM
	MOVEI T1,136440		;MOVE <BSEL2><MEM><MARINC>
	CALL KMCXCT		;RESTORE DRAM LOCATION
	SOJG T4,BTCKD0		;ON TO NEXT DRAM LOCATION
;HERE TO LOAD THE CRAM
BTKLC0:	UMOVE T4,.BTKCC(Q1)	;GET COUNT FOR CRAM BYTES
	UMOVE Q3,.BTKCP(Q1)	;GET POINTER FOR CRAM BYTES
	JUMPLE T4,BTKLC9	;IN CASE NOT LOADING CRAM
	SETZ T3,		;FIRST ADDRESS TO LOAD
BTKLC2:	WRIO T3,BSEL4(Q2)	;PUT ADR IN REGISTER
	AOS T3			;NEXT CRAM ADR
	XCTBU [ILDB T1,Q3]	;GET NEXT BYTE FOR CRAM
	WRIO T1,BSEL6(Q2)	;PUT DATA IN RIGHT PLACE
	MOVEI T1,KMCRMO		;SELECT ROM OUTPUT
	WRIO T1,BSEL0(Q2)	;SET IT
	MOVEI T1,KMCRMO!KMCCWR	;NOW DO CRAM WRITE
	WRIO T1,BSEL0(Q2)
	SETZ T1,
	WRIO T1,BSEL0(Q2)	;CLEAR UP THE KMC11
	SOJG T4,BTKLC2		;ON FOR REST OF DATA
;NOW VERIFY CRAM LOAD
	UMOVE T4,.BTKCC(Q1)	;GET COUNT FOR CRAM BYTES
	UMOVE Q3,.BTKCP(Q1)	;GET POINTER FOR CRAM BYTES
	SETZ T3,		;FIRST ADR TO VERIFY
BTKLC4:	WRIO T3,BSEL4(Q2)	;PUT ADR IN KMC11
	MOVEI T1,KMCRMO		;FLAG FOR ROM OUTPUT
	WRIO T1,BSEL0(Q2)	;TELL IT TO READ CRAM
	RDIO T1,BSEL6(Q2)	;GET CRAM DATA
	XCTBU [ILDB T2,Q3]	;GET NEXT BYTE FROM USER
	UMOVEM Q3,.BTKCP(Q1)	;SAVE UPDATED CRAM POINTER
	CAME T1,T2		;IS CRAM RIGHT ?
	JRST [	TXO T1,BT%CVE	;FLAG FOR CRAM VERIFY ERROR
		JRST KMCILL ]	;REPORT ERROR THEN QUIT
	AOS T3			;NEXT CRAM ADR
	SOJG T4,BTKLC4		;ON TO NEXT CRAM LOCATION
BTKLC9:	UMOVEM T4,.BTKCC(Q1)	;SAVE UPDATED COUNT
;HERE TO LOAD THE DRAM
BTKLD0:	UMOVE T4,.BTKDC(Q1)	;GET COUNT FOR DRAM BYTES
	UMOVE Q3,.BTKDP(Q1)	;GET POINTER FOR DRAM BYTES
	JUMPLE T4,BTKLD9	;IN CASE NOT LOADING DRAM
	CALL MARCLR		;INITIALIZE THE MAR
	MOVEI T1,136440		;MOVE <BSEL2><MEM><MARINC>
BTKLD2:	XCTBU [ILDB T2,Q3]	;GIVE NEXT BYTE TO USER
	WRIO T2,BSEL2(Q2)	;PUT DATA IN BSEL2 FOR KMC11
	CALL KMCXCT		;HAVE KMC11 PUT DATA INTO MEM
	SOJG T4,BTKLD2		;COUNT BYTE AND THEN DO NEXT
	UMOVE T4,.BTKDC(Q1)	;GET COUNT FOR DRAM BYTES
	UMOVE Q3,.BTKDP(Q1)	;GET POINTER FOR DRAM BYTES
	CALL MARCLR		;INITIALIZE THE MAR
	MOVEI T1,055222		;MOVE <MEM><BSEL2><MARINC>
BTKLD4:	CALL KMCXCT		;GET NEXT BYTE FROM DRAM
	RDIO T2,BSEL2(Q2)	;GET DATA
	XCTBU [ILDB T3,Q3]	;GET WHAT USER WANTED
	UMOVEM Q3,.BTKDP(Q1)	;SAVE UPDATED DRAM POINTER
	CAME T2,T3		;DO THEY MATCH ?
	JRST [	TXO T2,BT%DVE	;DRAM VERIFY ERROR
		MOVE T1,T2	;PUT IN RIGHT REGISTER
		JRST KMCILL ]	;DONE WITH JSYS
	SOJG T4,BTKLD4		;LOOP BACK FOR REST OF VERIFY
BTKLD9:	UMOVEM T4,.BTKDC(Q1)	;SAVE UPDATED DRAM COUNT
;HERE TO LOAD THE REGISTERS
	MOVEI T1,KMCMCL		;DO A MASTER CLEAR AGAIN
	WRIO T1,BSEL0(Q2)
	SETZ T1,		;TO FINISH IT
	WRIO T1,BSEL0(Q2)
	WRIO T1,BSEL2(Q2)	;CLEAR BSEL2
	WRIO T1,BSEL4(Q2)	;CLEAR BSEL4
	WRIO T1,BSEL6(Q2)	;CLEAR BSEL6
	UMOVE T1,.BTKSA(Q1)	;GET STARTING ADDRESS
	SETZ T3,		;DEFAULT IS DON'T START
	JUMPGE T1,BTKLR0	;IN CASE NO STARTING ADDRESS
	TRO T3,KMCRUN		;IF GAVE A STARTING ADR ASSUME WANTS TO RUN
	LSHC T1,-^D8		;LEAVE ONLY BRANCH ADR BITS 9,8
	ANDI T1,3		;STRIP ANY EXTRANEOUS BITS
	LSH T1,^D3
	LSHC T1,^D8
	IORI T1,100400		;MAKES AN UNCONDITIONAL BRANCH
	CALL KMCXCT		;EXECUTE THE BRANCH
BTKLR0:	UMOVE T4,.BTKRC(Q1)	;GET COUNT FOR REGISTER BYTES
	UMOVE Q3,.BTKRP(Q1)	;GET POINTER FOR REGISTER BYTES
	JUMPLE T4,BTKLR9	;IN CASE NOT LOADING REGISTER
	XCTBU [ILDB T1,Q3]	;GET CONTENTS FOR BSEL0
	IOR T3,T1		;INCLUDE WITH RUN BIT
	MOVE T2,Q2		;COPY KMC11 ADR
	JRST BTKLR4
BTKLR2:	XCTBU [ILDB T1,Q3]	;GET NEXT BYTE FROM USER
	WRIO T1,(T2)		;LOAD REGISTER
BTKLR4:	ADDI T2,2		;READY FOR NEXT REGISTER
	TRNE T2,7		;LOADED ALL FOUR ?
	SOJG T4,BTKLR2		;ON TO NEXT
BTKLR9:	WRIO T3,BSEL0(Q2)	;NOW SET BSEL0 (I.E. RUN FLOP)
	UMOVEM T4,.BTKRC(Q1)	;SAVE UPDATED REGISTER COUNT
	UMOVEM Q3,.BTKRP(Q1)	;SAVE UPDATED REGISTER POINTER
	CAMN Q2,[KMCADR]	;IS THIS OUR KMC11 ?
	CALL COMINI		;INITIALIZE THE COMIOP
	RETSKP

KMCILL:	MOVEM T1,.BTKER(Q1)	;GIVE USER ERROR CODE
	BUG (INFO,KMCBRK,<KMC11 broken>,Q2)
	MOVEI T1,IOX5		;Device or data error
	RET			;REPORT PROBLEM THEN QUIT
;HERE TO INITIALIZE THE COMIOP

COMINI:	SKIPL P1,KDPLIM		;GET NUMBER OF DUP11'S
	RET			;NONE SO DONE
	MOVEI T1,KMCINQ+3	;START PUTTING ENTRIES HERE
	MOVEM T1,KMCINQ		;INITIALIZE THE PUTTER
	MOVEM T1,KMCINQ+1	;INITIALIZE THE TAKER
KMBT.8:	HRR P1,KDPPAG(P1)	;GET ADR OF LINES PAGE
	SETZM PGXBD1(P1)	;FIRST TRANSMIT BUFFER IS FREE
	SETZM PGXBD2(P1)	;SECOND TRANSMIT BUFFER IS FREE
	SETZM PGRBD1(P1)	;FIRST RECEIVE BUFFER IS FREE
	SETZM PGRBD2(P1)	;SECOND RECEIVE BUFFER IS FREE
    IFN FTRACE,<
	MOVEI T1,PGTRCE(P1)	;GET ADR OF TRACE
	MOVEM T1,PGTPTR(P1)	;SAVE PUTTER
    >;IFN FTRACE
	MOVEI T1,STASTR		;TRYING TO START LINE
	STOR T1,DDSTA		;REMEMBER NEW STATE
	MOVEI T1,1		;QUICK TIMER
	STOR T1,DDTIM		;SO WE SEND A START SOON
	HRRZ T2,PGKDPN(P1)	;GET LINE NUMBER
	LSH T2,3		;MULTIPLY BY 8
	ADD T2,[DUPADR]		;MAKES THIS LINES ADR
	SETZ T1,
	WRIO T1,(T2)		;CLEAR FIRST DUP11 REGISTER
	WRIO T1,2(T2)		;CLEAR 2ND DUP11 REGISTER
	WRIO T1,4(T2)		;CLEAR 3RD DUP11 REGISTER
	WRIO T1,6(T2)		;CLEAR 4TH DUP11 REGISTER
	HRRZ T1,PGKDPN(P1)	;THIS IS LINE NUMBER
	LSH T1,^D8		;POSITION FOR LH UNIBUS BYTE
	IORI T1,BASEIN		;COMMAND TYPE
	ANDI T2,CSRMSK		;STRIP EXTRA BITS
	CALL KMCINP		;GIVE MSG TO KMC11
	HRRZ T1,PGKDPN(P1)	;LINE NUMBER
	LSH T1,^D8		;POSITION FOR LH UNIBUS BYTE
	IORI T1,CNTLIN		;WILL BE A CONTROL IN MESSAGE
	MOVEI T2,CDDCMP!CENABL	;DDCMP AND ENABLE LINE
	CALL KMCINP		;GIVE MSG TO KMC11
	MOVEI T3,PGRBD1(P1)	;FIRST RECEIVER BUFFER
	CALL RCVENB		;START THE RECEIVER ... BUFFER 1
	MOVEI T3,PGRBD2(P1)	;2ND RECEIVER BUFFER
	CALL RCVENB		;START THE RECEIVER ... BUFFER 2
	HRR P1,PGKDPN(P1)	;GET LINE NUMBER AGAIN
	AOBJN P1,KMBT.8		;LOOP BACK FOR REST OF DUP11 LINES
	RET
	SUBTTL	BOOT JSYS -- DUMP THE KMC11

BTKMD:	CALL BTGKMA		;GET KMC11 ADR FROM ARGUMENT BLOCK
	UMOVE T4,.BTKRC(Q1)	;GET COUNT FOR SAVING REGISTERS
	UMOVE Q3,.BTKRP(Q1)	;POINTER FOR STORING REGISTERS
	JUMPLE T4,BTKDR9	;IN CASE DOESN'T WANT REGISTERS
	MOVE T3,Q2		;COPY KMC11 ADR
BTKDR2:	RDIO T1,(T3)		;GET DATA FROM BSEL#
	XCTBU [IDPB T1,Q3]	;SAVE NEXT BYTE FOR USER
	SOJLE T4,BTKDR9		;IF NO ROOM DONE
	ADDI T3,2		;ON TO NEXT REGISTER
	TRNE T3,7		;DONE ALL FOUR ?
	JRST BTKDR2		;ON FOR NEXT
	CALL BTSTOP		;STOP THE KMC11 IF RUNNING
	MOVEI T1,121202		;MOVE <NPR>,<BSEL2>
	CALL BTKDR6
	MOVEI T1,021002		;MOVE <IBUS 0>,<BSEL2>
	CALL BTKDR6
	CALL BTKDR6
	CALL BTKDR6
	CALL BTKDR6
BTKDR9:	CALL BTSTOP		;STOP THE KMC11 IF RUNNING
	UMOVEM T4,.BTKRC(Q1)	;SAVE UPDATED REG COUNTER
	UMOVEM Q3,.BTKRP(Q1)	;SAVE UPDATED POINTER

;HERE TO DUMP THE KMC11 CRAM
BTKDC0:	UMOVE T4,.BTKCC(Q1)	;GET COUNTER FOR CRAM DATA
	UMOVE Q3,.BTKCP(Q1)	;GET POINTER FOR CRAM DATA
	JUMPLE T4,BTKDC9	;IN CASE DOESN'T WANT TO DUMP CRAM
	SETZ T2,		;CRAM ADR TO DUMP NEXT
BTKDC2:	WRIO T2,BSEL4(Q2)	;SELECT ADR TO DUMP
	MOVEI T1,KMCRMO		;FLAG TO DUMP CRAM
	WRIO T1,BSEL0(Q2)	;TELL IT TO DUMP CRAM
	RDIO T1,BSEL6(Q2)	;GET LOCATION FROM CRAM
	XCTBU [IDPB T1,Q3]	;PUT BYTE IN USER CORE
	SOJLE T4,BTKDC9		;COUNT BYTE
	AOJA T2,BTKDC2		;ON FOR NEXT BYTE
BTKDC9:	UMOVEM T4,.BTKCC(Q1)	;SAVE UPDATED CRAM COUNTER
	UMOVEM Q3,.BTKCP(Q1)	;SAVE UPDATED POINTER

;HERE TO DUMP THE KMC11 DRAM
BTKDD0:	UMOVE T4,.BTKDC(Q1)	;GET COUNTER FOR DRAM DATA
	UMOVE Q3,.BTKDP(Q1)	;GET POINTER FOR DRAM DATA
	JUMPLE T4,BTKDD9	;IN CASE DOESN'T WANT TO DUMP THE DRAM
	CALL MARCLR		;INITIALIZE THE MAR
BTKDD2:	MOVEI T1,055222		;MOVE <MEM>,<BSEL2>,<MARINC>
	CALL KMCXCT		;GET NEXT DRAM BYTE
	RDIO T2,BSEL2(Q2)	;GET BYTE WE JUST PUT IN BSEL2
	XCTBU [IDPB T2,Q3]	;GIVE BYTE TO USER
	SOJG T4,BTKDD2		;ON FOR NEXT BYTE
BTKDD9:	UMOVEM T4,.BTKDC(Q1)	;SAVE UPDATED DRAM COUNTER
	UMOVEM Q3,.BTKDP(Q1)	;SAVE UPDATED DRAM POINTER
	RETSKP
;HERE TO FORCE KMC11 TO GIVE US INTERNAL INFORMATION
BTKDR6:	JUMPLE T4,R		;IN CASE COUNT ALREADY EXHAUSTED
	CALL KMCXCT		;XCT FIRST INSTRUCTION
	ADDI T1,21		;NEXT SOURCE & DEST
	CALL KMCXCT		;EXECUTE NEXT INSTRUCTION
	ADDI T1,17		;INCREMENT SOURCE,DECREMENT DESTINATION
	RDIO T2,BSEL2(Q2)	;GET DATA WE JUST FORCED TO BSEL2 & BSEL3
	XCTBU [IDPB T2,Q3]	;SAVE THIS REGISTER
	SOJA T4,R		;COUNT BYTE GIVEN TO USER

;HERE TO CLEAR THE MAR
MARCLR:	MOVEI T1,004000		;CLEAR MAR LOW
	CALL KMCXCT		;DO IT
	MOVEI T1,010000		;CLEAR MAR HI
	;CALL KMCXCT		;DO IT
	;RET

;HERE TO EXECUTE A KMC11 INSTRUCTION
; CALL WITH KMC11 INSTRUCTION IN T1
KMCXCT:	MOVEI T2,KMCRMI
	WRIO T2,BSEL0(Q2)	;PUT BSEL1 IN KNOWN STATE
	WRIO T1,BSEL6(Q2)	;LOAD BSEL6 & BSEL7
	MOVEI T2,KMCRMI!KMCSUP
	WRIO T2,BSEL0(Q2)	;DO ONE INSTRUCTION
	SETZ T2,		;TO CLEAN UP BSEL0
	WRIO T2,BSEL0(Q2)	;CLEAN OUT BSEL0
	RET

;HERE TO STOP THE KMC11 AS PART OF BOOT JSYS
BTSTOP:	NOINT			;PREVENT INTERRUPTS
	CAMN Q2,[KMCADR]	;IS THIS OUR KMC11 ?
	CALL KMCHLT		;YES SO CLEAN UP FIRST
	SETZ T1,		;TO CLEAR BSEL0
	WRIO T1,BSEL0(Q2)	;STOP THE KMC11
	OKINT
	RET
	SUBTTL	BOOT JSYS -- RETURN LINE COUNTERS

BTRLC:	CALL BTGPRT		;GET PORT NUMBER
	MOVE T1,PGZTIM(P1)	;GET TIME SINCE ZEROED COUNTERS
	UMOVEM T1,.BTZTM(Q1)	;GIVE NUMBER TO USER
	HRLI T4,-11		;NUMBER OF STATUS COUNTERS
	HRRI T4,PGCOCN(P1)	;POINT TO STATUS COUNTERS
	MOVEI T3,.BTSCC(Q1)	;ADR OF USERS COUNT FOR STATUS COUNTERS
	CALL BTRLCS		;GIVE STATUS COUNTERS TO USER
	HRLI T4,-11		;NUMBER OF RECEIVE COUNTERS
	HRRI T4,PGRMCN(P1)	;POINT TO RECEIVE COUNTERS
	MOVEI T3,.BTRCC(Q1)	;ADR OF USERS COUNT FOR RECEIVER COUNTERS
	CALL BTRLCS		;GIVE RECEIVE COUNTERS TO USER
	HRLI T4,-11		;NUMBER OF TRANSMIT COUNTERS
	HRRI T4,PGXMCN(P1)	;POINT TO TRANSMIT COUNTERS
	MOVEI T3,.BTTCC(Q1)	;ADR OF USERS COUNT FOR TRANSMITTER COUNTERS
	CALL BTRLCS		;GIVE TRANSMIT COUNTERS TO USER
	SKIPG P1		;DID WE ZERO COUNTERS ?
	SETZM PGZTIM(P1)	;START ZERO TIMER AGAIN
	RETSKP

BTRLCS:	UMOVE T2,1(T3)		;GET USERS BYTE POINTER
BRLCS2:	UMOVE T1,(T3)		;GET COUNT USER GAVE
	SOJL T1,BRLCS8		;CHECK FOR USER HAS ENOUGH
	UMOVEM T1,(T3)		;GIVE USER UPDATED COUNTER
	;PIOFF
	MOVE T1,(T4)		;GET NEXT COUNTER
	SKIPG P1		;WANT TO ZERO COUNTER ?
	SETZM (T4)		;CLEAR COUNTER
	;PION
	XCTBU [IDPB T1,T2]	;GIVE COUNTER TO USER
	AOBJN T4,BRLCS2		;LOOP BACK FOR NEXT COUNTER
BRLCS8:	UMOVEM T2,1(T3)		;GIVE UPDATED POINTER TO USER
	RET
	SUBTTL	BOOT JSYS -- CONVERT LINE-ID TO PORT NUMBER

BTCLI:	CALL BTGPLX		;SETUP T4 WITH USER POINTER
				; AND T3 TO POINT TO ASCIZ \KDP_0_\
BTCLI2:	ILDB T1,T3		;GET NEXT BYTE FROM OUR STRING
	XCTBU [ILDB T2,T4]	;GET NEXT BYTE FROM USER STRING
	JUMPE T1,BTCLI5		;IF DONE WITH OUR STRING
	CAMN T1,T2		;DO TWO BYTES MATCH
	JRST BTCLI2		;ON FOR REST OF STRING
BTCLI5:	TRC T2,60		;STRIP EXTRA BITS
	CAML T2,KDPNLN		;IS NUMBER IN RANGE ?
	JRST BTERR		;LOSE
	UMOVEM T2,.BTPRT(Q1)	;RETURN PORT NUMBER TO USER
	XCTBU [ILDB T1,T4]	;GET 0 BYTE FROM USER STRINT
	RETSKP
	SUBTTL	BOOT JSYS -- CONVERT PORT NUMBER TO LINE-ID

BTCPN:	CALL BTGPLI		;GET PORT NUMBER AND POINTERS TO LINEID
	ILDB T1,T3		;GET NEXT BYTE FOR USER
	XCTBU [IDPB T1,T4]	;GIVE BYTE TO USER
	JUMPN T1,.-2		;LOOP ON FOR REST OF NAME
	HRRZ T2,PGKDPN(P1)	;GET DUP11 LINE NUMBER
	IORI T2,"0"		;MAKE IT ASCII
	XCTBU [DPB T2,T4]	;FINISH NAME
	XCTBU [IDPB T1,T4]	;MAKE IT ASCIZ
	UMOVEM T4,.BTLID(Q1)	;GIVE POINTER BACK TO USER
	RETSKP

;HERE TO GET PORT NUMBER AND POINTER TO LINEID FOR BTCLI & BTCPN
BTGPLI:	CALL BTGPRT		;GET PORT NUMBER
BTGPLX:	UMOVE T4,.BTLID(Q1)	;GET USERS POINTER
	HLRZ T1,T4		;GET PART OF BYTE POINTER
	CAIN T1,777777		;SPECIAL CASE ?
	HRLI T4,440700		;MAKE IT ASCII POINTER
	MOVE T3,[POINT 7,[ASCIZ \KDP_0_\]]
	RET
	SUBTTL	HERE TO INITIALIZE THE KMC11

KDPINI::MOVE T1,[KMCADR]	;ADR OF KMC11
	CALL UBGOOD		;CHECK TO SEE IF INSTALLED
	RET			;NO KMC11
	MOVSI P2,-KDPN		;NUMBER OF DUP11'S ASSEMBLED FOR
	MOVEI P1,KMCPAG		;POINT TO FIRST DUP11 PAGE
DPINI2:	HRRZM P1,KDPPAG(P2)	;SAVE ADR OF PAGE FOR LINE
	;HRL T1,P1		;BUILD BLT POINTER
	;HRRI T1,1(P1)		; TO CLEAR
	;SETZM (P1)		; THE LINES
	;BLT T1,777(P1)		; PAGE
	HRRZM P2,PGKDPN(P1)	;SAVE LINE NUMBER IN LINES PAGE
	HRRZ T1,P2		;COPY DUP11 NUMBER
	LSH T1,3		;OFFSET FROM BASE ADDRESS
	ADD T1,[DUPADR]		;MAKE ADDRESS OF THIS DUP11
	CALL UBGOOD		;SEE IF IT EXISTS
	JRST DPINI3		;DON'T HAVE THE DUP11
	MOVEI T1,KMCUBN		;UBA UNIT NUMBER
	MOVEI T2,1		;ONLY NEED ONE PAGE
	CALL ALUBWA		;GET A UBA ADR FOR PAGE
	BUG (HLT,DUPUBA,<no Unibus Address>)
	HRLZM T2,PGUBAD(P1)	;SAVE UNIBUS ADR OF PAGE
	HRLM T2,KDPPAG(P2)	;SAVE UNIBUS ADR OF PAGE
	MOVEM T1,PGUBAM(P1)	;SAVE ADR OF UBA MAPPING REGISTER
	HRRZ T2,KDPPAG(P2)	;GET ADR OF PAGE
	LSH T2,-^D9		;CONVERT TO PAGE NUMBER
	IORI T2,UNBVBT		;FLAG VALID
	WRIO T2,@T1		;SET MAPPING REGISTER
	MOVE T1,[.RESP1,,BLKSIZ] ;PRIORITY AND SIZE OF BLOCK TO GET
	MOVX T2,RS%SE0+.RESNP	;GET IT FROM THE NETWORK POOL
	CALL ASGRES		;GET THE BLOCK
	BUG (HLT,DUPCOR,<No core for DUP11>)
	CALL SAVBLK		;SAVE ADR OF BLOCK
	ADDI P1,1000		;ON TO NEXT LINES PAGE
	AOBJN P2,DPINI2		;LOOP BACK FOR OTHER DUP11'S
DPINI3:	HRRZM P2,KDPNLN		;SAVE NUMBER OF DUP11'S
	HRLZS P2		;PUT NUMBER OF EXISTING DUP11'S IN LH
	MOVNM P2,KDPLIM		;REMEMBER HOW MANY THERE ARE
	SKIPL P1,KDPLIM		;GET NUMBER OF DUP11'S
	RET			;NONE

	MOVSI T1,(<XPCW>)	;INTERRUPT INSTRUCTION
	HRRI T1,KDPXPC		;XPCW ADR FOR VECTOR A (INPUT) INTERRUPTS
	SETZM 2(T1)		;CLEAR INTERRUPT FLAGS
	MOVEI T3,KMCVCA		;INTERRUPT ROUTINE FOR VECTOR A
	MOVEM T3,3(T1)		;SET INTERRUPT ROUTINE ADR
	MOVEI T2,KMCVEC/4	;OFFSET FOR VECTOR
	ADD T2,SMTEPT+KMCUBN	;GET ADR OF VECTOR TABLE
	MOVEM T1,(T2)		;SET VECTOR
	ADDI T1,4		;XPCW ADR FOR VECTOR B (OUTPUT) INTERRUPTS
	SETZM 2(T1)		;FLAGS FOR VECTOR B
	MOVEI T3,KMCVCB
	MOVEM T3,3(T1)		;INTERRUPT ROUTINE FOR VECTOR B
	MOVEM T1,1(T2)		;SET VECTOR B
	SKIPN PROFLG		;WANT TO START THE KMC11 ?
	RET			;DON'T START IT

;NOW BOOT THE KMC11
	MOVEI T2,KMCPAG+PGXMS1	;USE THIS FOR ARG BLOCK FOR BOOT JSYS
	SETZM (T2)		;CLEAR ARG BLOCK
	HRL T1,T2
	HRRI T1,1(T2)
	BLT T1,.BTKSA(T2)	;CLEAR ARGUMENT BLOCK
	MOVE T1,[KMCADR]	;ADDRESS OF KMC11 HDW
	MOVEM T1,.BTKMC(T2)	;SAVE IN ARGUMENT BLOCK
	MOVEI T1,<COMIOE-COMIOP>*2 ;SIZE OF COMIOP CODE
	MOVEM T1,.BTKCC(T2)	;SAVE IN ARGUMENT BLOCK
	MOVE T1,[POINT 18,COMIOP] ;POINTER TO COMIOP CODE
	MOVEM T1,.BTKCP(T2)	;SAVE IN ARGUMENT BLOCK
	MOVSI T1,400000		;WANT TO START AT 0
	MOVEM T1,.BTKSA(T2)	;SAVE IT IN ARGUMENT BLOCK
	MOVEI T1,.BTKML		;CODE FOR LOAD FUNCTION
	BOOT			;LOAD THE KMC11
	ERJMP [	BUG (INFO,KMCLOD,<KMC11 LOAD FAILED>)
		RET ]
	RET
;HERE TO STOP THE KMC11 uPROCESSOR
	RESCD
KMCHLT::SAVEP			;SAVE THE P'S
	MOVEI P1,KMCPAG		;DUMP INTO FIRST LINES BLOCK
	MOVE P2,[KMCADR]	;ADDRESS OF THE KMC11
	MOVE P3,[POINT 18,PGKMCR(P1)] ;POINT TO REG DUMP AREA
KMHLT2:	RDIO T1,BSEL0(P2)	;GET NEXT REGISTER FROM THE KMC11
	IDPB T1,P3		;SAVE IT
	ADDI P2,2		;POINT TO NEXT REGISTER
	TRNE P2,7		;DONE ALL REGS YET ?
	JRST KMHLT2		;LOOP BACK FOR REST
	SUBI P2,^D8		;FIX UP KMC11 ADR
	MOVEI T1,KMCRUN		;RUN FLOP
	BCIO T1,BSEL0(P2)	;STOP THE uPROCESSOR
	MOVE P1,KDPLIM		;LINE NUMBER
KMHLT3:	HRR P1,KDPPAG(P1)	;GET ADR OF LINES PAGE
	MOVEI T1,STADWN		;KMC11 IS NOT RUNNING
	CALL DEDLIN		;MOURN THE DEAD LINE
	HRR P1,PGKDPN(P1)	;GET THE LINE NUMBER AGAIN
	AOBJN P1,KMHLT3		;LOOP FOR REST OF DUP11 LINES
	RET
;HERE FROM NSPSRV TO CHECK FOR THINGS TO DO
; USED TO TELL NSPSRV IF LINE COMES UP OR DOWN

	SWAPCD
KDPTSK::SETZM KDPFLG		;HAVE CHECKED NOW
	SKIPL P1,KDPLIM		;GET NUMBER OF DUP11'S
	RET			;NONE
KMCTK0:	HRR P1,KDPPAG(P1)	;GET LINES PAGE
	PIOFF			;DISABLE INTERRUPTS
	LOAD T2,DCHNG		;GET CODE FOR READY TO BEGIN
	SETZRO DCHNG		;HAVE DONE IT NOW
	JUMPE T2,KMCTK8		;CHECK FOR NOTHING
	HRRZ T1,PGKDPN(P1)	;COPY LINE NUMBER FOR NSPSRV
	CAIE T2,DDUP		;DID LINE COME UP ?
	JRST [	PION		;REENABLE INTERRUPTS
		CALL DEDMCB	;TELL NSPSRV IT DIED
		JRST KMCTK9 ]	;DONE
	LOAD T2,DDSTA		;GET DDCMP STATUS
	CAIE T2,STASTK		;HAVE WE SENT STACK ?
	JRST KMCTK8		;STRANGE - LOST RACE
	MOVEI T2,STARUN		;LINE IS NOW RUNNING
	STOR T2,DDSTA
	PION			;REENABLE INTERRUPTS
	HRRZ T1,PGKDPN(P1)	;GET LINE NUMBER AGAIN
	CALL NODINI		;LET NSPSRV LINE CAME ON
KMCTK8:	PION			;REENABLE INTERRUPTS
KMCTK9:	HRR P1,PGKDPN(P1)	;GET LINE NUMBER AGAIN
	AOBJN P1,KMCTK0
	RET
;HERE TO GIVE "INPUT" TO THE KMC11
; CALL	MOVE T1,(0,,LINE NUMBER*400+TYPE)
;	MOVE T2,(BSEL4 DATA,,BSEL6 DATA)
;	CALL KMCINP
	RESCD			;CALLED FROM ALL LEVELS
KMCINP:	MOVEI T3,KMCRQI!KMCIEI!KMCIEO	;WANT TO GIVE INPUT
	PIOFF			;DISABLE RACE WITH INT LEVEL
	BSIO T3,@[BSEL0+KMCADR]	;REQUEST INPUT
	MOVE T3,KMCINQ		;GET PUTTER FOR INPUT QUEUE
	CAIN T3,KMCINQ+KMCQLN-1	;READY TO WRAP AROUND ?
	MOVEI T3,KMCINQ+1	;WRAPPING AROUND
	ADDI T3,2		;MAKE ADR OF QUEUE ENTRY
	CAMN T3,KMCINQ+1	;WILL THIS OVERFLOW THE QUEUE ?
	BUG (CHK,KMCNTI,<KMC11 not taking input>)
	MOVEM T1,-1(T3)		;PUT 1ST HALF IN QUEUE
	MOVEM T2,(T3)		;PUT 2ND HALF IN QUEUE
	MOVEM T3,KMCINQ		;SAVE UPDATED PUTTER
	PION
	RET
	SUBTTL	KMC11 INTERRUPT LEVEL SERVICE

;HERE FOR INPUT INTERRUPTS
KMCVCA:	MOVEM 17,KMCACS+17	;SAVE REG
	MOVEI 17,KMCACS		;BUILD BLT POINTER
	BLT 17,KMCACS+16	;SAVE REST OF REGS
	MOVE P,[-40,,KMCIPL]	;SET UP STACK
	MOVE T4,[KMCADR]	;GET ADDRESS OF THE KMC11 HDW
	RDIO T2,BSEL2(T4)	;GET RDI FLAG
	MOVE T1,KMCINQ+1	;GET INPUT QUEUE TAKER
	CAME T1,KMCINQ		;ARE PUTTER AND TAKE DIFFERENT ?
	TRNN T2,KMCRDI		;AND IS IT READY ?
	BUG (HLT,KMCIII,<KMC11 illegal input interrupt>,<T1,T2>)
	CAIN T1,KMCINQ+KMCQLN-1	;TIME TO WRAP AROUND AGAIN ?
	MOVEI T1,KMCINQ+1	;YES SO POINT TO BEGINING OF QUEUE
	ADDI T1,2		;ADVANCE POINTER FOR THIS ENTRY
	MOVEM T1,KMCINQ+1	;SAVE UPDATED TAKER
	MOVEI T2,KMCRQI		;WANT TO CLEAR RQUEST INPUT FLAG
	CAMN T1,KMCINQ		;IS QUEUE EMPTY NOW ?
	BCIO T2,BSEL0(T4)	;THIS IS LAST OF DATA
	MOVE T2,(T1)		;GET 2ND WORD IN QUEUE ENTRY
	MOVE T1,-1(T1)		;GET 1ST WORD IN QUEUE ENTRY
    IFN FTRACE,<
	LDB P1,[POINT 8,T1,27]	;GET LINE NUMBER
	HRRZ P1,KDPPAG(P1)	;GET LINES PAGE
	MOVE T3,PGTPTR(P1)	;GET TRACE POINTER
	HRROM T1,(T3)		;SAVE SEL2
	MOVEM T2,1(T3)		;SAVE SEL4 & SEL6
	ADDI T3,2
	CAIN T3,1000(P1)	;TIME TO WRAP AROUND ?
	MOVEI T3,PGTRCE(P1)	;YES
	MOVEM T3,PGTPTR(P1)	;SAVE UPDATED TRACE POINTER
    >;IFN FTRACE
	WRIO T2,BSEL6(T4)	;GIVE HALF OF DATA
	MOVSS T2		;GET OTHER HALF
	WRIO T2,BSEL4(T4)	;GIVE OTHER HALF
	WRIO T1,BSEL2(T4)	;TELL KMC11 WHAT THIS IS AND LINE #
	MOVSI 17,KMCACS		;BLT POINTER TO RESTORE REGS
	BLT 17,17		;RESTORE ALL REGS
	XJEN KDPXPC		;DISMISS INTERRUPT
;HERE FOR KMC11 OUTPUT INTERRUPTS
KMCVCB:	MOVEM 17,KMCACS+17	;SAVE REG
	MOVEI 17,KMCACS		;BUILD BLT POINTER
	BLT 17,KMCACS+16	;SAVE REST OF REGS
	MOVE P,[-40,,KMCIPL]	;SET UP STACK
	MOVE P1,[KMCADR]	;ADDRESS OF THE KMC11 HARDWARE
	RDIO T1,BSEL2(P1)	;GET 1ST 1/3 OF DATA (LINE NUMBER)
	TRNN T1,KMCRDO		;IS RDYO SET ?
	JRST KMVCB9		;DONE WITH INTERRUPT
	RDIO T2,BSEL4(P1)	;GET 2ND 1/3 OF DATA
	ANDI T2,177777		;CLEAR LH
	RDIO T3,BSEL6(P1)	;GET 3RD 1/3 OF DATA
	SETZ T4,		;PREPARE TO LET KMC11 KNOW WE READ IT
	WRIO T4,BSEL2(P1)	;LET KMC11 KNOW WE READ IT
	TRNE T1,100000		;CHECK FOR OUTPUT OVERFLOW
	JRST [	CALL KMCHLT	;STOP THE KMC11
		BUG (INFO,KMCFST,<KMC11 too fast>) ;INFORMATION HAS BEEN LOST
		JRST KMVCB9 ]	;DISMISS THE INTERRUPT
	LDB P1,[POINT 8,T1,27]	;GET THE LINE NUMBER
	HRR P1,KDPPAG(P1)	;GET PAGE ADDRESSES FOR LINE
    IFN FTRACE,<
	MOVE T4,PGTPTR(P1)	;GET TRACE POINTER
	HRRZM T1,(T4)		;SAVE SEL2
	HRLM T2,1(T4)		;SAVE SEL2
	HRRM T3,1(T4)		;SAVE SEL6
	ADDI T4,2
	CAIN T4,1000(P1)	;TIME TO WRAP AROUND ?
	MOVEI T4,PGTRCE(P1)	;YES
	MOVEM T4,PGTPTR(P1)	;SAVE UPDATED TRACE POINTER
    >;IFN FTRACE
	TRNE T1,3		;IS THIS BUFFER ADR OUT ?
	JRST CNTRLO		;THIS IS A CONTROL OUT
	ANDI T2,3777		;STRIP PAGE NUMBER
	ROT T2,-2		;CONVERT BYTES TO PDP10 WORDS
	ADDI T2,(P1)		;MAKE ADR
	HRRZM T2,P2		;SAVE ADR OF BUFFER DESCRIPTOR LIST
	HRLM T2,P1		;SAVE ADR OF BUFFER DESCRIPTOR LIST
	TRNN T1,KMCIOT		;TRANSMIT OR RECEIVE ?
	JRST XMTDNE		;TRANSMIT

;HERE WHEN RECEIVE DATA
	LOAD T1,DCHNG		;IN CASE JUST RESTARTED
	JUMPN T1,RCVFLU		;IGNORE IT UNTIL NSPSRV FGOING
	HRRZ T1,P1		;COPY PAGE ADDRESS
	LSH T1,-^D9		;CONVERT TO PAGE NUMBER
	CALL MONCLR		;INVALIDATE CACHE FOR THIS PAGE
	SKIPL PGRMS1-PGRBD1(P2)
	SKIPGE PGRMS1+1-PGRBD1(P2)
	JRST BUMHDR
	LDB T1,[POINT 8,PGRMS1+1-PGRBD1(P2),9] ;GET A0
	CAIE T1,A0		;IS IT A0 ?
	JRST BUMHDR		;NO
	HLRZ T1,PGRMS1-PGRBD1(P2) ;GET 1ST TWO BYTES OF HEADER
	ANDI T1,377		;LEAVE ONLY LEAD CHARACTER
	LOAD T2,DDSTA		;GET LINE STATUS
	CAIN T1,SOH		;WAS THIS A DATA MESSAGE ?
	JRST RCVDAT		;THIS WAS A DATA MESSAGE
	CAIN T1,ENQ		;WAS THIS A CONTROL MESSAGE ?
	JRST RCVCTL		;WE GOT A CONTROL MESSAGE
	CAIE T1,DLE		;WAS THIS A MAINTENANCE MODE MESSAGE ?
	JRST BUMHDR		;GARBAGE MESSAGE
	MOVEI T1,STAMAI		;NOW IN MAINTENANCE MODE
	CALL DEDLIN		;MOURN THE DEAD LINE
	JRST RCVFLU		;DISCARD MESSAGE

;HERE WHEN MESSAGE IS DETECTED AS BAD
; I.E. A0.NE.1, NOT STARTED WITH SOH, DLE, OR ENQ
BUMHDR:	DMOVE T1,PGRMS1-PGRBD1(P2) ;GET MSG HEADER
	BUG (CHK,BADHDR,<bad DDCMP header>,<T1,T2>)
	MOVEI T1,STADWN		;DON'T TRY TO USE LINE
	CALL DEDLIN		;DECLARE LINE DOWN
	JRST RCVFLU		;DISCARD MESSAGE
	SUBTTL	DDCMP RECEIVER -- DATA MESSAGE
;HERE WHEN RECEIVE A DATA MESSAGE
RCVDAT:	CAIN T2,STARUN		;ARE WE RUNNING ?
	CALL RCVAK3		;CHECK RESPONSE FIELD
	 JRST RCVFLU		;NOT RUNNING OR ERROR RETURN
	HLRZ T1,PGRMS1+1-PGRBD1(P2) ;GET MESSAGE NUMBER
	SOS T1			;MAKE PREVIOUS MESSAGE NUMBER
	ANDI T1,377		;LEAVE ONLY MESSAGE NUMBER
	LOAD T2,DDRMN		;GET LAST MESSAGE WE RECEIVED CORRECTLY
	CAME T1,T2		;IS THIS WHAT WE EXPECTED ?
	JRST RCVFLU		;NO SO IGNORE IT
;LOOP TO COPY DATA INTO BUFFER FOR NSPSRV
	MOVE T1,PGRMS1-PGRBD1(P2) ;GET DDCMP HEADER AGAIN
	ROT T1,^D8+2		;PUT LOW ORDER 8 BITS OF COUNT IN RH
	MOVE T2,T1		;COPY HIGH ORDER BITS
	ANDI T1,377		;LEAVE ONLY LOW ORDER BITS
	LSH T2,-2		;POSITION HIGH ORDER BITS
	ANDI T2,77*400		;STRIP EXTRA BITS
	IORB T1,T2		;LEAVES COUNT IN RH OF T1 & T2
	MOVNI P3,(T1)		;MAKE NEGATIVE COUNT AND PREPARE TO ROUND
	LSH P3,^D16		;ROUND TO NUMBER OF WORDS
	HRRZ T1,PGKDPN(P1)	;COPY LINE NUMBER
	CALL NSPSPC		;GET SPACE FOR THE MESSAGE
	JRST [	MOVEI T1,NCDBTU	;BUFFER TEMPORARILY UNAVAILABLE
		CALL XMTNAK	;SEND NAK MSG
		JRST RCVFLU ]
	PUSH P,T1		;SAVE ADR OF DATA BLOCK
	HRRI P3,PGRMS1+1-PGRBD1(P2) ;FINISH AOBJN POINTER TO INPUT
	HRRZI P4,-1(T1)		;COPY DEST ADR
RCVDT3:	HRLZ T1,(P3)		;GET NEXT 16 BITS TO COPY
	HLRZ T2,1(P3)		;GET NEXT 16 BITS TO COPY
	DMOVE T3,T1		;GET ANOTHER COPY OF EACH
	LSH T1,2+^D8		;LEAVE ONLY FIRST BYTE
	TLZ T3,600377		;STRIP BITS FROM 2ND BYTE
	LSH T3,2-^D8		;POSITION BYTE
	IOR T1,T3		;INCLUDE WITH FIRST
	ANDI T2,377		;STRIP EXTRA BITS FROM FIRST BYTE
	LSH T2,4+^D8		;POSITION
	IOR T1,T2		;INCLUDE 3RD BYTE WITH 1ST AND 2ND
	ANDI T4,377*400		;STRIP EXTRA BITS FROM 4TH BYTE
	LSH T4,4-^D8		;POSITION 4TH BYTE
	IOR T1,T4		;INCLUDE WITH 1ST 3 BYTES
	PUSH P4,T1		;SAVE WORD FOR NSPSRV
	AOBJN P3,RCVDT3		;LOOP BACK FOR REST OF MESSAGE
	POP P,T2		;GET DATA ADR BACK
	CALL NSPQ		;GIVE MESSAGE TO NSPSRV
	LOAD T1,DDRMN		;LAST MESSAGE RECEIVED OK
	AOS T1			;NEW LAST MESSAGE RECEIVED OK
	STOR T1,DDRMN		;SAVE NEW ONE
	AOS PGRMCN(P1)		;COUNT MESSAGE RECEIVED CORRECTLY
	CALL XMTACK		;TRY TO SEND AN ACK
	JRST RCVFLU		;THEN FLUSH MESSAGE
	SUBTTL	DDCMP RECEIVER -- CONTROL MESSAGE

;HERE WHEN RECEIVE A CONTROL MESSAGE

RCVCTL:	LDB T1,[POINT 6,PGRMS1-PGRBD1(P2),9] ;GET CONTROL TYPE
	CAILE T1,7		;IS TYPE LEGAL ?
	JRST RCVKRD		;BAD MESSAGE
	JRST @.+1(T1)		;DISPATCH ON MESSAGE TYPE
	JRST RCVKRD		; MSG TYPE = 0
	JRST RCVACK		; MSG TYPE = 1 = ACK
	JRST RCVNAK		; MSG TYPE = 2 = NAK
	JRST RCVREP		; MSG TYPE = 3 = REP
	JRST RCVKRD		; MSG TYPE = 4 = RESET
	JRST RCVKRD		; MSG TYPE = 5 = RESAK
	JRST RCVSTR		; MSG TYPE = 6 = START
	JRST RCVSTK		; MSG TYPE = 7 = STACK
	SUBTTL	DDCMP RECEIVER -- ACK MESSAGE

;HERE WHEN RECEIVE AN ACK MESSAGE
RCVACK:	JRST @.+1(T2)		;DISPATCH ON LINE STATE
	JRST RCVFLU		;KMC11 NOT RUNNING
	JRST RCVFLU		;MAINT MODE
	JRST RCVFLU		;SENDING STARTS
	JRST RCVAK0		;SENT STACK
	JRST RCVAK2		;RUNNING

;HERE WHEN RECEIVE AN ACK AFTER RECEIVING A START
RCVAK0:	OPSTR <SKIPE>,DCHNG	;HAS THIS HAPPENED ONCE BEFORE ?
	JRST RCVFLU		;PERHAPS IGNORE IT
	CALL XMTACK		;TRY TO SEND ANOTHER ACK
	MOVEI T1,DDUP		;REMEMBER IT CAME UP
	STOR T1,DCHNG		;TELL NSPSRV ASAP
	SETOM KDPFLG		;WANT TO RUN KDPTSK
	JRST RCVFLU		;THEN DISCARD MESSAGE

;HERE WHEN RECEIVE AN ACK WHILE RUNNING
RCVAK2:	CALL RCVAK3		;PROCESS MESSAGE NUMBER
	JRST RCVFLU
	JRST RCVFLU
;HERE TO CHECK R FIELD IN ACK OR DATA MESSAGE
; CALLED AT INTERRUPT LEVEL
RCVAK3:	LDB T3,[POINT 8,PGRMS1-PGRBD1(P2),27] ;GET R NUMBER
	LOAD T1,DDHMA		;GET HIGHEST MESSAGE ACKED BEFORE
	CAIN T1,(T3)		;IS THIS NEW INFORMATION
	JRST [	SKIPE T1,PGDOMQ(P1) ;IS MESSAGE QUEUE EMPTY ?
		RETSKP		;QUEUE NOT EMPTY SO KEEP REPPING
		STOR T1,DDREPC	;CLEAR REP COUNTER
		MOVEI T1,^D30	;LONG WAIT FOR NEXT REP
		STOR T1,DDTIM
		RETSKP ]
	SUB T3,T1		;FIND NUMBER OF MESSAGES THIS WILL ACK
	SKIPG T3		;IN CASE NUMBERS WRAPPED 377
	MOVEI T3,400(T3)	;HANDLE WRAP CASE
	CAIL T3,MAXOUT+1	;POSSIBLE ?
	JRST BADRSP		;BAD RESPONSE FIELD
	AOS T1			;PLUS ONE HIGHEST MESSAGE ACKED
	STOR T1,DDHMA		;SAVE UPDATED NUMBER
	DMOVE T1,PGRMS1-PGRBD1(P2) ;PICK UP MSG HEADER OR ACK/NAK
	DMOVEM T1,PGLACK(P1)	;SAVE FOR DEBUGING
	AOS PGXMCN(P1)		;COUNT MESSAGES TRANSMITTED OK
	MOVEI T1,TIMREP		;RESET REP TIMER CUZ ITS LOOKING GOOD
	STOR T1,DDTIM
	SETZ T1,		;CLEAR REP COUNTER
	STOR T1,DDREPC
	HLRZ T1,PGDOMQ(P1)	;GET FIRST MESSAGE IN QUEUE
	JUMPE T1,BADRSP		;IF NONE RESPONSE WAS BAD
	CAMN T1,PGDLMX(P1)	;WAS THIS LAST MESSAGE TRANSMITTED ?
	SETZM PGDLMX(P1)	;FORGET POINTER
	HLRZ T2,MBKLEN(T1)	;GET DRIVER INT LOC
	MOVE T1,MBKCOD(T1)	;GET DRIVER UNIQUE CODE
	SKIPE T2		;WAS THERE ONE ?
	CALL (T2)
	HLRZ T1,PGDOMQ(P1)	;GET ADR OF MESSAGE BLOCK ADR AGAIN
	HLRZ T2,MBKLNK(T1)	;GET ADR OF NEXT MESSAGE IN QUEUE
	HRLM T2,PGDOMQ(P1)	;NEW FIRST MESSAGE IN QUEUE
	CAIN T2,MBKFRE(T1)	;DID WE CHANGE CHUNKS ?
	JRST RCVAK4		;SAME CHUNK
	SKIPN T2		;WAS THERE A NEXT MESSAGE BLOCK ?
	SETZM PGDOMQ(P1)	;NO SO QUEUE NOW EMPTY
	HRRZ T1,MBKFRE(T1)	;GET CHUNK ADR FOR MESSAGE BLOCK
	CALL SAVBLK		;RELEASE BLOCK
RCVAK4:	JRST RCVAK3		;CHECK FOR MORE MESSAGES TO FREE

BADRSP:	DMOVE T1,PGRMS1-PGRBD1(P2) ;GET BAD DDCMP MESSAGE HEADER
	BUG (INFO,BADACK,<bad DDCMP ACK>,<T1,T2>)
	MOVEI T1,STADWN		;DON'T USE LINE
	CALL DEDLIN		;DECLARE LINE DOWN
	RET

;HERE TO FREE A BLOCK OF CORE
SAVBLK:	SKIPN T2,PGFCOR(P1)	;HOLDING ANY FREE BLOCKS ?
	JRST [	HRLZM T1,PGFCOR(P1) ;SAVE THIS ONE
		RET ]
	TRNE T2,-1		;HOLDING TWO ?
	JRST RELRES		;CAN'T HOLD ANY MORE
	HRRM T1,PGFCOR(P1)	;SAVE THIS ONE ALSO
	RET
	SUBTTL	DDCMP RECEIVER -- NAK MESSAGE

;HERE WHEN RECEIVE A NAK MESSAGE
RCVNAK:	JRST @.+1(T2)		;DISPATCH ON LINE STATE
	JRST RCVFLU		;KMC11 NOT RUNNING
	JRST RCVFLU		;MAINT MODE
	JRST RCVFLU		;SENDING STARTS
	JRST RCVNK0		;SENT STACK
	JRST RCVNK3		;RUNNING

;HERE IF RECEIVE A NAK AFTER SENDING A STACK
; THIS IS PROBABLY A REP RESPONSE SO DECLARE US UP
RCVNK0:	LDB T1,[POINT 8,PGRMS1-PGRBD1(P2),27] ;GET R FIELD
	JUMPN T1,RCVKRD		;IF NONZERO IS AN ERROR
	JRST RCVAK0		;TREAT AS AN ACK

;HERE IF RECEIVE A NAK WHILE RUNNING
RCVNK3:	LDB T1,[POINT 6,PGRMS1-PGRBD1(P2),35] ;GET NAK CODE
	CAILE T1,7		;IS NAK CODE REASONABLE ?
	SETZ T1,		;FIRST CELL IS MISC
	ADDI T1,PGNRNK(P1)	;POINT TO NAK COUNTER
	AOS @T1			;COUNT NAK
	SETZM PGDLMX(P1)	;RETRANSMIT FIRST MESSAGE IN QUEUE
	CALL RCVAK3		;PROCESS RESPONSE
	JRST RCVFLU		;ERROR RETURN
	CALL XMTDAT		;RETRANSMIT MESSAGE (IF ANY)
	JRST RCVFLU		;DISCARD MESSAGE
	SUBTTL	DDCMP RECEIVER -- REP MESSAGE

;HERE WHEN RECEIVE A REP MESSAGE
RCVREP:	JRST @.+1(T2)		;DISPATCH ON LINE STATE
	JRST RCVFLU		;KMC11 NOT RUNNING
	JRST RCVFLU		;MAINT MODE
	JRST RCVFLU		;SENDING STARTS
	JRST RCVRP0		;SENT STACK
	JRST RCVRP0		;RUNNING

;HERE WHEN RECEIVED A REP AND NEED TO SEND AN ACK OR A NAK RESPONSE
RCVRP0:	HLRZ T1,PGRMS1+1-PGRBD1(P2) ;GET MESSAGE NUMBER
	ANDI T1,377		;STRIP EXTRA BITS
	LOAD T2,DDRMN		;GET LAST THING WE GOT
	CAME T1,T2		;EVERYTHING OK ?
	JRST RCVRP3		;TELL HIM WE DIDN'T GET IT
	CALL XMTACK		;TRY TO SEND ACK
	JRST RCVFLU
RCVRP3:	MOVEI T1,NCDREP		;REASON CODE IS REP RESPONSE
	CALL XMTNAK		;TRY TO SEND NAK
	JRST RCVFLU
	SUBTTL	DDCMP RECEIVER -- START MESSAGE

;HERE WHEN RECEIVE A START MESSAGE
RCVSTR:	JRST @.+1(T2)		;DISPATCH ON LINE STATE
	JRST RCVFLU		;KMC11 NOT RUNNING
	JRST RSTRT3		;MAINT MODE
	JRST RSTRT5		;SENDING STARTS
	JRST RSTRT3		;SENT STACK
	JRST RSTRT0		;RUNNING

;HERE IF RECEIVE A START AFTER LINE WAS RUNNING
RSTRT0:	HRRZ T1,PGKDPN(P1)	;GET LINE NUMBER
	BUG (INFO,DDCSTR,<DDCMP restarted>,T1)
	MOVEI T1,STASTR		;SEND STARTS AGAIN
	CALL DEDLIN		;MOURN THE DEAD LINE

;HERE IF RECEIVE A START WHICH PUTS US INTO START MODE
RSTRT3:	MOVEI T1,STASTR		;AM NOW SENDING STARTS
	STOR T1,DDSTA		;SET NEW STATE
	MOVEI T1,1		;MINIMUM TIME
	STOR T1,DDTIM		;SO WE SEND A START SOON
	JRST RCVFLU		;DISCARD MESSAGE

;HERE IF RECEIVE A START WHILE SENDING STARTS
RSTRT5:	DMOVE T1,STCKMS		;GET PROTOTYPE STACK MESSAGE
	CALL XMTCTL		;TRY TO SEND IT
	JRST RSTRT3		;FAILED SO SEND START LATER
	MOVEI T1,STASTK		;NOW CLAIM WE RECEIVED A STACK
	STOR T1,DDSTA		;SAVE NEW STATUS
	SETONE DDXAK		;NEED TO SEND AN ACK
	JRST RCVFLU		;DISCARD MESSAGE

;HERE WHEN A LINE DIES - CLEANS UP AND LETS NSPSRV KNOW
; CALLED WITH NEW STATE IN T1
DEDLIN:	LOAD T2,DDSTA		;GET LINE STATUS
	MOVEI T3,DDOWN		;LINE IS DOWN
	CAIN T2,STARUN		;WAS LINE RUNNING ?
	STOR T3,DCHNG		;YES SO TELL NSPSRV IT DIED
	STOR T1,DDSTA		;SET NEW STATE
	STOR T1,DDTIM		;START TIMER ALSO
	SETOM KDPFLG		;SO WE CHECK FLAG
DEDLN2:	PIOFF			;STOP RACES
	HLRZ T3,PGDOMQ(P1)	;GET FIRST MESSAGE IN OUTPUT MESSAGE QUEUE
	JUMPE T3,DEDLN8		;IF NONE DONE
	PUSH P,MBKLEN(T3)	;SAVE DRIVER INT LOC
	PUSH P,MBKCOD(T3)	;SAVE DRIVER UNIQUE CODE
	HLRZ T2,MBKLNK(T3)	;GET ADR OF NEXT MESSAGE BLOCK
	HRLM T2,PGDOMQ(P1)	;FORGET MESSAGE
	HRRZ T1,MBKFRE(T3)	;GET ADR OF CHUNK
	CAIE T2,MBKFRE(T3)	;DOES THIS CHANGE CHUNKS ?
	CALL SAVBLK		;SAVE THE BLOCK FOR LATER USE
	PION			;REENABLE INTERRUPTS
	POP P,T1		;GET DRIVER UNIQUE CODE
	POP P,T2		;GET DRIVER INT LOC
	HLRZS T2		;PUT DREIVER INT LOC IN RH
	SKIPE T2		;WAS THERE ONE ?
	CALL (T2)
	JRST DEDLN2
DEDLN8:	SETZM PGDOMQ(P1)	;HAVE FLUSHED OUTPUT QUEUE
	SETZM PGDLMX(P1)	;NO LAST MESSAGE NOW
	SETZM PGDMNM(P1)	;INITIALIZE MESSAGE NUMBERS
	PION
	RET
	SUBTTL	DDCMP RECEIVER -- STACK MESSAGE

;HERE WHEN RECEIVE A STACK MESSAGE
RCVSTK:	JRST @.+1(T2)		;DISPATCH ON LINE STATE
	JRST RCVFLU		;KMC11 NOT RUNNING
	JRST RCVFLU		;MAINT MODE
	JRST RSTCK0		;SENDING STARTS
	JRST RSTCK0		;SENT STACK
	JRST RCVFLU		;RUNNING

RSTCK0:	CALL XMTACK		;SEND AN ACK
	MOVEI T1,STASTK		;CLAIM SENT A STACK
	STOR T1,DDSTA
	JRST RCVFLU		;DISCARD MESSAGE
	SUBTTL	DDCMP RECEIVER -- JUNK MESSAGE

;HERE WHEN RECEIVE A JUNK MESSAGE
RCVKRD:	MOVEI T1,NCDHFE		;HEADER FORMAT ERROR
	CALL XMTNAK		;COMPLAIN TO OTHER END

RCVFLU:	HLRZ T3,P1		;GET ADR OF BUFFER DESCRIPTOR
	CALL RCVENB		;REENABLE RECEIVER
	JRST KMVCB9		;DISMISS INTERRUPT
	SUBTTL	DDCMP TRANSMIT DONE

;HERE FOR TRANSMIT DONE
XMTDNE:	JUMPL T2,[SOJA T2,XMTDN5] ;IF SECOND DESCRIPTOR FLUSH MESSAGE
	HLRZ T1,PGXMS1-PGXBD1(T2) ;GET FIRST CHAR IN MESSAGE
	ANDI T1,377		;STRIP EXTRA BITS
	CAIE T1,ENQ		;WAS THIS A CONTROL MESSAGE ?
	JRST KMVCB9		;WAIT FOR DATA TO GO
XMTDN5:	LDB T1,[POINT 8,PGXMS1+1-PGXBD1(T2),9] ;GET A0
	CAIE T1,A0		;IS IT A0 ?
	BUG (CHK,MSGCLB,<DDCMP transmit message clobbered>)
	SETZM (T2)		;THIS BUFFER DESCRIPTOR LIST NOW FREE
	LOAD T1,DDNCD		;GET CURRENT NAK CODE
	SKIPE T1		;DO WE NEED TO SEND A NAK ?
	CALL XMTNAK		;TRY TO SEND IT NOW
	CALL XMTDAT		;TRY TO SEND NEXT MESSAGE
	JRST KMVCB9
	SUBTTL	KMC11 CONTROL OUT INTERRUPT
;HERE FOR CONTROL OUT INTERRUPT
CNTRLO:	ANDI T3,377		;LEAVE ONLY ERROR CODE
	ROT T3,-1		;FOR DISPATCH
	JUMPL T3,CNTLO3		;IN CASE BUM DISPATCH
	CAIL T3,10/2		;IN RANGE ?
	CAILE T3,26/2		;IN RANGE
CNTLO3:	JRST [	AOS PGCOXX(P1)	;COUNT TIMES THIS HAPPENS
		JRST KMVCB9 ]	;IGNORE INTERRUPT
	MOVEI T1,PGCOCN-4(P1)	;TABLE TO INCREMENT
	ADD T1,T3		;OFFSET FOR CODE
	AOS (T1)		;COUNT TYPE OF INTERRUPT
	JRST @.+1-4(T3)		;DISPATCH ON MESSAGE TYPE
	JRST CNTL10		;10 = INVALID DDCMP HEADER
	JRST CNTL12		;12 = BAD CRC
	JRST [	MOVEI T1,NCDBTU	;14 = BUFFER NOT AVAILABLE
		STOR T1,DDNCD	;SAVE REASON FOR NAK
		JRST KMVCB9 ]	;DISMISS
	JRST CNTL16		;16 = DATASET READY TRANSITION
	JRST CNTL20		;20 = NXM
	JRST CNTL22		;22 = TRANSMIT UNDERRUN
	JRST CNTL24		;24 = RECEIVER UNDERRUN
	JRST KMVCB9		;26 = KILL COMPLETE

;HERE WHEN GET A CONTROL TYPE 10 = INVALID DDCMP HEADER
CNTL10:	CALL FLUBFR		;FLUSH BUFFER
	JRST KMVCB9

;HERE WHEN GET A CONTROL TYPE 12 = BAD CRC
CNTL12:	CALL FLUBFR		;FLUSH BUFFER
	MOVEI T1,NCDBCC		;NAK CODE FOR BUM CRC
	CALL XMTNAK		;TRY TO SEND NAK
	JRST KMVCB9		;DISMISS

;HERE WHEN WE GET A CONTROL TYPE 16 = DATASET READY TRANSITION
CNTL16:	MOVX T3,DUPDSR		;BIT FOR DATASET READY
	XORB T3,PGDSTS(P1)	;CHANGE STATE
	TXNE T3,DUPDSR		;STILL UP ?
	 JRST KMVCB9		;CAME ON - DISMISS
	LOAD T3,DDSTA		;GET CURRENT STATE
	CAIE T3,STASTK		;ARE WE SENDING STACKS ?
	CAIN T3,STARUN		;OR ARE WE RUNNING ?
	SKIPA T1,[EXP STASTR]	;SEND STARTS AGAIN
	 JRST KMVCB9		;DISMISS
	HRRZ T2,PGKDPN(P1)	;GET LINE NUMBER
	CAIN T3,STARUN		;ARE WE RUNNING ?
	 BUG (INFO,DSRLST,<Dataset ready lost>,T2)
	CALL DEDLIN		;DATASET NOT READY SO DECLARE LINE DOWN
	JRST KMVCB9		;DISMISS

;HERE WHEN GET A CONTROL TYPE 20 = NXM
CNTL20:	CALL KMCHLT		;KILL THE KMC11
	BUG (INFO,KMCNXM,<KMC11 NXM>) ;TELL OPERATOR
	JRST KMVCB9

;HERE WHEN GET A CONTROL TYPE 22 = TRANSMIT UNDERRUN
CNTL22:	CALL FLUBFR		;FLUSH BUFFER
	JRST KMVCB9

;HERE WHEN GET A CONTROL TYPE 24 = RECEIVER UNDERRUN
CNTL24:	CALL FLUBFR		;FLUSH BUFFER
	JRST KMVCB9		;DISMISS

;HERE TO FREE BUFFER REFERENCED IN CONTROL OUT MSG
FLUBFR:	HLRZ T1,PGUBAD(P1)	;GET UNIBUS ADR OF PAGE
	SUB T2,T1		;LEAVE ONLY RELATIVE ADR ON PAGE
	ROT T2,-2		;CONVERT BYTES TO WORDS
	HRRZ T3,T2		;COPY BUFFER ADR
	ADDI T3,(P1)		;POINT TO BUFFER DESCRIPTOR
	CAIE T3,PGRBD1(P1)	;WAS THAT FIRST RECEIVER BUFFER ?
	CAIN T3,PGRBD2(P1)	;OR 2ND RECEIVER BUFFER
	JRST RCVENB		;REENABLE BUFFER
	CAIE T3,PGXBD1(P1)	;WAS THAT 1ST TRANSMIT BUFFER ?
	CAIN T2,PGXBD2(P1)	;OR 2ND TRANSMIT BUFFER ?
	SETZM (T3)		;FREE BUFFER
	RET

KMVCB9:	MOVSI 17,KMCACS		;BLT POINTER TO RESTORE REGS
	BLT 17,17		;RESTORE ALL REGS
	XJEN KDPXPC+4		;DISMISS INTERRUPT
	SUBTTL	HERE FROM NSPSRV WITH OUTPUT MESSAGES

;ACCEPTS:
;	F/ DRIVER UNIQUE CODE
;	T1/ DRIVER INT LOC,,DTE NUMBER
;	T2/ BYTE POINTER TO NSP DATA (WITH OR WITHOUT HEADER)
;	T3/ RH = COUNT OF BYTES IN DATA POINTED TO BE B
;	    B0 SET IF MESSAGE ALREADY SENT
;
;	RETURNS:
;	+1 IF NO PACKETS AND CALLED FROM SCHEDULER. REQUEST NOT
;	   QUEUED.
;	+2 REQUEST QUEUED
;
;MAY BE CALLED FROM PI OR NON-PI LEVEL .
	; ..

DCNMSO::SAVEP			;SAVE THE P'S
	HRRZM T1,P1		;SAVE THE LINE NUMBER
	CAML P1,KDPNLN		;IS LINE NUMBER IN RANGE ?
	RET			;NO SO LOSE RETURN
	STKVAR <DRVMSG,DRVCOD,DRVLEN,DRVFLG>
	MOVEM F,DRVCOD		;SAVE DRIVER CODE
	MOVEM T2,DRVMSG		;SAVE POINTER TO MESSAGE
	HLRZS T2		;LEAVE ONLY BYTE POINTER BITS
	CAIE T2,441000		;RIGHT BITS ?
	BUG (CHK,MSGPTR,<Bad msg pointer>)

	HRR T1,T3		;BUILD MBKLEN
	MOVEM T1,DRVLEN		;SAVE IT
	MOVEM T3,DRVFLG		;SAVE FLAGS
	MOVE P1,KDPPAG(P1)	;GET ADR OF LINES PAGE
	LOAD T1,DDSTA		;GET LINE STATUS
	CAIE T1,STARUN		;IS LINE RUNNING ?
	RET			;CAN'T HANDLE MESSAGE
DCNMS1:	SKIPE PGFCOR(P1)	;IS THERE A FREE CORE BLOCK ?
	JRST DCNMS2		;ENOUGH CORE
	MOVE T1,[.RESP1,,BLKSIZ] ;PRIORITY AND SIZE OF BLOCK TO GET
	MOVX T2,RS%SE0+.RESNP	;GET IT FROM THE NETWORK POOL
	CALL ASGRES		;GET THE BLOCK
	JRST [	CONSO PI,PIPIIP	;ARE WE AT INTERRUPT LEVEL ?
		SKIPE INSKED	;FROM SCHEDULER ?
		RET		;LOSE
		SKIPE NSKED	;ARE WE NOSKED ?
		RET		;LOSE - CAN'T BLOCK
		HRLI T1,P1	;COPY LINES BLOCK ADR
		HRRI T1,SPCTST	;CHECK FOR ROOM
		MDISMS		;WAIT
		JRST DCNMS1 ]	;TRY AGAIN
	PIOFF			;DISABLE INTERRUPTS
	CALL SAVBLK		;SAVE BLOCK FOR LATER USE
	PION			;REENABLE INTERRUPTS
DCNMS2:	SKIPGE DRVFLG		;ALREADY SHUFFLED ?
	JRST DCNMS4		;IN CASE ALREADY SHUFFLED DATA
	MOVE T4,DRVLEN		;GET LENGTH OF MESSAGE
	MOVNI T4,(T4)		;NEGATE AND PREPARE FOR ROUNDING
	LSH T4,^D16		;ROUND AND PUT IN LH OF REG
	HRR T4,DRVMSG		;GET ADR OF MESSAGE
DCNMS3:	MOVE T1,(T4)		;GET NEXT 4 BYTES
	MOVE T2,T1		;COPY BYTES
	MOVE T3,T1		;COPY AGAIN
	LSH T1,-2-^D8		;POSITION BYTE 1
	LSH T2,-2+^D8		;POSITION BYTE 2
	TLZ T2,600377		;STRIP EXTRA BITS
	IOR T1,T2		;INCLUDE WITH BYTE 1
	LSH T3,-4-^D8		;POSITION BYTE 3
	ANDI T3,377
	HRR T1,T3		;INCLUDE BYTE 3 WITH 1ST AND 2ND
	LSH T2,-2		;POSITION BYTE 4
	ANDI T2,377*400		;MASK OFF EXTRA BITS
	IOR T1,T2		;INCLUDE WITH FIRST 3 BYTES
	MOVEM T1,(T4)		;SAVE SHUFFLED WORD
	AOBJN T4,DCNMS3		;LOOP BACK FOR REST OF DATA
DCNMS4:	PIOFF			;DISABLE INTERRUPTS WHILE WE QUEUE IT
	SKIPN T4,PGDOMQ(P1)	;GET OUTPUT MESSAGE QUEUE FOR THE LINE
	JRST [	SETZM PGDLMX(P1) ;NO PREVIOUS MSG SENT
		HRRZ T3,PGFCOR(P1) ;GET BLOCK ADR
		SKIPN T3	;IS THERE ANYTHING THERE ?
		MOVSS T3,PGFCOR(P1) ;NO SO GET OTHER HALF
		HLLZS PGFCOR(P1) ;REMOVE FROM FREE SPACE
		HRLM T3,PGDOMQ(P1) ;THIS IS FIRST MESSAGE
		HRRZ T1,T3	;COPY ADR OF CHUNK
		HRLI T1,BLKSIZ-4 ;NUMBER OF FREE WORDS LEFT
		JRST DCNMS6 ]
	MOVEI T3,MBKFRE(T4)	;ADR OF NEXT MESSAGE BLOCK
	MOVE T1,MBKFRE(T4)	;GET FREE WORD
	SUB T1,[3,,0]		;ADJUST FOR NEW STATUS
	JUMPGE T1,DCNMS5
	HRRZ T3,PGFCOR(P1)	;GET OLD BLOCK
	SKIPN T3		;WAS THERE ONE ?
	MOVSS T3,PGFCOR(P1)	;NO SO USE ONE WE JUST GOT
	HLLZS PGFCOR(P1)	;NO LONGER FREE
	HRRZ T1,T3		;COPY ADR OF CHUNK
	HRLI T1,BLKSIZ-4	;NUMBER OF FREE WORDS LEFT
DCNMS5:	HRLM T3,MBKLNK(T4)	;SET LINK TO NEXT
DCNMS6:	MOVEM T1,MBKFRE(T3)	;SAVE FREE STUFF
	MOVE T1,DRVMSG		;GET ADR OF MESSAGE
	HRRZM T1,MBKLNK(T3)	;SAVE LINK WORD
	MOVE T1,DRVCOD		;GET DRIVER UNIQUE CODE
	MOVEM T1,MBKCOD(T3)	;SAVE IT
	MOVE T1,DRVLEN		;GET LENGTH
	MOVEM T1,MBKLEN(T3)	;SAVE IT
	HRRM T3,PGDOMQ(P1)	;THIS IS NOW LAST MESSAGE IN QUEUE
	CALL XMTDAT		;TRY TO SEND THE MESSAGE
	LOAD T1,DDTIM		;GET TIMER
	SKIPN T1		;ALREADY RUNNING ?
	MOVEI T1,TIMREP		;START IT
	STOR T1,DDTIM
	PION
	JRST RSKP		;WIN RETURN

;HERE TO SEE IF WE CAN CONTINUE JOB NEEDING CORE
SPCTST:	SKIPN PGFCOR(T1)	;DID WE GET SOME CORE YET ?
	JRST 0(4)		;NOT YET
	JRST 1(4)		;GOT SOME
	SUBTTL	HERE ONCE A SECOND TO CHECK THINGS

KDPCHK::MOVEI T1,^D1000		;TIME TILL WE WANT TO CHECK AGAIN
	MOVEM T1,KDPTIM
	SKIPL P1,KDPLIM		;GET NUMBER OF DUP11'S
	RET			;NONE
KMCHK0:	HRR P1,KDPPAG(P1)	;GET PAGE ADR
	AOS PGZTIM(P1)		;TIME SINCE COUNTERS ZEROED
	LOAD T1,DDTIM		;GET TIMER FOR LINE
	JUMPE T1,KMCHK2		;IF TIMER NOT RUNNING WE'RE DONE
	SOS T1			;DECREMENT THE TIMER
	STOR T1,DDTIM		;SAVE UPDATED TIMER
	JUMPN T1,KMCHK2		;IF TIMER DIDN'T EXPIRE DONE WITH LINE
	LOAD T1,DDSTA		;GET LINE STATE
	PIOFF			;DISABLE INTERRUPTS
	CALL @TIMDSP(T1)	;DISPATCH ON LINE STATE
	PION			;REENABLE INTERRUPTS
KMCHK2:	HRR P1,PGKDPN(P1)	;GET LINE NUMBER
	AOBJN P1,KMCHK0		;LOOP BACK FOR REST OF LINES
	RET			;HAVE DONE ALL LINES

TIMDSP:	JRST R			;KMC11 NOT RUNNING
	JRST R			;MAINT MODE
	JRST XSTART		;SENDING STARTS
	JRST REPCHK		;SENT STACK
	JRST REPCHK		;RUNNING
	SUBTTL	DDCMP TRANSMITTER -- DATA MESSAGES

XSTART:	MOVEI T1,TIMSTR		;IF THIS ONE DOESN'T GET RESULTS
	STOR T1,DDTIM		;TRY AGAIN SOON
	DMOVE T1,STRTMS		;GET PROTOTYPE START MESSAGE
	CALL XMTCTL		;SEND THE START MESSAGE
	RET			;FAILED - WE'LL TRY AGAIN LATER
	RET
	SUBTTL	DDCMP TRANSMITTER -- REP MESSAGE

;HERE TO CHECK IF WE NEED TO SEND A REP MESSAGE
REPCHK:	LOAD T2,DDREPC		;GET REP COUNTER
	AOS T2			;MAKE IT LARGER
	CAILE T2,REPMAX		;IS THIS STILL OK ?
	JRST REPHGH		;DROP LINE
	STOR T2,DDREPC		;SAVE UPDATED REP COUNTER
	MOVEI T1,TIMREP		;HOW LONG TO WAIT UNTIL WE SEND ANOTHER REP
	STOR T1,DDTIM		;RESET TIMER
	MOVE T1,REPMSG		;GET PROTOTYPE REP MESSAGE
	LOAD T2,DDHMA		;HIGHEST MESSAGE ACKED
	SKIPE PGDOMQ(P1)	;ANY MESSAGES IN QUEUE ?
	TLOA T2,MAXOUT(T2)	;HIGHEST ACKED PLUS MAX SENT
				; IF NUMBER WRAPS IS OK CUZ OF A0
	MOVSS T2		;HIGHEST ACKED IS HIGHEST SENT
	TLO T2,A0*400		;GET REST OF REP MESSAGE
	CALL XMTCTL		;SEND THE REP MESSAGE
	RET
	RET

;HERE IF REP TIMER GOES TOO HIGH
REPHGH:	HRRZ T2,PGKDPN(P1)	;GET DDCMP LINE NUMBER
	CAIN T1,STARUN		;WERE WE RUNNING ?
	 BUG (INFO,DDCTIM,<DDCMP timed out>,T2) ;TELL OPER LINE TIMED OUT
	MOVEI T1,STASTR		;SEND STARTS AGAIN
	CALL DEDLIN		;DECLARE LINE DOWN
	RET			;DISMISS
	SUBTTL	DDCMP TRANSMITTER -- ACK MESSAGE

XMTACK:	LOAD T1,DDNCD		;GET NAK CODE PENDING
	JUMPN T1,XMTNAK		;IF THERE IS ONE SEND IT INSTEAD
	SETONE DDXAK		;WANT TO SEND AN ACK
XMTAK3:	SKIPN PGXBD1(P1)	;IS FIRST BUFFER BUSY ?
	SKIPE PGXBD2(P1)	;OR IS THE 2ND BUFFER BUSY ?
	RET			;DON'T SEND ACK YET
	OPSTR <SKIPN>,DDXAK	;DO WE WANT TO SEND AN ACK ?
	RET			;NOT NOW
	LOAD T1,DDRMN		;HIGHEST MESSAGE WE RECEIVED
	LSH T1,^D8		;POSITION FOR MESSAGE
	IOR T1,ACKMSG		;GET PROTOTYPE ACK MESSAGE
	MOVE T2,ACKMSG+1	;GET REST OF PROTOTYPE MESSAGE
	CALL XMTCTL		;SEND THE MESSAGE
	RET			;FAILED
	SETZRO DDXAK		;HAVE SENT ACK NOW
	RET
	SUBTTL	DDCMP TRANSMITTER -- NAK MESSAGE

; CALL	MOVEI T1,<NAK REASON CODE>
XMTNAK:	STOR T1,DDNCD		;SAVE NAK REASON IN CASE NEED TO SEND LATER
	LOAD T2,DDRMN		;HIGHEST MESSAGE WE RECEIVED
	LSH T2,^D8		;POSITION NUMBER
	IOR T1,T2		;PUT FOLLOWING REASON FOR NAK
	IOR T1,NAKMSG		;GET PROTOTYPE NAK MESSAGE
	MOVE T2,NAKMSG+1	;GET REST OF PROTOTYPE NAK MESSAGE
	CALL XMTCTL		;SEND THE MESSAGE
	RET			;FAILED
	LOAD T1,DDNCD		;GET NAK CODE
	MOVEI T2,PGNXNK(P1)	;WHERE WE COUNT TRANSMITTED NAKS
	CAIG T1,7		;TOO LARGE TO COUNT ?
	ADDI T2,(T1)		;INDEX INTO NAK TABLE
	AOS (T2)		;COUNT NAKS SENT
	SETZRO DDNCD		;HAVE SENT NAK NOW
	RET
	SUBTTL	DDCMP TRANSMITTER -- CONTROL MESSAGE

XMTCTL:	MOVEI T3,PGXBD1(P1)	;ASSUME 1ST XMIT BUFFER DESCRIPTOR LIST
	SKIPE @T3		;IS IT FREE ?
	MOVEI T3,PGXBD2(P1)	;NOT FREE ... TRY 2ND
	SKIPE @T3		;IS IT FREE ?
	RET			;CAN'T DO IT NOW ... RETURN TO CALLER
	DMOVEM T1,PGXMS1-PGXBD1(T3) ;PUT MESSAGE IN BUFFER

	HRLZI T1,PGXMS1-PGXBD1(T3) ;ADDRESS OF BUFFER
	TLZ T1,777000		;MAKE ADR ON PAGE
	LSH T1,2		;MAKE PDP11 ADR IN LH
	ADD T1,PGUBAD(P1)	;MAKE ABSOLUTE PDP11 ADR
	HRRI T1,^D6		;BUFFER IS 6 BYTES LONG
	MOVSI T2,BDLLDS!BDLRSY!BDLSOM!BDLEOM ;COMPLETE MESSAGE
	TLZE T1,400000		;CHECK UNIBUS ADR
	TLO T2,004000		;PUT IN STATUS REG
	TLZE T1,200000		;CHECK UNIBUS ADR
	TLO T2,002000		;PUT IN STATUS REG
	DMOVEM T1,(T3)		;SAVE BUFFER DESCRIPTOR LIST

	LSH T2,4-^D18		;POSITION MEMORY EXTENSION BITS
	ANDI T2,140000		;LEAVE ONLY MEMORY EXTENSION BITS
	TRO T2,BFRENB		;SET ENABLE
	HLL T2,T1		;COPY BUFFER ADR
	SUB T2,[4*<PGXMS1-PGXBD1>,,0]	;POINT TO DESCRIPTOR
	HRRZ T1,PGKDPN(P1)	;COPY LINE NUMBER
	LSH T1,^D8		;POSITION
	IORI T1,BFADIN		;TYPE OF COMMAND
	CALL KMCINP		;GIVE BUFFER DESCRIPTOR LIST TO KMC11
	RETSKP
	SUBTTL	DDCMP TRANSMITTER -- DATA MESSAGES

;HERE TO CHECK POSSIBILITY OF SENDING A DATA MESSAGE
; CALLED AT INTERRUPT LEVEL OR WITH PIOFF
XMTDAT:	HLRZ T1,PGDOMQ(P1)	;GET ADR OF FIRST MESSAGE IN QUEUE
	SKIPE T2,PGDLMX(P1)	;GET ADR OF LAST MESSAGE SENT
	HLRZ T1,MBKLNK(T2)	;GET ADR OF NEXT MESSAGE IN QUEUE
	JUMPE T1,XMTAK3		;IN CASE NONE TO SEND NOW
	LOAD T3,DDHMA		;GET HIGHEST MESSAGE NUMBER ACKED
	SKIPN PGDLMX(P1)	;IS THIS FIRST MSG ?
	JRST XMTDT2		;YES
	LOAD T2,DDHXM		;HIGHEST MESSAGE NUMBER SENT
	SUB T2,T3		;MAKE DIFFERENCE
	SKIPGE T2		;DID NUMBERS WRAP AROUND ?
	MOVEI T2,400(T2)	;YES SO ADJUST
	CAIL T2,MAXOUT		;DO WE HAVE ENOUGH MESSAGES IN PIPE ?
	JRST XMTAK3		;DON'T SEND TOO MANY
XMTDT2:	MOVEI T4,PGXBD1(P1)	;ASSUME 1ST XMIT BUFFER DESCRIPTOR LIST
	SKIPE @T4		;IS IT FREE ?
	MOVEI T4,PGXBD2(P1)	;TRY 2ND XMIT BUFFER DESCRIPTOR LIST
	SKIPE @T4		;IS IT FREE ?
	RET			;WILL TRY AGAIN LATER
	SETZRO DDXAK		;DON'T NEED A EXPLICIT ACK NOW
	SKIPN PGDLMX(P1)	;IS THIS FIRST MESSAGE IN QUEUE ?
	STOR T3,DDHXM		;1ST MSG IN QUEUE SO RESET MSG NUMBER
	HRRZM T1,PGDLMX(P1)	;REMEMBER ADR OF LAST MESSAGE SENT
	HRRZ T3,MBKLEN(T1)	;GET LENGTH (BYTES) OF MESSAGE
	HRRZ T2,T3		;COPY COUNT
	LSH T2,-^D8		;LEAVE HIGH ORDER BITS OF COUNT
	HRLI T2,SOH		;BEGIN DATAMESSAGE HEADER
	DPB T3,[POINT 8,T2,9]	;PUT REST OF COUNT IN
	LOAD T3,DDRMN		;HIGHEST MESSAGE NUMBER RECEIVED
	LSH T3,^D8		;POSITION
	IOR T2,T3		;BYTE(18)SOH+CNT*400,CNT+R*400
	MOVEM T2,PGXMS1-PGXBD1(T4) ;SAVE FIRST HALF OF MSG HEADER
	LOAD T3,DDHXM		;LAST MESSAGE SENT
	AOS T3			;MAKES NEW MSG NUMBER
	STOR T3,DDHXM		;REMEMER WE SENT IT
	IORI T3,A0*400		;ADD A0
	HRLZM T3,PGXMS1+1-PGXBD1(T4) ;SAVE REST OF MSG HEADER
	HRRZ T1,PGDLMX(P1)	;GET ADR OF MESSAGE BLOCK AGAIN
	HRRZ T2,MBKLEN(T1)	;GET LENGTH OF MESSAGE (BYTES)
	HRLZ T1,MBKLNK(T1)	;GET ADR OF MESSAGE
	HRRI T1,PGXMS1+2-PGXBD1(T4);?}HERE WERE GOING TO PUT MESSAGE
	MOVEI T2,3(T2)		;PREPARE TO ROUND
	LSH T2,-2		;CONVERT BYTES TO WORDS
	ADDI T2,(T1)		;LAST ADR IN MESSAGE
	BLT T1,(T2)		;COPY DATA

	HRLZI T1,PGXMS1-PGXBD1(T4) ;ADR OF BUFFER
	TLZ T1,777000		;MAKE RELATIVE TO START OF PAGE
	LSH T1,2		;MAKE IT A BYTE ADR
	ADD T1,PGUBAD(P1)	;MAKE AN 11 ADR
	HRRI T1,6		;BYTE COUNTE FOR HEADER
	MOVSI T2,BDLRSY!BDLEOM!BDLSOM	;FLAGS
	TLZE T1,400000		;CHECK UNIBUS ADR BITS
	TLO T2,004000		;INCLUDE IN STATUS
	TLZE T1,200000		;CHECK UNIBUS ADR BITS
	TLO T2,002000		;INCLUDE IN STATUS
	HLR T2,T1		;COPY ADR OF HEADER
	ADDI T2,10		;MAKES ADR OF DATA
	HRR T3,PGDLMX(P1)	;GET ADR OF MESSAGE AGAIN
	HRL T3,MBKLEN(T3)	;GET DATA COUNT
	HLR T3,T2		;COPY FLAGS
	TRZ T3,BDLRSY		;DON'T RESYNC
	TRO T3,BDLLDS		;LAST SEGMENT NOW
	DMOVEM T1,(T4)		;SAVE FIRST 2 WORDS OF BUFFER DESCRIPTOR LIST
	MOVEM T3,2(T4)		;SAVE SECOND BUFFER DESCRIPTOR

	LSH T2,4-^D18		;POSITION MEMORY EXTENSION BITS
	ANDI T2,140000		;LEAVE ONLY MEMORY EXTENSION BITS
	TRO T2,BFRENB		;SET ENABLE
	HLL T2,T1		;COPY BUFFER ADR
	SUB T2,[4*<PGXMS1-PGXBD1>,,0]	;POINT TO DESCRIPTOR
	HRRZ T1,PGKDPN(P1)	;COPY LINE NUMBER
	LSH T1,^D8		;POSITION
	IORI T1,BFADIN		;TYPE OF COMMAND
	CALL KMCINP		;GIVE BUFFER DESCRIPTOR LIST TO KMC11
	RET			;DONE
	SUBTTL	HERE TO ENABLE RECEIVER

; CALL	MOVEI T3,PGRBD1(OR PGRBD2)(P1)
RCVENB:	SETOM PGRMS1-PGRBD1(T3)	;DEBUGGIN AID
	SETOM PGRMS1+1-PGRBD1(T3) ;DITTO
	HRLZI T1,PGRMS1-PGRBD1(T3) ;ADR OF BUFFER
	TLZ T1,777000		;MAKE ADR RELATIVE TO PAGE
	LSH T1,2		;CONVERT TO BYTE ADR
	ADD T1,PGUBAD(P1)	;MAKES RIGHT UNIBUS ADDR
	HRRI T1,600		;LENGTH OF BUFFER
	MOVSI T2,BDLLDS
	TLZE T1,400000		;CHECK UNIBUS ADR
	TLO T2,004000		;PUT IN STATUS REG
	TLZE T1,200000		;CHECK UNIBUS ADR
	TLO T2,002000		;PUT IN STATUS REG
	DMOVEM T1,(T3)		;SAVE BUFFER DESCRIPTOR LIST

	LSH T2,4-^D18		;COPY BUFFER ADR BITS 17 & 16
	ANDI T2,140000		;STRIP EXTRA BITS
	IORI T2,BFRENB		;ENABLE BUFFER
	HLL T2,T1		;COPY BUFFER ADR
	SUB T2,[4*<PGRMS1-PGRBD1>,,0] ;MAKE ADR OF BUFFER DESCRIPTOR LIST
	HRRZ T1,PGKDPN(P1)	;COPY LINE NUMBER
	LSH T1,^D8		;POSITION LINE NUMBER
	IORI T1,BFADIN!KMCIOT	;TYPE OF REQUEST
	CALL KMCINP		;GIVE THIS TO THE KMC11
	RET
	TNXEND
	END