Trailing-Edge
-
PDP-10 Archives
-
BB-J724B-SM_1982
-
sources/xtencm.p11
There are 5 other files named xtencm.p11 in the archive. Click here to see a list.
.SBTTL XTENCM - PDP-10/20 interface common code
; NOTE: this module contains all the common code for supporting the
; PDP-10 interface. it works only with the new Xdriver modules
; and features smaller, higher performance design plus more legroom
; for the rest of the system.
.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
; REVISION HISTORY
; 4(001) 10-OCT-80 RLS
; INITIAL CREATION. BASED ON VERSION 4(030) OF HDTE10 CODE BUT 90%
; REPLACED.
; 4(002) 17-Nov-80 KR
; Fix GETCM to decrement TCIMC for 2780/3780 flow
; control (WACKO).
; 4(003) 11-MAR-81 RLS
; Make LINABO clear LS.ENB when it sets LF.DIS - the dte error now disables
; the line.
; 4(004) 20-MAR-81 RLS
; Check for input/output running in TREAD/TWRITE an reject request if not.
; 4(005) 01-APR-81 RLS
; Reflect fact that TCCMSG,TCDMSG now in global storage instead of TENTSK tcb.
; 4(006) 07-Apr-81 RLS
; Changes to reflect use of message header for data storage.
; 4(007) 17-APR-81 RLS
; Transform static flow control to static/line control
; 4(010) 21-MAR-82 RLS GC0 4.2.1285
; Don't clear device active bit in TREAD if abort or eof set.
; 4(011) 15-APR-82 RLS GCO 4.2.1322
; Set retry count parameter in line block at enable time.
; 4(012) 26-APR-82 RLS GCO 4.2.1334
; set default device characteristics in BLDTCB
; 4(013) 18-JUN-82 RLS GCO 4.2.1392
; do input abort processing simlilar to input eof.
; 4(014) 11-JUL-82 RLS GCO 4.2.1434
; go pioff and become TENTSK in QDRAIN long enough to DEQMID a message.
; 4(015) 15-JUL-82 RLS GCO 4.2.1449
; QDRAIN forgot to do 1 more level of indirect to reference hasp device
; queues.
; 4(016) 20-AUG-82 RLS GCO 4.2.1496
; in BLDTCB initialize fcs bits to allow io.
VTENCM=016
VEDIT=VEDIT+VTENCM
.SBTTL xmodule interface definitions
;in driver tcb:
;T.HDR: ;beg of arg block from xdriver
;T.FN: .BLKB 1 ;primary function code - tentsk dispatches on it
;T.RES: .BLKB 1 ;result code returned to ten
;T.DEV: .BLKB 1 ;device(0 for 2780/3780,component code for hasp)
;T.LIN: .BLKB 1 ;line number
;T.LNG: .BLKW 1 ;requested number of bytes to transfer
;xdriver functions called
;DLRESP - called to initiate a response to a ten request
;
; args: R0/result code to return
; R1/transfer size to return
;
; returns: carry clear if all copasetic
; carry set if ten down
;BLECHI,BLECHO - read from,send to ten a string
;
; args: R0/byte count
; R1/beginning byte ptr
;
; returns: carry clear, R0/updated byte count
; R1/updated byte ptr
; condition codes reflect "TST R0"
; carry set if fatal error has occurred(ten dead,protocol error)
;BYTCHI,BYTCHO - 1 byte xfer from,to ten
;
; args: R0/byte (out to ten)
;
; returns: carry clear,Z clear - byte transferred: R0/byte (input from ten)
; carry clear,Z set - byte not transferred
; carry set if mortally wounded
;
; note: calls to BYTCHI,BYTCHO should be checked on return:
; BCS <ten dead error>
; followed by
; BEQ <no character xferred error>
; or BNE <character xferred>
.SBTTL XTENCM conventions
;general register usage
;R5/task tcb - the xdriver task normally
;R4/lcb associated with request(line specified)
;R3/xlate tcb(for dev specified),chunk or msg ptr - context dependent
;R2/requested transfer size for read,write functions
;R0,R1 may be freely used, others are safe over function calls unless
; specificially set as a return value.
;function returns: usually carry clear,response code set in t.res. carry set
; will cause TENTSK to abort things.
; carry is used for success(clear)/failure(set) for internally
; called functions.
.SBTTL XTENCM parameters
;device defintions
DV.COU = 1 ;console output device
DV.CIN = 2 ;console input device
DV.CDR = 3 ;card reader
DV.LPT = 4 ;line printer
DV.PUN = 5 ;card punch
; note: these definitions are used only in XTENCM - the rest of the
; fe code still uses absolute numbers!!
;result codes returned to ten
TR.SUC = 1 ;success response - request filled(nearly always)
TR.DLY = 2 ;delay response - some data transfer may have
; been done
TR.REJ = 3 ;request rejected - no data transferred
; the following are not now returned but
; ought to be...maybe someday.
TR.EOF = 4 ;input end of file - last data transferred
TR.ABO = 5 ;input abort - available data transferred
TR.LGA = 6 ;line gone away - available data transferred
.SBTTL TENTSK - pdp-10 interface task
; this task interfaces to the pdp-10 through the device specific functions
TENSNZ: DSCHED #EBTENI ;wake only if something to do
TENTSK: TST TENALV ;check if 10 has ever come to life
BEQ TENSNZ ;no - nothing to do
TST DLGONE ;is 10 already dead?
BNE 15$ ;yes - go process ten death
CLR R1
BISB T.FN(R5),R1 ;get primary function code
BEQ TENSNZ ;no - yawn
CLRB T.FN(R5) ; no current header
.IF NE,FTRACE
CLR R0 ;trace args
BISB T.LIN(R5),R0
CLR R2
BISB T.DEV(R5),R2
TRACE TRCTEN,<R1,R0,R2,T.LNG(R5)> ;trace op code,line,device,length
.ENDC ;.IF NE,FTRACE
MOV #TENDSP,R0 ;get the primary function code dispatch table
CALL DLDISP ;dispatch to primary function processor
BCS 15$ ;fatal error
10$: CLR R0 ; get the result code and xfer amt
BISB T.RES(R5),R0
MOV T.LNG(R5),R1 ; and the amount we want to declare
CALL DLRESP ;end the operation
BCS 15$ ;10 has crashed
BR TENTSK ;go do something else
; here on fatal protocol error or 10 crashed
15$: ;ten really dead - flush all lines
.IF NE,DEBUG
BIT #TRCTER,TRCHLT ;stop on pdp-10 error?
BEQ 16$ ;no.
STOPCD TER ;yes, pdp-10 error
16$:
.ENDC ;.IF NE,DEBUG
CALL DTCERR ;disable the lines
BR TENSNZ ;wait for another command
.SBTTL TENTSK wake ups for interface driver use
WAKFNC: SAVE R5 ; R1/ptr to new header block from ten
MOV TCDLDR,R5 ; get the tentsk tcb
BNE 10$ ; make sure it hasn't disappeared
STOPCD TEN ; curious mode
10$: MOVB (R0)+,T.FN(R5) ; xfer header data to task block
MOVB (R0)+,T.RES(R5) ; which is naturally oraganized the same as
MOVB (R0)+,T.DEV(R5) ; the header block
MOVB (R0)+,T.LIN(R5)
MOVB (R0)+,T.LNG(R5)
MOVB (R0)+,T.LNG+1(R5)
RESTOR R5
WAKTEN: TST TCDLDR ; wake tentsk
BNE 10$
STOPCD TEN ; rather gross
10$: SIGNAL TCDLDR,EBTENI ; wake the interface task
RETURN
.SBTTL DLDISP - table dispatcher
; subroutine to call a subroutine based on an index.
; this is used as a dispatcher.
;
; R0 = pointer to dispatch table. the first entry is
; the max index, the remainder being pointers
; to subroutines.
; R1 = index, 0 based.
;
; dispatch table format:
;
; word 0/offset to 1st location beyond legal dispatches
; words 1-n/legal dispatch addresses
; word n+1 /illegal function code dispatch address
;
; zero dispatch entries take the illegal code dispatch
;
; all returned values and conditions are set by the dispatch function
;
; note: function code of 0 is illegal by default
DLDISP: ASL R1 ; get word offset
BLE 20$ ; illegal function code
CMP R1,(R0) ; check upper bound
BLT 25$ ; legal range
20$: MOV (R0),R1 ; get the offset to illegal dispatch
25$: ADD R0,R1 ; get the dispatch cell adr
MOV (R1),R1 ; get the dispatch address
BEQ 20$ ; ignore possible loop
TRACE TRCTEN,R1 ;trace dispatch address
JMP (R1) ; dispatch to function
.SBTTL TENDSP - primary function code dispatch table
TENDSP: ; dispatch table for pdp-10 initiated operations
15$: .WORD <16$-15$> ; offset to illegal fucntion code dispatch
.WORD TREAD ;1=read data into the pdp-10
.WORD TWRITE ;2=write data from the pdp-10
.WORD DEVSTS ;3=read device status
.WORD DEVCMD ;4=write device command
.WORD LINSTS ;5=read line status
.WORD LINCMD ;6=write line command
.WORD PRTSTS ;7=read dn60 status
.WORD PRTCMD ;8=write dn60 command
.WORD 0 ;9=examine 11 location - device driver fcn
.WORD 0 ;10=deposit in 11 location - device driver fcn
16$: .WORD RETREJ ;illegal primary function code - reject it
.SBTTL DTCERR - port abort, flush everything
; here on pdp-10 protocol error.
; abort all streams and disable all lines.
DTCERR: ;error return for set dev and line
.IF NE,DEBUG
BIT #TRCTER,TRCHLT ;stop on pdp-10 errors?
BEQ 11$ ;no.
STOPCD TER ;yes, pdp-10 error
11$:
.ENDC ;.IF NE,DEBUG
MOV #NLINES,R1 ;number of lines possible
MOV #LINTBL,R2 ;start with line 0
12$: MOV (R2)+,R4 ;get the lcb
BEQ 15$ ;no such line
CALL LINABO ;abort this line
15$: SOB R1,12$
SEC ;signal failure
RETURN
.SBTTL LINABO - abort a line
; args: R4/lcb of line to abort
;
; returns: nothing in particular
LINABO: BIT #LF.DIP,LB.FGS(R4) ;check if line disable in progress
BNE 16$ ;yes - treat as already done
BIT #LS.ENB,(R4) ;don't bother unless line is enabled
BEQ 15$ ;but make sure the modem is off
ATRACE <(SP),R4>
.IF NE,DEBUG
BIT #TRCABO,TRCHLT ;check if we want to die instantly
BEQ 1$
STOPCD DBG
1$:
.ENDC ;.IF NE,DEBUG
SAVE <R1,R2,R3,R4> ;save all the safe regs
12$: CALL DISLN0 ;disable the line
13$: RESTOR <R4,R3,R2,R1>
15$:
16$: RETURN
.SBTTL PRTSTS - read DN60 status
PRTSTS: MOV T.LNG(R5),R2 ;get the req size
BEQ RETREJ ;ten doesn't want to know very much
CLR T.LNG(R5) ; init amount xferred
MOV #D60ST1,R1 ;where the port status info begins
MOV #D60ST2,R0 ;point to beyond last last word
SUB R1,R0 ;how big it is
CALL XCHKSZ ;check req/arg size
CALL BLECHO ;send the cruft
BCS RETFAL ;tendeath
BNE RDLYX0 ;no partials allowed
RETSUC: MOVB #TR.SUC,T.RES(R5) ;suc exit
SETSUC: CLC ;make it suc
RETURN
RDLYX0: CLR T.LNG(R5) ;special delay with no return
RETDLY: MOVB #TR.DLY,T.RES(R5) ;delayed return
BR SETSUC
RETREJ: MOVB #TR.REJ,T.RES(R5) ;reject return
CLR T.LNG(R5) ;no data on reject
BR SETSUC
RETFAL: CALL RETREJ ;return for xdriver errors
SETERR: SEC ;make a failure
RET: RETURN
XCHKSZ: CMP R0,R2 ;common recursor to BLECHI,BLECHO
BLE 10$ ;use smaller of available or requested
MOV R2,R0 ;use requested
10$: ADD R0,T.LNG(R5) ;optimistically update the bytes transferred
SUB R0,R2 ;reduce requested amt not done
RETURN
GETLN: CLR R0 ;get line from ten request and validate it
BISB T.LIN(R5),R0
CMP NSLINS,R0 ;do we have that many lines
BLE SETERR ;no - barf
BR SETSUC ;yes - be agreeable
GETLB: CLR R4
CALL GETLN ;get the lcb for line specified in request
BCS RET ;nonesuch
ASL R0 ;word offset
MOV LINTBL(R0),R4 ;return lcb in r4
BEQ SETERR ;no entry for this line - lose
MOV R4,TCLCB(R5) ;save the lcb in case we need it later
BR SETSUC ; and suc!
GTLBEN: CALL GETLB ;get the lcb and make sure line is enabled
BCS RET ;no lcb
BIT #LF.DIP,LB.FGS(R4) ;check if line disable in progress
BNE SETERR ;yes - treat as already done
BIT #LS.ENB,(R4) ;lcb exists - check line up
BNE SETSUC ;yes - suc
BR SETERR ;no - lose
GETXLT: CALL GETDEV ;find the xlate tcb for line,,dev
BCS RET
ASL R1 ;r1/generic device number
ADD R4,R1 ;word offset into block of tcb's in lcb
MOV LB.TCD(R1),R3 ; get the task block
BEQ SETERR ;none - lose
MOV R3,TCXLT(R5) ;save it for later
BR SETSUC ;and return in r1
GENDEV: MOVB T.DEV(R5),R1 ;get generic device number specified
BIC #177770,R1 ;lo 3 bits relevant
RETURN
WRDARG: CALL BYTCHI ; get a word arg from driver
BCS 15$
BEQ 15$ ; no input available
MOV R0,-(SP) ; save the low order byte
CALL BYTCHI
BCS 9$
BEQ 14$ ; no input in the middle
SWAB R0 ; shift the high byte
BISB (SP)+,R0 ; put it together
CLRC CZ ; carefully set the exit conditions
RETURN
9$: MOV (SP)+,R0 ; return the lo byte for what it's worth
10$: BR SETERR ; return false
14$: MOV (SP)+,R0 ; return the half-assed result
CLC
SEZ
15$: RETURN
TWAT: SAVE <R0,R1,R2,R3,R4> ; save thee registers cause the WAIT
CALL WAIT ; routine isn't smart enough
RESTOR <R4,R3,R2,R1,R0>
RETURN
.SBTTL TREAD - read data (into the ten)
; subroutine to perform the "read data" function.
; message que is examined for a message from that line
; and if one is found it becomes current message.
TREAD: CALL GTLBEN ;get the lcb/enabled
BCS 35$ ;no, lose.
CALL GETXLT ;find the xlate task
BCS 36$ ;curious
MOV T.LNG(R5),R2 ; get the request size
CLR T.LNG(R5) ;init the amt xferred
TRACE TRCTEN,<R3,R2,TCFG2(R3)>
11$: CALL GENDEV ; get the device number
CALL GETCM ;get current or new message
BCS 22$ ;no message for the id.
;r3/msg ptr
12$: MOV MSGLCH(R3),R1 ;get pointer to the current chunk
BEQ 21$ ;end of message found
TST R2 ;have we finished?
BLE 19$ ;yes - depart
MOV (R1)+,T.CMSG(R5) ;save pointer to next chunk
MOV (R1),R0 ;get count, point to data
;r0/# bytes left in chunk
BEQ 17$ ;check for empty chunk
MOV MSGPTR(R3),R1 ;get ptr to next byte to send
; the following is the register allocation for tread:
; R0/#bytes in chunk available
; R1/ptr into chunk
; R2/requested bytes not done
; R3/current msg ptr
; R4/lcb
; R5/TENTSK tcb
; MSGLCH(R3)/current chunk to be sent
; MSGPTR(R3)/current byte to be sent
15$: CALL XCHKSZ ;get right size
TRACE TRCTEN,<R4,R0,R1,R2,R3>
CALL BLECHO ;send some bytes to ten
BCC 16$
JMP RETFAL ;oops!
16$: SUB R0,T.LNG(R5) ;adjust by amount not xferred - may be 0
ADD R0,R2 ; also amt requested not done
MOV MSGPTR(R3),R0 ;get beg output ptr
MOV R1,MSGPTR(R3) ;save updated ptr
SUB R1,R0 ;R0/-<number chars xferred>
MOV MSGLCH(R3),R1 ;get the current chunk
ADD R0,CHLEN(R1) ;update byte count for chunk
BGT 19$ ;if not zero, we can't do more now
17$: MOV T.CMSG(R5),R1 ;emptiness - get adr of next chunk in message
MOV R1,MSGLCH(R3) ;save in message header
ADD #CHDAT,R1 ;build data pointer
MOV R1,MSGPTR(R3) ;save new data pointer
BR 12$ ;send next chunk
19$: JMP RETSUC ;report suc since we do have more data
; here on end of message
21$: MOV R3,R0 ;get the hollow hulk
CALL FREMSG ;flush the msg
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BNE 33$ ;no.
CLR @TCPDM(R5) ;clear device message ptr
BR 11$ ;join the main loop
.ENDC ;.IF NE,FT.HSP
33$: CALL GTCBMO ;get 2*line number in r1
CLR TCCMSG(R1) ;we have no current message
BR 11$ ;find next message and sent to ten
; here if there is no message for that line
22$: TST T.LNG(R5) ;no data - did we xfer any?
BGT 25$ ;yes - delay return
MOV TCXLT(R5),R3 ;point to xlate task
BIT #TCIAC!TCIEC,TCFG2(R3) ;eof or abort?
BNE 37$ ;yes - reject(gets attention)
23$: BIT #TCIRN,TCFG2(R3);if input not running should not be doing data
; transfers
BEQ 36$ ;reject the request
24$: CALL CLRDAC ;clear the device active bit
25$: JMP RETDLY ;delay
35$: TST R4 ; here if not enabled line
BEQ 37$ ; check for any lcb and clear dev active if possible
36$: CALL CLRDAC ;clear the device active bit
37$: JMP RETREJ ;send reject to ten
.SBTTL CLRDAC - clear device active bit
CLRDAC: SAVE <R0,R1,R3> ;R4/lcb
CALL GETDEV ; get the generic device no.
BCS 30$ ; can't do anything
TST R1 ;check for zero device number
BNE 35$ ;non zero, hasp device
MOV TCXLT(R5),R3 ;2780/3780 - get xlate task
BIT #TCOPR!TCOPG!TCORN!TCOEF!TCOEC!TCOAB!TCOAC,TCFG2(R3)
BNE 20$ ;branch if device is doing output
;input
CALL CACTI ;clear input active
BR 30$
20$: CALL CACTO ;clear output active
30$: RESTOR <R3,R1,R0>
RETURN
35$: CALL HCLRAC ;clear hasp device active
BR 30$
.SBTTL GETCM - find next message to be read by the 10
; this subroutine looks for a current message and if )
; none is found, gets oldest message with the id.
;
; R1/device number
;
; R3/msg ptr on success return
GETCM: MOV R2,-(SP)
MOV R1,R2 ; keep dev*2 over here
ASL R2
CALL GTCBMO ;get device msg que offset in r1
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BNE 13$ ; no
MOV TCCMSG(R1),R1 ;get ptr to dev msg q = block of dev msg q's
BNE 12$ ;there's one
SEC ;strange
BR 16$
12$: ADD R2,R1 ;get device msg ptr
MOV R1,TCPDM(R5) ;save ptr to dev msg
MOV (R1),R3 ;any device message?
BNE 17$ ;yes.
MOV TCXLT(R5),R3 ;point to device's tcb
MOV TCCTP(R3),R1 ;get the rcb
MOV LB.LNU(R4),R3 ;get line #
SWAB R3 ;put in left byte
ADD R3,R1 ;make i.d. for the message
CALL 30$ ;look for a message
BCS 16$
CALL BSCFLO ;check bsc flow control
MOV R3,@TCPDM(R5) ;save device msg ptr
BR 17$
.ENDC ;.IF NE,FT.HSP
13$: MOV TCCMSG(R1),R3 ;is there a current message?
BNE 17$ ;yes, continue with it.
MOV LB.LNU(R4),R1 ;get line # (i.d. for 2780/3780)
CALL 30$ ;look for a message
BCS 16$ ;no message for this i.d.
MOV R3,TCCMSG(R1) ;remember current message
17$: CLC ;successful
16$: MOV (SP)+,R2
20$: RETURN
30$: CALL DEQMID ;get oldest msg with that id
BCS 20$ ;there is none.
MOV R0,R3 ;put it in the right place
MOV TCXLT(R5),R2 ;point to xlate task
DEC TCIMC(R2) ;decrement count of input messages
;restore line number before returning
GTCBMO: ;get device msg que offset in r1
MOV LB.LNU(R4),R1 ;get line number
ASL R1 ;line number * 2
RETURN
.SBTTL TWRITE - write data (from ten to remote)
; subroutine to perform the "write data" function. data is
; fetched through the dte20 and placed in chunks. the chunks
; are sent to the xlate task for translation and subsequent
; queueing to the line driver
TWRITE: CALL GTLBEN ;get an enabled lcb - r4
BCS 14$ ;too bad
CALL GETXLT ; get the xlate task - r3
BCS 14$ ;tsk!
MOV T.LNG(R5),R2 ; get the req size
CLR T.LNG(R5) ;init amount xferred
CLR TCXFR(R5) ; init count of chunks q'd to xlate this pass
10$: TRACE TRCTEN,<R3,R2,TCFG2(R3)>
11$: MOV TCXLT(R5),R3 ;get the xlate task
BIT #TCOAB!TCOAC,TCFG2(R3) ;check if aborting
BNE 14$ ;yes - no sense in writing anything
BIT #LF.SIM,LB.FGS(R4);if emulation
BNE 12$ ;don't require following conditions
;termination - don't trust him
BIT #TCORN!TCOPG,TCFG2(R3);make sure output running
BEQ 14$ ;reject the request
12$: CALL OUTFLO ;check if device is suspended or chunks low
BCC 20$ ;no - cramituem
;yes - can't handle it now
TRACE TRCFLO,<R3,TCFG2(R3),LB.FRE(R4),LB.RES(R4),TCXFR(R5)>
;CHECK FOR BAD REASONS
15$: BIT #TCOAB!TCOAC,TCFG2(R3) ;has stream been aborted?
BNE 14$
13$: JMP RETDLY ;no,indicate delayed operation
14$: JMP RETREJ ;operation rejected
20$: CALL GETCHK ;can do some output
BCS 13$ ;except that we can't after all
MOV R0,R1
MOV R0,R3 ;put chunk ptr in usual place
ADD #CHDAT,R1 ; make byte ptr
MOV #CHDATL,R0 ;space available
CALL XCHKSZ
MOV R0,CHLEN(R3) ;be optimistic
CALL BLECHI ;get some bytes
BCS 55$ ;10 death
BGT 40$ ; did it all go?
CALL 50$ ; yes - q the chunk
30$: TST R2 ;are we done?
BGT 11$
35$: JMP RETSUC ;done
40$: SUB R0,T.LNG(R5) ; sub amt not received from total
ADD R0,R2 ; also amt requested not done
SUB R0,CHLEN(R3) ; and from chunk amt
BGT 45$ ; did anything happen?
MOV R3,R0 ;no transfer happened
CALL FRECHK ;flush the chunk
BR 13$ ;delay
45$: CALL 50$ ;chunk did not fill - q it
BR 35$ ;and suc
50$: MOV R3,R0 ;what to do with a nonempty chunk
MOV TCXLT(R5),R1
INC TCXFR(R5) ;count the chunks queued to xlate this time
ADD #TXLN,LB.RES(R4);reserve enough chunks to translate
JMP QUECHK ;queue the chunk to the xlate task
55$: MOV R3,R0 ; ten died - return the chunk
CALL FRECHK
SEC
RETURN
.SBTTL DEVSTS - read device status
; subroutine to perform the "read device status" function.
; the status message is assembled in a buffer and sent to-ten
; as indirect data. no exceptional conditions are possible.
DEVSTS: CALL GTLBEN ; get an enabled lcb
BCS 30$ ; to bad
CALL GETXLT ; some hope - get the xlate tcb
BCS 30$
MOV T.LNG(R5),R2 ; get the request size
BEQ 30$ ; this is an easy one!
CLR T.LNG(R5) ; init amount xferred
TRACE TRCTEN,<R3,R2,TCFG2(R3)>
MOV #DVSTSB,R0 ; get the staging area
MOVB TCDVT(R3),(R0)+ ;get device type
MOVB TCCTP(R3),(R0)+ ;get component type
MOV TCPGC(R3),(R0)+ ;get page count register
MOV TCFG1(R3),(R0)+ ;get flags word 1
MOV TCFG2(R3),(R0)+ ;get flags word 2
MOV TCRSZ(R3),(R0)+ ;get record size for the device
MOV LB.FGS(R4),(R0)+ ;get the line flags
MOV LB.SIG(R4),(R0)+ ;get the line signature
;device status now collected
MOV #DVSTSB,R1 ;ptr to it
SUB R1,R0 ;how much
CALL XCHKSZ ;set xfer size
CALL BLECHO ;send it
BCC 20$
15$: RETURN ; 10 gasping
20$: BNE 25$ ;don't send partials
JMP RETSUC
25$: JMP RDLYX0 ;send 0 xfer delay
30$: JMP RETREJ ;send arrogant reply
DVSTSB: .BLKW 7 ; the amount needed
.WORD 0 ; overrun catcher and detector
.SBTTL LINSTS - read line status
; subroutine to perform the "read line status" function.
; if the line is not initialized, give a 0-length reply
LINSTS: CALL GETLN ; validate line number
BCS 30$ ; if out of range, go reject
MOV T.LNG(R5),R2 ; get the req size
CLR T.LNG(R5) ; init the xferred data count
ASL R0 ; make word index for line
MOV LINTBL(R0),R4 ; check for line block
BEQ 25$ ; if it doesn't exist, it is disabled
MOV R4,TCLCB(R5) ; remember line block
TRACE TRCTEN,<R4,R2,(R4)>
MOV #LNSTSB,R0 ; the staging area for scattered data
MOVB LB.DVT(R4),(R0)+ ; get terminal type
MOVB LB.FGS(R4),(R0)+ ; get line flags
MOVB LB.FGS+1(R4),(R0)+ ; and the high byte also
CLR R1 ;generate info flags
BIT #LS.ENB,(R4)
BEQ 9$
BIS #B0,R1 ;indicate line is enabled
9$: BIT #LF.TSP,LB.FGS(R4) ;output transparent?
BEQ 10$ ;no.
BIS #B3,R1 ;hope nobody else uses bit 3
10$: MOV R0,-(SP) ; save buf ptr
MOV R4,R0 ; get lcb arg
CALL @LB.DTS(R4) ; set dtr and dsr into r1
MOV (SP)+,R0
11$: MOVB R1,(R0)+ ; stuff the line info
; send this much separately
MOV #LNSTSB,R1 ; where it is
SUB R1,R0 ; how much
CALL XCHKSZ ; size check
CALL BLECHO ; send it
BCS 69$ ; losing anyhow
BNE 40$ ; can't get very far
; include line statistics
MOV #LB.ST1,R1 ; where they are
MOV #LB.ST2+2,R0
SUB R1,R0 ; how much
ADD R4,R1 ; in the lcb
CALL XCHKSZ ; set the xfer size
CALL BLECHO ; and send them too
BCC 20$
69$: RETURN ; our world is crumbling
20$: BNE 40$ ; no partials
25$: JMP RETSUC ; suc'd
30$: JMP RETREJ ; thumb node at ten
40$: JMP RDLYX0 ; no partials allowed
LNSTSB: .BLKW 2 ; the amount needed
.WORD 0 ; overrun catcher and detector
.SBTTL PRTCMD - write port command
; subroutine to perform the "write dn60 command" function.
; the first byte of the data is the function code, if other
; data is needed it follows the function code.
PRTCMD:
JMP RETREJ ; no defined port commands
.SBTTL LINCMD - write line command
; subroutine to perform the "write line command" function.
; THE FIRST BYTE OF THE DATA IS THE FUNCTION CODE, IF OTHER
; data is needed it follows the function code.
;
; line commands which require an enabled line are called with r4/lcb
; if line up. reject returned otherwise.
;
; line commands set the proper response code
LINCMD: CALL BYTCHI ; get the command
BCS 40$
BEQ 25$ ; no arg ?
MOV LNCDSP,R1 ; get the offset to illegal command
ASL R0 ; special check for commands requiring enabled
; line to execute
BLE 10$ ; illegal
CMP R0,R1
BLE 20$
10$: MOV R1,R0 ; dispatch to illegal command processor
20$: MOV LNCDSP(R0),R0 ; legal offset - check implemented command
BEQ 10$
CMP #ENBLIN,R0 ; check for commands not requiring enabled line
BEQ 30$ ; enable is one
CMP #DISLIN,R0 ; disable is another
BEQ 30$
SAVE R0 ; save dispatch over gtlben call
CALL GTLBEN ; get an enabled line
RESTOR R0 ; get dispatch back
BCC 31$ ; ok to go
25$: JMP RETREJ ; no - reject the command
30$: ATRACE <R0,R4> ; always trace enable,disable
.IIF NE,FTRACE, BR 32$
31$: TRACE TRCTEN,<R0,R4> ; remember where we went if debugging
32$: CALL (R0) ; dispatch to command processor - use call for debugging
40$: RETURN
LNCDSP: ; line command dispatch table
11$: .WORD <12$-11$> ;offset to illegal code dispatch
.WORD ENBLIN ;1 = enable
.WORD SETDTR ;2 = set dtr
.WORD CLRDTR ;3 = clear dtr - abort and hang up
.WORD DISLIN ;4 = disable
.WORD SETCSD ;5 = set cts delay
.WORD SETSLO ;6 = set length of silo warning area
.WORD SETTRN ;7 = set output in transparent mode
.WORD CLRTRN ;8 = set output in non-transparent mode
.WORD SETTBL ;9 = set transmission block length
.WORD SETRPM ;10= set records per message
.WORD SETSIG ;11= set line signature
.WORD SETSON ;12= set station signed on(lf.son)
12$:
.WORD RETREJ ; illegal code
.SBTTL ENBLIN - line enable processing
; subroutine for line command 1: enable the line
ENBLIN: CALL GETLN ; get the line number
BCC 1$
JMP RETREJ ; one we don't know about
1$: ASL R0
MOV LINTBL(R0),R4 ;already a line control block?
BEQ 24$ ;something is screwed up for sure
11$: BIT #LF.DIP,LB.FGS(R4) ;check if line disable in progress
BNE 18$ ;yes - treat as already done
BIT #LF.EIP,LB.FGS(R4) ;check if enable in progress
BNE 10$ ;yes - skip disabling checks
BIT #LS.ENB,(R4) ;is the line enabled?
BNE 24$ ;yes, can't enable it again.
; check for disable completed
BIT #LF.DAC, LB.FGS(R4) ; did bsc disable the line ?
BEQ 18$ ;no, give delayed return
10$: MOV LB.TC1(R4),R0 ;get pointer to bsc task
BEQ 26$ ;no bsc, exit
MOV TCBP2,R3 ;r3 must point to start of chain
CALL RELTCB ;release tcb and unlink from chain
MOV R3,TCBP2 ;update start of chain of tcbs
26$: ;clean up lcb
MOV #NDHASP+1,R2 ;get number of xlate tcbs + bsc tcb
MOV R4,R1 ;point to lcb 4(024)
ADD #LB.TC1,R1 ;start with bsc task
27$: CLR (R1)+ ;clear xlate tcb pointer in lcb
SOB R2,27$
CALL MAKLB ;now init the line block
25$:
MOV R4,TCLCB(R5) ;remember lcb
CALL BYTCHI ;get device type
BCC 17$ ;none specified
5$: RETURN
17$: BEQ 24$ ; arg deficiency is rejectionable
MOV R0,LB.DVT(R4) ;store device type
BEQ 24$ ;illegal protocol type
CMP R0,#TTHASP ;check range
BGT 24$ ;also illegal
CALL BYTCHI ;get characteristics
BCS 5$ ;not specified
BEQ 24$ ; arg deficiency is rejectionable
MOV R0,LB.FGS(R4) ;store characteristics
BIT #LF.PRI,R0 ;primary?
BNE 12$ ;yes.
MOV #3*JIFSEC,LB.EQW(R4) ;no, make secondary
MOV #SECRTY,LB.ERC(R4) ;set secondary retry count
12$:
.IF EQ,FT.HSP ;check if hasp present
CMP #TTHASP,LB.DVT(R4) ;is this a hasp line?
BEQ 19$ ;yes, but hasp not present- error
;no, continue
20$:
.ENDC ;.IF EQ,FT.HSP
BIC #LF.DAC,LB.FGS(R4) ;disable not complete anymore
BIS #LF.EIP,LB.FGS(R4) ;enable in progress
BIS #LS.ENB,(R4) ;enable the line
CALL FLOSHR ;recalculate chunks allocations
CALL BLDTCB ;build tcb's for xlate tasks
BCS 18$ ;out of storage
CALL GTCBMO ;get 2*line number in r1
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BEQ 14$ ;yes.
.ENDC ;.IF NE,FT.HSP
CLR TCCMSG(R1) ;clear it
.IF NE,FT.HSP ;hasp present
BR 16$ ;and exit
; here for hasp line, set device msg ptr
14$: CLR R2 ;initialize offset in table
MOV R1,R0 ; calc device msg q adr
BEQ 32$
ASR R0 ; get the line number
31$: ADD #2*NDHASP,R2 ; gen offset to block of q's for line
SOB R0,31$
32$: ADD #TCDMSG,R2 ; tcb offset for this line's block of q's
MOV R2,TCCMSG(R1) ;tccmsg entries = ptrs(line) to blocks of dev msg q's
MOV #5,R1 ;initialize all device msg ptrs
15$: CLR (R2)+ ;clear msg ptr
SOB R1,15$ ;cover all device msg ptrs
.ENDC ;.IF NE,FT.HSP
16$: BIC #LF.EIP,LB.FGS(R4) ;enable complete and no longer in progress
21$: JMP RETSUC ; we did it!
; here if short on storage
18$: JMP RETDLY ; delay return
;here if requested a line we do not have
24$: JMP RETREJ ; send him refuse
.IF EQ,FT.HSP ;no hasp but hasp line indicated-error
; here if hasp request and no hasp support
19$: BIS #LF.DAC,LB.FGS(R4) ;indcate line has been disabled by bsc task
BR 24$ ;no hasp support- return
.ENDC ;.IF EQ,FT.SHP
; subroutine to build the line control block and the
; task control blocks needed for each line.
;
; args: R4/lcb ptr
;
; return: initialized line block
MAKLB: CALL INITLB ;make the line block pure
MOV LB.LNU(R4),R0 ;get line number
ASL R0 ;make word offset
MOV #1*JIFSEC,LB.EQW(R4) ;time between sending enq's
MOV #PRIRTY,LB.ERC(R4) ;default line retry count to primary
MOV LB.ERC(R4),LB.EQN(R4) ;number of enq's to send before assuming line is down
MOV #MDMXSD,LB.MDS(R4) ;length of silo warning area for kmc11
MOV #XBLKDF,LB.MBL(R4) ; set default trnasmission block size
CALL DABCLR ;make sure device active bits are off
RETURN ;return after bulding lcb
;this subroutine builds tcb for the bsc and xlate tasks.
; in 3780/2780 we need only one tcb for xlate task
; while for hasp-multileaving we need 5 tcb's in simulate
; and 4 tcb's in support mode of operation
BLDTCB: MOV LB.TC1(R4),R0 ;point to bsc tcb
BNE 10$ ;its already set up
CALL GETTCB ;get a task control block
BCC 7$ ;got the tcb
JMP FLSALL ;out of storage
7$: MOV #LINSTR,TCPC(R0) ;store initial address
CALL STKINI ;init task stack
BIS #BR3,TCPS(R0) ;set priority level to 3
MOV R4,TCLCB(R0) ;store lcb pointer
MOV R0,LB.TC1(R4) ;store bsc task pointer
CALL LDTENV ;load driver entry vectors into task block
MOV #104301,TCTFCS(R0);init fcs words
MOV #104301,TCRFCS(R0)
MOV TCBP2,R1 ;medium priority tcb list
MOV R0,TCBP2 ;put this tcb on the list
MOV R1,TCHAIN(R0) ; ...
BIT #LF.TSP,LB.FGS(R4) ;check for transparent mode
BEQ 10$
BIS #TCTSP,TCFG1(R0) ;yes - also tell bsc task
10$: CLR R2 ;clear device # initially
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BEQ 11$ ;yes.
.ENDC ;.IF NE,FT.HSP
CALL BLDPRO ;set protocol flag for bsc
MOV #1,LB.NTC(R4) ; no, set up for 1 tcb for 2780/3780
CALL GETTCB ;get a task control block
BCS FLSALL ;no room.
MOV #XLATE,TCPC(R0) ;store start adr of task
CLR TCDEV(R0) ;device is 0 for 2780/3780
CALL BLDPRO ;set protocol flag for xlate task
.IF NE,FT.HSP ;hasp present
BR 13$ ;go past hasp settings
11$: MOV #4,LB.NTC(R4) ;set up # of tcb's for hasp devices
BIT #LF.SIM,LB.FGS(R4) ;sim mode?
BEQ 12$ ;no, 4 tcb for sup mode
INC LB.NTC(R4) ;5 tcbs for sim mode
12$: INC R2 ;make r2 device #
CALL GETTCB ;get tcb for xlate task
BCS FLSALL ;no room
MOV #XLHASP,TCPC(R0) ;set up start adr of task
MOV R2,TCDEV(R0) ;and device # in the tcb
.ENDC ;.IF NE,FT.HSP
13$: BIS #BR1,TCPS(R0) ;set priority level to 1
CALL STKINI ;init task stack
MOV R4,TCLCB(R0) ;store lcb pointer
MOV R4,R1 ;preserve lcb ptr in r4
ADD R2,R1 ;add device # to get xlate tcb adr
ADD R2,R1 ; add device # to get xlate tcb adr
MOV R0,LB.TCD(R1) ; store comp. pointer
MOV TCBP3,R1 ; get low-priority tcbs
MOV R0,TCBP3 ; put this tcb on the list
MOV R1,TCHAIN(R0) ; ...
CALL DEVINI ;init device characteristics
; here to get storage for line buffer for each device
BIT #TCIOM,TCFG1(R0) ;if this is an input mode device
BNE 14$ ;...don't need a line buffer
CALL GETPRM ;output device - get storage for it
BCS FLSALL ;out of storage
MOV TCBP3,R1 ;get pointer to xlate tcb
MOV R0,TCBFP(R1) ;store pointer to line buffer
MOV #CHSIZE,TCBFC(R1) ;store length of line buffer
14$:
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BNE 15$ ;all done for 2780/3780
CMP LB.NTC(R4),R2 ;done with all devices xlate tcb's
BNE 12$ ;no
.ENDC ;.IF NE,FT.HSP
15$: MOV LB.SLV(R4),R1 ;get vector address
MOV #PR.LIN*40,R0 ;get initial ps
MOV R4,(R1) ;store pc for interrupt a
ADD #LVECRI,(R1)+
MOV R0,(R1)+ ;store ps for interrupt a
MOV R4,(R1) ;store pc for interrupt b
ADD #LVECXI,(R1)+
MOV R0,(R1)+ ;store ps for interrupt b
CLC ;clear c to flag success
RETURN
; here if we run out of storage getting a tcb.
FLSALL: CALL FLSTCB ;flush everything
SEC ;set c as a flag
RETURN
STKINI: SAVE R1 ;init a task stack
;R0/task block ptr
;R4/line block ptr
MOV TCSP(R0),R1 ;get task stack ptr
CLR -(R1) ;KG11/0
CLR -(R1) ;R0/0
CLR -(R1) ;R1/0
CLR -(R1) ;R2/0
CLR -(R1) ;R3/0
MOV R4,-(R1) ;R4/line block
MOV R1,TCSP(R0) ;save updated stack ptr
CLR TCCHKQ(R0) ;init the task's chunk queue
MOV R0,TCCHK2(R0)
ADD #TCCHKQ,TCCHK2(R0) ;make end ptr point to head
RESTOR R1
RETURN
LDTENV: SAVE <R0,R1,R2> ;load bsc task block with line driver entry pts
;R4/line block ptr
MOV LB.TC1(R4),R0 ;get bsc task block ptr
MOV #T$ENL,R1 ;set up line driver entry points
MOV LB.TYP(R4),R2 ;get line driver type
ASL R2
MOV DRVTBL(R2),R2 ;get entry vector block from line driver
ADD #T.ENV,R0 ;ptr to block in task block
10$: MOV (R2)+,(R0)+ ;xfer to task block
SOB R1,10$
RESTOR <R2,R1,R0>
RETURN
BLDPRO: CMP #TT2780,LB.DVT(R4) ;set protocol flag for task
BNE 10$
BIS #TCOBS,TCFG1(R0) ;2780
10$: RETURN
DEVINI: ;init some device things
CALL DEVIOM ;set device io mode
CMP #TTHASP,LB.DVT(R4)
BNE 10$
BIS #TCCMP,TCFG1(R0) ;hasp - set component selection
MOV #220,TCCTP(R0) ;set the component type
ADD TCDEV(R0),TCCTP(R0)
CMP TCDEV(R0),#DV.LPT ;set carriage control
BEQ 10$ ;for lpt
CMP TCDEV(R0),#DV.COU
BNE 20$ ;and console output but not anything else
10$: BIT #LF.SIM,LB.FGS(R4) ;carraige controls depend on mode
BEQ 15$
BIS #TCPRI,TCFG1(R0) ;emulation - set carriage control on input
BR 20$
15$: BIS #TCPRO,TCFG1(R0) ;termination - set carriage control on output
20$: CMP #TT2780,LB.DVT(R4) ;for 3780,hasp
BEQ 30$
BIS #TCCPS,TCFG1(R0) ;set space compression
30$: MOV TCDEV(R0),R1 ;set default device record size
MOVB DVRSZ(R1),TCRSZ(R0)
RETURN
;default device record sizes
DVRSZ: .BYTE 0 ;0 - must be set dynamically when line turns around
.BYTE 80. ;1 - console output
.BYTE 80. ;2 - console input
.BYTE 80. ;3 - cdr
.BYTE 132. ;4 - lpt
.BYTE 80. ;5 - cdp
DEVIOM: MOV R4,R1 ;set the input/output mode flag for a device
MOV TCDEV(R0),R1 ;get the device number
ASL R1 ;make word offset
BIT #LF.SIM,LB.FGS(R4) ;modify offset according to emulate/terminate
BNE 10$ ;emulate will be low byte of word
INC R1 ;terminate will be high byte of word
10$: CMPB DEVIOT(R1),#.INDEV ;check for input mode
BNE 20$ ;no - output device
BIS #TCIOM,TCFG1(R0) ;mark as input device
20$: RETURN
.INDEV=1 ;flag for input mode device
.OUDEV=0 ;flag for output mode device
;io mode table has 1 word entry for each device
; low order byte for emulation mode
; high order byte for termination mode
DEVIOT: .BYTE .OUDEV,.OUDEV ;0 - set as output mode so it will have a line buffer
.BYTE .INDEV,.OUDEV ;1 - console output
.BYTE .OUDEV,.INDEV ;2 - console input
.BYTE .OUDEV,.INDEV ;3 - cdr
.BYTE .INDEV,.OUDEV ;4 - lpt
.BYTE .INDEV,.OUDEV ;5 - cdp
; subroutine to release bsc and xlate tcbs
; args: R4/lcb
FLSTCB: MOV LB.TC1(R4),R0 ;get ptr to bsc task
BEQ FLXTCB ;no bsc, look for xlate tcb's
MOV TCBP2,R3 ;r3 must point to start of chain
CALL RELTCB ;release tcb and unlink from chain
MOV R3,TCBP2 ;update start of chain of tcbs
CLR LB.TC1(R4) ;clear bsc tcb pointer
FLXTCB: MOV LB.NTC(R4),R2 ;get # of tcb's for xlate
BEQ 16$ ;just in case its zero
.IF NE,FT.HSP ;hasp present
CMPB #TTHASP,LB.DVT(R4) ;2780/3780 mode?
BNE 11$ ;bypass hasp device logic
INC R2 ;hasp has one more to check
.ENDC ;.IF NE,FT.HSP
11$: MOV R2,R1 ;start with highest device #
ASL R1 ;device # mutliplied by 2
12$: ADD R4,R1 ;get tcb ptr to device's
MOV LB.TCD-2(R1),R0 ;xlate task
BEQ 15$ ;none for this, check next device
MOV R0,-(SP) ;save xlate tcb ptr
MOV TCBFP(R0),R0 ;release line buffer if any
BEQ 13$
CALL FREPRM
13$: MOV (SP),R0 ;get tcb ptr back
MOV TCSBF(R0),R0 ;any compressed buffer to release?
BEQ 14$ ;no.
MOV R4,TCLCB(R5) ;make this our line for the moment
CALL FRECHK ;now release the chunk
14$: MOV (SP)+,R0 ;restore xlate ptr
CLR LB.TCD-2(R1) ;clear pointer to tcb
MOV TCBP3,R3 ;point to start of tcb chain
CALL RELTCB ;release and unlink tcb for xlate
MOV R3,TCBP3 ;update pointer to start of tcb chain
15$: SOB R2,11$ ;do for all device xlate tcb's
CLR LB.TCD(R4) ;clear any prev xlate pointer
16$: CLC ;indicate success
RETURN
; this subroutine frees the tcb whose address is in r0 and
; unlinks the tcb from the chain whose start is pointed to
; by r3. r3 is returned with updated pointer to start of chain.
; r1 is destroyed by this routine. r0 and r2 are preserved.
RELTCB: MOV R2,-(SP) ;save r2
CMP R3,R0 ;is it first tcb of chain?
BNE 13$ ;no, hunt thru the chain
MOV TCHAIN(R0),R3 ;yes, update pointer to start of chain
11$: CALL FRETCB ;free the tcb
12$: MOV (SP)+,R2 ;restore r2
CLC ;indicate success
RETURN
13$: MOV R3,R1 ;make first tcb the previous one
14$: MOV TCHAIN(R1),R2 ;point to next tcb in chain
BEQ 16$ ;tcb missing from que
CMP R0,R2 ;match our tcb?
BEQ 15$ ;yes.
MOV R2,R1 ;make current the prev one
BR 14$ ;hunt till match
15$: MOV TCHAIN(R2),TCHAIN(R1) ;unlink tcb from chain
BR 11$ ;free the tcb and exit
; here if tcb is found missing from the que
16$: STOPCD DTM ;tcb missing
.SBTTL the rest of the line commands
; subroutine to do line command 02: set dtr
SETDTR: MOV R4,R0 ; copy LCB into correct register
CALL @LB.DON(R4) ; set data terminal ready
LCSUC: JMP RETSUC ; local suc return
; subroutine to do line command 03: clear dtr
CLRDTR: MOV R4,R0 ; copy LCB into correct register
CALL @LB.DOF(R4) ; clear data terminal ready
BR LCSUC
; subroutine to do line command 04: disable
DISLIN: CALL GETLB ; get lcb
BCS LCSUC ; if no lcb, assume its already done
DISLN0: BIT #LF.DAC,LB.FGS(R4) ;check for completely disabled line
BNE LCSUC ;yes - nothing to do
BIT #LF.DIP,LB.FGS(R4) ;disable in progress?
BNE LCSUC ;yes - not done yet
BIT #LS.ENB,(R4) ;no - check if line is enabled
BEQ LCSUC ;yes - disable in progress
;no - start disable process
MOV LB.TC1(R4),R0 ;wake up the BSC task
BEQ PKLEEN ;hmmmm - must be enable in progress
TRACE TRCLIN,<R4,(R4),LB.FGS(R4),TCFG2(R0),TCST2(R0)>;trace it 1st
BIC #LS.ENB,(R4)
SIGNAL R0,EBINTR ;wake him no matter what he is waiting on
LCDLY: JMP RETDLY ; local delay return
PKLEEN: TRACE TRCLIN,<R4,(R4),LB.FGS(R4)> ;disable line in process of enabling
BIC #LS.ENB,(R4) ;disable the line
BIC #LF.EIP,LB.FGS(R4) ;no longer in progress
CALL FLOSHR ;return its resources
BR LCSUC ;and suc
; subroutine to do line command 05: set cts delay
SETCSD: CALL WRDARG ; get the csd word
BCS LCRET ; death nell
BEQ LCREJ ; no arg - reject
MOV R0,LB.CSD(R4) ; store it
BR LCSUC
LCRET: RETURN ; local return for bcs's
LCREJ: JMP RETREJ ; local reject return
; subroutine to do line command 06: set length of silo warning area
; (this is only effective if the line driver includes a kmc11)
SETSLO: CALL WRDARG ; silo warning area size word
BCS LCRET
BEQ LCREJ ; no arg - reject
TST R0
BLE LCREJ ; kmc can't handle 0
MOV R0,LB.MDS(R4) ; STORE IT
CLR LB.MDU(R4) ;clear max depth used
BR LCSUC
; subroutine to do line command 07: set output in transparency
; this applies only to hasp-multileaving lines
SETTRN: BIS #LF.TSP,LB.FGS(R4) ;set flag in line control block
MOV LB.TC1(R4),R1 ;get pointer to bsc tcb
BIS #TCTSP,TCFG1(R1) ;set trasparent flag for bsc
BR LCSUC
; subroutine to do line command 08: set output in non-transparency
; this applies only to hasp-multileaving lines
CLRTRN: BIC #LF.TSP,LB.FGS(R4) ;set flag in line control block
MOV LB.TC1(R4),R1 ;point to bsc tcb
BIC #TCTSP,TCFG1(R1) ;clear transparency for bsc to look at
BR LCSUC
; subroutine to set transmission block size
SETTBL: CALL WRDARG ; get the block size
BCS LCRET
BEQ LCREJ ; reject it in disgust
MOV R0,LB.MBL(R4) ; store it
JMP RETSUC
; subroutine to set records per message for transmission block
SETRPM: CALL WRDARG ; get the arg
BCS LCRET
BEQ LCREJ ; no arg - reject
MOV R0,LB.MLR(R4) ; store it
JMP RETSUC
; subroutine to set line signature
SETSIG: CALL WRDARG ; get the signature
BCS LCRET
BEQ LCREJ ; no arg - reject
MOV R0,LB.SIG(R4) ; cram it
JMP RETSUC
; subroutine to do line command 12: set station signed on
SETSON: BIS #LF.SON,LB.FGS(R4) ;claim station signed on
JMP RETSUC
.SBTTL DEVCMD - write device command
; subroutine to perform the "write device command" function.
; the first byte of the data is the function code, if other
; data is needed it follows the function code.
DEVCMD: CALL GTLBEN ; get an enabled lcb
BCS 10$ ; loser
CALL GETXLT ; get the xlate tcb
BCC 20$ ; dev was ok too
10$: JMP RETREJ ; dump on user
20$: CALL BYTCHI ; get the devics command
BCS 25$ ; forget everything
BEQ 10$ ; paucity of args
MOV R0,R1
MOV #DVCDSP,R0
TRACE TRCTEN,<R3,R1,TCFG2(R3)>
CALL DLDISP ; dispatch on command
25$: RETURN ; return whatever
.SBTTL DEVCMD dispatch table
DVCDSP:
12$: .WORD <13$-12$> ;offset to illegal code dispatch
.WORD SETCHR ;1 = set characteristics
.WORD 0 ;2 = reserved
.WORD DMPOUT ;3 = dump output [1(627)]
.WORD CLRIPR ;4 = clear "input permission was requested"
.WORD 0 ;5 = reserved
.WORD DOINCC ;6 = interpret cc on input
.WORD NOINCC ;7 = dont
.WORD DOOUCC ;8 = interpret cc on output
.WORD NOOUCC ;9 = dont
.WORD 0 ; reserved
.WORD 0 ; reserved
.WORD DOCSEL ;12 = do component selection
.WORD NOCSEL ;13 = dont
.WORD ENBPGC ;14 = enable page counter
.WORD DISPGC ;15 = disable it
.WORD 0 ;16 = reserved
.WORD DOSPCM ;17 = do space compression
.WORD NOSPCM ;18 = dont
.WORD PR2780 ;19 = use old bsc protocol
.WORD PR3780 ;20 = dont
.WORD REQOPR ;21 = request output permission
.WORD GRNTIP ;22 = grant input permission
.WORD OUTEOF ;23 = signal output eof
.WORD CLROEC ;24 = clear output eof complete
.WORD OUTABO ;25 = signal output abort
.WORD CLROAC ;26 = clear output abort complete
.WORD CLRIEC ;27 = clear input eof complete
.WORD INPABO ;28 = signal input abort
.WORD CLRIAC ;29 = clear input abort complete
.WORD SUSPND ;30 = suspend device (hasp)
.WORD UNSUSP ;31 = unsuspend device (hasp)
.WORD SETDRS ;32 = set device record size
13$:
.WORD RETREJ ; illegal command
.SBTTL device commands
;device command processors are called with
;
; args: R4/lcb
; R3/xlate tcb
;
;they return
;
; carry clr - with specific response code set in header block
; carry set - ten interface error
; subroutine to do device command 01: set characteristics
SETCHR: CALL WRDARG ; get the characteristics
BCS DVRET
BEQ DVREJ ; no arg - reject
MOV R1,TCDVT(R3) ;store device type
BR DVSUC
; subroutine to do device command 03: dump output
DMPOUT: BIS #TCDMP,TCFG1(R3) ;set "dump output"
JMP XLTWAK ; wake the xlate task and suc
; subroutine to do device command 04: clear "input permission was requested"
CLRIPR: BIC #TCIPG!TCIWR,TCFG2(R3) ;clear "input permission was requested"
BR DVSUC
; note that command 05 is reserved
; subroutine to do device command 06: set "interpret cc on input"
DOINCC: BIS #TCPRI,TCFG1(R3) ;set "cc on input"
BR DVSUC
; subroutine to do device command 07: no interpret cc on input
NOINCC: BIC #TCPRI,TCFG1(R3) ;clear "cc on input"
BR DVSUC
; subroutine to do device command 08: interpret cc on output
DOOUCC: BIS #TCPRO,TCFG1(R3) ;set "cc on output"
BR DVSUC
; subroutine to do device command 09: no cc on output
NOOUCC: BIC #TCPRO,TCFG1(R3) ;clear "cc on output"
BR DVSUC
; subroutine to do device command 12: do component selection
; this is used by hasp multileaving only
DOCSEL: CALL BYTCHI ;get component code
BCS DVRET
BEQ DVREJ ; no arg - reject
TST R0 ;test component code for legal device
.IF NE,FT.HSP ;hasp present
BNE 10$ ;go make sure it is HASP
CMP #TTHASP,LB.DVT(R4) ;0 not legal for hasp
BEQ DVREJ
.IFF
BNE DVREJ ;only 0 legal
.ENDC ;.IF NE,FT.HSP
10$: MOVB R0,TCCTP(R3) ;store component code
BIS #TCCMP,TCFG1(R3) ;indicate "component selection"
BR DVSUC
; subroutine to do device command 13: no component selection
NOCSEL: BIC #TCCMP,TCFG1(R3) ;indicate no component selection
BR DVSUC
; subroutine to do device command 14: set printer page counter
; (not yet completely implemented in xlate)
ENBPGC: CALL WRDARG ; get the page count
BCS DVRET
BEQ DVREJ ; no arg - reject
MOV R0,TCPGC(R3) ; stuff it
BIS #TCPCE,TCFG1(R3) ;turn on page counter
BIC #TCPCO,TCFG1(R3) ; and turn off interrupt flag
DVSUC: JMP RETSUC ; local suc return
DVRET: RETURN ; local return for bcs's
DVREJ: JMP RETREJ ; local reject return
; subroutine to do device command 15: no printer page counting
DISPGC: BIC #TCPCE!TCPCO,TCFG1(R3) ;clear page counter bits
BR DVSUC
; subroutine to do device command 17: do space compression
DOSPCM: BIS #TCCPS,TCFG1(R3) ;indicate do compression
BR DVSUC
; subroutine to do device command 18: don't do space compression
NOSPCM: BIC #TCCPS,TCFG1(R3) ;indicate dont do compression
BR DVSUC
; subroutine to do device command 19: use old bsc protocol
PR2780: BIS #TCOBS,TCFG1(R3) ; use 2780 protocol
MOV LB.TC1(R4),R0 ;point to bsc task
BIS #TCOBS,TCFG1(R0) ;tell bsc task to use old bsc
BR DVSUC
; subroutine to do device command 20: dont use old bsc
PR3780: BIC #TCOBS,TCFG1(R3) ; use 3780 protocol
MOV LB.TC1(R4),R0 ;point to bsc task
BIC #TCOBS,TCFG1(R0) ;tell bsc task not to use old bsc protocol
BR DVSUC
; subroutine to do device command 21: request output permission
REQOPR: BIT #TCIPR,TCFG2(R3) ;input permission requested?
BNE 10$ ;yes, this is a no-op.
BIS #TCOPR,TCFG2(R3) ;no, flag output permission requested
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BNE 10$ ;no
MOV LB.TC1(R4),R0 ;point to bsc task
BIS #TCOPR,TCFG2(R0) ;tell bsc task there is output to do
.ENDC ;.IF NE,FT.HSP
10$: JMP XLTWAK ; wake the xlate task and return suc
; subroutine to do device command 22: grant input permission
GRNTIP: BIT #TCIPR!TCIWR,TCFG2(R3) ;has input permission been requested?
BEQ 10$ ;no, this is a no-op.
BIS #TCIPG,TCFG2(R3) ;yes, flag input permission granted
10$: JMP XLTWAK ; wake the xlate task and return suc
; subroutine to do device command 23: signal output eof
OUTEOF: BIS #TCOEF,TCFG2(R3) ;flag end-of-file on output
JMP XLTWAK ; wake the xlate task and return suc
; subroutine to do device command 24: clear output eof complete
CLROEC: BIC #TCOEF!TCOEC,TCFG2(R3) ;clear output eof flags
CLACWK: CALL CLRDAC ; clear device active set by eof condition
JMP XLTWAK ; wake the xlate task and return suc
; subroutine to do device command 25: signal output abort
OUTABO:
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BEQ 10$ ;yes, indicate abort to device
.ENDC ;.IF NE,FT.HSP
MOV LB.TC1(R4),R0 ;point to bsc task
BIS #TCOAB,TCFG2(R0) ;signal abort to bsc task
10$: BIS #TCOAB,TCFG2(R3) ;signal abort to xlate task
JMP XLTWAK ; wake the xlate task and return suc
; subroutine to do device command 26: clear output abort complete
CLROAC: BIC #TCOAB!TCOAC,TCFG2(R3) ;clear abort bits
CALL CACTO ;clear active bit
JMP XLTWAK ; wake the xlate task and return suc
; subroutine to do device command 27: clear input eof complete
CLRIEC: BIC #TCIEC,TCFG2(R3) ;clear input eof complete
BR CLACWK ; clear active bit and wake xlate task
; subroutine to do device command 28: signal input abort
INPABO:
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BEQ 10$ ;yes, indicate abort to device
.ENDC ;.IF NE,FT.HSP
MOV LB.TC1(R4),R0 ;point to bsc task
BIS #TCIAB,TCFG2(R0) ;signal abort to bsc task
10$: BIS #TCIAB,TCFG2(R3) ;signal abort to xlate task
BR XLTWAK ; wake the xlate task and return suc
; subroutine to do device command 29: clear input abort complete
CLRIAC: BIC #TCIAB!TCIAC,TCFG2(R3) ;clear abort bits
CALL CACTI ;clear the active bit
BR XLTWAK ; wake the xlate task and return suc
; subroutine to do device command 30: suspend device
SUSPND: BIS #TCDSP,TCFG2(R3) ;mark device suspended
.IF NE,FT.HSP ;hasp present
BIT #TCIOM,TCFG1(R3) ;input device ?
BEQ 10$ ;no, exit
MOV TCDEV(R3),R1 ;get dev #
MOV LB.TC1(R4),R0 ;point to bsc tcb
ASL R1 ;dev # * 2
MOV SUSTBL(R1),R1 ;get suspend bit for device
BIC R1,TCTFCS(R0) ;r0 still points to bsc
;this indication goes to remote
.ENDC ;.IF NE,FT.HSP
10$: BR XLTWAK ; wake the xlate task and return suc
; this subroutine to do device command 31: unsuspend device
UNSUSP: BIC #TCDSP,TCFG2(R3) ;mark device unsuspended
.IF NE,FT.HSP ;hasp present
BIT #TCIOM,TCFG1(R3) ;input device ?
BEQ 10$ ;no, exit
MOV TCDEV(R3),R1 ;get dev #
MOV LB.TC1(R4),R0 ;point to bsc tcb
ASL R1 ;dev # * 2
MOV SUSTBL(R1),R1 ;get suspend bit for device
BIS R1,TCTFCS(R0) ;r0 still points to bsc
;this indication goes to remote
.ENDC ;.IF NE,FT.HSP
10$: BR XLTWAK ; wake the xlate task and return suc
; subrotine to do device command 32: set device record size
SETDRS: CALL WRDARG ; get the device record size
BCS DVRET1
BEQ DVREJ1 ; no arg - reject
MOV R0,TCRSZ(R3) ; crammit
BR XLTWAK ; wake the xlate task and return suc
DVRET1: RETURN ; local return for bcs's
DVREJ1: JMP RETREJ ; local reject return
.SBTTL misc. support functions
; subroutine to drain a device input queue on an abort.
;
; Parameters: R3/device tcb
; R4/line block ptr
.ENABL LSB
QDRAIN: SAVE <R0,R1>
11$: MOV LB.LNU(R4),R1 ;get line number
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BNE 12$ ;no, use line no as i.d.
SWAB R1 ;put line # in left byte
ADD TCCTP(R3),R1 ;make i.d. for hasp device
.ENDC ;.IF NE,FT.HSP
12$: PIOFF ; protect this process
SAVE R5
MOV TCDLDR,R5 ;have to be TENTSK for this
CALL DEQMID ;get message from this line
RESTOR R5
BCS 13$
PION
CALL 30$ ;flush it
BR 11$
13$: PION
CALL GTCBMO ;now flush any messages being processed
ADD #TCCMSG,R1 ;make ptr to device message cell
.IF NE,FT.HSP ;hasp present
CMP #TTHASP,LB.DVT(R4) ;hasp line?
BNE 15$ ;no, @R1/message
MOV (R1),R1 ;yes,@R1/ptr to block of device queues
BEQ 20$ ;this can't happen of course
MOV TCDEV(R3),R0 ;get device number
ASL R0
ADD R0,R1 ;R1 was ptr to block of device messages
.ENDC ;.IF NE,FT.HSP
15$: MOV (R1),R0 ;get the message
BEQ 20$ ;none
CALL 30$ ;toss it
CLR (R1) ;not there anymore
20$: RESTOR <R1,R0>
RETURN ; done
30$: ATRACE <6(SP),R3,R0>
LOSDAT:
CALL FREMSG ;flush the garbage
RETURN
.DSABL LSB
; here to wake the xlate task and give ok return.
XLTWAK: SIGNAL R3,EBINTR ;maybe, wake it.
10$: JMP RETSUC
; this subroutine checks if a device number is legitimate
; for the mode of the line. the device number must be zero
; for 3780/2780. the device number must be between one and
; five, inclusive, for hasp. this routine also saves the
; address of the last call that had the a device number.
;
; args: R4/lcb
;
; return: c-bit clear, R1/device number
; c-bit set implies device number illegitimate for mode
GETDEV: CALL GENDEV ; get the generic device number - in r1
.IF NE,FT.HSP ;hasp present
BEQ 1$ ;if zero, better be 3780/2780
BIT #LF.SIM,LB.FGS(R4) ;are we doing simulation ?
BNE 4$ ;yes, up to device # 5 allowed
CMP R1,#DV.LPT ;no, support, only lpt device allowed
BGT 2$ ;error, > than 4 for hasp simulation
BR 5$ ;now make sure line is in hasp mode
4$: CMP R1,#DV.PUN ;greater than 5 ?
BGT 2$ ;yes, error, number to big for hasp
5$: CMP #TTHASP,LB.DVT(R4) ;no, hasp mode ?
BNE 2$ ;no, error, its 3780/2780
BR 3$ ;yes, device number is good
1$: CMP #TTHASP,LB.DVT(R4) ;hasp mode ?
BNE 3$ ;no, 3780/2780, zero is good
.IFF
BEQ 3$ ;2780/3780, zero is good
.ENDC ;.IF NE,FT.HSP
2$: MOV (SP),DLIMPC ;save the address of the caller
SEC ;tell caller he had a bad device number
RETURN
3$: CLC ;tell caller his device number is good
RETURN
DLIMPC: .WORD 0 ;pc of last call with bad device number