Trailing-Edge
-
PDP-10 Archives
-
BB-J724B-SM_1982
-
sources/xdte10.p11
There are 27 other files named xdte10.p11 in the archive. Click here to see a list.
.SBTTL XDTE10 - driver for a DECsystem-10 through a DTE-20
; This module replaces the DL10 module in the DN60 front-end
; program to use the DTE-20 on a 1090 configuration rather
; than the DTE-20 on the 2040 or the DL10 on a 1070.
;
; Note that the hardware is the same for TOPS-10 and TOPS-20, but
; the TOPS-10 version is driven by D60SER/D6SINT, which interface
; to the TOPS-10 DTESER module for the DN60. The TOPS-20 version
; is driven by the TOPS-20 module FESRV which interfaces to
; DTESRV. FESRV was enhanced for the DN60 project, but
; is not special-purpose as D60SER/D6SINT is.
;
; This module conditionally assembles to interface to FESRV on
; TOPS-20 by setting the switch FTFEDV to a nonzero value.
;
; XDTE10.P11 is a replacement for the old HDTE10.P11 to use the
;common protocol module XTENCM and its standard interface.
.REPT 0
Things still to do, loose ends:
o separate common code for XDTE10 and XDTE20 (and perhaps XDMC20)
o move DLGONE to driver
o change DLACKF to be .WORD 0
o move DTE save code to TRPINT
.ENDR;.REPT 0
.REPT 0
COPYRIGHT (c) 1982,1981,1980, 1979
DIGITAL EQUIPMENT CORPORATION, maynard, mass.
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.
.ENDR;.REPT 0
VDTE10=033 ;XDTE10 edit number
VEDIT=VEDIT+VDTE10 ;DN60 total edit number
.REPT 0
Revision History
Edit Who Date What
5(31) KR 13-Oct-80 Strip out all common code, implement standard interface
This new module is (very) loosely based on 4(30) of
HDTE10.
5(32) RLS 28-JAN-81 Insert FTFEDV condtional code to create a TOPS-20/FESRV
protocol driver. Primary difference is that the DN60
header comes as an indirect message and any data
comes as a separate FE header,indirect transfer pair.
Also, each indirect part must be explicitly ack'd.
5(33) RLS 12-JUN-81 Insert FTP5 conditional code to create TOPS-20
release 5 protocol. Primary differences are an
expanded header(up to 8 words) and the exclusive
use of direct mode transfers. The response
header includes a 2 word device status and a 2
word line status. TENTSK may elect to return
no data on a read dta fcn - handled by setting
the queue size to zero and ringing the 10 doorbell.
Similarly the deposit fcn doesn't even return a
header...no header returned => no data returned.
.ENDR;.REPT 0
.REPT 0
This section contains the DTE-20 driver and the queued protocol
interface conforming to the RSX-20F specifications for
communication between the PDP-11 and DECsystem-10.
This module contains device-dependent code for talking to
the TOPS-10 modules D60SER/D6SINT and DTESER. It calls a common
protocol module, XTENCM.P11, via the standard interface, namely
calling either WAKTEN to wake up the DL10/DTE task if the -10
has had some sort of error, or WAKFNC to provide a function and
wake up the task if it has work to do.
The following symbols defined in this module are referred to by the
rest of the DN60 code:
DLSTCS routine to store stopcode value
DSPDLT once/tick timer code
DSPDLS once/second timer code
INITDL initialize -10 interface hardware
DLRESP send back response to -10
BLECHI block transfer of input data
BLECHO block transfer of output data
BYTCHI byte transfer of input data
BYTCHO byte transfer of output data
DT10DS two word device status - FTP5
DT10LS two word line status - FTP5
The following symbols defined elsewhere are used by this module:
T.HDR displacement of header in DL10/DTE task block
T.FN function code
T.RES result code
T.DEV device number
T.LIN line number
T.LNG (word) length of data
WAKTEN routine to wake DL10/DTE task
WAKFNC routine to give a function to DL10/DTE task and wake it
TENSLP routine to put DL10/DTE task to sleep waiting for EBTENI
DLGONE cell set to -1 when -10 interface is dead, 0 when it is alive
note, driver alone can set or clear it
This module implements the DN60-DTE interaction as a single state
machine, pieces of which are executed at both interrupt and non-interrupt
level. The subroutine NXTPRT does the next part of the state machine;
it has one of six interrupt conditions (I..xxx) set in cell INTCND. Each
state examines interrupt conditions in a fixed order, and decides upon
a new state to enter.
The interrupt conditions are generated by both the DTE hardware and the
DN60 software; the hardware conditions are to-10 done interrupt, to-11 done
interrupt and doorbell interrupt. The interrupt handler generates another
condition, TGHA doorbell, if valid examine is not on in the status word from
the -10 on a doorbell. The remaining two interrupt conditions are 1) response
ready (generated by DLRESP which the common module calls when it has finished
building the reply to a request) and 2) TGHA timer expired, which means the
once a second code has decremented the TGHA timer to zero.
.ENDR;.REPT 0
.SBTTL Symbol definitions
;Parameters
.IIF NDF,FTP5,FTP5=0 ;default to version 4 rpotocol
.IIF NE,FTP5,FTFEDV=0 ;if version 5 protocol, can't have 4
.IIF NDF,FTFEDV,FTFEDV=0 ;default to no FE device interface
.IIF NE,FTFEDV,MAXDAT=376 ;FE device will only xfer small amount
.IIF NDF,MAXDAT,MAXDAT=^D5*CHDATL ;max data transferred in a single request
.IIF NDF,TGHMAX,TGHMAX=5. ;max number of seconds to wait for TGHA
.IIF NDF,DLYPRM,DLYPRM=0 ;make no DTE delay default
;Define more mnemonic interrupt bits
I..10D=TS.XNT ;-10 done
I..11D=TS.ETD ;-11 done
I..DBL=TS.XEE ;-11 doorbell
I..TGH=TS.MPE ;TGHA doorbell (software bit)
I..RSP=TS.EPE ;DLRESP (software bit)
I..TMO=TS.XER ;TGHA timer expire (software bit)
;(The hardware error bits used to define the software interrupt conditions
;are guaranteed never to be on during the state machine, as the interrupt
;code traps them before dispatching to the state machine.)
;DN60 function definitions
DF.RED=1. ;READ DATA INTO THE PDP-10
DF.WRT=2. ;WRITE DATA FROM THE PDP-10
DF.RDS=3. ;READ DEVICE STATUS
DF.WDC=4. ;WRITE DEVICE COMMAND
DF.RLS=5. ;READ LINE STATUS
DF.WLC=6. ;WRITE LINE COMMAND
DF.RPS=7. ;READ PORT STATUS
DF.WPC=8. ;WRITE PORT COMMAND
DF.EXA=9. ;examine function
DF.DEP=10. ;deposit function
DF.MAX=DF.DEP ;max fcn code
;NOTE: Even valued functions have indirect data from the ten and odd valued
; functions do not(they send indirect data to the ten). This fact is used
; in FE device service to determine whether anything follows the FEH from
; the ten. Non-FE service just tests the indirect data flag in DT11FN.
;The driver needs to know DF.EXA and DF.DEP, since it fulfills them at interrupt
;level instead of dispatching to the task.
.SBTTL DTE20 HARDWARE BITS
TE.BRL= 5 ;(?)DTE bus request level
TE.LVL= PR.TEN ;PROCESSOR LEVEL FOR DTE20 INTERRUPTS
TE.VEC=774 ;VECTOR FOR DTE20 INTERRUPTS
TE.DYC=0 ;DELAY COUNTER
TE.XW3=2 ;DEPOSIT OR EXAMINE WORD 3
TE.XW2=4 ;DEPOSIT OR EXAMINE WORD 2
TE.XW1=6 ;DEPOSIT OR EXAMINE WORD 1
TE.XA1=10 ;TEN ADDRESS WORD 1
TS.DEP=B12 ;DEPOSIT
TS.POF=B11 ;EXAMINE/DEPOSIT PROTECT OFF
TS.PEX=B15 ;PHYSICAL EXAMINE
TE.XA2=12 ;TEN ADDRESS WORD 2
TE.XBC=14 ;TO-10 BYTE COUNT (?)
TE.EBC=16 ;TO-11 BYTE COUNT
TS.IFB=B15 ;I FLIPFLOP BIT
TS.ZST=B14 ;ZSTOP
TS.EBM=B13 ;TO 11 BYTE MODE
TE.XAD=20 ;TO-10 PDP-11 MEMORY ADDRESS
TE.EAD=22 ;TO-11 PDP-11 MEMORY ADDRESS
TE.XDT=24 ;TO-10 PDP-11 DATA WORD
TE.EDT=26 ;TO-11 PDP-11 DATA WORD
TE.DG1=30 ;DIAGNOSTIC WORD 1
TE.DG2=32 ;DIAGNOSTIC WORD 2
TS.RST=B6 ;RESET DTE20
TE.STW=34 ;STATUS WORD
TS.XNT=B15 ;TO-10 NORMAL TERMINATION
TS.XTS=B14 ;TO-10 NORMAL TERMINATION STATUS
TS.XER=B13 ;TO-10 ERROR TERMINATION (AND STATUS)
TS.XEC=B12 ;CLEAR TO-10 ERROR TERMINATION
TS.XEE=B11 ;10 REQUESTED -11 INTERRUPT
TS.RES=B11 ;REQUEST -11 STATUS
TS.EIS=B10 ;10 REQUESTS 11 INTERRUPT STATUS
TS.MPE=B9 ;11 MEMORY PARITY ERROR
TS.EEX=B8 ;11 REQUESTED 10 INTERRUPT
TS.ETD=B7 ;TO-11 TRANSFER DONE
TS.ENT=B6 ;TO-11 NORMAL TERMINATION
TS.EEE=B5 ;11 INTERRUPT ENABLE
TS.EPE=B4 ;E-BUS PARITY ERROR
TS.RM=B3 ;RESTRICTED MODE
TS.DEI=B3 ;DISABLE -11 INTERRUPT
TS.XDN=B2 ;DEPOSIT/EXAMINE DONE
TS.EET=B1 ;TO-11 ERROR TERMINATION (AND STATUS)
TS.IEN=B0 ;INTERRUPTS ENABLED
TS.CET=B0 ;CLEAR TO-11 ERROR TERMINATION
TE.DG3=36 ;STATUS WORD 3
TS.TBM=B0 ;TO TEN BYTE MODE
.SBTTL RSX-20F queued protocol definitions
;THIS DEFINES THE DEVICE QUEUE POINTERS AND FUNCTION CODES
; FOR THE RSX-20F QUEUED PROTOCOL.
; DEVICE QUEUE POINTERS
DLDCTY =1 ;DEVICE CODE FOR CTY
DLDL11 =2 ;DEVICE CODE FOR DL11
DLDH11 =3 ;DEVICE CODE FOR DH11 (1)
DLDDLS =4 ;DEVICE CODE FOR DATA LINE SCANNER (1)
DLDLPT =5 ;DEVICE CODE FOR LPT
DLDCDR =6 ;DEVICE CODE FOR CDR
DLDCLK =7 ;DEVICE CODE FOR CLOCK
DLDPFE =10 ;PSEUDO DEVICE FOR FE
DLDDAS =12 ;DN61 DEVICE CODE
DLDCPU =200 ;PSEUDO DEVICE PDP10 CPU
DLDKLE =201 ;KL ERROR PSEUDO DEVICE
; TO ELEVEN QUEUE ENTRY
; FUNCTION CODE DEFINITIONS
DTFRQD =1 ;REQUEST DEVICES
DTFHAD =2 ;HERE ARE DEVICES
DTFSTR =3 ;STRING DATA
DTFLNC =4 ;LINE/CHARACTER DATA
DTFRDS =5 ;RETURN DEVICE STATUS
DTFSDS =6 ;SET DEVICE STATUS
DTFHDS =7 ;HERE IS DEVICE STATUS
DTFDES =10 ;DEVICE ERROR STATUS
DTFRTD =11 ;RETURN TIME OF DAY
DTFHTD =12 ;HERE IS TIME OF DAY
DTFFOD =13 ;FLUSH OUTPUT DEVICE QUEUE
DTFSNA =14 ;SEND ALL
DTFTDU =15 ;DEVICE DIAL UP
DTFTHU =16 ;DEVICE HANG UP
DTFSAK =17 ;ACKNOWLEDGE DEVICE DONE
DTFXOF =20 ;X-OFF (TTY ONLY)
DTFXON =21 ;X-ON (TTY ONLY)
DTFSTS =22 ;SET TTY SPEED
DTFSLA =23 ;set line allocation
DTFBTP =24 ;11 REBOOT WORD
DTFAKA =25 ;ACK ALL
DTFSPT =26 ;START/STOP LINE
DTFEDR =27 ;ENABLE/DISABLE REMOTES
DTFLDR =30 ;LOAD LP RAM
DTFLDV =31 ;LOAD LP VFU
DTFDAS =32 ;DN60 FUNCTION DATA
DTFFNM =33 ;1 GREATER THAN MAX FUNCTION
.SBTTL DTE20 COMMUNICATION AREA OFFSETTS (WORD NAMES)
;The comm region consists of a circular list of blocks - one for each processor
;communicating with each other. Each block is composed of a base area which has
;some info about the "owning" processor and a series of "TO" blocks, one for
;each processor to which the owning processor communicates. In theory, the size
;of each area may vary but only in 8 36-bit word units.
;A processor sends status info to another processor by setting the data in
;his owned "TO" block for that processor and,similarly, reads info for himself
; from that processor by looking at that processor's "TO" block for himself.
;The 11 addresses data in the comm region relative to an address space that
;is individually relocated for the particular dte through which the 11 examines
;the 10's memory. Immediately preceeding the comm region is a series of single
;words, one for each connected processor. The relative address zero points at
;the particular word associated with the processor who is looking at 10 memory.
;This word contains the processor's own identifying number and the offset,
;relative to the beginning of the comm region, of the processor's own area.
;The beginning of the comm region is located in the processor's address space
; at <processor number>+1. Thus the address of the processor's own area is
;located at "offset"+<processor number>+1.
;The 11 examines/deposits 36 bit words in 10 memory - these are formatted in
;the 11 as three consective 16 bit words:
; word 0 - low order 4 bits - 10 word bits 0-3
; word 1 - 10 word bits 4-19
; word 2 - 10 word bits 20-35
;11's processor word - relative address 0
; xam word 1 ;must be zero
; xam word 2
; high byte ;processor number for me
; low byte ; unused
; xam word 3 ; offset to my area relative to beg of
; comm region
;processor's own area
; base block offsets
PBPID=0 ;PROCESSOR IDENTIFICATION WORD
; XAM WORD 1
PB.TEN=10 ;this processor is a 10
PB.VER=7 ;mask for comm version number
; xam word 2
; high byte = protocol version being used
; low byte
PB.NPR=370 ;mask for number of processors in this area
PB.SIZ=7 ;mask for size of base area(in 8 word units)
; xam word 3
; word = processor name
PBPNA=1 ;POINTER TO COMM AREA OF NEXT PROCESSOR (CIRC LIST)
PBCPS=2 ;CLOCK CPS COUNT
PBTOD=3 ;TIME OF DAY
PBDAT=4 ;DATE
PBPW1=5 ;keepalive count
PBPW2=6 ;PROCESSOR STATUS WORD2
PBPW3=7 ;PROCESSOR STATUS WORD3
PBPW4=10 ;PROCESSOR STATUS WORD4
PBPW5=11 ;PROCESSOR STATUS WORD5
PBPW6=12 ;PROCESSOR STATUS WORD6
PBPW7=13 ;PROCESSOR STATUS WORD7
PBPW10=14 ;PROCESSOR STATUS WORD10
PBPW11=15 ;PROCESSOR STATUS WORD11
PBPW12=16 ;PROCESSOR STATUS WORD12
PBPW13=17 ;PROCESSOR STATUS WORD13
PBASIZ=20 ;size of base area = offset to 1st TO block
; TO block offsets
TOPID=0 ;FOR PROCESSOR IDENTIFICATON WORD
; xam word 1
TO.TEN=10 ;this connection is to a 10
TO.DTE=4 ;a DTE connects these two processors
TO.DTN=3 ;mask for the DTE number
; xam word 2
; high byte unused
; low byte
TO.PRO=370 ;mask for protocol in use: 0=RSX20F(TOPS-20 version 4
; 1=MCB
; 2=DN60(TOPS-20 version 5)
TO.SIZ=7 ;mask for size of this TO block
; xam word 3
; word = processor number that this block is "TO"
TOPCA=1 ;POINTER TO COMM AREA OF THE PROCESSOR ASSOC WITH THIS BLOCK
; xam word 1 - unused
; xam wrod 2 - unused
; xam word 3
; word = offset to "TO" processor's own area relative to beginning of comm region
TOSTAT=2 ;COMMUNICATION STATUS WORD
; xam word 1
TO.PFL=10 ;power fail indicator
TO.REL=4 ;reload 11 indicator
TO.INI=2 ;MCB,DN60 protocol initializing flag
TO.VEX=1 ;valid examine flag - guaranteed to be set
; xam word 2
TO.QP=100 ;queued protocol in use
TO.FWD=4 ;do a word mode xfer(16 bit)
TO.IND=2 ;indirect transfer
TO.IT=1 ;xfer in progress from me to him
; xam word 3
; high byte = 10 queue count
; low byte = 11 queue count
TOXFSZ=3 ;queue size word
; xam word 1 - unused
; xam word 2 - unused
; xam word 3
; word(12 bits) = numbers of bytes in this transfer
;remaining 4 words are not relavent to the 11
.SBTTL Macro definitions
;Macros to disable and enable interrupts from the dte
.MACRO DTEOFF
MOV #TS.DEI,TE.STW(R5) ;disable dte interrupts
.ENDM
.MACRO OFFDTE
MOV DTEBAD,-(SP)
ADD #TE.STW,(SP)
MOV #TS.DEI,@(SP)+ ;disable dte interrupts
.ENDM
.MACRO DTEON
MOV #TS.EEE,TE.STW(R5) ;enable dte interrupts
.ENDM
.MACRO ONDTE
MOV DTEBAD,-(SP)
ADD #TE.STW,(SP)
MOV #TS.EEE,@(SP)+ ;enable dte interrupts
.ENDM
;Macro to declare next state in state machine
;Call NXTINT to define following code as next state
;or NXTINT #name to define "name" as next state
;or NXTINT cell to define contents of cell as next state
.MACRO NXTINT ADR,?TAG
.IF B,<ADR>
MOV #TAG,NXTPC
GOBACK
TAG:
.IFF;.IF B,<ADR>
MOV ADR,NXTPC
.ENDC;.IF B,<ADR>
.ENDM NXTINT
;Macro to go back to state dispatch level
.MACRO GOBACK
.IF NE,DTBUG
JMP NXTCN1 ;try to schedule another condition
.IFF;.IF NE,DTBUG
JMP NXTCND
.ENDC;.IF NE,DTBUG
.ENDM GOBACK
;Macro to define state entry block for a state -- must be used at state entry point
;Contains the interrupt bits that cause 11err state, the bits that cause
;10err state, followed by pairs of masks and dispatch addresses (terminated
;by a zero word).
.MACRO INTTYP ERR11,ERR10,ARG,?TAG
STBDSP=.
E10DSP=.-STBDSP
.WORD ERR10 ;means -10 has done protocol wrong and
; should be considered down
STBDSP=.-STBDSP
.IRP DISP,<ARG>
DSPENT DISP ;generate bit mask, dispatch address
.ENDR;.IRP DISP,<ARG>
.WORD 0
TAG:
.ENDM INTTYP
;Macro to define dispatch entries within state entry block
.MACRO DSPENT BITS,ADR
.WORD BITS,ADR
.ENDM DSPENT
;Macro for call that only stores PC (i.e. is really a JMP)
.MACRO XCALL ADR
CALL ADR
.ENDM XCALL
;Macro to test carry and XCALL an error routine if set
.MACRO IFCRY WHERE,?TAG
BCC TAG
XCALL WHERE
TAG:
.ENDM IFCRY
;Macro to test equal and XCALL an error routine if not set
.MACRO IFNE WHERE,?TAG
BEQ TAG
XCALL WHERE
TAG:
.ENDM IFNE
.MACRO IFEQ WHERE,?TAG
BNE TAG
XCALL WHERE
TAG:
.ENDM IFEQ
;Macro to do DTE examine
;Call EXAM disp for examine,dest to examine and copy to dest
; EXAM disp for examine,, to examine and leave in TE.XW1-3
.MACRO EXAM LOWADR,DEST,TAG,?TAG1
CLR TE.XA1(R5) ;set examine EVA, protectin off, bits 13-19 0
MOV LOWADR,TE.XA2(R5) ;set low order address, start examine
CALL DLWEDN ;wait for examine done to set
BCC TAG1
CLR TE.XA1(R5) ;set examine EVA, protectin off, bits 13-19 0
MOV LOWADR,TE.XA2(R5) ;set low order address, start examine
CALL DLWEDN ;wait for examine done to set
BCS TAG ;is timeout, don't store value
TAG1:
.IF NB,<DEST>
MOV TE.XW1(R5),DEST ;store first word of result (KL bits 0-3
; right justified)
MOV TE.XW2(R5),DEST+2 ;store bits 4-19
MOV TE.XW3(R5),DEST+4 ;store bits 20-35
.ENDC;.IF NB,<DEST>
.IIF NE,FTRACE, MFPS -(SP)
TRACE TRCDTE,<TE.XW1(R5),TE.XW2(R5),TE.XW3(R5)>
.IIF NE,FTRACE, MTPS (SP)+
.ENDM EXAM
;Macro to do DTE deposit
;Call DEPO disp for deposit,source to copy source and deposit
; DEPO disp for deposit,, to use contents of TE.XW1-3
.MACRO DEPO LOWADR,SRC,TAG,?TAG1
.IF NB,<SRC>
MOV SRC,TE.XW1(R5) ;get first word (KL bits 0-3)
MOV SRC+2,TE.XW2(R5) ;get second word (bits 4-19)
MOV SRC+4,TE.XW3(R5) ;get third word (bits 20-35)
.ENDC;.IF NB,<SRC>
TRACE TRCDTE,<TE.XW1(R5),TE.XW2(R5),TE.XW3(R5),LOWADR>
MOV #TS.DEP,TE.XA1(R5) ;set deposit EVA, protection on, bits 13-19 0
MOV LOWADR,TE.XA2(R5) ;move low order address and start deposit
CALL DLWEDN ;wait for done flag
BCC TAG1
MOV #TS.DEP,TE.XA1(R5) ;set deposit EVA, protection on, bits 13-19 0
MOV LOWADR,TE.XA2(R5) ;move low order address and start deposit
CALL DLWEDN ;wait for done flag
BCS TAG ;carry will be set if -10 times out
TAG1:
.ENDM DEPO
.SBTTL Data storage
; THE DTE DATA BASE.
DTIDBL: .WORD 0 ;KEEP DOORBELL INTERRUPT COUNT HERE
DTIXDN: .WORD 0 ;KEEP TEN DONE INTERRUPT COUNT HERE
DTIEDN: .WORD 0 ;ELEVEN DONE INTERRUPT COUNT HERE
DTEPCA: .WORD 0 ;ADDRESS OF PRIV OFFSET TABLE ENTRY
DTPSTA: .WORD 0 ;OUR DTE20 STATUS WORD AND
DTEBAD: .WORD 0 ; DTE ADDRESS (INITTED AT STARTUP)
DTEDTO: .WORD 0 ;DEPOSIT/EXAMINE TIMEOUT
;ALSO USED FOR STORING
;INTERRUPT VECTOR LOCATION
;IN CHK11.P11 MODULE
DLACKF: .WORD 0 ;NON-ZERO WHEN IN PRIMARY PROTOCOL
DTQSTA: ;ZEROED AT STARTUP
DT11ST: .BYTE 0 ;STATE OF TO-11 MECHANISM
DT10ST: .BYTE 0 ;AND OF TO-10
DT10AK: .WORD 0 ;IF NON-ZERO, ED DATA EXPECTED AND MUST BE ACKED
DTPTCT: .WORD 0 ;COUNT OF MESSGES PUNTED
; POINTERS TO COMMUNICATIONS AREA
DLCMBS: .WORD 0 ;BASE OF COMMUNICATION AREA
DLMYPN: .WORD 0 ;MY PROCESSOR NUMBER
DLDPOF: .WORD 0 ;DEPOSIT OFFSET FROM EXAMINE
; PROCESSOR IDENTIFICATION TABLE
; DTPIDT FORMAT:
; 5 WORDS/ENTRY
; 16 ENTRYS IN THE TABLE ONE FOR EACH PROCESSOR IN COMMUNICATION
; COMMUNICATION NUMBERS ARE LIMITED TO THE RANGE 0-15.
; (PROCESSOR 0) DTPIDT: ADDRESS OF DTE20 TO ACCESS THIS PROCESSOR
DTENM=0
; (PROCESOR 0) ADDRESS TO COMMUNICATE TO PROCESSOR 0
DTEMYN =2
; (PROCESSOR 0) ADDRESS TO COMMUNICATE TO PROCESSOR 0 (WRITE)
DTDMYN =4
; (PROCESSOR 0) ADDRESS FROM GENERAL
DTEHSG =6
; (PROCESSOR 0) ADDRESS FROM SPECIFIC
DTEHSM =10
; (PROCESSOR 1) ADDRESS OF DTE20 TO USE TO ACCESS THIS PROCESSOR
; ...........
DTPIDT:
.NLIST
.REPT 16.*5.
.WORD 0
.ENDR
.LIST
DTXTM3: .WORD 0 ;EXAMINE WORD 3 (TEMP STORAGE) TO BE
DTXTM2: .WORD 0 ;EXAMINE WORD 2 -USED ONLY BECAUSE EXAMINE
DTXTM1: .WORD 0 ;EXAMINE WORD 1 - OR DEPOSIT
; MAY FAIL AND
; MUST BE REDONE
DTSTT: .WORD 0 ;TO 10 STATUS
.WORD 0
.WORD 0
DTQCNT =DTSTT+4 ;BOTH OF BELOW
DT10QC =DTSTT+4 ;TO 10 QUEUE COUNT
DT11QC =DTSTT+5 ;TO 11 QUEUE COUNT
DTKPLV: .WORD 0 ;last successful 11 keep alive
NXKPLV: .WORD 0 ;next time we really want to do one
.IF NE,DEBUG
DTESAV:
.NLIST
.REPT 20 ;FOR SAVING DTE20 REGISTERS
.WORD 0
.ENDR
.LIST
.ENDC ;.IF NE,DEBUG
;Queued protocol header input buffer
DT11HD:
.IF EQ,FTP5
.WORD 0 ;count of bytes in this message
DT11FN: .WORD 0 ;queued protocol function code
DT11DV: .WORD 0 ;queued protocol device number
.WORD 0 ;unused
.IF NE,FTFEDV
DT11UC: .WORD 0 ;FE#,,BYTE COUNT TO FOLLOW
.ENDC ;DEFINED ONLY FOR FE DEVICES
.ENDC ;.IF EQ,FTP5
D11HDL=.-DT11HD ;length of to 11 direct header
DT11DF: .WORD 0 ;DN60 function code
DT11AD: .WORD 0 ;address (exam/depo) or DN60 line,,dev
DT11DT: .WORD 0 ;data (deposit) or length of indirect msg
.IF NE,FTP5
DT11A3: .WORD 0 ;arg3 - unused
DT11A4: .WORD 0 ;arg4 - unused
DT11A5: .WORD 0 ;arg5 - unused
DT11A6: .WORD 0 ;arg6 - unused
DT11A7: .WORD 0 ;arg7 - unused
.ENDC ;IF NE,FTP5
D11DFL=.-DT11DF ;length of to 11 DN60 header
.IF NE,FTFEDV
DTACKR: .WORD 0 ;ack flag - nonzero => ack must be sent
; THIS HEADER IS FOR SENDING "ACK" TO THE TEN
; EACH TIME 11 RECEIVED INDIRECT DATA.
DTAKHD: .WORD 0 ;NO OF BYTES IN THIS HEADER
DTAKFN: .WORD 0 ;ACK FUNCTION CODE
DTAKDV: .WORD 0 ;FE DEVICE CODE
.WORD 0 ;unused
DTAKUC: .WORD 0 ;HAS FE# RIGHT JUSTIFIED
.ENDC ;.IF NE,FTFEDV
;Queued protocol header output buffer
.IF NE,FTP5
RSPSIZ: .WORD 0 ;size of response header
.ENDC ;IF NE,FTP5
DT10HD:
.IF EQ,FTP5
.WORD 0 ;count of bytes in this message
DT10FN: .WORD 0 ;queued protocol function code (must be 32)
DT10DV: .WORD 0 ;queued protocol device number (must be DLDDAS)
.WORD 0 ;unused
.IF NE,FTFEDV ;DEFINED ONLY FOR FE DEVICES
DT10UC: .WORD 0 ;FE#,,BYTE COUNT TO FOLLOW
.ENDC ;NE FTFEDV
.ENDC ;.IF EQ,FTP5
D10HDL=.-DT10HD ;length of to ten direct header
DT10DF: .WORD 0 ;DN60 function code
DT10AD: .WORD 0 ;address (exam/depo) or DN60 line,,dev
DT10DT: .WORD 0 ;data (deposit) or length of indirect msg
.IF NE,FTP5
DT10A3: .WORD 0 ;return val3 - unused
DT10DS: .WORD 0,0 ;device status
DT10LS: .WORD 0,0 ;line status
.ENDC ;IF NE,FTP5
D10DFL=.-DT10DF ;length of to ten dn60 header
;Queued protocol comm-region status
TCSTFX: .BLKW 3 ;status word from -10
;Queued protocol data buffers (indirect part)
INBUF: ;input data buffer
OUTBUF: ;output data buffer
.BLKB MAXDAT
;Buffer control cells (used by BLECHI, BLECHO, BYTCHI, BYTCHO)
OUTPTR: .WORD 0 ;current output pointer
OUTCTR: .WORD 0 ;bytes left to go till output overflow
INPPTR: .WORD 0 ;current input pointer
INPCTR: .WORD 0 ;bytes left to go till input runs out
;TGHA Control cells
TGHCNT: .WORD 0 ;0 means TGHA not running, > 0 means seconds
; before TGHA timer expires
;State machine dispatch information
NXTPC: .WORD 0 ;next state address
TNXTPC: .WORD 0 ;copy of NXTPC while TGHA is running
.IF NE,DTBUG
WITHIN: .WORD 0 ;indicate we are within the state machine
.ENDC;.IF NE,DTBUG
;State machine interrupt conditions
INTCND: .WORD 0 ;interrupt conditions active at current
; entry into state machine
;State machine stack
.IIF NDF,STKLEN,STKLEN=40. ;default number of words of stack
INTGW: .WORD 0 ;guard word for overwriting stack
.BLKW STKLEN ;body of stack
INTSTK: ;address for start of stack + 2
STATSP: .WORD 0 ;current state machine stack pointer
INTSP: .WORD 0 ;current caller (of state machine) stack pointer
;-10 link state information
;DLGONE: .WORD 0 ;0 when talking, -1 when down
;actually defined elsewhere
PROTER: .WORD 0 ;when DLGONE = -1, 0=ten down, 1=protocol
; error
;Debugging information
.IF NE,DTBUG
LSTTWC: .BLKW STKLEN ;copy of stack for last caller of TENDWN
SAVSTK: .WORD 0 ;tag for start of saved stack and pointer
; save area
LSTINT: .WORD 0 ;interrupt conditions on last running of state
; machine
INTFLG: .WORD 0 ;flag that we are within DTE interrupt
.ENDC;.IF NE,DTBUG
.SBTTL DTE initialization
INITDL: ;initialize DTE communications
SAVE <R5> ;save standard hardware register
PIOFF
MOV DTEBAD,R5 ;get hardware address
TST DLACKF ;are we in primary protocol?
BEQ 14$ ;no, just try to start it
MOV #50,R2 ;number of tries
MOV #TS.RST,TE.DG2(R5) ;yes, reset DTE-20
10$: CALL CHKTEN ;check on -10's health
BCS 14$ ;dead, go try to start it up again
SOB R2,10$ ;keep trying till count exhausted
.IF NE,DTBUG
INC #0
.ENDC;.IF NE,DTBUG
99$: PION
RESTOR <R5> ;restore registers
RETURN
14$: CLR DLACKF ;indicate out of primary protocol
MOV #TS.EEX,TE.STW(R5) ;ring -10 doorbell to wake it up
MOV #50,R2 ;times to try
15$: CALL CHKTEN ;see if up now
BCC 19$ ;yes, mark it up
SOB R2,15$ ;keep trying
.IF NE,DTBUG
INC #0
.ENDC;.IF NE,DTBUG
BR 99$ ;give up if takes too long
19$: TRACE TRCPRO,<R2,JIFCLK>
MOV #-1,DLACKF ;mark primary protocol runnning
CLR DLGONE ;mark -10 up
CALL DLINDB ;setup DTE block(s)
BCS 21$ ;if error, die
CALL INISTA ;initialize state machine
BR 99$ ;return
21$: ;here because -10 looked up but was
; really down
CLR DLACKF ;flag primary protocol not running
MOV #-6,DLGONE ;note ten is down
BR 99$ ; and exit
.SBTTL Stopcode processing
DLSTCS: ;here on stopcode to ask -10 to reload us
TST DLGONE ;see if -10 alive
BNE 99$ ;no, no chance at asking him to reload either
.IF NE,DTBUG
TST STPFLG ;have we been here once?
BEQ 5$ ;no, continue
HALT ;just die
5$:
MOV #-1,STPFLG
.ENDC;.IF NE,DTBUG
SAVE <R2,R3,R5>
MOV DTEBAD,R5
MOV DTEPCA,R3
PIOFF
CALL SAVDTE ;save DTE registers on stopcode
BIS #TO.REL,DTSTT ;set reload bit
CALL SETSTS ;send status to -10
BCS 90$
MOV #TS.EEX,TE.STW(R5) ;and ring -10 doorbell
90$: PION
RESTOR <R5,R3,R2>
99$: RETURN
.IIF NE,DTBUG,STPFLG: .WORD 0
.SBTTL DTE-20 interrupt
.REPT 0
This routine runs a single-valued state machine (instead of one for input
and one for output as the old code did) at interrupt level; any incorrect
interrupt causes the driver to inform the common code that the -10 is down.
The events that may trigger a change of state are:
1) receipt of a normal doorbell interrupt (i.e. with valid examine set)
2) receipt of a to-11 done interrupt
3) receipt of a to-10 done interrupt
4) receipt of a TGHA doorbell interrupt (i.e. with valid examine not set)
5) call to DLRESP by DL10/DTE task to send a response back to the -10
6) TGHA timer expiration
The major states and their processing (in parenthesis) and state transitions
(F: means failure, S: means success) are:
idle between transactions 4=>(set TGHA flag and timer)wfg-idle
1=>(setup to read header)F:wfg-wfeh,S:wfeh
2,3=>-10 error
5,6=>-11 error
wfeh waiting to read header 4=>(set TGHA flag and timer)wfg-wfeh
2=>(test for indirect function)S:wfeb,F:(check for
examine/deposit)F:(wake DL10/DTE task)wftsk,
S:(build answer header, ring -10 doorbell,
send header)F:wsth,S:wfth
1,3=>-10 error
5,6=>-11 error
wfeb waiting for indirect 4=>(set TGHA flag and timer)wfg-wfeb
doorbell 1=>(setup to read data)F:wfg-wfeb,S:wfed
2,3=>-10 error
5,6=>-11 error
wfed waiting to read data 4=>(set TGHA flag and timer)wfg-wfed
2=>(wake DL10/DTE task)wftsk
1,3=>-10 error
5,6=>-11 error
wftsk waiting for common 4=>(set TGHA flag and timer)wfg-wftsk
module to respond 1,2,3=>-10 error
5=>(ring -10 doorbell, send header)F:wsth,S:wfth
6=>-11 error
wsth waiting to send -10 4=>ignore
doorbell again 1=>(abort response)wfeh
6=>(ring -10 doorbell, send header)F:-10 down,S:wfth
2,3=>-10 error
5=>-11 error
wfth waiting for -10 done 4=>(set TGHA flag and timer)wfg-wfth
for header 3=>(check for indirect)F:idle,S:(ring -10 doorbell,
send data)F:wstd,S:wftd
1=>(check for indirect)F:wfeh,S:-10 error
2=>-10 error
5,6=>-11 error
wstd trying to resend -10 4=>ignore
doorbell for data 1=>(abort response)wfeh
6=>(ring -10 doorbell, send data)F:-10 down,S:wftd
2,3=>-10 error
5=>-11 error
wftd waiting for -10 done 4=>(set TGHA flag and timer)wfg-wftd
for data 3=>idle
1=>(abort response)wfeh
2=>-10 error
5,6=>-11 error
wfg-xx waiting for TGHA 1,2,3=>(clear TGHA flag and timer;pass interrupt on)xx
4=>ignore
6=>(clear TGHA flag and timer;check for valid examine)
F:-10 down,S:xx
5=>-11 error
-10 err illegal protocol (set DLGONE to -1, wake DL10/DTE task)idle
-10 dwn -10 not responding (set DLGONE to -1, wake DL10/DTE task)idle
-11 err logic error in FE trap
.ENDR;.REPT 0
DT.INT: INTSKD
SAVE <R0,R1,R2,R3,R4,R5> ;save a couple of registers
CLKOFF ;turn off clock so it won't screw us
MOV DTEBAD,R5 ;copy base address into standard register
DTEOFF
MTPS #PR.TEN*40 ;set ten interface priority level
.IF NE,DTBUG
TST INTFLG ;are we already within interrupt?
BEQ 2$ ;no, continue
MOV TE.STW(R5),#0 ;yes, remember current status
STOPCD DTE ; and die
2$:
MOV #-1,INTFLG
.ENDC;.IF NE,DTBUG
MOV DTEPCA,R3 ;get DTE table address
MOV TE.STW(R5),R0 ;get interrupt bits
TRACE TRCDTE,R0
.IF NE,DTBUG
MOV R0,LSTINT ;save last interrupt
.ENDC;.IF NE,DTBUG
BIT #TS.XER!TS.MPE!TS.EPE!TS.EET,R0;check for hard errors
BNE 20$ ;yes, mark -10 down
BIT #TS.ETD!TS.XNT!TS.XEE,R0;check useful bits
.IF NE,DTBUG
BNE 1$ ;if some on, skip following
INC #0 ;count how often it happens
MOV R0,#0 ;and record status bits
BR 99$ ;ignore interrupt
1$:
.IFF;.IF NE,DTBUG
BEQ 99$ ;exit if none on
.ENDC;.IF NE,DTBUG
MOV R0,INTCND ;store interrupt conditions
BIC #^C<I..DBL!I..11D!I..10D>,INTCND;only leave on ones we handle
BIT #I..DBL,R0 ;is it a doorbell?
BEQ 10$ ;no, just do normal dispatch
CALL GETSTS ;get status word from -10
BCS 9$ ;if no examine done, -10 is down
TST TCSTFX ;check valid examine
BNE 10$ ;yup, do normal dispatch
9$: BIC #I..DBL,INTCND ;no, call this TGHA doorbell
BIS #I..TGH,INTCND ; instead of normal doorbell
10$: CALL CLRINT ;clear hardware interrupt conditions
CALL NXTPRT ;do next part of state machine
99$: MTPS #BR7 ;allow us to get out of here
DTEON
RESTOR <R5,R4,R3,R2,R1,R0> ;restore registers
.IIF NE,DTBUG, CLR INTFLG ;no longer within interrupt
CLKON ;turn the clock back on
RTI ;dismiss interrupt
20$: CALL DTEDWN ;mark -10 down
BR 99$ ; and dismiss interrupt
DTEDWN: ;subroutine to declare -10 down when
;not in state machine
TRACE TRCPRO,<(SP),NXTPC,JIFCLK>
.IF NE,DEBUG
BIT #TRCTER,TRCHLT
BEQ 1$
STOPCD TER
1$:
.ENDC;.IF NE,DEBUG
CALL INISTA ;initialize state machine
CLR PROTER ;not due to protocol error
MOV #-1,DLGONE ;mark it down
CALL WAKTEN ;wake up DTE/DL10 task
RETURN ;exit
CLRINT: ;subroutine to clear hardware conditions
SAVE R0
10$: BEQ 99$ ;if equal, all hardware bits cleared
BIT #I..11D,R0 ;to -11 done?
BEQ 20$ ;no, try another
MOV #TS.ENT,TE.STW(R5) ;clear to -11 done
BIC #I..11D,R0 ;clear flag bit
BEQ 99$ ;for speed
20$: BIT #I..10D,R0 ;to -10 done?
BEQ 30$ ;no, try next
MOV #TS.XTS,TE.STW(R5) ;yes, clear it
BIC #I..10D,R0
BEQ 99$
30$: BIT #I..DBL,R0 ;doorbell?
BEQ 99$ ;no, finished
MOV #TS.EIS,TE.STW(R5) ;clear condition
BIC #I..DBL,R0
99$: RESTOR R0
RETURN
.SBTTL dispatch for state machine
NXTPRT: ;subroutine to execute next part of
; state machine code
TRACE TRCDTE,<(SP),PS>
.IF NE,DTBUG
TST WITHIN
BEQ 1$
STOPCD
1$:
.ENDC;.IF NE,DTBUG
SAVE <R0,R1,R2,R3,R4,R5> ;save caller regs
MOV SP,INTSP ; and stack pointer
MOV STATSP,SP ;get state machine stack pointer
RESTOR <R5,R4,R3,R2,R1,R0> ;restore state machine's regs
MOV (SP)+,NXTPC ;get entry point to state machine
TRACE TRCPRO,<NXTPC,JIFCLK>
.IF NE,DTBUG
CMP #INTSTK,SP ;make sure we are at appropriate point
BEQ 77$
STOPCD
77$:
MOV #-1,WITHIN
.ENDC;.IF NE,DTBUG
NXTCND: CALL FNDCND ;find an active condition
BCC ERRCHK ;if none, check for illegal interrupts
NXTCN0:
TRACE TRCDTE,<CNDINT,CNDHLD>
JMP @CNDHLD ;handle condition
.IF NE,DTBUG
NXTCN1: ;return here from state
TRACE TRCDTE,NXTPC
.IF NE,DEBUG
CMP #INTSTK,SP
BEQ 78$
STOPCD
78$:
.ENDC;.IF NE,DEBUG
BR NXTCND ; and go look for another
.ENDC;.IF NE,DTBUG
ERRCHK: ;here to see if error condition
TST INTCND ;any more interrupt conditions
BEQ DISMIS ;no, we are done
CALL PRTCHK ;go check for protocol error interrupts
IFCRY S.10ER ;if error, declare -10 down
XCALL S.11ER ;must be -11 logic error
DISMIS: ;when condition is finished, come here
TRACE TRCPRO,<NXTPC,JIFCLK>
SAVE <NXTPC,R0,R1,R2,R3,R4,R5>;save new state and registers
MOV SP,STATSP ;save stack pointer for state machine
MOV INTSP,SP ;restore caller's stack pointer
RESTOR <R5,R4,R3,R2,R1,R0> ;restore caller's registers
DISM0: ;here to exit from TENDWN
.IF NE,DTBUG
TST INTCND
BEQ 5$
INC #0
5$:
CLR WITHIN
.ENDC;.IF NE,DTBUG
CLR INTCND ;make sure no unfinished business left
RETURN ;return to caller of NXTPRT
FNDCND: ;find active condition
SAVE <R0,R1> ;need a couple of registers
MOV NXTPC,R0 ;get pointer to current state block
ADD #STBDSP,R0 ;point to dispatch part
10$: MOV (R0)+,R1 ;get bit(s) to dispatch on
BEQ 30$ ;if none, return carry clear
BIT R1,INTCND ;a condition met?
BEQ 20$ ;no, advance to next
MOV (R0)+,CNDHLD ;yes, save dispatch address
BIC R1,INTCND ;mark conditions satisfied
MOV R1,CNDINT ;save last conditions (in case state
; machine wants to know)
RESTOR <R1,R0> ;restore regs
SEC ;indicate we got something
RETURN
20$: MOV (R0)+,R1 ;advance past dispatch address
BR 10$ ;try next entry
30$: RESTOR <R1,R0> ;restore regs
CLC
RETURN
CNDHLD: .WORD 0 ;dispatch address for condition
CNDINT: .WORD 0 ;conditions this dispatch
PRTCHK: SAVE R0 ;save a register
MOV #E10DSP,R0 ;displacement of -10 protocol error mask
ADD NXTPC,R0 ;get address of mask bits
CLC ;assume no error conditions
BIT (R0),INTCND ;check mask against conditions
BEQ 99$ ;exit if none match
SEC ;flag error
99$: RESTOR R0
RETURN
.SBTTL State machine
.IF NE,FTP5
.ENABL LSB
S.INI0: ;initial protocol start exchange
INTTYP <I..RSP!I..TMO>,<I..10D!I..11D>,<<I..TGH,5$>,<I..DBL,10$>>
5$: CALL TGHWAI
10$: BIT #TO.INI,TCSTFX ;check if 10 is initializing
BNE 15$
GOBACK
15$:
S.IN00: BIS #TO.INI,DTSTT ;yes - we are too
CALL SETSTS ;tell him we agree
BCC 20$
CALL TGHWAI
BR 15$
20$: MOV #TS.EEX,TE.STW(R5) ;ring -10 doorbell to wake it up
NXTINT ;now he must agree that we agree
.DSABL LSB
S.INI1: ; we are agreeing that we are both starting
INTTYP <I..RSP!I..TMO>,<I..10D!I..11D>,<<I..TGH,5$>,<I..DBL,10$>>
5$: CALL TGHWAI
10$: BIT #TO.INI,TCSTFX ;does he agree that we agree with him?
BNE S.IN00 ;no - then we don't agree about startup
15$: BIC #TO.INI,DTSTT ;yes - tell him we agree that he agrees that we agree
CALL SETSTS
BCC 20$
CALL TGHWAI
BR 15$
20$: MOV #TS.EEX,TE.STW(R5) ;ring -10 doorbell to wake it up
NXTINT #S.IDLE ;and we are started
GOBACK
.ENDC ;.IF NE,FTP5
S.11ER: STOPCD S11 ;-11 logic error
S.10ER: MOV #-1,PROTER ;indicate protocol error
XC: XCALL TENDWN ;flag -10 down
S.10DW: CLR PROTER ;no protocol error
BR XC ;flag it down
.ENABL LSB
TGHSTD: CALL TGHWAI
99$: GOBACK
S.IDLE: ;initial state (between messages)
INTTYP <I..RSP!I..TMO>,<I..10D!I..11D>,<<I..TGH,TGHSTD>,<I..DBL,10$>>
10$:
S.IDL0: BIT #TO.IND,TCSTFX+2 ;doorbell for indirect?
IFNE S.10ER ;yes, -10 goofed
S.IDL1: CMPB DT10QC,TCSTFX+4 ;compare our queue count with -10's
BEQ 99$ ;if same, ignore
20$: CALL SETHDR ;setup to read header
BCC 30$
CALL TGHWAI
BR 20$
30$: NXTINT
.DSABL LSB
S.WFEH: ;waiting for -11 done of header
.IF NE,FTFEDV
SAWFEH: ;substate: waiting for FEH for DN60 header
.ENDC ; .IF NE,FTFEDV
INTTYP <I..RSP!I..TMO>,<I..DBL!I..10D>,<<I..TGH,TGHSTD>,<I..11D,10$>>
10$: MOV #DT11HD,R0 ;point to correct header
CALL SWPHDR ;swap header bytes
.IF EQ,FTP5
TRACB TRCPRO,DT11HD,D11HDL/2 ;trace the FEH header
.IFF
TRACB TRCPRO,DT11DF,D11DFL/2 ;trace the DN60 header
.ENDC ;.IF EQ,FTP5
CALL VALHDR ;check constant header info
.IF NE,FTFEDV
BCC 19$
.IIF NE,DTBUG, INC #0 ;count these for the hell of it
12$: NXTINT #S.IDLE ;if illegal header - ignore it!
GOBACK
.IFF
IFCRY S.10ER ;illegal header
.ENDC ; .IF NE,FTFEDV
19$:
.IF NE,FTFEDV
CMPB DT11FN,#DTFSAK ;check for unexpected ack
BEQ 12$ ;20 sends another after transaction complete
15$:
CALL GETSTS ;try to get status
BCS 30$ ;if -10 timeout, declare it dead
TST TCSTFX ;check for valid examine
BNE 20$ ;no, assume TGHA running
30$: CALL TGHWAI ;go into TGHA wait
BR 19$ ;if timeout and -10 is up, read status again
20$: ;here for indirect - the DN60 header
NXTINT
SAWFEB: ;wait for indirect doorbell - DN60 header
INTTYP <I..RSP!I..TMO>,<I..10D!I..11D>,<<I..TGH,TGHSTD>,<I..DBL,10$>>
10$: BIT #TO.IND,TCSTFX+2 ;indirect doorbell?
BNE 20$ ;yes, continue
INC #0 ;count how often this happens
BIS I..DBL,INTCND ;dummy up interrupt condition
NXTINT #S.IDLE ;change state immediately
GOBACK ; and go to it
20$: CALL INPHD ;setup to read data
BCC 25$
CALL TGHWAI
BR 20$
25$: NXTINT
SAWFED: ;wait for -11 done for indirect data - DN60 header
INTTYP <I..TMO!I..RSP>,<I..DBL!I..10D>,<<I..TGH,TGHSTD>,<I..11D,10$>>
10$: MOV #DT11HD,R0 ;point at to-11 header
CALL SWPHDF ;swap the bytes
.ENDC ; .IF NE,FTFEDV
.IF EQ,FTP5
TRACB TRCPRO,DT11DF,D11DFL/2 ;trace the DN60 header
.ENDC ;.IF EQ,FTP5
.IF EQ,FTFEDV
CALL GETSTS ;try to get status
BCS 30$ ;if -10 timeout, declare it dead
TST TCSTFX ;check for valid examine
BNE 21$ ;no, assume TGHA running
CALL TGHWAI ;go into TGHA wait
BR 19$ ;if timeout and -10 is up, read status again
30$: XCALL TENDWN ;declare -10 down
.ENDC ;.IF EQ,FTFEDV
;(never returns)
21$: MOVB DT11DF,R1 ;get DN60 function code
CMPB #DF.EXA,R1 ;is it examine
BEQ 80$ ;yes, special case
CMPB #DF.DEP,R1 ;is it deposit?
BEQ 80$ ;yes, special case
.IF NE,FTFEDV+FTP5
BIT #1,DT11DF ;check DN60 function code for indirect dat
BEQ 20$ ;even function codes are writes from ten to eleven
.IFF
TST DT11FN ;is it indirect function?
BMI 20$ ;yes, go bring in data
.ENDC ;.IF NE,FTFEDV+FTP5
.IIF NE,FTFEDV, CALL DTSACK ;send ack with FEH for response
CLR INPCTR ;no input data
CALL WKTSK ;wake up DL10/DTE task
NXTINT #S.WFTK ;declare next interrupt
99$: GOBACK
80$: CALL DLTEXM ;build examine/deposit response
.IF NE,FTP5
MOV #DT10HD,R0 ;point to the right header
CALL SWPHDF ;swap DN60 header for ten
.ENDC ;.IF NE,FTP5
.IIF NE,FTFEDV, CALL DTSACK ;send ack with FEH for response
81$: CALL SNDHDR ;try to send it to -10
BCS 75$ ;if error ringing ten, try to repeat
.IF NE,FTP5
TST RSPSIZ ;if response size is zero
BNE 70$
JMP SFAKDN ;there won't be any to 10 done
70$:
.ENDC ;IF NE,FTP5
NXTINT #S.WFTH ;declare next interrupt
GOBACK
75$: NXTINT #S.WSTH ;next state is trying to send header
CALL TGHWAI ;but put ourselves into TGHA wait first
BR 81$ ;go try again to send
20$: ;here if indirect data coming
.IF NE,FTFEDV
CALL DTSAK ;send ack and wait for indirect data
BR 81$ ;go try again to send
SBWFEB: ;waiting for doorbell for FEH for data
INTTYP <I..RSP!I..TMO>,<I..10D!I..11D>,<<I..TGH,TGHSTD>,<I..DBL,10$>>
10$: BIT #TO.IND,TCSTFX+2 ;doorbell for indirect?
IFNE S.10ER ;yes, -10 goofed
CMPB DT10QC,TCSTFX+4 ;compare our queue count with -10's
BEQ 11$ ;if same, ignore
CALL SETHDR ;setup to read header
BCC 15$
11$: GOBACK ;don't leave state if it fails
15$: NXTINT
SBWFEH: ;substate: waiting for FEH for DN60 data
INTTYP <I..RSP!I..TMO>,<I..DBL!I..10D>,<<I..TGH,TGHSTD>,<I..11D,10$>>
10$: MOV #DT11HD,R0 ;point to correct header
CALL SWPHDR ;swap header bytes
TRACB TRCPRO,DT11HD,D11HDL/2 ;trace the FEH header
CALL VALHDR ;check constant header info
BCC 19$
.IIF NE,DTBUG, INC #0 ;count these for the hell of it
12$: NXTINT #S.IDLE ;if illegal header - ignore it!
GOBACK
19$: CMPB DT11FN,#DTFSAK ;check for unexpected ack
BNE 15$
.IIF NE,DTBUG, INC #0 ;count these for the hell of it
BR 12$ ;have seen this happen here, followed
;by a non-fe header. seemed to be
;associated with tgha event.
15$: CALL GETSTS ;try to get status
BCS 30$ ;if -10 timeout, declare it dead
TST TCSTFX ;check for valid examine
BNE 20$ ;no, assume TGHA running
30$: CALL TGHWAI ;go into TGHA wait
BR 19$ ;if timeout and -10 is up, read status again
20$: ;here for indirect - the DN60 data
.ENDC ; .IF NE,FTFEDV
NXTINT #S.WFEB
GOBACK
S.WFEB: ;wait for indirect doorbell
INTTYP <I..RSP!I..TMO>,<I..10D!I..11D>,<<I..TGH,TGHSTD>,<I..DBL,10$>>
10$: BIT #TO.IND,TCSTFX+2 ;indirect doorbell?
.IF NE,FTP5
BEQ 20$ ;no, continue
.IFF
BNE 20$ ;yes, continue
.ENDC ;IF NE,FTP5
INC #0 ;count how often this happens
BIS I..DBL,INTCND ;dummy up interrupt condition
NXTINT #S.IDLE ;change state immediately
GOBACK ; and go to it
20$: CALL SETDAT ;setup to read data
BCC 21$
CALL TGHWAI
BR 20$
21$: NXTINT
S.WFED: ;wait for -11 done for indirect data
INTTYP <I..TMO!I..RSP>,<I..DBL!I..10D>,<<I..TGH,TGHSTD>,<I..11D,10$>>
10$:
.IF NE,FTFEDV
BIT #1,DT11DF ;CHECK FOR WRITE FUNCTION
BNE 11$
;for some mysterious reason write commands have to get their data from the
; indirect header byte count(WRITE DATA only but do it for all for consistency)
CLR DT11DT ;get length of msg
MOVB DT11UC,DT11DT ;from FEH of indirect msg
.ENDC ; .IF NE,FTFEDV
11$: MOV DT11DT,INPCTR ;get length of input data
CMP INPCTR,#MAXDAT ;limit to buffer size
BLE 12$
MOV #MAXDAT,INPCTR
12$: CALL WKTSK ;wake up task
.IIF NE,FTFEDV, CALL DTSACK ;set up ack of data read to go back with
;FEH of response
NXTINT
S.WFTK: ;wait for task to respond
INTTYP 0,<I..10D!I..11D!I..DBL>,<<I..TGH,TGHSTD>,<I..RSP,10$>>
10$:
.IF NE,FTP5
MOV #DT10HD,R0 ;point to the right header
CALL SWPHDF ;swap DN60 header for ten
.ENDC ;.IF NE,FTP5
CALL SNDHDR ;try to send header
BCC 20$ ;it went, go finish up
NXTINT #S.WSTH ;declare next state
CALL TGHWAI ;but as a TGHA state
BR 10$ ;try again
20$: NXTINT ;success, we are in a new state
S.WFTH: ;waiting for to -10 done on header
INTTYP <I..RSP!I..TMO>,<I..11D>,<<I..TGH,TGHSTD>,<I..10D,20$>,<I..DBL,10$>>
10$: BIT #TO.IND,TCSTFX+2 ;doorbell for indirect?
IFNE S.10ER ;yes, -10 error
CALL ABTXMT ;abort transmit in progress
.IIF NE,FTFEDV, CLR DTACKR ;clear ack flag
JMP S.IDL1 ;and wait for header from -10
20$:
SFAKDN: ;here when no to 10 done will happen
.IF NE,FTFEDV
TST DTACKR ;trace ack header if acking indirect data
BEQ 21$
TRACB TRCPRO,DTAKHD,D10HDL/2 ;length
21$:
MOV DTACKR,R0 ;check for ack only
BEQ 25$ ;no ack at all
CLR DTACKR ;done with ack header
CMP R0,#D10HDL ;ack - check if FEH of response with it
BGT 25$ ;yes - go send the indirect data
NXTINT #SBWFEB ;no, just ack => expecting indirect data from 10
GOBACK
25$: TRACB TRCPRO,DT10DF,D10DFL/2 ;trace DN60 header returned
MOV #DT10HD,R0 ;point to the right header
CALL SWPHDF ;swap DN60 header for ten
26$: CALL OUTHD ;send DN60 header to ten
BCC 40$
NXTINT #S.WSTD
CALL TGHWAI
BR 26$
40$: NXTINT
SAWFTD: ; waiting for to-10 done on DN60 header
INTTYP <I..RSP!I..TMO>,<I..11D>,<<I..TGH,TGHSTD>,<I..10D,20$>,<I..DBL,10$>>
10$: CALL ABTXMT ;abort transmit
CLR DTACKR ;clear ack flag
JMP S.IDL0 ;next state
20$: BIC #TO.IND!TO.FWD,DTSTT+2 ;clear indirect in progress and byte mode
NXTINT ;now wait for ack of indirect part sent
SAWFAK: ;waiting for ack header
INTTYP <I..RSP!I..TMO>,<I..10D!I..11D>,<<I..TGH,TGHSTD>,<I..DBL,10$>>
10$: BIT #TO.IND,TCSTFX+2 ;doorbell for indirect?
IFNE S.10ER ;yes, -10 goofed
CMPB DT10QC,TCSTFX+4 ;compare our queue count with -10's
BNE 15$ ;if same, ignore
GOBACK
15$: CALL SETHDR ;setup to read header
BCC 20$ ;don't leave state if it fails
CALL TGHWAI
BR 15$
20$: NXTINT
SBWFAK: ;waiting for -11 done of ack header
INTTYP <I..RSP!I..TMO>,<I..DBL!I..10D>,<<I..TGH,TGHSTD>,<I..11D,10$>>
10$: MOV #DT11HD,R0 ;point to correct header
CALL SWPHDR ;swap header bytes
TRACB TRCPRO,DT11HD,D11HDL/2 ;trace the FEH header
CALL VALHDR ;check constant header info
BCC 19$
.IIF NE,DTBUG, INC #0 ;count these for the hell of it
NXTINT #S.IDLE ;if illegal header - ignore it!
GOBACK
19$:
CMPB DT11FN,#DTFSAK ;check for expected ack
BEQ 15$
CALL S.10ER ;ten is confused
15$: ;now time to think about sending response data
;NOTE: DN60 header has been swapped at this point
MOV DT10DT,R0 ;any data to go back ?
BEQ 20$ ;no - done with transaction
CMPB #DF.EXA,DT10DF+1 ;maybe - check if it was examine/deposit response
BEQ 20$ ;yes - data is in DN60 header
CMPB #DF.DEP,DT10DF+1
BEQ 20$ ;yes - no data to return
BITB #1,DT10DF+1 ;check for write function
BNE 30$ ;no - data returns to 10
;yes - no data is returned to 10
20$: NXTINT #S.IDLE ;done - fall back to ground state(exhausted)
GOBACK
30$: SWAB R0 ;FE service can only handle a byte??
MOVB R0,DT10UC ;set no. bytes to follow
CALL SNDHDR ;try to send header
BCC 40$ ;it went, go finish up
NXTINT #S.WSTH ;declare next state
CALL TGHWAI ;but as a TGHA state
BR 30$ ;try again
40$: NXTINT ;success, we are in a new state
SAWFTH: ;waiting for to -10 done on header for data
INTTYP <I..RSP!I..TMO>,<I..11D>,<<I..TGH,TGHSTD>,<I..10D,20$>,<I..DBL,10$>>
10$: BIT #TO.IND,TCSTFX+2 ;doorbell for indirect?
IFNE S.10ER ;yes, -10 error
CALL ABTXMT ;abort transmit in progress
JMP S.IDL1 ;and wait for header from -10
20$:
TRACB TRCPRO,DT10HD,D10HDL/2
.ENDC ;.IF NE,FTFEDV
.IF NE,FTP5
CMPB DT10DF+1,#DF.EXA ;check for examine/deposit
BEQ 25$ ;examine
CMPB DT10DF+1,#DF.DEP
BEQ 25$ ;deposit
BITB #1,DT10DF+1 ;check for read data type function
BNE 30$ ;yes - have to respond
;no - header is sufficient
.IFF
TST DT10FN ;check for indirect function
BMI 30$ ;yes, continue it
.ENDC ;IF NE,FTP5
25$: BIC #TO.IND!TO.FWD,DTSTT+2 ;clear byte mode (and indirect for the hell of it)
NXTINT #S.IDLE ;next stop is idle
GOBACK
30$: CALL SNDDAT ;send data
BCC 40$ ;continue if it worked
NXTINT #S.WSTD
CALL TGHWAI
BR 30$
40$: NXTINT
S.WFTD: ;waiting for to -10 done on data
INTTYP <I..RSP!I..TMO>,<I..11D>,<<I..TGH,TGHSTD>,<I..10D,20$>,<I..DBL,10$>>
10$: CALL ABTXMT ;abort transmit
.IIF NE,FTFEDV, CLR DTACKR ;clear ack flag
JMP S.IDL0 ;next state
20$: BIC #TO.IND!TO.FWD,DTSTT+2 ;clear indirect in progress and byte mode
.IF NE,FTFEDV
NXTINT ;now wait for ack of indirect part sent
SCWFAK: ;waiting for ack header
INTTYP <I..RSP!I..TMO>,<I..10D!I..11D>,<<I..TGH,TGHSTD>,<I..DBL,10$>>
10$: BIT #TO.IND,TCSTFX+2 ;doorbell for indirect?
IFNE S.10ER ;yes, -10 goofed
CMPB DT10QC,TCSTFX+4 ;compare our queue count with -10's
BNE 15$ ;if same, ignore
GOBACK
15$: CALL SETHDR ;setup to read header
BCC 20$ ;don't leave state if it fails
CALL TGHWAI
BR 15$
20$: NXTINT
SDWFAK: ;waiting for -11 done of ack header
INTTYP <I..RSP!I..TMO>,<I..DBL!I..10D>,<<I..TGH,TGHSTD>,<I..11D,10$>>
10$: MOV #DT11HD,R0 ;point to correct header
CALL SWPHDR ;swap header bytes
TRACB TRCPRO,DT11HD,D11HDL/2 ;trace the FEH header
CALL VALHDR ;check constant header info
BCC 19$
.IIF NE,DTBUG, INC #0 ;count these for the hell of it
NXTINT #S.IDLE ;if illegal header - ignore it!
GOBACK
19$:
CMPB DT11FN,#DTFSAK ;check for expected ack
BEQ 15$
CALL S.10ER ;ten is confused
15$:
.ENDC ;.IF NE,FTFEDV
;transaction complete - at last!!
NXTINT #S.IDLE
GOBACK
S.WSTH: ;waiting to send header
INTTYP <I..RSP>,<I..10D!I..11D>,<<I..TGH,10$>,<I..DBL,20$>,<I..TMO,30$>>
20$: CALL ABTXMT
JMP S.IDL0
10$: GOBACK
30$: CALL SNDHDR
BCC 31$
CALL TGHWAI
BR 30$
31$:
.IF NE,FTP5
TST RSPSIZ ;check if to 10 done will happen
BNE 35$
JMP SFAKDN ;no - fake it
35$:
.ENDC ;IF NE,FTP5
NXTINT #S.WFTH
GOBACK
S.WSTD: ;waiting to send data
INTTYP <I..RSP>,<I..10D!I..11D>,<<I..TGH,10$>,<I..DBL,20$>,<I..TMO,30$>>
20$: CALL ABTXMT
JMP S.IDL0
10$: GOBACK
30$: NXTINT #S.IDLE
GOBACK
.SBTTL Subroutines for state machine
TGHWAI: ;subroutine to wait for TGHA pause to
; finish
TRACE TRCDTE!TRCPRO,<(SP),NXTPC,JIFCLK> ;trace caller and state coming from
;Call only at top level stack in state machine
; This subroutine can only be called from the state machine; it assumes
; 10 will have turned off DTE for up to TGHMAX seconds. The TGHA state ends
; when: 1) the timer expires and -10 still doesn't have valid examine. This
; means the -10 is down, and results in a call to S.10DW. 2) the timer expires
; and the -10 is alive. This returns to the caller of TGHWAI. 3) another
; interrupt condition occurs while timing. This immediately terminates the
; TGHA state, and returns to the beginning of the state TGHWAI was called in
; with the interrupt condition set.
.IF NE,DTBUG
TST TGHCNT ;are we already in TGHA?
BEQ 5$ ;no, skip it
STOPCD RTC ;recursive TGHA call!
5$:
.ENDC;.IF NE,DTBUG
MOV (SP)+,TGHRET ;save return address
MOV NXTPC,TNXTPC ;save current state
MOV #TGHMAX,TGHCNT ;set timeout counter
NXTINT ; and go into new state
WAITGH: INTTYP 0,0,<<I..DBL,10$>,<I..11D,20$>,<I..10D,30$>,<I..TGH,99$>,<I..RSP,40$>,<I..TMO,50$>>
10$: BIS #I..DBL,INTCND ;re-iterate interrupt condition
11$: NXTINT TNXTPC ;force chance of state
99$: GOBACK ;go do it
20$: BIS #I..11D,INTCND ;re-iterate condition
BR 11$
30$: BIS #I..10D,INTCND
BR 11$
40$: BIS #I..RSP,INTCND
BR 11$
50$: NXTINT TNXTPC ;restore original state
JMP @TGHRET ;return to caller
TGHRET: .WORD 0 ;caller return for TGHWAI
WKTSK: ;subroutine to wake TENTSK
;The caller must set up INPCTR with the number of data bytes read
MOV DT11DT,OUTCTR ;maximum to transfer is requested amount
CMP OUTCTR,#MAXDAT ;check for buffer overflow
BLE 5$ ;no, use it
MOV #MAXDAT,OUTCTR ;yes, cut down to our buffer size
5$: MOV #OUTBUF,OUTPTR ; and where to start
MOV #INBUF,INPPTR ;when input starts
CALL CPYHDR ;copy header from input to output area
MOV #DT11DF,R0 ;point to DN60 part of header
CALL WAKFNC ;wake up task
SETSKD TCDLDR ;force scheduling pass
RETURN
INISTA: ;subroutine to initialize state machine
SAVE R5
MOV SP,R5 ;copy stack pointer
MOV #INTSTK,SP ;reset stack pointer to state machine stack
.IF EQ,FTP5
SAVE #S.IDLE ;start idling
.IFF
SAVE #S.INI0 ;startup exchange required
.ENDC ;.IF EQ,FTP5
SAVE <#0,#0,#0,DTEPCA,#0,DTEBAD>;initialize state regs and return
MOV SP,STATSP ;save state machine stack pointer
MOV #S.IDLE,NXTPC ;save current (and next) state
CLR TGHCNT ;assume TGHA not running
CLR INTCND ;make sure nothing left over
.IIF NE,FTFEDV, CLR DTACKR ;clear ack flag
.IIF NE,DTBUG, CLR WITHIN
MOV R5,SP ;restore old stack pointer
RESTOR R5 ;and register
RETURN ;return to caller
TENDWN: ;subroutine for state machine to declare
; -10 down
.IF NE,DTBUG
CALL STKSAV ;save state machine stack
.ENDC;.IF NE,DTBUG
.IF NE,DEBUG
BIT #TRCTER,TRCHLT
BEQ 1$
STOPCD TER
1$:
.ENDC;.IF NE,DEBUG
CALL WAKTEN ;wake up DTE/DL10 task
MOV INTSP,SP ;restore caller's stack pointer
CALL INISTA ;initialize state machine
MOV #-1,DLGONE ;mark it down
RESTOR <R5,R4,R3,R2,R1,R0> ;restore caller's registers
JMP DISM0 ;exit
.SBTTL Software-generated interrupt conditions
DLRESP: ;send response to -10
;NOTE: this code is called from DL10/DTE task to return the data
;length and result code and to initiate their return to the -10.
;It corresponds to the interrupt condition I..RSP in the state machine.
MOVB R0,DT10DF+1 ;save result code
MOV R1,DT10DT ;and copy length
TRACE TRCTEN!TRCPRO,<R0,R1,JIFCLK> ;trace the results
.IF EQ,FTP5
.IF EQ,FTFEDV
TST R1
BEQ 6$ ;if 0, leave indirect function bit clear
BIT #1,DT10DF ;was it a write function?
BEQ 6$ ;yes, never have data to send
BIS #100000,DT10FN ;else set indirect function bit
.ENDC ; .IF EQ,FTFEDV
.ENDC ;.IF EQ,FTP5
6$: CLKOFF ;flush the clock
OFFDTE ;disable dte interrupts
BIS #I..RSP,INTCND ;set the interrupt condition
CALL NXTPRT ;do next part of state machine
PIOFF ;protect from clenches
ONDTE ;allow dte interrupts
CLKON ;also crocks
PION ;unclench
RETURN
TGHEXP: ;called from once per second code
; when timer for TGHA expires
PIOFF ;no interrupts
CALL GETSTS ;read status word
BCS 10$ ;if it timed out, -10 is dead
CMP NXTPC,#WAITGH ;make sure we are waiting for TGHA
BEQ 4$ ;yup, continue
XCALL S.11ER ;die
4$:
.IF NE,DTBUG
TST INTCND ;make sure no left-over interrupt conditions
BEQ 5$
STOPCD INZ
5$:
.ENDC;.IF NE,DTBUG
CLR TGHCNT ;no longer timing tgha
MOV #I..TMO,INTCND
CALL NXTPRT
10$: PION
RETURN
.SBTTL Timer entry points
DSPDLT: ;tick timer
TST DLGONE
BNE 99$
TST TGHCNT ;is TGHA timer running?
BEQ 99$ ;no, retire
MOV DTEBAD,R5 ;point to hardware
DTEOFF
MOV DTEPCA,R3 ;get DTE block pointer
CALL CHKTEN ;check if ten is healthy
BCS 98$ ;if not - wait for tgha interval
CALL TGHEXP ;try TGHA expiration for size
98$: DTEON
99$: CLC
RETURN
DSPDLS: ;second timer
TRACE TRCDTE,<DLGONE,TGHCNT>
TST DLGONE
BEQ 1$
DEC DLGONE ;count it down
RETURN
1$: SAVE <R3,R5> ;save standard hardware register
MOV DTEBAD,R5 ;point to hardware
DTEOFF
MOV DTEPCA,R3 ;get DTE block pointer
TST TGHCNT ;is TGHA timer running?
BEQ 50$ ;no, test -10
DEC TGHCNT ;decrement timer
BNE 99$ ;if not up, we are done
70$: CALL DTEDWN ;if not, declare -10 down
99$: DTEON
RESTOR <R5,R3>
RETURN
50$: ;here if -10 needs to be up
CALL CHKTEN ;check that it is
BCC 60$
MOV #I..TGH,INTCND ;no - set tgha state
CALL NXTPRT
BR 99$
60$: CALL CRAML0 ;cram keepalive
BCC 99$
CALL CRAML0
BR 99$ ;ignore error
CRAMLV: MFPS -(SP) ;preserve condition codes over this fcn
CMP JIFCLK,NXKPLV ;do this at odd times if not done recently
BLO 10$
CALL CRAML0
10$: MTPS (SP)+
RETURN
CRAML0: CLR TE.XW1(R5)
CLR TE.XW2(R5)
MOV JIFCLK,TE.XW3(R5) ;the count to -20
MOV #TS.DEP,TE.XA1(R5) ;set deposit flag
MOV #PBPW1,TE.XA2(R5) ;start xfer
CALL DLWEDN ;wait for exam/dep
BCS 10$
MOV JIFCLK,DTKPLV ;save last successful keepalive
MOV DTKPLV,NXKPLV
ADD #JIFSEC,NXKPLV ;next time it becomes urgent to do it
TRACE TRCDTE,JIFCLK ;trace last successful keepalive
CLC
10$: RETURN
.ENABL LSB
CHKTEN: CALL DTECHK
BCC 5$
CALL DTECHK
BCS 9$ ;branch if -10 down
5$: TST TE.XW3(R5) ;check for processor number
BEQ 9$ ;ten not up yet if zero
TRACE TRCDTE,<(SP),JIFCLK,TE.XW1(R5),TE.XW2(R5),TE.XW3(R5)>
CHKSUC: CLC
RETURN
9$: TRACE TRCDTE,<(SP),JIFCLK>
CHKFAL:
10$: SEC
RETURN
.DSABL LSB
DTECHK: CLR TE.XA1(R5) ;look at
DTEXAM: CLR TE.XA2(R5) ; out comm region header entry
JMP DLWEDN ;wait for examine done
.SBTTL DTE subroutines
;Turn on the DTE-20 and setup DTE table
;
; THIS ROUTINE WILL SET UP THE TABLES NECESSARY TO
; INITIALIZE THE COMMUNICATIONS BETWEEN THE PDP-10
; AND THE PDP-11.
;
; CALL: CALL DLINDB
;
; ON RETURN:
; C = 0: R0 = 1 TO INDICATE SUCCESS
; C = 1: ERROR
;
; NOTE THAT THIS ROUTINE USES R5 IN A NON-STANDARD WAY.
; THIS IS BECAUSE IT WAS TAKEN FROM THE DN87S CODE AND
; WE WOULD PREFER NOT TO HAVE TO RE-WRITE IT TO MAKE IT
; CONFORM TO THE DN60 CODING CONVENTIONS.
;
DLINDB: MOV R5,-(SP)
CLR -(SP)
CLR -(SP)
MOV DTEBAD,R0 ;FIND THE COMMON DTE-20
CLR R1 ;SET UP TO FIND PROCESSOR NUMBER
CLR R2 ;START TRANSFER OF ABS WORD 0 OF EPT (MY PROCESSOR NUMBER
MOV #DTXTM3,R3 ;SET UP ADDRESS TO STORE WORDS
CLR R4
CALL DLSWED ;WAIT FOR EXAMINE/DEPOSIT
BCS 11$ ;E BOX STOP
MOV @R3,R4 ;YES --FIND OFFSET TO MY R/W AREA
MOVB @#DTXTM2+1,R2 ;FIND THE PROCESSOR NUMBER
; PROCESSOR NUMBER TO LOW ORDER BITS
BIC #177760,R2 ;MASK OFF JUNK(0.-15. LEGAL)
MOV R2,DLMYPN ;SAVE PROCESSOR NUMBER
INC R2 ;FIND COMMUNICATIONS VIRTUAL 2
MOV R2,DLCMBS ;SAVE BASE OF COMMUNICATIONS AREA
ADD R4,R2 ;ADD OFFSET TO BASE OF COMM AREA
MOV R2,DLDPOF ;SET CORRECT OFFSETT
TRACE TRCDTE,<DTXTM1,DTXTM2,DTXTM3,DLMYPN,DLCMBS,DLDPOF>
CALL DLSWED ;WAIT FOR TRANSFER
BCC 12$
11$: JMP DLINDR
12$: TRACE TRCDTE,<DTXTM1,DTXTM2,DTXTM3>
MOV @#DTXTM2,R5 ;PICK UP THE NUMBER OF 8 TM BLOCKS
BIC #177770,R5 ;FIND THE NUMBER OF 8 WORD BLOCKS IN MY AREA
BEQ 33$ ;die if none
SUB #2,R5 ;ACCOUNT FOR MY GENERAL SECTION
.IIF NE,FTP5,INC R5 ;faker
BGT 34$ ;MCB uses 2 blocks,FE service 3
33$: STOPCD DTE
34$: MOV R2,2(SP)
MOV R5,0(SP) ;SAVE COUNT OF BLOCKS
DLIND1: ADD #PBASIZ,2(SP) ;LOOK AT A COMMUNICATIONS AREA TO ANOTHER PROCESSOR
MOV 2(SP),R2
CLR R4
CALL DLSWED ;WAIT FOR TRANSFER
BCC 77$ ; E BOX STOPPED
11$: JMP DLINDR
77$: TRACE TRCDTE,<DTXTM1,DTXTM2,DTXTM3>
MOV @R3,R4 ;FIND PROCESSOR NUMBER
MOV #DTPIDT,R5 ;SET INITIAL POINTER
BIC #177770,R4 ;MASK OFF JUNK
BEQ 13$ ;YES -- CONTINUE
12$: ADD #5*2,R5 ;NO -- LOOK AT NEXT ENTRY
SOB R4,12$ ;TRY UNTIL ALL DONE
13$: TRACE TRCDTE,<DTXTM1,DTXTM2,DTXTM3,R4,R5>
MOV @#DTXTM2,R4 ;FIND NUMBER OF 8 WORD BLOCS
BIC #177770,R4 ;MASK OFF POSSIBLE GARBAGE
SUB R4,@SP ;UPDATE COUNT OF BLOCKS
CLR @R5 ;SET UP TO CLEAR TABLE IF NO DTE
MOV @#DTXTM1,R4 ;PICK UP DTE NUMBER
TRACE TRCDTE,<R4,R5>
BIT #TO.DTE,R4 ;DTE HERE?
BEQ 15$ ;NO -- DON'T ENTER IN TABLE
SWAB R4 ;MAKE MOD 40 (8)
ROR R4
ROR R4
ROR R4
BIC #177637,R4 ;MASKOFF JUNK
ADD #174400,R4 ;POINT TO FIRST BLOCK OF DTE'S
CMP R4,DTEBAD ;PRIMARY DTE?
BNE 14$ ;NO -- DON'T SET TABLE POINTER
MOV R5,DTEPCA ;SAVE TABLE OFFSET
TRACE TRCDTE,<R4,R5>
14$: MOV R4,@R5 ;SET DTE ADDRESS IN TABLE
MOV #DLYPRM,@R4 ;SET UP DELAY COUNTER
MOV #TS.EEE,TE.STW(R4) ;YES -- ENABLE INTERRUPT ON IT
15$: MOV R2,DTEMYN(R5) ;SET THE ADDRESS OF EXAMINE MY AREA FOR N
; MAKE ADDRESS OF THE ADDRESS OF DEPOSIT MY AREA FOR N
MOV R2,DTDMYN(R5) ;STORE IT
SUB DLDPOF,DTDMYN(R5) ;RESTORE SUBRESS FOR EXAMINE OF THIS BLOCK
TRACE TRCDTE,<R2,DTDMYN(R5)>
ADD #TOPCA,R2 ;READ POINTER TO HIS COMM AREA
CLR R4
CALL DLSWED ;WAIT FOR EXAMINE/DEPOSIT
BCS DLINDR ;E BOX STOPPED
MOV @R3,R2 ;FIND THE EXAMINE ADDRESS
ADD DLCMBS,R2 ;ADD OFFSET TO COMMON AREA
MOV R2,DTEHSG(R5) ;SET DTEHSG ADDRESS IN TABLE - ptr to his base area
ADD #PBASIZ,R2 ;POINT TO HIS FIRST TABLE FOR OTHER PROCESSORS
TRACE TRCDTE,<DTXTM1,DTXTM2,DTXTM3,R2>
17$: CLR R4
CALL DLSWED ;WAIT FOR EXAMINE/DEPOSIT
BCS DLINDR
TRACE TRCDTE,<DTXTM1,DTXTM2,DTXTM3>
CMPB DLMYPN,@R3 ;SAME PROCESSOR NUMBER?
BEQ 19$ ;YES -- FOUND MY ENTRY
MOV @#DTXTM2,R4 ;NO -- FIND NEXT ENTRY IN LIST
BIC #177770,R4 ;IT IS IN 8 WORD INCREMENTS
;;++KR-FIX FOR TOPS-20 MONITOR PROBLEM
BNE 20$ ;;++KR-NON ZERO IS GOOD
INC R4 ;;++KR-MAKE IT NON ZERO
20$:
;;++KR-END FIX
ASL R4 ;SO IT MUST BE SHIFTED LEFT 3 BITS
ASL R4 ;
ASL R4 ;
ADD R4,R2 ;READ NEXT BLOCK
BR 17$ ;AND TRY AGAIN
19$:
TRACE TRCDTE,R2
MOV R2,DTEHSM(R5) ;STORE DTEHSM ADDRESS - 10'S TO me area offset
MOV @SP,R5 ;DONE ALL BLOCKS??
BLE 96$
JMP DLIND1 ;NO -- TRY NEXT BLOCK
96$: MOV #-1,TENALV ;let all know it has happened at least once
CLR DTQCNT ;RESET PROTOCOL COUNTERS
CLR DTQSTA ;INIT STATE MECHANISM, CLEAR CARRY
DLINDR: MOV (SP)+,R5 ;RESTORE STACK
MOV (SP)+,R5
MOV (SP)+,R5
RETURN
; THIS SUBROUTINE STARTS A DEPOSIT/EXAMINE SEQUENCE AND WAITS FOR
; ITS COMPLETION. IT CHECKS TO SEE IF THE BOOTSTRAP
; PROTOCOL IS NECESSARY BY CHECKING THE EXAMINE VALID BIT
; AFTER EVERY EXAMINE/DEPOSIT. IT IS NOT NECESSARY TO
; CHECK MORE THAN ANY ONE RANDOM EXAMINE VAILD BIT
; BECAUSE IF ONE IS 0 THEN THE PROCESSOR HAS
; TO REVERT TO THE BOOTSTRAP PROTOCOL.
;
; CALL: CALL DLSWED
;
; R0 -- ADDRESS OF DTE-20
; R1 -- HIGH ORDER EXAMINE/DEPOSIT ADDRESS WORD (FOR TE.XA1)
; R2 -- LOW ORDER EXAMINE/DEPOSIT ADDRESS WORD (FOR TE.XA2)
; R3 -- ADDRESS TO XFER 3 WORD BLOCK TO OR FROM
;
; ON RETURN:
;
; C = 0: SUCCESS, NO REGISTERS ALTERED.
; C = 1: ERROR.
DLSWED: MOV R3,-(SP) ;SAVE REGISTERS
SAVE R5
MOV R0,R5
BIT #TS.DEP,R1 ;CHECK FOR DEPOSIT
BNE 12$ ;YES -- GO TO DEPOSIT PART OF SUB
CALL 30$
BCC 10$
CALL 30$
BCS 14$ ;COMPLAIN ABOUT E BOX STOPPED
10$: MOV TE.XW3(R0),(R3)+ ;STORE THE WORD XFERED
MOV TE.XW2(R0),(R3)+
MOV TE.XW1(R0),(R3)+
.IF NE,DTBUG
CALL TRCIT
.ENDC;.IF NE,DTBUG
11$: TST R4 ;PRIV EXAMINE/DEP?
BNE 14$ ;YES -- DON'T DO CHECKS
CLR TE.XA1(R0) ;SEE IF WE CAN READ ANYTHING
CLR TE.XA2(R0) ;START TRANSFER
CALL DLWEDN ;WAIT FOR XFER
BCC 9$
CLR TE.XA2(R0) ;START TRANSFER
CALL DLWEDN ;WAIT FOR XFER
BCS 14$ ;E BOX STOPPED
9$: TST TE.XW3(R0) ;VALID?
BNE 14$ ;YES -- PROCEED
BR 13$ ; NO - JUST SET CARRY AND RETURN
; HERE TO DO AN EXAMINE.
12$: MOV (R3)+,TE.XW3(R0) ;TRANSFER TO 10
MOV (R3)+,TE.XW2(R0) ;SET UP WORD IN DTE
MOV (R3)+,TE.XW1(R0)
.IF NE,DTBUG
CALL TRCIT
.ENDC;.IF NE,DTBUG
CALL 30$
BCC 11$ ;GO TO COMMON EXAMINE VALID BIT CHECK
CALL 30$
BCC 11$ ;GO TO COMMON EXAMINE VALID BIT CHECK
; HERE IF THE 'EXAMINE VALID' BIT IS OFF. GIVE AN ERROR RETURN.
13$:
.IF NE,DTBUG
STOPCD DBG ;-10 STOPPED UNEXPECTEDLY
.ENDC;.IF NE,DTBUG
SEC
14$: RESTOR R5
MOV (SP)+,R3 ;RESTORE R3
RETURN ;RETURN TO CALLER
30$: MOV R1,TE.XA1(R0) ;SET UP ADDRESS OF XFER IN DTE
MOV R2,TE.XA2(R0) ;START XFER
JMP DLWEDN ;WAIT FOR EXAMINE/DEPOSIT
.IF NE,DTBUG
TRCIT:
TRACE TRCDTE,<-2(R3),-4(R3),-6(R3)>
RETURN
.ENDC;.IF NE,DTBUG
; R3/DPTIDT block for this processor
GETSTS: ;subroutine to read comm region status word
TRACE TRCDTE,(SP)
SAVE R2
MOV #TOSTAT,R2 ;calculate offset of status word from
; beginning of to- section
ADD DTEHSM(R3),R2 ;add in comm region offset of the
; to- section for me in KL's area
EXAM R2,TCSTFX,69$ ;examine it
69$: RESTOR R2
RETURN ;return, carry will be set if timeout
SETSTS: ;subroutine to write comm region status word
TRACE TRCDTE,<(SP)>
SAVE R2
MOV #TOSTAT,R2 ;get displacement of status within to- section
ADD DTDMYN(R3),R2 ;convert to deposit offset
DEPO R2,DTSTT,20$ ;store status
20$: RESTOR R2
RETURN
SETQSZ: ;subroutine to store queued protocol
;R0/ transfer size
CLR TE.XW1(R5) ;zero high
CLR TE.XW2(R5) ; order bits of -10 word
MOV R0,TE.XW3(R5) ;put size of transfer in low word
TRACE TRCDTE,R0
MOV #TOXFSZ,R0 ;get offset of queue size
ADD DTDMYN(R3),R0 ;make into deposit offset
DEPO R0,,69$ ;deposit queue size
69$: RETURN
ABTXMT: ;here to abort transmit already started
INC #0 ;count how many times we are in this situation
ATRACE <(SP),INTCND> ;trace these always
RETURN ;can't do it, DTE20 doesn't have a way
;to cut down byte count.
SETHDR: ;setup to read header
.IF NE,FTP5
MOV #DT11HD,R1 ;get address of where to put it
GETDAT:
.ENDC ;.IF NE,FTP5
BIS #TO.IT,DTSTT+2 ;set queue in progress bit in status to -10
INCB DT10QC ;increment our counter
CMPB TCSTFX+4,DT10QC ;see if we match
BEQ 10$ ;ok, continue
.IF NE,DTBUG
MOVB DT10QC,#0
MOVB TCSTFX+4,#0
.ENDC;.IF NE,DTBUG
DECB DT10QC
SEC
99$: RETURN
10$: CALL SETSTS ;write status
BCS 99$ ;return on error
CALL GETQSZ ;get the xfer size
BCS 99$
.IF NE,FTP5
CMP R0,#MAXDAT ;is it too big?
BLE 11$ ;no, continue
MOV #MAXDAT,R0 ;yes, cut it down
INC #0 ;count how often this happens
11$:
.ENDC ;.IF NE,FTP5
TST R0 ;check size
BNE 20$
.IF NE,FTFEDV
MOV #D11HDL,R0 ;else use default size
.IFF
MOV #D11HDL+D11DFL,R0 ;else use default size
.ENDC ; .IF NE,FTFEDV
20$: CALL CRAMLV ;cram keepalive
.IF EQ,FTP5
MOV #DT11HD,R1 ;get address of where to put it
.ENDC ;.IF EQ,FTP5
CALL DTSTRT ;start input
BIC #TO.IT,DTSTT+2 ;clear TOIT bit to indicate not indirect
CALL SETSTS ;set status
RETURN ;return to caller
.IF NE,FTFEDV
INPHD: ;get DN60 header - indirect data
CALL GETQSZ ;extract queue size word from dte
BCC 5$
RETURN ;return failure
5$: CMP R0,#D11DFL ;check max length dn60 header
BLE 10$
MOV #D11DFL,R0 ;use only this much
INC #0 ;count these
10$: MOV #DT11DF,R1 ;where to read the dn60 header
BR INPDAT ;do it
.ENDC ; .IF NE,FTFEDV
SETDAT: ;subroutine to setup to read indirect data
.IF NE,FTP5
MOV #INBUF,R1 ;address to put it
BR GETDAT ;go get it
.IFF
CALL GETQSZ ;extract queue size from dte
BCC 5$
RETURN ;return failure
5$: CMP R0,#MAXDAT ;is it too big?
BLE 10$ ;no, continue
MOV #MAXDAT,R0 ;yes, cut it down
INC #0 ;count how often this happens
10$: MOV #INBUF,R1 ;address to put it
INPDAT: CALL DTSTRT ;start input, R0/bytes to read, R1/buffer
BIS #TO.IT,DTSTT+2 ;set TOIT bit to indicate indirect in progress
CALL SETSTS ;deposit status
10$: RETURN
.ENDC ;.IF NE,FTP5
GETQSZ: ;extract queue size word from dte
CLR R0
SAVE R2
MOV #TOXFSZ,R2
ADD DTEHSM(R3),R2
EXAM R2,,69$
MOV TE.XW3(R5),R0 ;get it into proper register
69$: RESTOR R2
RETURN
DTSTRT: ;subroutine to start to-11 transfer
;R0 = byte count
;R1 = address to read to
;TCSTFX must have status word after last doorbell
NEG R0 ;make byte count negative and set carry
BIC #170000,R0 ;clear status bits at top of count word
RORB R0 ;divide negative byte count by two
BIT #TO.FWD,TCSTFX+2 ;was this supposed to be word mode?
BNE 10$ ;yes, skip setting byte flag
ROLB R0 ;restore original negative byte count
BIS #TS.EBM,R0 ;set byte mode
10$: BIS #TS.IFB,R0 ;set to interrupt both on done
MOV R1,TE.EAD(R5) ;set address
MOV R0,TE.EBC(R5) ; and count (which starts transfer)
CLC ;make sure this sucs
RETURN
SNDHDR: ;subroutine to start sending header to -10
.IF NE,FTFEDV
MOV DTACKR,R0 ;check if ack needed
BEQ 10$ ;no - just header
MOV #DTAKHD,R1 ;yes - R0/size, get ack ptr
.IF NE,FTRACE
CMP R0,#D10HDL
BLE 5$
TRACB TRCPRO,DTAKHD,D10HDL
BR 20$
5$:
.ENDC ;.IF NE,FTRACE
TRACB TRCPRO,DTAKHD,D10HDL/2
BR 20$
.ENDC ;.IF NE,FTFEDV
10$:
.IF EQ,FTP5
MOV #DT10HD,R1 ;point to start address
MOV (R1),R0 ;get size of header
.IF EQ,FTFEDV
TRACB TRCPRO,DT10DF,D10DFL/2
.IFF
TRACB TRCPRO,DT10HD,D10HDL/2 ;trace the FEH header
.ENDC; .IF EQ,FTFEDV
.IFF
MOV #DT10DF,R1 ;point to DN60 header
MOV RSPSIZ,R0 ;and it's this big
TRACB TRCPRO,DT10DF,<<D10DFL>/2> ;trace the DN60 header
.ENDC ;.IF EQ,FTP5
20$: MOV R1,TE.XAD(R5) ;set up -10 address
CALL SETQSZ ;send queue size
BCS 99$
MOV #TS.TBM,TE.DG3(R5) ;set byte mode (always for header)
INCB DT11QC ;increment queue count
BIC #TO.IT,DTSTT+2 ;clear TOIT bit to indicate not indirect
CALL SETSTS ;deposit status word
BCS 98$
CALL CRAMLV ;cram keepalive
MOV #TS.EEX,TE.STW(R5) ;ring -10 doorbell
99$: RETURN
98$: DECB DT11QC
SEC
RETURN
;THIS SUBROUTINE HAS TWO ENTRY POINTS . DTSACK TO SEND
; AN ACK + FEH TO THE TEN AND DTSAK FOR SENDING THE
; ACK ALONE TO THE TEN TO ACKNOWLEDGE RECEIPT OF DATA.
.IF NE,FTFEDV
DTSACK: MOV #D10HDL*2,R0 ;SEND ACK + FEH TOGETHER
BR DTSAC ;SET UP ACK HEADER
DTSAK: MOV #D10HDL,R0 ;SEND ONLY THE ACK TO-TEN
DTSAC:
MOV R0,DTACKR ;set ack flag with length of msg
MOV #D10HDL,DTAKHD ;LENGTH OF HEADER
MOV #DTFSAK,DTAKFN ;ACK FUNCTION
MOV #DLDPFE,DTAKDV ;FE DEVICE
CLR DTAKUC ;CLEAR BEFORE PUTTING FE#
MOVB DT11UC+1,DTAKUC ;FE# RIGHT JUSTIFIED
RETURN
.ENDC ;.IF NE,FTFEDV
.IF NE,FTFEDV
OUTHD: MOV #D10DFL,R0 ;output DN60 header
MOV #DT10DF,R1
BR OUTDAT
.ENDC ; .IF NE,FTFEDV
SNDDAT: ;subroutine to start sending indirect data
.IF NE,FTFEDV
CLR R0 ;get no. bytes we said we would send
BISB DT10UC,R0
.IFF
MOV DT10DT,R0 ;get size ready for deposit
.IF NE,FTP5
SWAB R0 ;previously swapped
BNE 5$ ;check for zero length xfer
INC R0 ;yes - xfer 1 fake byte
; DN60 header indicates truth
5$:
.ENDC ;IF NE,FTP5
.ENDC ; .IF NE,FTFEDV
MOV #OUTBUF,R1 ;get big buffer ptr
OUTDAT: ;output data
;R0/bytes to send
;R1/buffer ptr
CALL SETQSZ ;set queued protocol transfer size
BCS 99$
MOV R1,TE.XAD(R5) ;set output address
.IF NE,FTP5
BIC #TO.IND,DTSTT+2 ;all version 5 xfers are direct
INCB DT11QC ;increment queue count
BIC #TO.IT,DTSTT+2 ;clear TOIT bit to indicate not indirect
.IFF
BIS #TO.IND,DTSTT+2 ;say we are doing indirect transfer
.ENDC ;IF NE,FTP5
MOV #TS.TBM,TE.DG3(R5) ;set byte mode in hardware
CALL SETSTS ;deposit status
.IF NE,FTP5
BCS 98$
.IFF
BCS 99$
.ENDC ;.IF NE,FTP5
CALL CRAMLV ;cram keepalive
MOV #TS.EEX,TE.STW(R5) ;ring -10 doorbell
99$: RETURN
.IF NE,FTP5
98$: DECB DT11QC
SEC
RETURN
.ENDC ;.IF NE,FTP5
;DLWEDN ;subroutine to wait for examine/deposit done
; THIS SUBROUTINE WAITS FOR EXAMINE/DEPOSIT TRANSFERS AND
; CHECKS TO SEE THAT E BOX HAS NOT STOPPED.
; CALL: CALL DLWEDN
; R5 -- ADDRESS OF DTE-20
; ON RETURN:
; C = 0: SUCCESS
; C = 1: ERROR
.ENABL LSB
DLWEDN: MOV #3000,DTEDTO ;SET UP TIMEOUT FOR TS.XDNE
11$: BIT #TS.XDN,TE.STW(R5) ;WAIT FOR TRANSFER TO COMPLETE
BNE 12$ ;DONE
DEC DTEDTO ;TIMEOUT?
BNE 11$ ;NO -- CONTINUE WAITING
ATRACE <(SP),TE.STW(R5)>;trace this if anything is traced
EXMFAL: SEC ;YES, ERROR.
RETURN
; HERE WHEN THE TRANSFER IS COMPLETE.
12$: BIT #TS.EPE,TE.STW(R5) ;CHECK FOR E BUS PARITY ERROR
BNE 13$ ;WE HAVE E-BUS PARITY
TRACE TRCDTE,TE.STW(R5)
EXMSUC: CLC ;CLEAR CC-C
RETURN
; WE HAVE AN E-BUS PARITY ERROR. CALL THIS A FATAL ERROR.
13$: STOPCD DTE20 ;E-BUS PARITY ERROR
.DSABL LSB
SAVDTE: ;subroutine to save DTE registers
SAVE <R2,R3,R5> ;save registers
MOV DTEBAD,R5 ;point to DTE
MOV #-1,DTEMSK ;assume all registers NXM
MOV #DTERGS,R2 ;point to table
SAVE NXMGO
MOV #10$,NXMGO
MOV #100000,R3 ;mask bit for first register
5$: MOV @R5,(R2) ;save register (or cause NXM)
BIC R3,DTEMSK ;clear its bit
6$: ADD #2,R5 ;point to next register
ADD #2,R2 ;don't use auto-increment because
; it is unpredictable around NXM
CLC
ROR R3 ;shift bit
BNE 5$ ; until shifted away
RESTOR NXMGO
RESTOR <R5,R3,R2> ;restore registers
RETURN
10$: ;here on NXM
MOV #70707,@R2 ;save distinctive pattern for NXM
BR 6$ ; and continue
DTEMSK: .WORD 0 ;B15=reg 0,B14=reg 1, etc.
DTERGS: .BLKW 20 ;copy sixteen words of DTE
.SBTTL Examine/Deposit functions
;The examine and deposit requests are handled completely at interrupt level,
;so that we can examine a DN60 that is looping at task level.
DLTEXM: ;subroutine to do examine/deposit
CALL CPYHDR ;setup output header
.IIF NE,FTP5, MOV #6,RSPSIZ ;default examine response size
CMPB DT10DF,#DF.DEP ;is this a deposit function?
BNE 10$ ;no, default length OK
.IF EQ,FTP5
MOV #D10HDL+2,DT10HD ;yes, deposit data is only 1st word of DN60 header
.IFF
MOV #2,RSPSIZ ;send only the 1st word of the DN60 header
.ENDC ;.IF EQ,FTP5
10$:
SAVE NXMGO ;save previous NXM trap
MOV #50$,NXMGO ;where to go on NXM
CMPB DT11DF,#DF.DEP ;is it deposit?
BEQ 20$ ;yes, go do it
MOV @DT11AD,DT10DT ;pick up word or NXM
11$: RESTOR NXMGO ;put back old NXM trap
MOVB #1,DT10DF+1 ;put success result code
RETURN ;return to caller
20$: MOV DT11DT,@DT11AD ;store data or get NXM
BR 11$ ;success, return OK
50$: ;here if examine/deposit NXM
RESTOR NXMGO ;restore old NXM trap
MOVB #3,DT10DF+1 ;set reject code for result
RETURN ; and exit
.SBTTL General subroutines
SWPHDR: ;routine to swap header pointed to by R0
.IF EQ,FTP5
SWAB DT11HD-DT11HD(R0) ;swap first word (queued protocol length)
SWAB DT11FN-DT11HD(R0) ;swap queud protocol function
SWAB DT11DV-DT11HD(R0) ;swap queued protocol device code
.IF NE,FTFEDV
SWAB DT11UC-DT11HD(R0) ;swap fe#,bytes
RETURN
.ENDC ; .IF NE,FTFEDV
.ENDC ;.IF EQ,FTP5
SWPHDF: SWAB DT11DF-DT11HD(R0) ;swap DN60 function,,result
SWAB DT11AD-DT11HD(R0) ;swap address for dep/exam, or line,,dev
SWAB DT11DT-DT11HD(R0) ;swap dep data or indirect length
.IF NE,FTP5
SWAB DT11A3-DT11HD(R0) ;swap remaining args
SWAB DT11A4-DT11HD(R0) ;swap remaining args
SWAB DT11A5-DT11HD(R0) ;swap remaining args
SWAB DT11A6-DT11HD(R0) ;swap remaining args
SWAB DT11A7-DT11HD(R0) ;swap remaining args
.ENDC ;IF NE,FTP5
RETURN ;exit
VALHDR: ;validate fe header pointed to by R0
.IF EQ,FTP5
.IF NE,FTFEDV
CMP DT11DV-DT11HD(R0),#DLDPFE;make sure device is DN60 device
BNE 10$ ;if not, return error
CMPB DT11FN-DT11HD(R0),#DTFSAK ;check for ack FEH
BEQ 99$ ;yes - valid header, no indirect coming
TST DT11FN-DT11HD(R0) ;check if indirect
BPL 10$ ;this is not so pretty good
CMPB DT11FN-DT11HD(R0),#DTFSTR;make sure function is string data
BEQ 99$ ;if so, all is kosher
;if not, this header is to be ignored!
;unbelievable !!!!
.IFF
CMPB DT11FN-DT11HD(R0),#DTFDAS;make sure function is DN60
BNE 10$ ;if not, return error
CMP DT11DV-DT11HD(R0),#DLDDAS;make sure device is DN60 device
BEQ 99$ ;if so, don't set error
.ENDC ; .IF NE,FTFEDV
10$: SEC
RETURN
.ENDC ;.IF EQ,FTP5
99$: CLC
RETURN
CPYHDR: ;subroutine to copy input to output header
.IF EQ,FTP5
.IF NE,FTFEDV
MOV #D10HDL,DT10HD ;size of output header
.IFF
MOV #D10HDL+D10DFL,DT10HD ;size of output header
.ENDC ; .IF NE,FTFEDV
MOV DT11DV,DT10DV ;copy queued protocol device
MOV DT11FN,DT10FN ;copy queued protocol function
.IF NE,FTFEDV
BIS #100000,DT10FN ;set indirect bit
MOVB DT11UC+1,DT10UC+1 ;xfer the FE #
MOVB #D10DFL,DT10UC ;set the bytes to follow to DN60 header size
.IFF
BIC #100000,DT10FN ;clear indirect bit
.ENDC ; .IF NE,FTFEDV
.IFF
MOV #D11DFL,RSPSIZ ;set response header size
.ENDC ;.IF EQ,FTP5
CPYDFL: MOV DT11DF,DT10DF ;copy DN60 function
MOV DT11AD,DT10AD ;copy address or line,,dev
CLR DT10DT ;clear data transferred
.IF NE,FTP5
CLR DT10A3 ;precleen response header
CLR DT10DS
CLR DT10DS+2
CLR DT10LS
CLR DT10LS+2
.ENDC ;IF NE,FTP5
RETURN ;done
.SBTTL Interface to read/write data part of message
.REPT 0
This interface consists of 4 routines, BLECHI and BLECHO to
read and write blocks of data, and BYTCHI and BYTCHO to read
and write a single byte. The first two have a byte count in
R0 and an address in R1, the latter two simply transfer the
single byte to/from R0.
.ENDR;.REPT 0
BLECHI: ;block transfer in
TRACE TRCTEN,<(SP),TCXLT(R5),R0,INPCTR>
CLR -(SP) ;assume 0 bytecount returned
CMP R0,INPCTR ;see if request too big
BLE 10$ ;no, assumption right so branch
SUB INPCTR,R0 ;yes, calculate returned bytecount
MOV R0,(SP) ;save it for later
MOV INPCTR,R0 ;change request to amount we have
10$: SAVE R2 ;save source address register
MOV INPPTR,R2 ;get source address
SUB R0,INPCTR ;update input count
CLC ;ensure carry bit clear
BIT #1,R2 ;source address odd?
BNE 20$ ;yes, go check for match
BIT #1,R1 ;destination address even too?
BNE 50$ ;no, go do byte moves for mismatch
30$: ROR R0 ;divide by two to get words
BEQ 32$ ;if none, go check for extra byte
31$: MOV (R2)+,(R1)+ ;copy word
SOB R0,31$ ;loop till count exhausted
32$: BCC 33$ ;if original count was not odd, go finish
MOVB (R2)+,(R1)+ ;else copy odd byte
CLC
33$: MOV R2,INPPTR ;update input pointer
RESTOR <R2,R0> ;restore work register and set count remaining
;plus condition codes
RETURN
20$: BIT #1,R1 ;is destination address odd
BEQ 50$ ;no, go process mismatch
MOVB (R2)+,(R1)+ ;copy preceding odd byte
SOB R0,30$ ;update count and jump into loop if more
BR 33$ ;just exit if that was all
50$: MOVB (R2)+,(R1)+ ;copy one byte
SOB R0,50$ ;repeat till count exhausted
BR 33$ ;go finish up
BLECHO: ;block transfer out
TRACE TRCTEN,<(SP),TCXLT(R5),R0,R1>
CLR -(SP) ;assume 0 bytecount returned
CMP R0,OUTCTR ;see if request too big
BLE 10$ ;no, assumption right so branch
SUB OUTCTR,R0 ;yes, calculate returned bytecount
MOV R0,(SP) ;save it for later
MOV OUTCTR,R0 ;change request to amount we have
10$: SAVE R2 ;save destination address register
MOV OUTPTR,R2 ;get destination address
SUB R0,OUTCTR ;update remaining output count
CLC ;ensure carry bit clear
BIT #1,R2 ;destination address odd?
BNE 20$ ;yes, go check for match
BIT #1,R1 ;source address even too?
BNE 50$ ;no, go do byte moves for mismatch
30$: ROR R0 ;divide by two to get words
BEQ 32$ ;if none, go check for extra byte
31$: MOV (R1)+,(R2)+ ;copy word
SOB R0,31$ ;loop till count exhausted
32$: BCC 33$ ;if original count was not odd, go finish
MOVB (R1)+,(R2)+ ;else copy odd byte
CLC
33$: MOV R2,OUTPTR ;update output pointer
RESTOR <R2,R0> ;restore work register and set count remaining
;plus condition codes
RETURN
20$: BIT #1,R1 ;is source address odd
BEQ 50$ ;no, go process mismatch
MOVB (R1)+,(R2)+ ;copy preceding odd byte
SOB R0,30$ ;update count and jump into loop if more
BR 33$ ;just exit if that was all
50$: MOVB (R1)+,(R2)+ ;copy one byte
SOB R0,50$ ;repeat till count exhausted
BR 33$ ;go finish up
BYTCHI: ;input one byte
TST INPCTR
BGT 10$
CLC
SEZ
RETURN
10$: DEC INPCTR
CLR R0
BISB @INPPTR,R0
INC INPPTR
TRACE TRCTEN,<(SP),TCXLT(R5),R0>
CLRC CZ
RETURN
BYTCHO: ;output one byte
TRACE TRCTEN,<(SP),TCXLT(R5),R0>
TST OUTCTR ;any room?
BGT 10$ ;yes, continue
CLC
SEZ
RETURN
10$: DEC OUTCTR
MOVB R0,@OUTPTR
INC OUTPTR
CLRC CZ
RETURN
.IF NE,DTBUG
.SBTTL Debugging subroutines
STKSAV: ;subroutine to save state machine stack
SAVE <R0,R1,R2> ;save some registers
MOV #SAVSTK,R1 ;point to source
MOV #INTSTK,R0 ;address of source
MOV #STKLEN,R2 ;get count
10$: MOV -(R0),-(R1) ;push onto save stack
SOB R2,10$ ;copy whole stack
MOV SP,R2 ;copy current pointer
SUB #INTSTK,R2 ;displacement
ADD #SAVSTK,R2 ; into saved stack
MOV R2,SAVSTK ;save stack pointer
20$: RESTOR <R2,R1,R0>
RETURN
.ENDC;.IF NE,DTBUG